0

Niveaux de dioxyde de carbone PPM à l’aide du capteur MH-Z19B

Je teste actuellement un capteur basé sur l’infrarouge non dispersif (NDIR) pour détecter les niveaux de parties par million (PPM) de dioxyde de carbone (CO2) à l’aide d’un capteur MH-Z19B, couplé à un NodeMCU V3 basé sur ESP8266.

Capteur MH-Z19B connecté à un NodeMCU ESP8266

Comparé à d’autres technologies de capteurs (telles que le chauffage par filament des plaques électrochimiques utilisé par le capteur MQ-135), le MH-Z19B présente les avantages suivants :

  • est calibré en usine (n’a pas besoin d’étalonnage)
  • est précis et ne fluctue pas radicalement
  • Les valeurs PPM sont déjà corrigées pour les dépendances à la température
  • fonctionne facilement dès la sortie de la boîte, sans période de « rodage » de 24 à 48 heures
  • est spécifique au CO2 PPM (le chauffage par filament des plaques électrochimiques n’est pas spécifique à un gaz particulier, et répond à plusieurs gaz)

Le MH-Z19B est connecté au NodeMCU V3 comme suit.

Diagramme schématique montrant les connexions des câbles entre le capteur MH-Z19B et le NodeMCU V3.

J’ai programmé le NodeMCU V3 basé sur ESP8266 pour qu’il se connecte à mon réseau WiFi et envoie les mesures CO2 PPM du capteur MH-Z19B à un canal Thingspeak.

Le graphique ci-dessous montre l’heure précédente des mesures de CO2 PPM, mise à jour toutes les 15 secondes.

La jauge ci-dessous montre la dernière lecture de CO2 PPM du capteur MH-Z19B.

Le code C++ suivant lit le CO2 PPM (et la température du capteur) à partir du port UART (récepteur asynchrone universel) du capteur MH-Z19B (c’est-à-dire les broches Rxd et Txd) et les télécharge sur ma chaîne Thingspeak.

Remarque : il n’y a aucune erreur dans le code C++ ci-dessous et dans le diagramme schématique ci-dessus. Avec les connexions série, une transmission d’un appareil doit être envoyée à une réception sur l’autre appareil, et la réception d’un appareil doit être envoyée à une transmission de l’autre appareil.

#include <ESP8266WiFi.h>
#include <SoftwareSerial.h>
SoftwareSerial co2Serial(D3, D4); // define MH-Z19 RX TX D3 (GPIO0) and D4 (GPIO2)
unsigned long startTime = millis();
const char* ssid     = "Your WiFi SSID";
const char* password = "Your WiFi Password";
const char* host = "api.thingspeak.com";
String apiKey = "Your Thingspeak API write key of your Thingspeak channel"; // thingspeak.com api key goes here
WiFiClient client;
void setup() {
  Serial.begin(9600);
  co2Serial.begin(9600);
  connectToWiFi();
}
void loop() {
  Serial.println("------------------------------");
  Serial.print("Time from start: ");
  Serial.print((millis() - startTime) / 1000);
  Serial.println(" s");
  int ppm_uart = readCO2UART();  
  delay(15000);
}
int readCO2UART() {
  byte cmd[9] = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79};
  char response[9];
  Serial.println("Sending CO2 request...");
  co2Serial.write(cmd, 9); //request PPM CO2
  
  // clear the buffer
  memset(response, 0, 9);
  int i = 0;
  while (co2Serial.available() == 0) {
  
       Serial.print("Waiting for response ");
       Serial.print(i);
        Serial.println(" s");
    delay(1000);
    i++;
  }
  if (co2Serial.available() > 0) {
    co2Serial.readBytes(response, 9);
  
  }
  // print out the response in hexa
  for (int i = 0; i < 9; i++) {
    Serial.print(String(response[i], HEX));
    Serial.print("   ");
  }
  Serial.println("");
  // checksum
  byte check = getCheckSum(response);
  if (response[8] != check) {
    Serial.println("Checksum not OK!");
    Serial.print("Received: ");
    Serial.println(response[8]);
    Serial.print("Should be: ");
    Serial.println(check);
  }
  // ppm
  int ppm_uart = 256 * (int)response[2] + response[3];
  Serial.print("UART CO2 PPM: ");
  Serial.println(ppm_uart);
  // temp
  byte temp = response[4] - 40;
  Serial.print("Sensor Temperature: ");
  Serial.println(temp);
  // status
  byte status = response[5];
  Serial.print("Status: ");
  Serial.println(status);
  if (status == 0x40) {
    Serial.println("Status OK");
  }
if (client.connect(host,80)) {
    String postStr = apiKey;
    postStr +="&field1=";
    postStr += String(ppm_uart);
    postStr +="&field2=";
    postStr += String(temp);
    postStr += "\r\n\r\n";
  
    client.print("POST /update HTTP/1.1\n");
    client.print("Host: api.thingspeak.com\n");
    client.print("Connection: close\n");
    client.print("X-THINGSPEAKAPIKEY: "+apiKey+"\n");
    client.print("Content-Type: application/x-www-form-urlencoded\n");
    client.print("Content-Length: ");
    client.print(postStr.length());
    client.print("\n\n");
    client.print(postStr);
  }
  client.stop();
  Serial.print("Uploaded to Thingspeak ");
  return ppm_uart;
}
byte getCheckSum(char *packet) {
  byte i;
  unsigned char checksum = 0;
  for (i = 1; i < 8; i++) {
    checksum += packet[i];
  }
  checksum = 0xff - checksum;
  checksum += 1;
  return checksum;
}
void connectToWiFi(){
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
 
  Serial.print("Connecting to ");
  Serial.println(ssid); 
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");  
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

Remarque : dans le code C++ ci-dessus, mes informations d’identification WiFi et la clé d’écriture de l’API du canal Thingspeak ont ​​été supprimées.

Les futures mises à jour de ce code C++ peuvent être trouvées sur https://github.com/robertwisbey/esp8266_mh-z19b_thingspeak.

En plus d’intégrer les données Thingspeak sur des pages Web comme ci-dessus ou de visualiser directement les données des chaînes Thingspeak sur le site Web Thingspeak, vous pouvez également visualiser les chaînes Thingspeak dans une application pour smartphone appelée Thingview (lien iOS ou lien Android).

Exemple de capture d’écran iOS de l’application Thingview configurée pour lire mon canal Thingspeak MH-Z19B

L’avantage de Thingspeak est que vous pouvez configurer une application « React » et une application « ThingHTTP », et les coupler avec la plate-forme IFTTT (IF This Then That), afin qu’elle vous envoie des notifications lorsque le niveau de CO2 PPM dépasse un seuil configuré.

Exemple de notifications IFTTT couplées à la valeur seuil de l’application Thingspeak React de 400 PPM

Remarque : dans la capture d’écran ci-dessus, j’ai intentionnellement défini une valeur seuil faible de 400 PPM afin de recevoir des notifications envoyées à mon iPhone. Normalement, vous définirez une valeur seuil plus élevée, telle que 1 000 PPM.

Plus d’informations sur la configuration de Thingspeak avec IFTTT suivront bientôt !