Medidor de CO


2
          El CO2 es un gas presente en la atmosfera y no es dañino para las personas a su concentración habitual, pero su aumento ,aparte de influir en el cambio cllimático, nos da una idea de la calidad del aire que respiramos en ambientes cerrados. En la atmosfera la concentración actual ronda las 400ppm. Un aumento en una habitación a cifras de 1000 o incluso 2000ppm no tiene porque ser perjudicial, pero es indicativo de falta de aireación y que puede estar asociada a otros contaminantes biológicos (bacterias, virus) o químicos emanados por muebles (pintura, barnices), polvo de casa (ácaros), maquinaria, etc.   
           Este medidor está basado en el sensor MHZ19B que mide hasta 5000ppm. Tiene una excelente sensibilidad y precisión. Se alimenta a 5v y tiene salida de datos por serie y PWM. La gráfica del montaje la he limitado a 2000ppm, aunque continua marcando las cifras numéricamente en pantalla.
          El sistema consta del sensor MHZ19, una pantalla de 2,2 pulgadas (resolución de 240x320) y un Nodemcu V3 por la posibilidad de enviar los datos via wifi si así se deseara. 

          El conexionado es bastante sencillo. Aparte de la pantalla, el MHZ19 se comunica por serie con el microprocesador. He usado el UART serial del Nodemcu, eso significa que para cargar el código se quita el MHZ19 o se quita el puente que une el Rx del Nodemcu con el Tx del sensor. No es necesario quitar el del Tx. 
         
          El circuito lo he montado en una placa de tiras. Hay que tener en cuenta que el Nodemcu y el sensor están soldados por el lado del cobre de las tiras. Es decir, en la imagen inferior estos dos componentes están detrás de la placa.
         Montaje "al aire"
          Tras la pantalla inicial, comienza la toma de datos cada dos minutos y medio, que en 12 horas son 288 medidas. El sensor requiere un tiempo para calentarse y estabilizar las lecturas. En los primeros minutos las cifras no son fiables.
          La gráfica representa valores hasta 2000ppm, pero da valores superiores numéricamente. Con valores de 2000ppm se debería ventilar el local donde estemos.

    Al aire libre y alejado de trafico urbano he obtenido lecturas de 389ppm.
          El sensor esta sobreelevado por si usamos una caja para que quede en el exterior. Quitando el puente blanco podemos programar al desconectar el Rx del Nodemcu.
//Gráfica nivel de CO2 en 121h. Sensor MHZ19b y TFT 2.2''
//www.jopapa.me  XI/2020

#include <Adafruit_GFX.h>       // include Adafruit graphics library
#include <Adafruit_ILI9341.h>   // include Adafruit ILI9341 TFT library  240x320

#define TFT_CS    D2     // TFT CS  pin is connected to NodeMCU pin D2
#define TFT_RST   D3     // TFT RST pin is connected to NodeMCU pin D3
#define TFT_DC    D4     // TFT DC  pin is connected to NodeMCU pin D4
// initialize ILI9341 TFT library with hardware SPI module
// SCK (CLK) ---> NodeMCU pin D5 (GPIO14)
// MOSI(DIN) ---> NodeMCU pin D7 (GPIO13)
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);

#include "MHZ19.h"                                       
MHZ19 myMHZ19;
unsigned long getDataTimer = 0;
int i=0;
int valor=0;
int CO2; int mapCO2;
unsigned long intervalo = 150000;   //2' 30''
unsigned long millisAnterior = 0;

void setup() {
Serial.begin(9600);
tft.begin();
myMHZ19.begin(Serial);                               
myMHZ19.autoCalibration();             // Calibration ON (OFF autoCalibration(false))
millisAnterior =millis();
textInicio();
textFijo();
textHoras();
}


void loop(void) { 
  if(millis() - millisAnterior >= intervalo) {   //Cada 2' 30''
   testlines();
   millisAnterior=millis();
  } 
}



