MATERIAL DE ESTUDIO Flujo de ejecución de una aplicación en App Inventor El flujo de cualquier programa en Android se basa en eventos, es decir, tiene que ocurrir una acción para que la reacción correspondiente se realice, es decir, el programa “espera” a. Esto ocurre tanto en las aplicaciones generadas con la programación “tradicional” como las generadas con App Inventor o Protocoder.
Diagrama ejecución Android En el caso de la programación en otros lenguajes, como Arduino, la programación se basa en un ciclo en el que de manera lineal se ejecuta el código. Dentro de este ciclo, tendremos que comprobar si las acciones han ocurrido para entonces ejecutar las acciones correspondientes.
DRA. ING. RINA FAMILIA
1
Diagrama ejecución Arduino
Creando la interfaz de usuario Para crear la interfaz de usuario, el desarrollador puede hacer uso de distintos elementos, desde botones y cuadros de texto, a elementos que modifican la manera en que los elementos visuales se colocan en pantalla. Para incluir elementos en App Inventor solo tendremos que buscar el que queremos incluir en la aplicación y arrastrarlo en la pantalla Visor, pero hay ciertos elementos que nos facilitarán crear una interfaz mejor, como los elementos Disposición.
Disposición Los elementos de Disposición, o Layout en en inglés, permiten modificar la forma en que se colocan los elementos. Existen varios tipos: Tabular: Ordena los elementos en forma de tabla. •
DRA. ING. RINA FAMILIA
2
•
•
Vertical: Ordena los elementos colocándolos uno
después de otro en orientación
vertical.
•
Horizontal: Ordena los elementos colocándolos uno
después de otro en orientación
horizontal.
Pueden incluirse disposiciones dentro de disposiciones, por lo que combinando varias podemos conseguir un buen diseño de interfaz.
Aplicación En esta entrada vamos a hacer una aplicación que utilizará el reloj del dispositivo para ejecutar la vibración, demostrando así como la aplicación responde a eventos. Diseño de la UI Para comenzar, utilizaremos un contenedor vertical ( Disposición Vertical ) en el que organizaremos el resto de elementos. Fijamos las propiedades Ancho y Alto para que se ajusten al contenedor:
DRA. ING. RINA FAMILIA
3
A continuación, dentro del contenedor vertical, incluimos una disposición Horizontal y una disposición Tabular. Modificamos ambos anchos para que se ajusten al contenedor:
Dentro del contenedor horizontal que hemos incluido en el paso anterior, incluimos dos botones, que se encargarán de iniciar y parar la ejecución del programa. Modificamos su nombre y texto por Iniciar y Parar y cambiamos su Ancho para que se ajusten al contenedor:
DRA. ING. RINA FAMILIA
4
Entre el contenedor vertical y el contenedor horizontal, incluiremos el elemento Lienzo (Dibujo y animación), que utilizaremos para cambiar el intervalo entre vibraciones al arrastrar sobre el eje Y, y cambiar el tiempo de vibración al arrastrar sobre el eje X. Modificamos su alto y ancho para que se ajusten al contenedor.
DRA. ING. RINA FAMILIA
5
A continuación, dentro del contenedor tabular, colocamos cuatro etiquetas:
Cambiamos el nombre de arriba a abajo y de izquierda a derecha por: Label_vibracion, tiempo_vibracion_label, Label_intervalo y tiempo_intervalo_label. Estas variables se encargarán de mostrar la palabra Vibración, el tiempo de vibración, mostrar intervalo y el tiempo de intervalo entre cada vibración, respectivamente. Modificamos el texto que muestran las etiquetas de Label_vibracion y label_intervalo por Vibración e Intervalo, respectivamente. Cambiamos el texto de las variables tiempo_vibracion_label y tiempo_intervalo_label por los valores con los que incializaremos las variables en la parte de programación, 100 y 1000 respectivamente.
DRA. ING. RINA FAMILIA
6
Por último, incluiremos el elemento Reloj, incluido dentro de sensores, que utilizaremos como temporizador, y el elemento Sonido, incluido dentro de Medios, que utilizaremos para hacer vibrar el dispositivo. Estos dos elementos no tienen representación gráfica dentro de la interfaz.
Programación En el modo Bloques programamos la aplicación. Para comenzar, declaramos las variables globales intervalo y vibración, para ello, arrastramos el bloque “inicializar global nombre como” y dentro de Matemáticas, el bloque para incluir números (primero
del listado matemáticas):
Una vez que hemos unido ambos bloques, cambiamos nombre por intervalo y vibracion, y en el bloque de números asignamos 1000 a intervalo y 100 a vibración:
A continuación, programamos los botones Iniciar y Parar. Para ello utilizaremos la orden set Reloj1.TemporizadorHabilitado, que se encarga de habilitar o deshabilitar el temporizador si asignamos el valor cierto o falso respectivamente.
Además, utilizaremos el bloque “poner Reloj1.IntervaloDelTemporizador como”, uniendolo con el bloque “cuando Iniciar.Clic” para que se asigne el v alor de la variable
global intervalo al intervalo del temporizador. Este intervalo será el tiempo que tarde en “activarse” el temporizador.
DRA. ING. RINA FAMILIA
7
Para obtener el bloque “tomar global intervalo”, nos situamos encima del nombre de la
variable en su declaración, aparecerá un desplegable y desde ahí arrastramos el bloque tomar “global intervalo” al conjunto anterior:
Ahora, cada vez que se pulse sobre el botón Iniciar, se modificará el valor de la frecuencia con la que se activará el temporizador. Para continuar, programaremos las acciones que se ejecutarán cuando se active el temporizador, para ello, dentro de Reloj1 arrastramos el bloque “cuando Reloj1.Temporizador”:
DRA. ING. RINA FAMILIA
8
Con el bloque anterior, unimos el bloque “llamar Sonido1.Vibrar” y un bloque “tomar global vibracion”:
Para finalizar, programaremos la respuesta del lienzo al movimiento utilizando el bloque “cuando Lienzo1.Arrastrado”:
Dentro de este bloque, incluiremos la sentencia de control “si entonces” (if -else) y un
bloque de comparación matemática:
Modificamos la comparación para que sea mayor que y incluimos en los miembros de la comparación, de izquierda a derecha, tomar YPrevio y tomar YActual:
Esta orden se ejecuta si nos desplazamos dentro del lienzo sobre el eje Y y hacia arriba, por lo que aumentaremos la variable. Podríamos asignar a la variable un valor en función de la posición que se haya tocado, pero para hacer la ejecución más estable e intuitiva, se aumentará el valor de la variable en una cantidad fija. En este caso, aumentaremos en 100 unidades el valor de la variable intervalo:
DRA. ING. RINA FAMILIA
9
Duplicamos el bloque Si-Entonces anterior y lo unimos a éste, modificamos la comparación para que sea menor que, obteniendo la detección del desplazamiento contrario al anterior, es decir, vamos a d etectar si se esta “bajando” dentro del lienzo. Al realizar el movimiento contrario, vamos a disminuir el valor de la variable:
Duplicación bloque Podemos reutilizar todo el bloque menos la operación de suma, que tenemos que cambiar por una resta:
Para modificar el tiempo que vibrará cada vez que se active el temporizador, utilizaremos el movimiento sobre el eje X del lienzo. Los bloques de programación son
DRA. ING. RINA FAMILIA
10
los mismos que los utilizados para el eje Y, modificando los valores Y por X, la variable intervalo por vibración y la modificación del valor pasa de valer 100 a 10.
Ejercicios para mejorar la compresión En el programa incluido, las variables pueden tomar valores negativos. Puedes modificar la aplicación para que si una variable toma un valor negativo se asigne el valor por defecto. Puedes programar también la aplicación para que sea necesario desplazarse una cierta distancia sobre el lienzo para que se modifique la variable.
Creando la interfaz
Para crear la interfaz utilizaremos “layaouts” para organizar los elementos, botones
para controlar el movimiento y un “canvas” que contendrá la pelota que vamos a mover. En primer lugar, incluimos un “layaout” vertical, donde incluiremos el resto de
elementos modificando su ancho y alto para que se ajusten al contenedor. A
DRA. ING. RINA FAMILIA
11
continuación, incluimos el “canvas” y modificamos su ancho y alto para que se ajusten
al contenedor.
Para terminar con el “canvas”, arrastramos el elemento Ball (pelota) dentro de éste. En
sus propiedades, modificamos el color a verde, cambiamos el radio a 20 y modificamos su posición para que sea X = 0 e Y = 0.
A continuación, arrastramos un elemento disposición vertical debajo del “canvas”, dejando en automático la propiedad alto y modificando su ancho a ajustar al contenedor. Si se modifica el alto a ajustar al contenedor nos facilitará incluir los elementos dentro del mismo, pero después modificaremos su alto a automático. Dentro de éste, un botón, y otro elemento de disposición vertical (que utilizaremos como separador), cambiando su alto a 10 pixels y su ancho a ajustar al contenedor. En el
DRA. ING. RINA FAMILIA
12
caso del botón, modificaremos el ancho para ajustar al contenedor y dejaremos el alto en automático.
Además, modificamos el texto en el botón para que muestre el carácter “^”, cambiamos
la propiedad shape (forma), a rounded (redondeado) y renombramos el botón como up. Para poner los tres botones centrales utilizaremos una disposición horizontal, a la que modificamos su ancho para que sea fill parent , es decir, se ajuste al contenedor, en el que incluiremos los siguientes elementos: 3 botones y 2 disposiciones horizontales (puede usarse cualquiera de ellas) que tendrán un tamaño de 10 pixels de ancho y alto. En el caso de los botones, modificamos su tamaño para que se ajusten al contenedor, así cambiarán su ancho ajustándose a la pantalla. De izquierda a derecha, cambiaremos su texto y nombre para que sean: • • •
< left o reset > right
También cambiamos la propiedad shape para que sea rounded .
DRA. ING. RINA FAMILIA
13
Por último, incluimos otro botón debajo de la disposición horizontal donde hemos incluido los tres botones. Para este botón, modificamos el ancho para que se ajuste al contenedor, su nombre por Down, su texto por v y la forma por redondeada. Incluimos un elemento de disposición, con un alto de 10 pixels para que funcione como separador.
A continuación, debajo del botón Down incluimos un “layout” vertical, modificando su alto a 10 pixels y su ancho a ocupar el contenedor, utilizando esta disposición como separador, evitando así que el botón se “funda” con el borde de la pantalla. Para
finalizar, cambiamos el ancho del contenedor vertical que está debajo del canvas para que sea automático.
DRA. ING. RINA FAMILIA
14
Programando la aplicación Para programar la aplicación vamos a la pestaña Blocks. En primer lugar, programaremos el botón UP arrastrando el bloque. Clic:
A continuación, arrastramos el bloque Call Ball1.MoveTo y lo unimos al bloque anterior.
DRA. ING. RINA FAMILIA
15
Para programar el movimiento utilizaremos los valores X e Y del bloque anterior. En este caso, la posición X será constante y se modificará la posición Y, reduciendo su valor en el número de unidades que determinemos. Para programar el movimiento de la X, dentro de Ball1 arrastramos el bloque Ball1.X y para el movimiento Y un bloque de resta, donde restaremos la cantidad 10 a la posición actual de Y.
Cambiamos Ball1.X por Ball1.Y , para tomar la posición Y actual de Ball1.
Para programar el movimiento del botón Down, duplicamos el conjunto anterior, modificamos Up por Down y cambiamos el bloque resta por suma.
En el caso de los botones left y right modificaremos la posición X, manteniendo constante la posición Y. Para el botón left se reducirá la posición y para el botón right , aumentará.
DRA. ING. RINA FAMILIA
16
Por último, programaremos el botón reset igualando X e Y a 0.
Código Arduino En este caso vamos a utilizar el código correspondiente que permita recibir una cadena de caracteres del tipo =avanzar+, por lo que programaremos la aplicación de App Inventor para que envíe las ordenes de esta manera, pudiendo así reutilizar el código. Se han programado diferentes modos de funcionamiento que incluyen órdenes de movimiento (avanzar, retroceder, izquierda, derecha, parar y 180º), modos de funcionamiento automáticos ( obstaculos, siguelineas y sigueluz ).
App Inventor Para comenzar, creamos un nuevo proyecto, que en nuestro caso se llama PrintBot_Botones.
Creando la interfaz de usuario Para crear esta UI utilizaremos botones, “listPicker” y “layaouts”.
DRA. ING. RINA FAMILIA
17
Dentro de las propiedades de la pantalla, modificamos las propiedades alingHorizontal a Center y Title a “PrintBot con Botones”. Para conectar a un dispositivo Bluetooth utilizaremos un listPicker , es decir, un elemento que mostrará un listado, en este caso, de los dispositivos Bluetooth que se hayan sincronizado previamente a través de los ajustes de Android. Modificamos su nombre a ConnectBT , el texto que muestra a Connect Bluetooth y su ancho a fill parent .
A continuación, incluimos un botón que utilizaremos para desconectar del dispositivo
DRA. ING. RINA FAMILIA
18
Bluetooth. Modificamos su nombre a DisconnectBT , el texto que muestra a Disconnect Bluetooth y su ancho a fill parent .
A continuación, incluimos un layaout con altura de 10 píxeles, que funcionará como separador y un layaout vertical, donde incluiremos tres botones para los modos automáticos de funcionamiento.
Dentro del layaout vertical, incluimos tres botones y cambiamos su nombre y texto a Line Follower , Avoid obstacles y Light Follower , respectivamente. Modificamos también el tamaño de los botones a fill parent . Podemos cambiar el tamaño del layaout que contiene los botones a fill parent o darle un tamaño fijo. En este caso, utilizamos la ultima opción y daremos un ancho al layaout de 150 píxeles.
DRA. ING. RINA FAMILIA
19
A continuación, incluimos un layaout con una altura de 30 píxeles para que funcione como separador y un layaout TableArrangement al que modificamos las propiedades Rows y Columns a 3.
Para continuar, incluimos 5 botones en forma de cruceta dentro del layaout TableArrangement y modificamos su tamaño a 50 píxeles.
DRA. ING. RINA FAMILIA
20
Cambiaremos su texto y nombre, de arriba a abajo y de izquierda a derecha, para que sean: • • • • •
^ upBtn < leftBtn o stopBtn > rightBtn v downBtn
Para finalizar, incluimos los elementos BluetoothClient , que utilizaremos para enviar y recibir datos, y Notifier , que utilizaremos para mostrar notificaciones en pantalla.
DRA. ING. RINA FAMILIA
21
Programando la aplicación En primer lugar, programaremos la conexión Bluetooth. El elemento ListPicker , que hemos llamado ConnectBT tiene dos funciones principales BeforePicking y AfterPicking, que nos permite realizar acciones diferentes antes y después, respectivamente, de haber seleccionado un elemento del listado. Para la función BeforePicking, utilizamos la orden set ConnectBt.Elements to , que se encuentra dentro de los bloques de ConnectBT y cambiará los elementos del listado. Estos bloques los uniremos al bloque BluetoothClient1.AddressesAndNames, por lo que veremos al pulsar los dispositivos Bluetooth que se hayan sincronizado previamente a través de los ajustes de Android. Una vez que pulsemos sobre el botón Connect Bluetooth, aparecerá un menú contextual en el que podremos escoger el dispositivo al
que conectarnos.
En el caso de la función AfterPicking, programaremos la ejecución de la conexión. Para lo cual incluiremos un condicional if-else. En la condición usaremos el bloque call
DRA. ING. RINA FAMILIA
22
BluetoothClient1.Connect address , y a este último uniremos el bloque ConnectBT.Selection,
que almacena el elemento que se ha seleccionado del selector de lista. Si se realiza la conexión correctamente, la función de conexión devolverá el valor true, por lo que se ejecutará la parte then.
A continuación, en la parte then del condicional, incluimos el bloque call Notifier1.ShowAlert notice , que mostrará un toast (mensaje flotante en la pantalla) y un
bloque de texto para imprimir la palabra Connected , mostrando que se ha realizado la conexión correctamente.
La programación del botón Disconnect Bluetooth utilizamos el bloque when DisconnectBT.Click do y el bloque call BluetoothClient1.Disconnect .
Para programar el comportamiento de los botones de movimiento manual y automático utilizaremos el bloque call BluetoothClient1.SendText text , textos y el modificador join, que concatena las cadenas de caracteres. En este caso, queremos enviar una cadena de caracteres que tenga el tipo =avanzar+. En el caso del botón upBtn, la programación que utilizaremos es:
Para el resto de botones, copiaremos el conjunto de bloques anterior y modificaremos el botón al que accede y la cadena de caracteres que se envía según la siguiente lista: • •
Line_Follower : siguelineas Avoid_Obstacles: obstaculos
DRA. ING. RINA FAMILIA
23
• • • • • •
Light_Follower : sigueluz upBtn: avanzar leftBtn: izquierda stopBtn: parar rightBtn: derecha downBtn: retroceder
La programación final de los botones de movimiento manual es:
La programación final de los botones de movimiento automático es:
Acelerómetro y sensor de orientación El acelerómetro funciona midiendo la fuerza gravitatoria en los ejes (X, Y, Z) con el circuito interno de un chip. Si queréis conocer más sobre el funcionamiento del acelerómetro, podéis ver este vídeo (inglés).
DRA. ING. RINA FAMILIA
24
El sensor de orientación da información al dispositivo (un terminal móvil en este caso) del valor del acimut en grados sexagesimales y, las rotaciones pitch y roll . Si quieres conocer más sobre qué función tiene cada sensor dentro del dispositivo móvil puedes visitar este enlace.
DRA. ING. RINA FAMILIA
25
Diseño de la UI
Para diseñar la interfaz de usuario se utilizarán diferentes layaouts, un canvas, una imagen, y cuatro etiquetas o labels. También se utilizarán el acelerómetro y el sensor de orientación que se encuentran dentro del menú sensors. En las propiedades de la pantalla, modificamos la propiedad alignHorizontal a center y título a Accelerometer & Orientation. A continuación, se añade un layout en el que modificaremos su alto para que ocupe 30 px y modificamos su nombre a separador_30.
DRA. ING. RINA FAMILIA
26
Para utilizar las imágenes que serán nuestra brújula, en primer lugar hay que subirlas. Para ello, pulsamos sobre el botón upload file , seleccionamos los archivos y los subimos. Una vez que ambos estén cargados ya podremos utilizarlos. A continuación, incluimos un canvas manteniendo las propiedades ancho y alto en automático y, modificaremos la propiedad backgroundImage a la imagen NSWE.png.
En el siguiente paso, incluimos un ImageSprite dentro del canvas y modificamos la propiedad Picture por la imagen compass.png. A continuación, centramos la imagen, desplazándola con el ratón hasta encontrar la posición deseada y modificamos el nombre del ImageSprite por compass.
DRA. ING. RINA FAMILIA
27
Debajo del canvas, introducimos una etiqueta, que mostrará el acimut en grados, y modificamos su nombre a labelAzimuth. Debajo de la etiqueta, incluimos un layout con una altura de 50 píxeles, que utilizaremos como separador.
Para representar visualmente los datos del acelerómetro, utilizaremos tres etiquetas que colocaremos dentro de un layaout vertical. Cambiaremos su nombre, comenzando por arriba, a Acel_X , Acel_Y y Acel_Z . El texto de los botones se va a modificar directamente desde la programación de la aplicación. Para finalizar, incluimos los elementos AccelerometerSensor y OrientationSensor DRA. ING. RINA FAMILIA
28
Programación En la parte de programación de nuestra App utilizaremos los bloques del sensor de orientación y del acelerómetro. En primer lugar programaremos el sensor de orientación. Para ello, utilizaremos el bloque OrientationChanged :
La propiedad .heading de una imagen indica la posición a la que “apuntará” la parte superior de una imagen, por lo que se utilizará para modificar la posición de la imagen compass para que vaya en conjunto con el valor del acimut que marque el dispositivo. Para ello, unimos el bloque set compass.Heading to a get azimuth y ambos al bloque anterior.
DRA. ING. RINA FAMILIA
29
A continuación, modificamos el texto mostrado en labelAzimuth utilizando el bloque set labelAzimuth.text to . Uniremos a este bloque un bloque join, que concatena cadenas de caracteres, un cuadro de texto (en el que pondrá “Azimuth = “) y get Azimuth.
Para programar el bloque del acelerómetro, utilizaremos el bloque when AccelerometerSensor1.AccelerationChanged .
Utilizaremos los bloques, por ejemplo, set Acel_X.Text to y a éste se unirá el bloque join, donde concatenaremos, en este caso “X =” y el valor de la aceleración X que
obtendremos mediante get xAccel .
Se duplicará el conjunto de los bloques para que Acel_Y y Acel_Z la aceleración en el eje Y y en el eje Z.
DRA. ING. RINA FAMILIA
30
.
Conexiones eléctricas Para esta entrada solo se utilizarán los servos de rotación continua, aunque si tienes tu PrintBot montado al completo puedes utilizarlo igualmente. En nuestro caso, utilizaremos el pin 9 para conectar el servo izquierdo y el pin 8 para el derecho.
Programación Arduino El código Arduino de esta entrada es una modificación del enlazado y lee a través del Bluetooth las palabras que se envían desde App Inventor al terminal. Para saber qué palabra se ha leído se utiliza la función readFromAndroid y para realizar la acción en función de la palabra se utiliza la función writeData. Si se modifica el programa de App Inventor es esta función la que hay que cambiar para adecuarlo a los cambios. DRA. ING. RINA FAMILIA
31
Diseño de la UI En la interfaz de usuario se van a utilizar un ListPicker , botones, canvas y labels, además de layouts para organizar los elementos. Para comenzar, incluimos un layout horizontal para organizar los elementos que permitirán conectar y desconectar a un dispositivo Bluetooth. Dentro de éste, movemos un listPicker y un botón, a los que cambiamos su texto y llamamos ConnectBT y DisconnectBT respectivamente. Para finalizar, cambiamos el ancho de los tres elementos a fill parent .
A continuación, incluimos un canvas con sus propiedades ancho y alto en fill parent . Utilizaremos el canvas para detectar los gestos
Debajo del canvas, arrastramos un layout horizontal que contendrá un botón para hacer que el PrintBot gire 180º y un layout vertical en el que incluiremos dos etiquetas, que mostrarán el ángulo hacia el que se realiza el gesto y la dirección correspondiente al gesto detectado. Modificaremos el tamaño de todos los elementos a fill parent para que ocupen el mismo espacio en pantalla. DRA. ING. RINA FAMILIA
32
Cambiamos el nombre y el texto del botón anterior por turn180, el nombre y texto de las etiquetas por heading y orientation.
Para finalizar añadimos los elementos BluetoothClient y Notifier .
Programación Para detectar los gestos, utilizaremos un canvas , el bloque Flung que detecta gestos y su propiedad heading que indica el ángulo hacia el que se realiza el gesto.
DRA. ING. RINA FAMILIA
33
En primer lugar, programaremos la conexión y desconexión Bluetooth. Esta programación se ha explicado más detalladamente aquí.
A continuación, programamos el botón turn180 para que envíe la palabra 180 cuando sea pulsado.
Para hacer que el PrintBot se pare, utilizaremos el bloque Touched del canvas, que se activa cuando pulsamos en cualquier punto de éste. Cuando se pulse, enviaremos por Bluetooth STOP y cambiaremos el texto de la etiqueta orientation a STOP .
Para terminar la programación tenemos que detectar los gestos que se realizan en la pantalla del terminal. Para detectar gestos se utiliza el bloque Flung del canvas y, la variable heading, que nos da la dirección en grados a la que se realiza el gesto. Para determinar la dirección a la que se realiza el gesto, dividiremos la superficie en sectores como en la imagen siguiente, y utilizando condicionales if asignando a cada intervalo una dirección.
DRA. ING. RINA FAMILIA
34
Por ejemplo, para determinar el gesto hacia arriba utilizamos los siguientes bloques:
En primer lugar, se comprueba mediante un if que el valor leído en heading esté entre 45 y 135 grados. Si es correcto, se envía a través del Bluetooth la palabra UP y se cambia el texto de la etiqueta orientation a UP . Para el gesto hacia abajo comprobamos si heading está entre -45 y -135 grados y para el gesto hacia la derecha entre -45 y 45 grados. Si se cumple la condición enviamos y cambiamos el texto de heading por DOWN y RIGHT respectivamente. En el caso del gesto hacia la izquierda, no funciona utilizando el bloque and dentro de la comparación del if . Para que funcione correctamente utilizamos el bloque or , comprobando si es mayor de 135 o menor de -135 grados. Si se cumple la condición, se envía y se cambia el texto de heading por LEFT . La programación del conjunto con la detección de todos los gestos se puede ver en la siguiente imagen:
DRA. ING. RINA FAMILIA
35