Esta entrada corresponde a la segunda parte del proyecto
iniciado en Arduino, que tenía por objeto medir la temperatura dentro de un
tostador de café. Ahora, con el circuito funcionando, y entregando el valor de
la temperatura mediante un módulo bluetooth pasaremos a desarrollar una
aplicación móvil que sea capaz de recibir estos valores y graficarlos.
La aplicación se desarrollará a través de AppInventor (https://appinventor.mit.edu),
y será compatible con cualquier dispositivo Android. En este caso lo hice
pensando para ser utilizada especialmente en un Tablet.
Diseño:
Visualmente la aplicación contendrá los siguientes elementos
ordenados en las siguientes disposiciones:
En BarraSuperiorHorizonal estarán los elementos necesarios
para iniciar la conexión vía bluetooth. Corresponde a:
- Etiqueta de texto Conectar
- Etiqueta de texto EstadoBT
- Botón "Buscar" (SelectorBT)
- Botón Conectar.
En VisorTiempoTemp se contienen dos diposiiciones: una correspondiente al cronómetro y otra a la temperatura. Ambas contienen etiquetas de texto que
mostrarán los datos a graficar, en tiempo real.
La temperatura se mostrará desde que se realice la conexión bluetooth. El cronómetro sólo comenzará a correr desde que se presione el botón inicio. Al presionar este botón, también se comenzarán a graficar los datos en el Canvas.
La temperatura se mostrará desde que se realice la conexión bluetooth. El cronómetro sólo comenzará a correr desde que se presione el botón inicio. Al presionar este botón, también se comenzarán a graficar los datos en el Canvas.
DisposicionGrafico, contiene el Canvas a través del cual graficaremos los datos.
La aplicación además contendrá los siguientes componentes no visibles:
- Cliente de Bluetooth
- Reloj1
- Reloj2
- Notificador1
- Componentes de almacenamiento TinyDB y File, pero esos por ahora no los utilizaremos, ya que son parte de una extensión a este proyecto, que quizás suba en una próxima entrada.
Programa:
Lo primero será iniciar la conexión bluetooth con el Arduino.
Es necesario recordar que previo a cualquier intento de conexión por parte de
nuestra aplicación, el dispositivo bluetooth a conectar debe estar enlazado al tablet
o celular que utilizaremos.
Teniendo en cuenta lo anterior, para programar el enlace de la aplicación utilizaremos los siguientes
bloques:
- El primer bloque se ejecuta al clickear el SelectorBT, antes de seleccionar, y consultará las direcciones y nombres de los dispositivos bluetooth enlazados al dispositivo Android en que estamos ejecutando nuestra aplicación, y los ubicará como elementos del SelectorBT. Es decir, los mostrará como elementos disponibles para ser seleccionados.
- El segundo bloque se ejecuta una vez seleccionado un elemento del SelectorBT, es decir, tras seleccionar el dispositivo bluetooth. Este bloque pondrá la dirección y nombre del dispositivo bluetooth en la etiqueta EstadoBT.
- El tercer bloque se ejecuta al clickear el boton ConectarBT. Este realiza la conexión al dispositivo indicado a través del ClienteBluetooth1.
Con todo esto, nuestra aplicación ya estará recibiendo los datos de temperatura.
Para mostrar estos datos haremos lo siguiente:
Definimos una variable global llamada Temp como texto.
Utilizamos el timer de Reloj2 (configurado para ejecutarse cada un segundo) para desencadenar las siguientes acciones:
- Si el cliente de Bluetooth se encuentra conectado:
- Se cambiará el texto de la etiqueta EstadoBT a "Conectado".
- Se verificará si es que existen bytes disponibles para recibir (si es que son superiores a 0), y en tal caso:
- La variable global Temp almacenará la información recibida.
- La etiqueta Temperatura mostrará los valores guardados en la variable.
De esta manera recibimos la temperatura desde Arduino y que es enviada a través de bluetooth, y es mostrada a través de una etiqueta en la pantalla de nuestro Android.
- Ahora, si al ejecutarse el timer de Reloj2 el cliente de bluetooth no está conectado, simplemente se pondrá como texto de la etiqueta EstadoBT como "Desconectado".
(Aquí en algún momento tuve un problema que me costó varias tardes: realizada la conexión y recibiendo datos a través de bluetooth, estos se encontraban aparentemente en un formato desconocido, y al mostrarlos en la etiqueta Temperatura aparecía, en vez de los números de la temperatura medida, una fila de 6 a 8 signos de interrogación (???????). Finalmente este problema se debió a que el módulo bluetooth de Arduino se encontraba configurado a una velocidad incorrecta. En la entrada anterior dejé indicado paso a paso cómo configurar correctamente el módulo para evitar este problema).

Nuestro gráfico tendrá dos variables: tiempo y temperatura. El primero irá en el eje X de nuestro canvas, y el segundo en el eje Y.
Trazaremos entonces a lo largo del eje X las líneas que nos indicarán los minutos y en el eje Y trazaremos líneas correspondientes a la temperatura.
Para este proyecto yo necesito a lo más graficar 15 minutos. La escala será de 1 pixel por segundo, por lo que necesitaré trazar líneas para 900 segundos (15 min x 60 seg.), y pondré entonces el canvas con una extensión horizontal total de 900 pixeles.
En cuanto a la temperatura, necesitaré graficar valores desde 0 a 300 °C, los que también se graficarán a proporción de 1 pixel por grado °C. Quedará entonces el canvas con un tamaño de 300 x 900 pixeles.
Los bloques para trazar estas líneas los haremos a través de los siguientes procedimientos:
- Para trazar las líneas correspondientes a los minutos:
El procedimiento LineasMinutos contiene dos variables locales, que funcionarán como contadores: ContadorMinutos y ContadorSegundos. Ambas variables son definidas como númericas y su valor inicial es 0.
Se creó una lista con los valores en segundos de cada uno de los minutos que se graficarán en nuestro canvas, y se ejecutará la acción por cada uno de estos elementos de la lista.
La acción comienza aumentando en 1 la variable ContadorMinutos, llevándonos así el conteo de los minutos (para el elemento 60, el contador será 1, para el elemento 120 será 2, para el elemento 180 será 3... etc.); luego define las propiedades del trazado que se hará (tamaño de letra, color de trazado y grosor de la línea).
Se dibuja la línea, tomando como puntos x1 y x2 la cantidad de pixeles que equivalen a la cantidad al elemento de la lista (es decir, a la cantidad de segundos del minuto a trazar); como punto y1 se utiliza la altura del canvas y como punto y2 cero, de tal manera que cada línea de dibujará de arriba a abajo del canvas y a la altura en el eje X que corresponderá a nuestro minuto, tomando como proporción de desplazamiento un pixel por segundo.
Luego, se cambia el color de trazado a negro, para indicar en letras el minuto al que corresponde la línea. Esta escritura se realiza a 30 pixeles de la orilla del canvas.
Se creó una lista con los valores en segundos de cada uno de los minutos que se graficarán en nuestro canvas, y se ejecutará la acción por cada uno de estos elementos de la lista.
La acción comienza aumentando en 1 la variable ContadorMinutos, llevándonos así el conteo de los minutos (para el elemento 60, el contador será 1, para el elemento 120 será 2, para el elemento 180 será 3... etc.); luego define las propiedades del trazado que se hará (tamaño de letra, color de trazado y grosor de la línea).
Se dibuja la línea, tomando como puntos x1 y x2 la cantidad de pixeles que equivalen a la cantidad al elemento de la lista (es decir, a la cantidad de segundos del minuto a trazar); como punto y1 se utiliza la altura del canvas y como punto y2 cero, de tal manera que cada línea de dibujará de arriba a abajo del canvas y a la altura en el eje X que corresponderá a nuestro minuto, tomando como proporción de desplazamiento un pixel por segundo.
Luego, se cambia el color de trazado a negro, para indicar en letras el minuto al que corresponde la línea. Esta escritura se realiza a 30 pixeles de la orilla del canvas.
- Para trazar las líneas correspondientes a la temperatura el procedimiento será prácticamente el mismo:
Como se puede ver, este procedimiento se diferenciará del anterior básicamente en que los elementos serán los que corresponden a las temperaturas que es de nuestro interés trazar, y los trazos irán en el eje contrario, es decir, aquí para referenciar valores del eje Y irán líneas paralelas al eje X.
Ambos procedimientos serán llamados al iniciar nuestra aplicación.
Con estos dos procedimientos ejecutandose al iniciar la aplicación, se habrá trazado una cuadrícula en el canvas con las líneas de los minutos en un sentido, y en el otro, con las líneas de temperatura.
Para trazar el gráfico de tueste, que corresponderá a la temperatura alcanzada por mi tostador en cada segundo, utilizaremos el Reloj1, que será el componente que utilizaremos para ejecutará las acciones cada 1 segundo que nos petmitirán trazar el gráfico.
Reloj1 lo definiremos como activado en propiedades, pero las acciones que se desencadenarán en él estarán sujetas a una condición. Crearemos una variable global llamada Listo y la definiremos como falsa. Las acciones contenidas en Reloj1 sólo se ejecutarán en el caso de que Listo sea verdadero.
El botón Inicio (contenido en la disposición VisorTiempoTemp) pondrá la variable Listo como verdadera, y entonces el Reloj1 comenzará a ejecutar las acciones que pondrán a correr el cronómetro en pantalla, y a su vez, graficarán la temperatura de cada segundo en nuestro canvas.
Para trazar líneas en el canvas, debemos utilizar el mismo bloque visto antes (call Grafico.DrawLine), en el cual recibe coordenadas "x1" e "y1", y "x2" e "y2" para trazar una línea.
Para designar estos valores, crearemos las siguientes variables globales:
- Variable global Antes, se definirá como una lista vacía, pero al iniciar se le asignará como valor una lista de dos elementos numéricos, en los que ambos serán 0.
Esta variable corresponderá al valor de x1 e y1, es decir, los valores de la temperatura en el "segundo anterior al actual". Se definen ambos como cero al iniciar, pues si sólo se quedasen como una lista vacía, el el primer segundo (al no tener asignado ningún valor) el programa no los reconocería como coordenadas y nos arrojaría error.
- Variable global Ahora, se define como una lista vacía. Corresponderá al valor de x2 e y2, valores de la temperatura en el segundo actual.
- Variable global Timer, se definirá como valor numérico 0. Llevará un conteo de los segundos transcurridos.
- Variable global Linea, se definirá como una lista vacía. Guardará un "historial" de los valores de la temperatura en cada uno de los segundos. Espero más adelante utilizarlos para trazar en el canvas los valores de tostados anteriores, y así usarlos de referencia en un tostado actual, pero no será parte de esta entrada.
El bloque que ejecutará Reloj1 será el siguiente:
El bloque Reloj1 ejecuta cada un segundo las acciones que en él se contienen.
Lo primero que realiza es comprobar si la global Listo es verdadera. Sólo en el caso de que así sea ejecutará las demás instrucciones en él contenidas
- Pondrá a correr el Timer, sumando cada segundo +1.
- Asignará a la variable Ahora una lista de dos elementos, compuesto el primero por el valor de Timer (es decir, del segundo actual), y el segundo valor será el de la temperatura.
- Aquí realiza una operación, debido a que canvas cuenta los valores en el eje Y (que es el de la temperatura en nuestro gráfico) desde el extremo superior, y para nuestros fines queremos graficarlos desde abajo.
- Se multiplica por -1 el valor de la temperatura (contenido en la variable global Temp) y entonces se resta a la altura del canvas, teniendo así, como un espejo, la posición que le correspondería a la temperatura contado desde abajo.
- Estos dos valores (tiempo y temperatura actuales) servirán para luego ingresarlos a x2 e y2 del bloque Draw.Line que trazará cada una de las líneas del gráfico.
- Se realiza una operación para llevar la cuenta en el cronómetro que está en la disposición VisorTiempoTemp:
- El conteo del tiempo, se realiza en la variable Timer, y este lleva directamente el conteo de la cantidad de segundos, por lo que debemos transformar ese número en minutos y segundos para mostrarlos en pantalla:
- Una condición verifica si en ese momento el valor visible en la etiqueta de texto Seg es igual a 59.
- Si lo es, significa que en este segundo (que es el posterior al que se muestra en la etiqueta) se está pasando a un nuevo minuto. Por tanto, harán las siguientes acciones:
- Se pondrá la etiqueta Seg en 0 y sumará +1 al valor contenido en la etiqueta Min.
- Si el valor visible en la etiqueta Seg no es igual a 59, significará que aun no es tiempo de contar un nuevo minuto, por lo que sumará un segundo al visor.
- Existe ahí dentro una nueva condición, que verifica la extensión de carácteres del visor, pues los primeros diez segundos (de 0 a 9) serán de sólo un carácter, por lo que por estética se corregirá, anteponiendo un cero a estos carácteres, de tal manera que se muestren como 00, 01, 02 y no cómo 0, 1, 2, etc.
- En el bloque siguiente, se agrega a la variable Linea el par de coordendadas del segundo actual, de tal manera que así llevará un historial de toda la medición.
- En los bloques siguientes se realizará el gráfico propiamente tal: aquí me tocó corregir dos cuestiones que me sucedieron al probar la apliación:
- En el primer segundo no hay un valor para x1 y x2, y estos se asignaron como 0,0 al iniciar, por lo que el gráfico mostraba una gran caída desde el punto superior al valor del primer segundo. Opté por que el gráfico sólo se inicie a partir del tercer segundo, y esto se hizo con la condición de que las acciones del gráfico sólo se ejecuten una vez que la variable Timer sea mayor a 3.
- La termocupla de Arduino, genera a veces mediciones "fantasma": registra valores muy altos o muy bajos en ciertos segundos, que no son reales, y hacen que el gráfico quede muy "saltado", debiendo ser una curva: para esto programé una especie de estabilizador: el gráfico ignorará las variaciones de temperatura que sean superiores o inferiores a 5 grados, y tal es la labor de las variables variacion1 y variacion2, y la condición que las contiene.
- El programa define el grosor y color de la línea a trazar y toma las coordenadas contenidas en las variables Antes (x1, y1) y Ahora (x2, y2), trazando una línea entre el valor medido en el segundo anterior y el valor medido en el segundo actual.
- Finalmente, se reemplaza el valor de Antes con el de Ahora, y el ciclo vuelve a comenzar, trazando el gráfico segundo a segundo.
Con esto queda completa la aplicación, y el resultado debiera ser un gráfico como el siguiente:
Es posible que en próximas entradas desarrolle algunas otras funcionalidades que agregaré a esta aplicación, que principalmente estarán orientadas a guardar los valores del gráfico para poder utilizarlos de referencia en futuras mediciones, así como generar algunas alertas en el caso de que las mediciones traspasen algunos rangos.
No hay comentarios:
Publicar un comentario