Objetivos
Material requerido.
Un Arduino MEGA | |
Un Sensor HX-Z19 | |
Un par de protoboards |
Leyendo la salida analógica delMHZ19
Muchos de los sensores que solemos usar en Arduino disponen de una salida analógica proporcional al valor medido y normalmente los Arduineros de pro estamos bastante acostumbrados a usar este tipo de interface por lo que nos resulta de lo más natural.
El MH-Z19 dispone de una salida analógica, además de la salida digital a través de la puerta serie y parece natural querer usarla si venimos de una vieja tradición de sensores con estas salidas, por lo que parecía bastante razonable usarla en uno de nuestros tutos, de cara a que, si por cualquier razón no puedes o no quieres usar una puerta serie, puedas tirar de la salida analógica.
Además, esto nos va a permitir hablar de un tema un poco más técnico, del que llevaba un tiempo con ganas de meterme, que es el ajuste de los sensores para corregir sus lecturas, cuando usamos un mecanismo externo de calibración, o al menos, de referencia.
Leer la concentración de CO2 con el MH-Z19, mediante la puerta serie en ppm (Partes por millón) y mediante la salida analógica en voltios, nos permite hacer un magnifico ejemplo, de como ajustar la medida de la concentración de gas con la segunda, manteniendo la primera como referencia de calibración.
Ciertamente, aunque el MHZ19 es auto calibrado, requiere un tiempo encendido que no he tenido paciencia para dejarle, por lo que suponer que la salida digital serie esta calibrada como referencia es mucho suponer, pero … de cualquier modo, nos va a servir a la perfección para el ejemplo que mas me interesa, que es calcular el ajuste de la salida analógica a partes por millón de gas, sirviéndonos de la salida digital como referencia.
El procedimiento de ajustar la salida de un sensor, a una referencia calibrada es bastante habitual y hace tiempo que tenia ganas de hablar un poco sobre ello (No puedo evitarlo) y a ser posible, desarrollar un procedimiento o método de uso general para otras ocasiones y sensores.
Poneros cómodos que vamos al lio.
Leyendo La salida analógica y la digital del MHZ19
Lo primero son las conexiones. Repetimos el diagrama de la sesión anterior para conectar el MHZ19 al Arduino MEGA y además añadimos la conexión de la salida analógica del sensor al puerto A0 del MEGA:
Podemos ya pasar a la parte del programa, que es muy similar al que usamos la ultima vez. Empezamos con la librería y definiendo una instancia del sensor:
#include <MHZ19.h> MHZ19 mhz(&Serial1);
Pasamos al Setup():
void setup() { Serial.begin(115200); Serial.println("Starting..."); Serial1.begin(9600); Serial.print("Digital"); Serial.print(","); Serial.println("Analog"); }
Lo primero es definir la velocidad de los puertos serie, 115.200 para los mensajes que enviemos a la consola (O el serial plotter) y 9.600 para la comunicación con el sensor de CO2. Y lo que si merece la pena comentar es la siguiente línea para finalizar el Setup
Serial.print("Digital"); Serial.print(","); Serial.println("Analog");
Voy a querer usar el serial plotter para representar gráficamente los valores del señor, en digital (A través de la puerta serie) y en analógico, para los valores que leamos en la puerta A0, por lo que quiero, poner unas etiquetas de que es cada cosa en el serial plotter.
Para ser franco me he pasado un buen rato buscando como mostrar múltiples valores en el Arduino serial plotter en Internet, sin éxito, y al final de pura casualidad he dado con la manera de hacerlo que es esta:
Con esta primera línea, simplemente fijamos las etiquetas a mostrar en el serial plotter y ya podemos pasar al loop(), que tampoco da para mucho. Hacemos una petición de leer datos
MHZ19_RESULT response = mhz.retrieveData();
Y ahora si la recepción ha sido satisfactoria
if (response == MHZ19_RESULT_OK) { int Digital = mhz.getCO2() ; int Analog = analogRead(A0) ; Serial.print(Digital); Serial.print(","); Serial.println(Analog); //Serial.print(F("Temperature: ")); // Serial.println( mhz.getTemperature()) ; //float F = mhz.getTemperature() ; //float C = (F -32) * 5 / 9.0 ; } else { Serial.print(F("Error, code: ")); Serial.println(response); } delay(1000); }
El ultimo delay fija el tiempo entre lecturas, y en un caso real probablemente habría que espaciarlas más de un segundo.
Analizando los datos
Me acuerdo mucho de un profesor de laboratorio en la Uní, que nos decía que los instrumentos de medida siempre daban una medida. El problema era que a veces no hay que creértelo porque hay mil motivos para falsear las lecturas. Un experto es quien al leer un instrumento dice tranquilamente que no se lo cree, y en cierto modo el resto de esta sesión va de eso. Veamos un ejemplo gráfico de las lecturas de nuestro sensor:
Aquí vemos como el sensor HXz19, va leyendo bajas concentraciones de CO2 y de repente un repunte brusco de la concentración que representa el momento en que le he estado soplando para provocar el incremento. Pero fíjate que la señal analógica no sigue un patrón tan acusado, ni mucho menos,
Ya a ojo se ve, que la señal digital no solo es mucho mayor en su reacción, sino que nos permite ver, que la señal analógica no es simplemente una versión lineal a menor escala de la señal digital y eso casi seguro que significa que tenemos que ajustar esta salida para dar valores en ppm si queremos que sean correctos. La cuestión ahora, es como hacer esta corrección razonablemente.
Me gustaría tomar los valores de ambas lecturas desde la consola, para poderlos copiar (Sin más que seleccionar y copiar) Así que, si repetimos el experimento con la consola, obtendremos una serie de valores parecidos a esto
1275,171 1275,170 1288,171 1288,171 1288,171 1288,171 1288,171 ………..
Y si pegamos todos esos valores en un fichero de texto y lo salvamos con extensión .csv o separados por comas, los podemos importar a Excel directamente para procesarlos.
El resultado que obtendrás, será algo así, si pones cabeceras:
Para calcular la tercera columna simplemente he calculado el cociente de la primera columna entre la segunda, para ver el factor de proporcionalidad e intentar que la lectura analógica iguale a la digital simplemente multiplicándola por una constante. Pero como esos factores son distintos, lo que hay en la celda E4, es el promedio de todos esos factores: 8,371.
Aquí os dejo los datos que he usado:
Sesion 515 (Programa arduino, Datos csv y Hoja excel
Si multiplico la columna B, las lecturas analógicas, por este factor promedio obtengo la columna C, lo que nos permite hacer un grafico para ver hasta que punto nos aproximamos a lo que queremos, teniendo como referencia la lectura digital (Por eso hemos tomado las dos)
Ya puedes ver que es una aproximación, aunque no muy buena ya que, al escalar la lectura analógica por un factor constante, amplificamos mucho los espurios del conversor analógico digital del Arduino (Que no es de los mejores) y además y vemos que en los máximos no alcanza a dar las lecturas que debería, lo que haría de nuestro sensor un asco notable.
No parece adecuado usar un factor multiplicador sin más, por lo que vamos a usar un ajuste polinómico (Dios mío, que palabro) pero que en realidad es una tontería. La idea básica es que si no podemos multiplicar sin mas por una constante de modo que:
Digital = a * Analog // siendo a una constante
Tendremos que intentar ajustar la respuesta mediante una fórmula polinómica de primer grado sencilla del tipo:
Digital = a * Analog + b
Bastará con calcular las constante a y b para que al hacer el cálculo de arriba podamos corregir nuestras lecturas analógicas para conseguir un valor razonable en ppm. ¿Vale, genial y cómo? Bien, es más fácil de lo que parece al principio. Pero tendremos que tirar calculo de bachiller.
Si tomo la serie de valores qq2.csv tengo que buscar un par de valores de la zona donde mas falla nuestra corrección anterior, por ejemplo
Y ahora aplicamos matemáticas básicas para generar un sistema de dos ecuaciones con dos incógnitas. Para hacerlo en abstracto y si llamamos PPM1 y PPM2 a las lecturas digitales del sensor y Analog1 y Analog2 a las lecturas de la puerta analógica correspondientes, tendríamos:
PPM1 = a * Analog1 + b PPM2 = a * Analog2 + b
Si restamos ambas ecuaciones obtenemos:
PPM2 - PPM1 = a * (Analog2 - Analog1) a = (PPM2 - PPM1) / (Analog2 - Analog1)
Sustituyendo los valores en la formula de arriba tenemos que:
a = (4532 – 1841) / (392 – 208) = 2.691 / 184 a = 14,625
Una vez conocido a, calcular b es trivial, ya que partiendo de la primera ecuación:
b = PPM1 / (a * Analog1 ) b = 1841 / (14,625 * 208) b = -1201
Si calculamos la tercera columna de la hoja de cálculo con esta aproximación obtenemos este gráfico:
Vale, muy bonito, ¿Pero que son esos picos de la estimación y porque no se ve la señal digital? Bien, los picos son una amplificación de los valores espurios que estoy recibiendo del convertidor analógico a digital que tendremos que filtrar. Pero si a la tercera columna le sumamos 200, el grafico que obtenemos es:
Donde se aprecia que la aproximación a través de un polinomio de primer grado la clava y arriba, la señal estimada, simplemente se superpone a la señal medida de forma digital.