Sensor CO2 MH-Z19 Parte 2

Objetivos

 

  • Usar la salida Analógica del sensor MH-Z19.
  • Comparar la salida analógica y la digital del mismo
  • Mostrar un método de ajuste lineal de lecturas.
  • Ver un ejemplo de un ajuste polinómico.
  •  

    Material requerido.

     

     Vista principal Un Arduino MEGA
     Sensor de CO2 Un Sensor HX-Z19
     Breadboard 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:

    MHZ19 con salida digital y analogica

    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:

  • Imprimir una vez los títulos separados por comas a la consola,
  • Imprimir después repetidamente los valores, separados por comas en el mismo orden que hicimos con la impresión de los textos.
  • El sistema, te perite de este modo imprimir 3, 4 o más valores con su color y etiquetas propias
  • Seguro que estará documentado en algún sitio, pero no he sido capaz de encontrarlo.  [/fancy-ul] [/three-fourth]
  •  

    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:

    Salidas analogica y digital en el hxz19

    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.

    importar datos CSV

    El resultado que obtendrás, será algo así, si pones cabeceras:

    ejemplo de importacion de datos csv

    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

    ¡Accede al contenido!

    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)

    escalado a factor constante

    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

    tabla excel

    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:

    Ajuste de datos

    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:

    ejemplo de correccion de lecturas

    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.

  • Con la desagradable excepción de los espurios que recibe en convertidor ADC que habría que filtrar con un ring buffer por ejemplo y que no me atrevo a desarrollar aquí para no abusar de la paciencia de los que hayan tenido la paciencia de aguantarme hasta aquí.
  • Fíjate también que estoy utilizando unas mediciones de CO2 bastante altas para buscar los valores altos y habría que probar que la estimación es buena para valores mas bajos, pero siempre podemos utilizar diferentes coeficientes a y b para rangos diferentes si la estimación no fuera satisfactoria, es decir unos coeficientes ay b para valores menores de 1000 y otros para valores superiores,
  • Por otro lado, he detectado un comportamiento extraño del sensor cuando le conectamos la señal digital y la analógica simultáneamente. Las lecturas digitales saltan de 600 a 1000 sin pensárselo un momento. Lo mismo me ha ocurrido al conectar al mismo ESP32 el MH-Z19 y un sensor CCS811 para este mismo experimento, pero he visto que se falsean las lecturas digitales fuertemente sin que entienda muy bien por qué.
  • He pensado que podía ser un problema de potencia en la alimentación (De su falta, más bien) pero el problema no ha mejorado al conectar una fuente externa. Así que no estoy seguro de cual es la causa, pero parece que al conectar la salida digital y la analógica varia la impedancia del sensor con lo que falsea las medidas.
  • El resumen es que deberéis calcular vuestros propios coeficientes para que las mediciones sean correctas. 
  •  

     

    IMAGEN DE MARCA