En una entrada del curso de programación con Arduino, hicimos un voltímetro y utilizábamos el puerto serie para imprimir los datos en la pantalla del ordenador.
En esta nueva entrada, vamos a utilizar Protocoder para crear una interfaz en la que podamos ver el valor leído y representarlo en una gráfica y además, podremos modificar el tiempo en el que se toman muestras.
Lista de materiales
- ZUM BT-328, placa Arduino o compatible.
- Dos trozos de cable de unos 15 centímetros o cables jumper
Conexiones Eléctricas
En este caso conectaremos el cable de color negro al pin GND de Arduino y el otro cable a una entrada analógica, en nuestro caso A0. En la imagen podéis ver las conexiones:
Limitaciones
Podemos leer solo valores positivos de tensión entre 0 y 5 Voltios.
El código Arduino
Como siempre, comenzamos declarando las variables globales del programa:
1 2 3 |
int pinSonda = A0; float escala = 100; //100 para voltios, 0.1 para milivoltios int delayTime = 0; |
En este caso, solo hay un cable conectado a la entrada analógica A0, que utilizaremos a modo de sonda, es decir, será con este cable con el que mediremos la tensión. Además, creamos la variable escala, que podremos modificar para obtener la lectura en voltios, si igualamos la variable a 100 o en milivoltios, si la igualamos a 0.1, más adelante veremos por qué hay que aplicar estos valores.
La variable delayTime se utiliza para modificar el tiempo de lectura. Los datos que reciba Arduino desde la conexión Bluetooth se almacenarán aquí.
Después, en la función setup, inicializamos el programa:
1 2 3 4 5 6 7 |
void setup(){ Serial.begin(19200); pinMode(pinSonda, INPUT); } |
En este caso, iniciamos la comunicación serie a 19200 bauds/segundo ya que es la velocidad de comunicación del módulo bluetooth incluido en las placas ZUM BT-328. También marcamos como entrada, INPUT, el pin donde hemos conectado el cable que actuará como sonda.
A continuación, en la función loop:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
void loop(){ while(Serial.available()>0){ delayTime = Serial.parseInt(); if (Serial.read() == '\n'){ delayTime = constrain(delayTime, 0, 500); } } float lecture = analogRead(pinSonda); lecture = map(lecture, 0, 1023, 0, 500); float voltaje = lecture/escala; Serial.println(voltaje); delay(delayTime); } |
En primer lugar comprobamos si hay datos en el puerto serie con Serial.available()>0. En caso de que existan datos, es decir, Serial.available sea mayor que 0, leemos los datos recibidos y los almacenamos en la variable delayTime. Estos datos son un número entero que enviamos desde la aplicación de Protocoder. Antes de enviar los datos, concatenamos el carácter ‘\n’ para definir el final del mensaje, si se lee por el puerto serie dicho carácter, utilizamos la función constrain para asegurarnos que el valor leído está dentro del rango esperado.
Después, creamos la variable lectura, y almacenamos el valor leído del pinSonda por la función analogRead y utilizamos la función map para transformar el valor de la lectura analógica, de 0 a 1023, hasta 0 a 500.
Después creamos la variable de tipo float voltaje donde aplicaremos el factor de escala. Si dividimos entre 100 obtendremos el valor de 0 a 5 voltios, pero si dividimos entre 0.1 aumentaremos la escala y obtendremos el valor en milivoltios. Dependiendo de el tipo de medida que queramos realizar puede interesarnos utilizar una escala u otra.
Por último, enviamos a Protocoder a través del puerto serie el valor leído para representarlo en la interfaz.
El código Protocoder
Utilizaremos Protocoder para crear una interfaz donde controlaremos la conexión Bluetooth y veremos los datos que se envían desde la placa Zum al terminal móvil. Incluiremos también botones para parar o iniciar la recepción de datos (sin necesidad de conectar/desconectar a un dispositivo Bluetooth), un slider para modificar el tiempo de muestreo y un texto para indicar dicha velocidad.
En primer lugar comenzamos ajustando las propiedades de la pantalla, como ya hemos visto en entradas anteriores:
1 2 3 4 5 6 7 8 9 10 11 |
ui.toolbar.title("Voltimeter"); ui.toolbar.bgColor(55, 155, 155, 255); ui.toolbar.show(true); //ui.screenMode("fullscreen"); ui.screenOrientation("landscape"); ui.allowScroll(false); var margin = 10; var w = ui.screenWidth - 15*margin; var h = 150; var y = h + margin; |
A continuación, crearemos los botones para conectar y desconectar, además, controlaremos la conexión y envío de datos:
Conexión a Buetooth
Crearemos un botón que “contendrá” las funciones relativas a la conexión y recepción de datos a través del Bluetooth.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
var btClient; var btFlag = false; var btnConnect = ui.addButton("Connect to bluetooth", margin, margin,w,h).onClick(function() { btClient = network.bluetooth.connectSerial(function(status) { console.log("connected " + status); if (status){ ui.toast("Connected"); btFlag = status; console.log("btFlag = " +btFlag); } }); btClient.onNewData(function(data) { if (voltFlag){ console.log(data + "\n"); labelV.setText(data); labelV.textSize(90); plot.update(data); // webPlot.update(data); } }); }); |
A la variable btClient “asignamos” la conexión Bluetooth, desde donde accederemos a las funciones relativas al Bluetooth.
Para conectar a un dispositivo Bluetooth, que previamente se haya emparejado a través de los ajustes de Android, utilizamos el siguiente código:
1 2 3 4 5 6 7 |
btClient = network.bluetooth.connectSerial(function(status) { console.log("connected " + status); if (status){ ui.toast("Connected"); btFlag = status; } }); |
Además, se imprimirá por consola y mediante un toast el estado de la conexión y se asignará true a btFlag, variable que utilizaremos para determinar el estado de la conexión bluetooth desde otras partes del programa.
Para recibir datos a través del bluetooth, utilizaremos la siguiente función:
1 2 3 4 5 6 7 8 9 10 |
btClient.onNewData(function(data) { if (voltFlag){ console.log(data + "\n"); labelV.setText(data); labelV.textSize(90); plot.update(data); // webPlot.update(data); } }); |
VoltFlag es una variable que toma el valor true al pulsar sobre el botón Start y false al pulsar sobre el botón Stop. Si se ha pulsado sobre Start, voltFlag valdrá true por lo que entrará dentro del if y se actualizará la etiqueta labelV (que muestra la tensión) y la gráfica.
Botón desconexión
Para realizar la desconexión creamos otro botón que activa la desconexión al bluetooth, con la orden btClient.disconnect(); , da información a través de un toast y cambia la variable btFlag a false, indicando que se ha pulsado sobre desconectar.
1 2 3 4 5 |
ui.addButton("Disconnect", margin, y, w,h).onClick(function() { btClient.disconnect(); ui.toast("Disconnected"); btFlag = false; }); |
Botones Start y Stop
Los botones start y stop, activan y desactivan, respectivamente, la actualización de datos en la gráfica y el texto sin necesidad de desconectar al dispositivo Bluetooth, aunque los datos se reciben igualmente. El código relativo a estos botones es:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
//start voltimeter var voltFlag = false ui.addButton("Start", w + margin, margin, w/2, h).onClick(function() { if (!voltFlag && btFlag){ voltFlag = true; //dashboard.show(true); ui.toast("Started!"); }else{ ui.toast("Not connected!!"); } }); //stop voltimeter ui.addButton("Stop", w+ margin, y, w/2, h).onClick(function() { if (voltFlag){ dashboard.show(false); voltFlag = false; ui.toast("Stoped!"); }else{ ui.toast("not Started"); } }); |
Etiquetas fuentes y slider
Para mostrar cierta información, como la lectura de tensión o el delay que vamos a aplicar a la ejecución del programa para modificar el tiempo de muestreo, utilizamos textos (etiquetas o label, en Inglés).
Para dar un toque personalizado a las etiquetas, utilizamos una fuente que simula una pantalla lcd de 7 segmentos. Para introducir una fuente, tenemos que descargar el archivo y subirlo a la carpeta del proyecto por medio del cuadro de subida de archivos, en la parte inferior derecha de la interfaz web de protocoder. Una vez que esté subida, cargamos la fuente en una variable con la orden:
1 |
var font = util.loadFont("LiquidCrystal-Light.otf"); |
Una vez que hemos cargado la fuente en una variable podemos utilizarla para modificar la tipografía de las etiquetas. Para crear una etiqueta, utilizamos por ejemplo:
1 |
var labelV = ui.addText("NO DATA", 3*w/2 + 4* margin ,margin,w/2,2*h + 2*margin); |
Siendo sus parámetros el texto a mostrar, posición X, posición y, ancho y alto, respectivamente.
Para modificar la fuente, el tamaño y el color, respectivamente, utilizamos:
1 2 3 |
labelV.font(font); labelV.textSize(55); labelV.color("#000000"); |
Esta etiqueta mostrará el texto “NO DATA” antes de empezar a recibir datos y pulsar sobre el botón Start, una vez que haya datos para mostrar, cambiará el tamaño de la letra y mostrará el valor de la tensión. Este cambio se realiza dentro de la función btClient.onNewData, que se encuentra dentro del botón Connect to Bluetooth.
A continuación, creamos un Slider que se utilizará para modificar el tiempo de muestreo del voltímetro, es decir, cada cuanto tiempo se toman medidas. Para modificar el tiempo, hacemos que los valores del slider vayan desde 0 hasta 500 milisegundos, mostrando el valor en una etiqueta, o label. Para enviar el valor a Arduino, creamos un botón con el texto send. Al pulsar sobre dicho botón, se enviará el valor a través de la conexión Bluetooth y se leerá en Arduino.
Para crear el Slider, utilizamos el siguiente código:
1 2 3 4 5 6 7 8 |
var delayTime=0; var delay = ui.addSlider(margin, 2*y, w, h, 0, 500).onChange(function(val){ delayTime = val; delayTime = Math.floor(delayTime); // cambiar el rango de la variable a itn var aux = delayTime + " ms"; labelD.setText(aux); }); |
Los parámetros del slider son posición X,posición Y, ancho, alto, valor inicial y valor máximo, respectivamente.
Creamos una variable delayTime, para almacenar el valor leído desde el Slider. Del Slider obtenemos un float y con la función Math.floor(); redondeamos el valor al valor entero más bajo. Guardamos el valor en una variable auxiliar concatenando la palabra “ms” y por último, en la variable labelD, un label que crearemos a continuación, escribimos el valor de la variable aux.
Para crear el labelD, utilizamos el siguiente código:
1 2 3 4 5 |
var labelD = ui.addText("delay time",3*w/2 + 4*margin,2*y + y/4,w/2,h); labelD.textSize(30); labelD.color("#000000"); labelD.font(font); |
Para terminar el conjunto de los elementos que controlan el cambio del tiempo de muestreo, falta crear el botón que enviará los datos:
1 2 3 4 5 6 |
var sendBtn = ui.addButton("SEND",w + margin,2*y,w/2,h).onClick(function(){ btClient.send(delayTime +"\n"); ui.toast("Send"); }); |
Con la orden btClient.send(); se envían los datos que estén dentro del paréntesis, en este caso, el valor de la variable delayTime que toma el valor del Slider, con el caracter “\n” concatenado.
Gráficas
Para representar de manera gráfica la lectura del voltímetro, utilizaremos una gráfica para representar los datos. Para crear una gráfica en el terminal utilizamos el siguiente código:
1 2 |
var min = -0.5,max = 5.5; var plot = ui.addPlot(margin, 3*y, 2*w, 400, min, max); |
Los parámetros son posiciónX, posiciónY, ancho, alto, valor mínimo y valor máximo. En el valor mínimo y máximo dejamos un pequeño margen de 0.5 por debajo y por encima, respectivamente, del mínimo y máximo esperado, 0-5V, de la lectura para evitar que queden muy cerca de los bordes. Para modificar la definición y el grosor de la gráfica utilizamos las funciones:
1 2 |
plot.setDefinition(2); plot.setThickness(1); |
Por último, para crear una gráfica que se vea en el dashboard de la interfaz web de protocoder, utilizamos la orden:
1 |
var webPlot = dashboard.addPlot("V", 100, 100, 1500, 500, min, max); |
Con parámetros titulo, posiciónX, posiciónY, ancho, alto, mínimo y máximo, respectivamente. Para actualizar esta gráfica, dentro de btClient.onNewData hay que quitar el comentario de la orden webPlot.update(data);.