Hi all,
this is my first try and first post her so please be gentle
I have a MH-Z19B attached to an ESP8266 NodeMCU v3 from AZ Delivery.
I am running the Arduino 1.8.13 and as a board I have selected the NodeMCU 0.9 (ESP-12 Module) and I also tried the NodeMCU 1.0 (ESP-12E Module). The "Generic ESP8266 Module" did not work with the SoftwareSerial pin definition ...
The cabling of the sensor to the ESP8266 is as follows:
MH-Z19B Pin TX is attached to ESP8266 Pin D7
MH-Z19B Pin RX is attached to ESP8266 Pin D6
MH-Z19B Pin GND is attached to ESP8266 Pin G (4 left of D7)
MH-Z19B Pin Vin is attached to ESP8266 Pin 3V (5 left of D7)
I created the following code from several repositories found in the web:
#include <SoftwareSerial.h>
#define MH_Z19_RX D7
#define MH_Z19_TX D6
// MH-Z19B Sensor
int co2ppm; // CO2 Messwert in ppm
SoftwareSerial co2Serial(MH_Z19_RX, MH_Z19_TX);
// SoftwareSerial co2Serial(D7, D6);
int readCO2() // Kommunikation mit MH-Z19 CO2 Sensor
{
byte cmd[9] = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79}; //request CO2 and temp values
//byte cmd[9] = {0xFF, 0x01, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79}; //returns firmware level
//byte cmd[9] = {0xFF, 0x01, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79}; //reset MCU
//byte cmd[9] = {0xFF, 0x01, 0x9B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79}; //returns Sensor range
char antwort[9];
co2Serial.write(cmd, 9);
// The serial stream can get out of sync. The response starts with 0xff, try to resync.
while (co2Serial.available() > 0 && (unsigned char)co2Serial.peek() != 0xFF)
{
co2Serial.read();
}
// Clear the Buffer
memset(antwort, 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(antwort, 9);
Serial.println("+++ Response Start String 1 +++ " + String(antwort[0], HEX) + " +++");
Serial.println("+++ Response Start String 2 +++ " + String(antwort[1], HEX) + " +++");
Serial.println("+++ Response CO2 High Value +++ " + String(antwort[2], HEX) + " +++");
Serial.println("+++ Response CO2 Low Value +++ " + String(antwort[3], HEX) + " +++");
Serial.println("+++ Response Temperature +++ " + String(antwort[4], HEX) + " +++");
Serial.println("+++ Response Status = 0x40 +++ " + String(antwort[5], HEX) + " +++");
Serial.println("+++ Response Unknown +++ " + String(antwort[6], HEX) + " +++");
Serial.println("+++ Response Unknown +++ " + String(antwort[7], HEX) + " +++");
Serial.println("+++ Response Checksum +++ " + String(antwort[8], HEX) + " +++");
Serial.println("+++ Response End String +++ " + String(antwort[9], HEX) + " +++");
}
//co2Serial.readBytes(antwort, 9);
byte crc = 0;
for (int i = 1; i < 8; i++)
{
crc += antwort[i];
}
crc = 255 - crc + 1;
Serial.println("+++ CRC Calculated: " + String(crc) + " +++");
if (antwort[0] != char(0xFF))
{
Serial.println("Invalid response <0xFF> from CO2 sensor!");
return -1;
}
if (antwort[1] != char(0x86))
{
Serial.println("Invalid response <0x86> from CO2 sensor!");
return -1;
}
if (antwort[8] == crc)
{
int antwortHigh = (int) antwort[2]; // CO2 High Byte
int antwortLow = (int) antwort[3]; // CO2 Low Byte
int ppm = (256 * antwortHigh) + antwortLow;
//Serial.println(antwortHigh);
//Serial.println(antwortLow);
//Serial.println(ppm);
return ppm; // Antwort des MH-Z19 CO2 Sensors in ppm
}
else
{
Serial.println("CRC error!");
return -1;
}
byte status = antwort[5];
Serial.print("Status: ");
Serial.println(status);
if (status != 0x40)
{
Serial.println("Status NOT ok");
}
}
void setup() {
//Setup for MH-Z19B Software Serial Communication
co2Serial.begin(9600); //Init sensor MH-Z19
Serial.begin(115200);
Serial.println();
}
void loop() {
// New MH-Z19 CO2 sensor readings
co2ppm = readCO2();
Serial.println("+++ PPM: " + String(co2ppm) + " +++");
delay(15000);
}
The repeating output in 15 second cycles shows that the "CO2 High Byte" value and the "CO2 Low Byte" value stay constant for ever - obviously at their max level - as the calculated PPM value (ppm = (256 * antwortHigh) + antwortLow) is always 5000 ppm. Also the response status = antwort[5] should be 0x40 but is 0x00.
16:52:17.160 -> +++ Response Start String 1 +++ ff +++
16:52:17.160 -> +++ Response Start String 2 +++ 86 +++
16:52:17.197 -> +++ Response CO2 High Value +++ 13 +++
16:52:17.197 -> +++ Response CO2 Low Value +++ 88 +++
16:52:17.197 -> +++ Response Temperature +++ 42 +++
16:52:17.197 -> +++ Response Status = 0x40 +++ 0 +++
16:52:17.197 -> +++ Response Unknown +++ 0 +++
16:52:17.197 -> +++ Response Unknown +++ 0 +++
16:52:17.197 -> +++ Response Checksum +++ 9d +++
16:52:17.197 -> +++ Response End String +++ ff +++
16:52:17.197 -> +++ CRC Calculated: 157 +++
16:52:17.197 -> +++ PPM: 5000 +++
As you can see in the commented lines for the command string:
byte cmd[9] = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79}; //request CO2 and temp values
//byte cmd[9] = {0xFF, 0x01, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79}; //returns firmware level
//byte cmd[9] = {0xFF, 0x01, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79}; //reset MCU
//byte cmd[9] = {0xFF, 0x01, 0x9B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79}; //returns Sensor range
I already tried to reset the sensor or find out the defined sensor range but without success.
Is there anyone who can tell me if the sensor is broken or if there is a chance to reset it to get it working properly?
Or maybe there is something substantially wrong with my code and someone has a hint how to fix this.
Thank you for any response and support!!!
Cheers
Justus