void testlines() {
  CO2 = myMHZ19.getCO2();                             // Solicita CO2 en ppm
  mapCO2 = map(CO2, 0, 2000, 0,240);                  //Ajusta a display 240x320
  Serial.print("CO2 (ppm): ");                     
  Serial.print(CO2);  
  Serial.print("-- mapCO2 (ppm): ");                     
  Serial.println(mapCO2);                                              

  int8_t Temp;
  Temp = myMHZ19.getTemperature();                     // Temperatura en Celsius
  Serial.print("Temperature (C): ");                 
  Serial.println(Temp);

  i++;
  if (i <= 288){              //Máximo número de lecturas para 12 horas
   tft.setRotation(0);
   tft.drawLine(0, i, mapCO2, i, ILI9341_BLACK);
  }

  textHoras();   //Repone horas en linea inferior

  //Borra espacio para valor de CO2
  tft.setRotation(0);
  for(int b=0; b<=70; b++){
   tft.drawLine(218, b, 240, b, ILI9341_WHITE); //(y,x, y', x')
  }
  tft.setRotation(1);
  tft.setTextSize(3);
  tft.setTextColor(ILI9341_BLACK);
  tft.setCursor(0, 0); tft.println(CO2);
}


void textInicio() {
    tft.setRotation(1);
    tft.fillScreen(ILI9341_WHITE);
    tft.setCursor(12, 60);
    tft.setTextColor(ILI9341_RED);
    tft.setTextSize(4);
    tft.println("Nivel de CO2");
    tft.setCursor(11, 120);
    tft.setTextColor(ILI9341_BLACK);
    tft.setTextSize(2);
    tft.println("Grafica 12h cada 2' 30''");
    tft.setCursor(33, 160);
    tft.println("Escala 0ppm a 2000ppm");
    delay(10000);       
}

void textFijo(){       //Eje y
  tft.setRotation(1);
  tft.fillScreen(ILI9341_WHITE);
  tft.setTextColor(ILI9341_BLACK);
  tft.setTextSize(1);
  tft.setCursor(300, 192);
  tft.println("400"); 
  tft.drawLine(0, 195, 290, 195, ILI9341_BLUE);  //(x,y,x',y')

  tft.setCursor(300, 144);
  tft.println("800"); 
  tft.drawLine(0, 147, 290, 147, ILI9341_BLUE);  //(x,y,x',y')

  tft.setCursor(294, 96);
  tft.println("1200"); 
  tft.drawLine(0, 99, 290, 99, ILI9341_BLUE);  //(x,y,x',y')
 
  tft.setCursor(294, 48);
  tft.println("1600"); 
  tft.drawLine(0, 51, 290, 51, ILI9341_BLUE);  //(x,y,x',y') 

  tft.setCursor(294, 0);
  tft.println("2000"); 
  tft.drawLine(0, 3, 290, 3, ILI9341_BLUE);  //(x,y,x',y')
}


void textHoras(){  
  //Lineas verticales
  tft.setRotation(0);
  for(int i=24; i<=288; i=i+24){
   tft.drawLine(0, i, 240, i, ILI9341_BLUE); //(y,x, y', x')
  }
  // horas en x
  tft.setRotation(1);
  for(int z=232; z<=240; z++){
   tft.drawLine(0, z, 320, z, ILI9341_BLACK);
  }
  //horas eje x  
  tft.setTextSize(1);
  tft.setTextColor(ILI9341_WHITE);
  tft.setCursor(70, 233); tft.println("3");
  tft.setCursor(142, 233); tft.println("6");
  tft.setCursor(214, 233); tft.println("9");
  tft.setCursor(282, 233); tft.println("12h");
}
Código
          Gráfica izquierda inferior, primero en mi minidespacho (8m2) con puerta abierta, después vacio y después con puerta cerrada.
          A la derecha mi mujer y yo con puerta cerrada se sobrepasan los 2300ppm. ¡¡¡A VENTILAR!!!

          A unos 50mts de una carretera con bastante tráfico, aunque libre de edificios en uno de los lados, en un tercer piso y viento en calma, marca cifras que oscilan sobre 500 a 600ppm. La gráfica superior cubre 24h con un máximo por la tarde. Recuerdo que es una carretera bastante abierta, en una ciudad serian cifras mucho más altas.
Menu