Giter VIP home page Giter VIP logo

mh-z19's People

Contributors

arminjo avatar bitboxx avatar drawlerr avatar hixfield avatar mpparsley avatar per1234 avatar schumar avatar sfeli avatar wifwaf avatar yoihito avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mh-z19's Issues

Readings way off

This is likely related to #36 but I did not want to hijack that thread.

I have a recent MH-Z19C (plug version). The C02 readings have been ok-ish from the beginning. I compare them to the readings I get out of a Sensirion SCD41 that sits next to it. The temperature was off by roughly +10°C.

However, after a few weeks the CO2 readings started declining gradually until they ended up far below 400ppm (120-300). The reported temperature was constantly around +-32°C.

To see whether this library may be at fault I tried two others for this sensor and got similar results. I concluded my sensor must have failed the test of time. However, after I scanned #36 I'm not so sure anymore.

Tonight I ran the sensor outside for half an hour. Here's what it reports now (inside again).

Device info

21:57:22.753 -> Firmware Version: 05.12
21:57:22.753 -> Range: 2000
21:57:22.787 -> Background CO2: 500
21:57:22.787 -> Temperature Cal: 50
21:57:22.823 -> ABC Status: ON

Basic usage plus background CO2

22:18:26.583 -> CO2 (ppm): 493
22:18:26.583 -> background CO2: 493
22:18:26.654 -> Temperature (C): 33
22:18:28.653 -> CO2 (ppm): 497
22:18:28.653 -> background CO2: 497
22:18:28.725 -> Temperature (C): 33
22:18:30.716 -> CO2 (ppm): 469
22:18:30.716 -> background CO2: 469
22:18:30.782 -> Temperature (C): 33
22:18:32.815 -> CO2 (ppm): 465
22:18:32.815 -> background CO2: 465
22:18:32.850 -> Temperature (C): 33
22:18:34.858 -> CO2 (ppm): 465
22:18:34.858 -> background CO2: 465
22:18:34.895 -> Temperature (C): 33
22:18:36.939 -> CO2 (ppm): 468
22:18:36.939 -> background CO2: 468
22:18:36.976 -> Temperature (C): 33
22:18:38.985 -> CO2 (ppm): 466
22:18:38.985 -> background CO2: 466
22:18:39.056 -> Temperature (C): 33
22:18:41.054 -> CO2 (ppm): 491
22:18:41.054 -> background CO2: 491
22:18:41.126 -> Temperature (C): 33
22:18:43.143 -> CO2 (ppm): 492
22:18:43.143 -> background CO2: 492
22:18:43.181 -> Temperature (C): 33
22:18:45.198 -> CO2 (ppm): 485
22:18:45.198 -> background CO2: 485
22:18:45.232 -> Temperature (C): 33
22:18:47.263 -> CO2 (ppm): 436
22:18:47.263 -> background CO2: 436
22:18:47.299 -> Temperature (C): 33
22:18:49.342 -> CO2 (ppm): 440
22:18:49.342 -> background CO2: 440
22:18:49.380 -> Temperature (C): 33
22:18:51.414 -> CO2 (ppm): 494
22:18:51.414 -> background CO2: 494
22:18:51.450 -> Temperature (C): 33
22:18:53.455 -> CO2 (ppm): 506
22:18:53.455 -> background CO2: 506
22:18:53.529 -> Temperature (C): 33

-> CO2 and background always the same
-> CO2 is off by ~500ppm compared to the SCD41 that I consider accurate
-> CO2 readings are highly volatile, jumping 10% in just a couple of seconds -> appears to be caused by the sensor calibrating
-> temperature is off by 10°C

Simplification proposal

In MHZ19.cpp, sections such as:

        #if defined (ESP32) && (MHZ19_ERRORS)
        ESP_LOGE(TAG_MHZ19, "message...");
        #elif MHZ19_ERRORS
        Serial.println("!ERROR: message...");
        #endif 

Could be simplified:

        #if MHZ19_ERRORS
        Serial.println("!ERROR: message...");
        #endif 

Thank you!

Trouble with HardwareSerial on nodemcu 12

Hello, thank for your library, it's very useful, especially Recovery and Calibrating part.
When i use SoftwareSerial, everything work great, but 3 hours later i don't receive any data from the sensor (i tested it several times). So i read, that using HardwareSerial on ESP gives more stability, and i tried to connect via HardwareSerial, but don't received any data. Maybe something wrong with my sketch, but i tried to minimum change it from original example sketch.
I just change strings

HardwareSerial mySerial(1);
to
HardwareSerial Serial2(2);

and also

mySerial.begin(BAUDRATE, SERIAL_8N1, RX_PIN, TX_PIN);
to
Serial2.begin(BAUDRATE, SERIAL_8N1);

Cause if i try to compile it with original code, i have error:

BasicUsage:21:56: error: invalid conversion from 'int' to 'SerialMode' [-fpermissive]
     mySerial.begin(BAUDRATE, SERIAL_8N1, RX_PIN, TX_PIN); // (ESP32 Example) device to MH-Z19 serial start   
                                                        ^
In file included from /Users/ac1d/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.2/cores/esp8266/Arduino.h:244:0,
                 from /var/folders/j2/rv6w5j790dq31zz952rgp0j00000gn/T/arduino_modified_sketch_904602/BasicUsage.ino:1:
/Users/ac1d/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.2/cores/esp8266/HardwareSerial.h:87:10: error:   initializing argument 3 of 'void HardwareSerial::begin(long unsigned int, SerialConfig, SerialMode, uint8_t)' [-fpermissive]
     void begin(unsigned long baud, SerialConfig config, SerialMode mode, uint8_t tx_pin)
          ^
exit status 1
invalid conversion from 'int' to 'SerialMode' [-fpermissive]

Connections:
MHZ19 TX -> GPIO13 (D7) (RXD2)
MHZ19 RX -> GPIO15 (D8) (TXD2)

#include <Arduino.h>
#include "MHZ19.h"                                        
//#include <SoftwareSerial.h>                                // Remove if using HardwareSerial or Arduino package without SoftwareSerial support
#include "HardwareSerial.h"

//#define RX_PIN 10                                          // Rx pin which the MHZ19 Tx pin is attached to
//#define TX_PIN 11                                          // Tx pin which the MHZ19 Rx pin is attached to
#define BAUDRATE 9600                                      // Device to MH-Z19 Serial baudrate (should not be changed)

MHZ19 myMHZ19;                                             // Constructor for library

//SoftwareSerial mySerial(RX_PIN, TX_PIN);                   // (Uno example) create device to MH-Z19 serial
HardwareSerial Serial2(2);                                // (ESP32 Example) create device to MH-Z19 serial

unsigned long getDataTimer = 0;

void setup()
{
    Serial.begin(9600);                                     // Device to serial monitor feedback
    //Serial.swap(); //GPIO15 (TX) and GPIO13 (RX)
    //Serial.flush(); //clear serial buffer
    //mySerial.begin(BAUDRATE);                               // (Uno example) device to MH-Z19 serial start   
    Serial2.begin(BAUDRATE, SERIAL_8N1);                    // (ESP32 Example) device to MH-Z19 serial start   
    
    
    myMHZ19.begin(Serial2);                                // *Serial(Stream) refence must be passed to library begin(). 
    
    myMHZ19.autoCalibration();                              // Turn auto calibration ON (OFF autoCalibration(false))
}

void loop()
{
    if (millis() - getDataTimer >= 2000)
    {
        int CO2; 

        /* note: getCO2() default is command "CO2 Unlimited". This returns the correct CO2 reading even 
        if below background CO2 levels or above range (useful to validate sensor). You can use the 
        usual documented command with getCO2(false) */

        CO2 = myMHZ19.getCO2();                             // Request CO2 (as ppm)
        
        Serial.print("CO2 (ppm): ");                      
        Serial.println(CO2);                                

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

        getDataTimer = millis();
    }
}

request overlapping

hi, i'm receiving RESULT_ERR_MATCH once at startup when using this code:

void setup()
{
    Serial.begin(9600);
    mhz_serial.begin(MHZ_BAUDRATE);

    mhz.printCommunication(false, true);
    mhz.begin(mhz_serial);
    mhz.autoCalibration(false);
}

void loop()
{
    if (millis() - getDataTimer >= 5000)
    {
        int CO2 = mhz.getCO2(false, true);
        Serial.println(CO2); // <-- zero at first (mhz.errorCode == 3 RESULT_ERR_MATCH)

        getDataTimer = millis();
    }
}

debug log:

---
request:  0xFF 0x01 0x85 0x00 0x00 0x00 0x00 0x00 0x7A  
response: 0xFF 0x85 0x08 0xE5 0x03 0x9E 0x00 0x00 0xED  
---
request:  0xFF 0x01 0xA2 0x00 0x00 0x00 0x00 0x00 0x5D  
response: 0xFF 0xA2 0x08 0xE5 0x03 0x9E 0x00 0x00 0xD0  
---
request:  0xFF 0x01 0x79 0x00 0x00 0x00 0x00 0x00 0x86  
response: 0xFF 0x79 0x01 0x00 0x00 0x00 0x00 0x00 0x86  
---
request:  0xFF 0x01 0x79 0x00 0x00 0x00 0x00 0x00 0x86  
---
request:  0xFF 0x01 0x86 0x00 0x00 0x00 0x00 0x00 0x79  
response: 0xFF 0x79 0x01 0x00 0x00 0x00 0x00 0x00 0x86 ERROR Code: 3
0
---
request:  0xFF 0x01 0x86 0x00 0x00 0x00 0x00 0x00 0x79  
response: 0xFF 0x86 0x03 0x9F 0x44 0x00 0x00 0x00 0x94  
927
---

not sure why 0x79 (ABC turn off) sent twice.
but first 0x86 (CO2 limited) requested before response for second 0x79 is received, so first 0x86 gets failed.

simillar happens with examples/BasicUsage, where co2 and temperature requests overlapping, resulting in failed response for both. fixed by requesting only one at a time.

Disable ABC every day?

Hello,

This is just a quick question:

In the project Readme says "ABC must be disabled each day, however this is handled by the library."
Is this correct? So the MHZ19B re-enables the auto cal every 24h? Could you confirm it, please?

Many thanks.

MHZ19::read returns sometimes RESULT_MATCH forever

The library seems to get out of sync sometimes after 2-3 days running without any problems. If such an error occurs i always get the response RESULT_MATCH forever.
I tried to analyze the code of MHZ19::read and what i understand so far is that you wait until you received at least 9 bytes of data. But what happens if you get more than 9 bytes because of an error? It seems that you just read 9 bytes, also if 10 bytes would be available. The next time the read function is called, you would have again 10 and not 9 bytes in your receive buffer (1 old byte from the previous corrupt message and the 9 bytes from the new message). But now everything is out of sync because of the invalid byte in the receive buffer which is never deleted.
Does this make any sense and could this be the reason for my problems?

I added the following patch to give it a try but i dont have any results so far:

while (mySerial->available() < MHZ19_DATA_LEN)
{
...
}

/* try to resync data */
while (mySerial->available() > MHZ19_DATA_LEN && (unsigned char)mySerial->peek() != 0xFF) 
{
    mySerial->read(); 
}

/* response recieved, read buffer */
mySerial->readBytes(inBytes, MHZ19_DATA_LEN);
    
/* clear receive buffer */
while (mySerial->available())
{
    mySerial->read();
} 

Serial communication - MH-Z19b + ESP-01S together or Arduino

Hi,

is possible to get these two modules working side by side over serial communication with Arduino UNO?

I get this error:
image

My part of the code:
`
#include <Wire.h>
#include <SoftwareSerial.h> // ESP-01S Wifi modul AT - serial komunikace
#include "Adafruit_BME280.h" // Bosch BME280 I2C (T+RH+P)
#include "MHZ19.h" // MH-Z19B (CO2)

#define MHZ19B_RX 10 // MH-Z19B - RX PIN (CO2 modul RX pin -> Arduino)
#define MHZ19B_TX 11 // MH-Z19B - TX PIN (CO2 modul TX pin -> Arduino)
#define ESP01S_RX 2 // ESP-01S - RX PIN (Wifi modul TX pin -> Arduino)
#define ESP01S_TX 3 // ESP-01S - RX PIN (Wifi modul RX pin -> Arduino)

int CO2ppm; // koncentrace CO2 (ppm)
unsigned long getDataTimer = 0; // MHZ19B timer

// ESP-01S Wifi modul - konfigurace zapojeni PINu - RX/TX
SoftwareSerial espSerial(ESP01S_RX,ESP01S_TX);

// MH-Z19B CO2 senzor - konfigurace zapojeni PINu - RX/TX (UART zapojeni)
MHZ19 myMHZ19; // knihovna
SoftwareSerial mhz19bSerial(MHZ19B_RX,MHZ19B_TX);

void setup()
{

// Arduino - komunikace
Serial.begin(9600); // Komunikace Arduino - 9600 baudrate

// Inicializace senzoru + modulu
// Bosch BME280 senzor (T+RH+P)
Serial.println("Inicializace...");
Serial.println("Detekce BME280 sensoru...");
if(!bme.begin(0x76)) // IC2 adresa pro komunikaci nastavena na 0x76
{
Serial.println("BME280 senzor nebyl detekovan. Zkontrolujte vase zapojení a/nebo IC2 adresu!");
while(1);
}
Serial.println("BME280 senzor uspesne nacten!");

  // MH-Z19B CO2 senzor
  mhz19bSerial.begin(9600); // Komunikace s CO2 modulem - 9600 baudrate
  myMHZ19.begin(mhz19bSerial); // Definovat seriovou komunikaci
  myMHZ19.autoCalibration(false); // Vypnout auto-kalibraci CO2


// ESP-01S - komunikace  
  espSerial.begin(115200); // Komunikace s Wifi modulem - 115200 baudrate
  espSerial.flush(); // Vymazat serial monitor
  espData("AT+RST", 1000, DEBUG); // Reset ESP-01S modulu
  espData("AT+CWMODE=1", 1000, DEBUG); // Nastavit rezim ESP-01S na "station mode"
  espData("AT+CWJAP=\""+ AP_SSID +"\",\""+ AP_PASSWORD +"\"", 1000, DEBUG); // Pripojit k Wifi siti
  delay(1000);

}

void readSensors(void)
{

// MH-Z19B - koncentrace CO2 (ppm)
if (millis() - getDataTimer >= 2000)
{
CO2ppm = myMHZ19.getCO2(); // Hodnota koncentrace CO2 (ppm)
getDataTimer = millis();
}
...

`

Get / Set - Cycle

Hello WifWaf,
on https://revspace.nl/ there is a indicator how to change the cycle of MH-Z19b.
Default is 5 seconds which will also be responded by :
int MHZ19::getCycle()
{
/* check get Cycle length (5 Sek default) /
provisioning(GETCYCLE);
if (this->errorCode == RESULT_OK)
/
convert MH-Z19 memory value and return */
return (int)makeInt(this->storage.responses.STAT[2], this->storage.responses.STAT[3]);
else
return 1;
}

But I'm not fine with setting other values.
Did you have checked this register (126) already?

If you like to investigate - I have setup some lines in a fork-version.
Nice to get your ideas and have a nice time . You see I'm a longeterm follower.

Stefan

ERROR 3 after powercycle - firmware download blocks init

Hi,

so i have an ATTiny1614 (16kB Flash, 2kB RAM) with megaTinyCore, a 4-digit serial display and the MHZ-19C. I'm using hardware serial to save memory.
When i flash the code everything works as expected but when i power cycle the board i get error 3 "Recieved data does not match the usual syntax expected".
Flash memory is at 31% and global variables consume 10%.

If it is a memory problem, why does it work right after flashing?

#include <Arduino.h>
#include "MHZ19.h"
#include <TM1637Display.h>

//Pins for 7-Segment
#define CLK 7
#define DIO 6

MHZ19 myMHZ19;                    // Constructor for CO2 Sensor
TM1637Display display(CLK, DIO);  // Constructor for 7-Segment

unsigned long getDataTimer = 0;
uint16_t errorCode=0;

void setup()
{
    display.setBrightness(0x05);
    Serial.begin(9600);                                     // Device to MH-Z19 should not be changed
    
    //mySerial.begin(BAUDRATE);                               // (Uno example) device to MH-Z19 serial start   
    myMHZ19.begin(Serial);                                // *Serial(Stream) refence must be passed to library begin(). 
    myMHZ19.printCommunication();    
     
    myMHZ19.autoCalibration(true);                              // Turn auto calibration ON (OFF autoCalibration(false))
    display.showNumberDec(millis(),false);
    delay(2000);
    display.showNumberDec(0,true);
}

void loop()
{   
    if (millis() - getDataTimer >= 2000)
    {
        int CO2; 

        /* note: getCO2() default is command "CO2 Unlimited". This returns the correct CO2 reading even 
        if below background CO2 levels or above range (useful to validate sensor). You can use the 
        usual documented command with getCO2(false) */

        CO2 = myMHZ19.getCO2();                             // Request CO2 (as ppm)
        if(myMHZ19.errorCode ==  RESULT_OK)
          display.showNumberDec(CO2,false);
        else{
          display.showNumberDec(myMHZ19.errorCode,true);
        }
        getDataTimer = millis();
    }
}

Incorrect PPM range with sensor

Hi, so I've started playing with this library, and I'm confused a little about range which .getCO2() returns.
My MH-Z19B has a sticker which states 0-5000ppm.
I've called getRange(), it returned 5000. But when I call getCO2 - I get a value between 0-10000ppm, which looks like 0-5000 stretched into 10000, for example I get something like 1100 in fresh air, which should be close to 400-500, and I get 10000 when do a couple of breaths near it for a minute.

Am I missing something? Thanks in advance.

I've ran RetrieveDeviceInfo.ino:

Firmware Version: 04.30
Range: 5000
Background CO2: 400
Temperature Cal: 40
ABC Status: OFF

Getting wrong temperature on MH-z19c

Hi,

I am usning MH-Z19c sensor on esp8266.

I am getting the same temperature value:

CO2: 672
Temperature: -40
Accuracy: 0
CO2: 675
Temperature: -40
Accuracy: 0
CO2: 682
Temperature: -40
Accuracy: 0
CO2: 684
Temperature: -40
Accuracy: 0
CO2: 689
Temperature: -40
Accuracy: 0
CO2: 691
Temperature: -40
Accuracy: 0
CO2: 693
Temperature: -40
Accuracy: 0

Please help me on this.

Wrong Temperature - wrong Co2?

Hi, I used your example script on my new (and first) MH-Z19B sensor. I have no experience with this type of Sensor, however i do not trust this temerature measurements:
CO2 (ppm): 1962 Temperature (C): 4
The Co2 could be possible due to an indoor room, but the temp is definitely off. And I guessing this makes the Co2 wrong too? Could this be script side oder is my sensor just broken?

Temperature values among different sensors

I built 4 devices, all with the same components including a CO2 sensor, all running the same arduino software. I put them side by side and they report wildy different temperature values (14, 24, 38, 45). Have you seen this problem? What should be this value?

High values after power reset

Hi! Thanks for the useful library!
I found a small problem: after a reboot on power, the sensor returns falsely large values, which breaks the display of CO2-level charts.
Here is a serial monitor dump after such reboot:

CO2 = 63882 ppm
CO2 = 7011 ppm
CO2 = 4013 ppm
CO2 = 1017 ppm
CO2 = 1016 ppm
CO2 = 1029 ppm
CO2 = 1042 ppm

It would be great to add a filter of values to the library if it's possible.

Kind regards, Max.

ESP32C3 support.

Compiling for an esp32c3 board, I have some issues with platfomio, like this:

C:/Users/Usuario/.platformio/packages/framework-arduinoespressif32@src-01b2ee0664276ec022da2783d94579c3/tools/sdk/esp32c3/include/log/include/esp_log.h:351:38: note: in expansion of macro 'ESP_LOG_LEVEL_LOCAL'
#define ESP_LOGE( tag, format, ... ) ESP_LOG_LEVEL_LOCAL(ESP_LOG_ERROR, tag, format, ##VA_ARGS)
^~~~~~~~~~~~~~~~~~~
.pio/libdeps/ESP32C3/MH-Z19/src/MHZ19.cpp:51:9: note: in expansion of macro 'ESP_LOGE'
ESP_LOGE(TAG_MHZ19, "Invalid Range value (0 - 65000)");
^~~~~~~~
.pio/libdeps/ESP32C3/MH-Z19/src/MHZ19.cpp:51:18: error: 'TAG_MHZ19' was not declared in this scope
ESP_LOGE(TAG_MHZ19, "Invalid Range value (0 - 65000)");

Reasoning behind sensor zero-calibration ?

Hi there,

I don't know if the question is about the library or about the sensor itself. I am using the method calibrate (); to calibrate the sensor but it does not have the behavior I expect, which is to determine the zero (400 ppm). Instead, other baselines appear. After calibrating, I print the sensor information and get results such as:

Outdoor:
imagen

Indoor:
imagen

Background CO2 seems to have been defined in the calibration process. Does that make sense to you? In that case, how can that Background CO2 be set with such a high value, if the calibration is done outdoors?

Thank you!

Note: By the way, outdoor temperatures were lower, at 7-9 °C.

library fails with CORE_DEBUG_LEVEL=3

Overview

The library fails when the debug level is increased, when you define CORE_DEBUG_LEVEL=3 for example, its necessary pass the TAG like this: '-D TAG_MHZ19="MHZ19"' on PlatformIO ini file for example.

.pio/libdeps/M5STICKCPLUS/MH-Z19/src/MHZ19.cpp: In member function 'void MHZ19::begin(Stream&)':
.pio/libdeps/M5STICKCPLUS/MH-Z19/src/MHZ19.cpp:37:18: error: 'TAG_MHZ19' was not declared in this scope
         ESP_LOGE(TAG_MHZ19, "Initial communication errorCode recieved");

BasicUsage fails on the Wemos D1 Mini

Using :

#define RX_PIN D5 // Rx pin which the MHZ19 Tx pin is attached to
#define TX_PIN D6 // Tx pin which the MHZ19 Rx pin is attached to
#define BAUDRATE 9600 // Native to the sensor (do not change)

in the basicusage sketch.

Other libraries are able to fetch the temperature and ppm, this library fails.
I hooked up an oscilloscope and can see that the device indeed replies (TX and RX are both active).

Output of the sketch:

!ERROR: Failed to verify connection(1) to sensor. Failed to stablise
!ERROR: Initial communication errorCode recieved
CO2 (ppm): 0
Temperature (C): -17
CO2 (ppm): 0
Temperature (C): -17
CO2 (ppm): 0
Temperature (C): -17
CO2 (ppm): 0
Temperature (C): -17
CO2 (ppm): 0
Temperature (C): -17
CO2 (ppm): 0
Temperature (C): -17
CO2 (ppm): 0
Temperature (C): -17

ErrorCode = 2 meaning timeout
I tried to increase timeout to 5000 but nothing changed...

Question. Correct interpretation of sensor readings

I am using version 1.5.3

Hi.
I calibrated on a windowsill with an open window, after calibration I upload my sketch and invoke getBackgroundCO2(), it was 500, then I corrected something in the code, upload it again and the value of getBackgroundCO2() became equal to getCO2(), is this correct behavior? I had the idea to calibrate the sensor, and then measure the delta from the background level of CO2, i.e. getCO2() - getBackgroundCO2(). Also, what seemed strange to me, the sensor readings in a ventilated room range from 1500 to 1600 ppm, is this an overestimated value?

Always reading 5000ppm on ESP32.

I encountered a weird problem and while most likely not related to the library, I wanted to make sure. I use the MH-Z19B with an ESP32. I already tried with an Arduino and an ESP8266 and everything worked fine.

Additionally when I use the sensor with a "LOLIN32" everything works, too.

Now the problem is the board I would like to use "LOLIN D32" has no 5V pin and when I connect the sensor to the 3.3V pin, I always receive 5000ppm as response. I did some research and it seems as if the sensor is getting a brownout and restarts continuosly...
I tried to use an external 5V power source (I connected GND and 5V to Vin and GND and also tried to connect only 5V to Vin) but now I get an error on startup ([E][MHZ19.cpp:44] begin(): Initial communication errorCode recieved) and always receive 0ppm.

Sorry for opening this potential Non-Issue and thanks in advance.

I used these connections on ESP32 / External 5V source.
Vin -> 5V
GND -> GND
17 -> RX
16 -> TX

I used this code:

#include <Arduino.h>
#include "MHZ19.h"

MHZ19 myMHZ19;                                             

unsigned long getDataTimer = 0;                                                        

void setup()
{
    Serial.begin(9600);

    Serial2.begin(9600, SERIAL_8N1);
    myMHZ19.begin(Serial2);
    myMHZ19.autoCalibration();
}                                                         

void loop()
{
    if (millis() - getDataTimer >= 5000)
    {
        int CO2Unlim = myMHZ19.getCO2();
        Serial.print("CO2 (ppm): ");
        Serial.println(CO2Unlim);

        getDataTimer = millis();                                                      
    }                                                                               
}  

Is using this board not supported yet or am I doing something wrong?

RAW measurement

Hi,

I'm I correct to assume that even if my sensors range is between 410 - 2000.

That the raw measurement that goes above 20000 is also correct? (The ppm count in the raw example)

Or is this gibberish data?

FYI: be warned about fake banggood MH-Z19b sensors

I recently ordered 3x MH-Z19 sensors from banggood. Because I wanted to construct 3 supplementary IOT CO2 sensors (refer to my project https://github.com/hixfield/HixCO2TemperatureIRBlaster). However, the readings that they produce are highly unstable and cannot be trusted. I created small YouTube video to show my readings (on request of banggood itself):

https://youtu.be/5_QQe75-SZI

Also found this post about it: https://revspace.nl/MH-Z19B#Fake_MH-Z19B_.28black_PCB.29

Add MH-Z16 and below 400ppm measurements, set different range / sensititivies of sensors used.

So nice to see this fantastic library. I struggled a lot 3 years ago, with all those commands...
https://www.hackteria.org/wiki/CO2_Soil_Respiration_Chamber

From my own experiments i started to prefer the MH-Z16, as it can also send ppm values below 400. For some experiments in plant monitoring or microbiological fermentation process we can also eat up more CO2 than we release.

It's quite similar, the library could add it with minor changes.

Whaaddabout those different sensitivities 0-2000, 0-5000, 0-10'000 and even more. How can i set this up using the library?

How to calibrate the sensor properly?

Hi, thank you for this great library.

I've checked and run the calibration example, but it didn't help me.
I was outside and run sketch couple times without any changes in code (except rx/tx). But mh-z19 still returns me values around 720. Did I do it wrong?
I have another CO2 monitor, which shows 460-470 at the same spot, and it seems to be a fair number.

So I noticed that my mh-z19 has wrong delta around 200-300 ppm. Is there a way to make a safe shift for that delta?

Cannot connect the sensor properly

I used an Arduino Micro and just used your example code and connected the sensor like this:

  • 5V (Arduino) to Vin (MH-Z19B)
  • GND to GND
  • Rx (Arduino) to Tx (MH-Z19B)
  • Tx (Arduino) to Rx (MH-z19B)

Unfortunately, I got this Error:
image

I changed the value of the rx_pin and tx_pin like this:
#define RX_PIN 10
#define TX_PIN 11

When I look at the Sensor, I can see the IR light turning on every 2 seconds or so. On the arduino, the tx light flashes on and of, but the rx light is permanentely of.

What can I do?

First measurement is not correct

I have mhz-19b

first measurement is not accurate, it returns always about 450 ppm, but the second if is correct (tested and compared with my second commercial device).

I use delay 60 second before the first read, is there anything what can be done better? Thank you!

getCO2() sends wrong serial command?

According to the MH-Z19's manual, the command to get the co2 reading is 0x86.
Following the basic usage example in this repository, it seems that 0x85 is being sent instead.
Here's a screenshot from a logic analyzer showing Tasmota correctly polling for the reading:
Logic_eUTjYcvB8w
Here's your arduino library:
Logic_wRio3f2ICs

The code I'm using:

#include <MHZ19.h>
#include <SoftwareSerial.h>
#define RX_PIN 8
#define TX_PIN 9
#define BAUDRATE 9600

MHZ19 myMHZ19;
SoftwareSerial mhzSerial(RX_PIN, TX_PIN);

unsigned long getDataTimer = 0; 

void setup() {
  mhzSerial.begin(BAUDRATE);
  myMHZ19.begin(mhzSerial);
  myMHZ19.setRange(2000);
  myMHZ19.setSpan(2000);
  
  Serial.begin(115200);
}

void loop() {
    if (millis() - getDataTimer >= 2000)                    // Check if interval has elapsed (non-blocking delay() equivilant)
    {
        int CO2;                                            // Buffer for CO2
        CO2 = myMHZ19.getCO2();                             // Request CO2 (as ppm)
    
        Serial.print("CO2 (ppm): ");                      
        Serial.println(CO2);                          
    
        getDataTimer = millis();                            // Update interval
    }
}

Am I doing something wrong here?

receiving zeros after warmup

hi, sometimes (like 10% chance) i'm receiving zeros from getCO2 after following init process:

void init_mhz() {
  mhz_serial.begin(MHZ_BAUDRATE);

  mhz.begin(mhz_serial);
  mhz.setFilter(true, true);

  mhz.setRange(2000);
  mhz.autoCalibration(true);

  // warming up
  while (true) {
    int co2 = mhz.getCO2(false, true);

    if (mhz.errorCode == RESULT_FILTER) {
      log_ln("sensors: mhz: warming up...", true);
    } else if (mhz.errorCode != RESULT_OK) {
      log_ln("sensors: mhz: failed to read CO2 on warmup.", true);
    } else {
      // warmed up (zeros can slip here)
      break;
    }

    delay(CO2_WARMING_READ_PERIOD);
  }
}

i'm using mhz.errorCode instead of simplier co2 == 0 (as in example), because i want to distinguish normal warming (RESULT_FILTER) and failing on warmup (!RESULT_OK).

maybe this is because i'm using TEMPLIM instead of TEMPUNLIM (what's the difference btw? didn't found any info about that. using TEMPLIM because this one specified in manual).

probably co2 == 0 case should be added to other filtering cases.

v1.4.2

error compiling

Hi, thanks for the library, makes life so much easier setting up the device

I tried the basic sketch with both library files inside the same directory and tried to compile it on an arduino pro mini (ATMEGA328 so uno compatible) and im getting the following error

MHZ19.cpp: In member function ‘byte MHZ19::read(byte*, MHZ19::Command_Type)’:
MHZ19.cpp:594:48: error: invalid conversion from ‘byte* {aka unsigned char*}’ to ‘char*’ [-fpermissive]
     mySerial->readBytes(inBytes, MHZ19_DATA_LEN);
                                                ^
In file included from /usr/share/arduino/hardware/arduino/cores/arduino/HardwareSerial.h:28:0,
                 from /usr/share/arduino/hardware/arduino/cores/arduino/Arduino.h:193,
                 from MHZ19.h:6,
                 from MHZ19.cpp:3:
/usr/share/arduino/hardware/arduino/cores/arduino/Stream.h:76:10: note:   initializing argument 1 of ‘size_t Stream::readBytes(char*, size_t)’
   size_t readBytes( char *buffer, size_t length); // read chars from stream into buffer
          ^

have i fucked up something obvious that i can't see?

!Error: Timed out waiting for response

Hi,
I am trying to use your library. Due to every connection seems okey i am not getting and data from my MHZ-19 sensor.

I constantly get the following error;

CO2 (ppm): 0
!Error: Timed out waiting for response
Temperature (C): -17

Thank you.

Library incompatible with I2C LCD?

I've been using a different MHZ19 library but am having serious bugs with it so I gave yours a try, however, when I upload it the LCD doesn't work. Uploading the old sketch brings it back online. I can't understand how this would affect the screen, but I've changed nothing in my code but what's needed to make each library work.

I'm running a Leonardo, so using hardware serial, if that's relevant.

Edit: Actually it seems like everything stopped working, the relays and the logic controlling them as well.

Any help?

Consider changing the license

The current license is GPL, which means that you cannot use this library in a project without releasing all of that project's source code under GPL as well.

I don't know if using GPL is a fully thought out choice or not, but it severely restricts where the library can be used.

Please consider releasing changing the license to LGPL (allows linking inside of a program), or to MIT (even better, basically allows all use in a propriety program).

The other 2 libraries I've found for using MH-Z19B are MIT licensed, but one of them only supports PWM (no serial support) and the other one isn't available in Arduino IDE's library manager:
https://github.com/tobiasschuerg/MH-Z-CO2-Sensors
https://github.com/crisap94/MHZ19

Changing the license at this point should be fairly simple, but after you've accepted contributions from other people, they need to agree to the license change as well, as far as I've understood.

The readme says that this library is derived/inspired by another library, which is licensed under GPLv3, so the distinction between derived and inspired is probably important if the license would be changed.

Error Code 3

Hello
I use esp32 UART to communication with MH-Z19 MH-Z19C

than, I tried the example ErrorCodes and I got message

Sent << DEC: 255 1 133 0 0 0 0 0 122
Received >> DEC: 66 77 9 129 8 200 3 52 1 ERROR Code: 3
Failed to receive CO2 value - Error
Response Code: 3
Sent << DEC: 255 1 133 0 0 0 0 0 122
Received >> DEC: 66 77 9 129 8 200 3 52 1 ERROR Code: 3
Failed to receive CO2 value - Error
Response Code: 3
Sent << DEC: 255 1 133 0 0 0 0 0 122
Received >> DEC: 66 77 9 130 8 198 3 51 1 ERROR Code: 3
Failed to receive CO2 value - Error
Response Code: 3
Sent << DEC: 255 1 133 0 0 0 0 0 122
Received >> DEC: 66 77 9 130 8 198 3 51 1 ERROR Code: 3
Failed to receive CO2 value - Error
Response Code: 3
Sent << DEC: 255 1 133 0 0 0 0 0 122
Received >> DEC: 66 77 9 130 8 199 3 50 1 ERROR Code: 3
Failed to receive CO2 value - Error
Response Code: 3
Sent << DEC: 255 1 133 0 0 0 0 0 122
Received >> DEC: 66 77 9 131 8 199 3 49 1 ERROR Code: 3
Failed to receive CO2 value - Error
Response Code: 3

Could you help me please?

Thank you @WifWaf

Storage Usage of this Library ..

Hello again 👍 ,

New Week, New Problem.. You know that I try to make an battery powered Device for my office.. So I would like to Use an Attiny.. But the Attiny 404 has 4kb of Space.. The Library with the BasicUsage won’t fit on that chip.
The attiny has a real serial connection and don’t need „SoftwareSerial“.. Only for understanding: 8kb Attiny has only 26% free Space for Code. This must be more.

How can I use this Libary without SoftwareSerial?

get background CO2

Now that I finally experiment I have another question.

I did a manual calibration as you suggested in your examples. I left the device outside for 20-30 minutes and then I pulled the DH pin to ground for 7 seconds. The readings calibrated to 400 and then i let it run for another 10 minutes to see if it's stays there.

After that i placed the device inside a closed room to show the higher readings. It did willfully. But then i checked the getBackgroundCO2 commend and I noticed the following.

The getBackgroundCO2 was always printing the same as the CO2 command

Background CO2: 3067
ABC Status: OFF
CO2 (ppm): 3067
Temperature (C): 20

Background CO2: 3100
ABC Status: OFF
CO2 (ppm): 3100
Temperature (C): 20

If I got the documentation correctly the getBackgroundCO2 should have been a constant 400 after the calibration. Have you any idea what am i missing?

Problem in "byte MHZ19::getCRC(byte inBytes[])"

File MHZ19.cpp
Lines 736 to746
The variable CRC, written in capital letters collides with a macro defined in CMSIS, resulting in a bunch of compiler errors.

Writing the variable crc in lower case letters solves the issue.

You are welcome
Michael

Error:
Arduino: 1.8.13 (Windows 7), Board: "Generic STM32F1 series, BluePill F103C8, Maple DFU Bootloader original, Enabled (generic 'Serial'), None, Low/Full Speed, Smallest (-Os default), Newlib Standard"

In file included from C:\Users\Michael\AppData\Local\Arduino15\packages\STM32\hardware\stm32\1.9.0\system/Drivers/CMSIS/Device/ST/STM32F1xx/Include/stm32f1xx.h:131,

             from C:\Users\Michael\AppData\Local\Arduino15\packages\STM32\hardware\stm32\1.9.0\cores\arduino/stm32/stm32_def.h:28,

             from C:\Users\Michael\AppData\Local\Arduino15\packages\STM32\hardware\stm32\1.9.0\cores\arduino/stm32/clock.h:43,

             from C:\Users\Michael\AppData\Local\Arduino15\packages\STM32\hardware\stm32\1.9.0\cores\arduino/wiring_time.h:23,

             from C:\Users\Michael\AppData\Local\Arduino15\packages\STM32\hardware\stm32\1.9.0\cores\arduino/wiring.h:38,

             from C:\Users\Michael\AppData\Local\Arduino15\packages\STM32\hardware\stm32\1.9.0\cores\arduino/Arduino.h:36,

             from C:\Users\Michael\Documents\Arduino\libraries\MH-Z19\src\MHZ19.h:14,

             from C:\Users\Michael\Documents\Arduino\libraries\MH-Z19\src\MHZ19.cpp:11:

C:\Users\Michael\Documents\Arduino\libraries\MH-Z19\src\MHZ19.cpp: In member function 'byte MHZ19::getCRC(byte*)':

C:\Users\Michael\AppData\Local\Arduino15\packages\STM32\hardware\stm32\1.9.0\system/Drivers/CMSIS/Device/ST/STM32F1xx/Include/stm32f103xb.h:685:43: error: expected ')' before '*' token

685 | #define CRC ((CRC_TypeDef *)CRC_BASE)

  |                              ~            ^

C:\Users\Michael\Documents\Arduino\libraries\MH-Z19\src\MHZ19.cpp:736:17: note: in expansion of macro 'CRC'

736 | byte x = 0, CRC = 0;

  |                 ^~~

C:\Users\Michael\AppData\Local\Arduino15\packages\STM32\hardware\stm32\1.9.0\system/Drivers/CMSIS/Device/ST/STM32F1xx/Include/stm32f103xb.h:685:43: error: expected ')' before '*' token

685 | #define CRC ((CRC_TypeDef *)CRC_BASE)

  |                             ~             ^

C:\Users\Michael\Documents\Arduino\libraries\MH-Z19\src\MHZ19.cpp:736:17: note: in expansion of macro 'CRC'

736 | byte x = 0, CRC = 0;

  |                 ^~~

C:\Users\Michael\Documents\Arduino\libraries\MH-Z19\src\MHZ19.cpp:740:25: error: lvalue required as left operand of assignment

740 | CRC += inBytes[x];

  |                         ^

C:\Users\Michael\Documents\Arduino\libraries\MH-Z19\src\MHZ19.cpp:743:17: error: 'crc' was not declared in this scope

743 | CRC = 255 - crc;

  |                 ^~~

In file included from C:\Users\Michael\AppData\Local\Arduino15\packages\STM32\hardware\stm32\1.9.0\system/Drivers/CMSIS/Device/ST/STM32F1xx/Include/stm32f1xx.h:131,

             from C:\Users\Michael\AppData\Local\Arduino15\packages\STM32\hardware\stm32\1.9.0\cores\arduino/stm32/stm32_def.h:28,

             from C:\Users\Michael\AppData\Local\Arduino15\packages\STM32\hardware\stm32\1.9.0\cores\arduino/stm32/clock.h:43,

             from C:\Users\Michael\AppData\Local\Arduino15\packages\STM32\hardware\stm32\1.9.0\cores\arduino/wiring_time.h:23,

             from C:\Users\Michael\AppData\Local\Arduino15\packages\STM32\hardware\stm32\1.9.0\cores\arduino/wiring.h:38,

             from C:\Users\Michael\AppData\Local\Arduino15\packages\STM32\hardware\stm32\1.9.0\cores\arduino/Arduino.h:36,

             from C:\Users\Michael\Documents\Arduino\libraries\MH-Z19\src\MHZ19.h:14,

             from C:\Users\Michael\Documents\Arduino\libraries\MH-Z19\src\MHZ19.cpp:11:

C:\Users\Michael\AppData\Local\Arduino15\packages\STM32\hardware\stm32\1.9.0\system/Drivers/CMSIS/Device/ST/STM32F1xx/Include/stm32f103xb.h:685:30: error: increment of read-only location '(CRC_TypeDef*)((1073741824 + 131072) + 12288)'

685 | #define CRC ((CRC_TypeDef *)CRC_BASE)

  |                             ~^~~~~~~~~~~~~~~~~~~~~~~~

C:\Users\Michael\Documents\Arduino\libraries\MH-Z19\src\MHZ19.cpp:744:5: note: in expansion of macro 'CRC'

744 | CRC++;

  |     ^~~

C:\Users\Michael\Documents\Arduino\libraries\MH-Z19\src\MHZ19.cpp:744:8: error: lvalue required as increment operand

744 | CRC++;

  |        ^~

In file included from C:\Users\Michael\AppData\Local\Arduino15\packages\STM32\hardware\stm32\1.9.0\system/Drivers/CMSIS/Device/ST/STM32F1xx/Include/stm32f1xx.h:131,

             from C:\Users\Michael\AppData\Local\Arduino15\packages\STM32\hardware\stm32\1.9.0\cores\arduino/stm32/stm32_def.h:28,

             from C:\Users\Michael\AppData\Local\Arduino15\packages\STM32\hardware\stm32\1.9.0\cores\arduino/stm32/clock.h:43,

             from C:\Users\Michael\AppData\Local\Arduino15\packages\STM32\hardware\stm32\1.9.0\cores\arduino/wiring_time.h:23,

             from C:\Users\Michael\AppData\Local\Arduino15\packages\STM32\hardware\stm32\1.9.0\cores\arduino/wiring.h:38,

             from C:\Users\Michael\AppData\Local\Arduino15\packages\STM32\hardware\stm32\1.9.0\cores\arduino/Arduino.h:36,

             from C:\Users\Michael\Documents\Arduino\libraries\MH-Z19\src\MHZ19.h:14,

             from C:\Users\Michael\Documents\Arduino\libraries\MH-Z19\src\MHZ19.cpp:11:

C:\Users\Michael\AppData\Local\Arduino15\packages\STM32\hardware\stm32\1.9.0\system/Drivers/CMSIS/Device/ST/STM32F1xx/Include/stm32f103xb.h:685:30: error: invalid conversion from 'CRC_TypeDef*' to 'byte' {aka 'unsigned char'} [-fpermissive]

685 | #define CRC ((CRC_TypeDef *)CRC_BASE)

  |                             ~^~~~~~~~~~~~~~~~~~~~~~~~

  |                              |

  |                              CRC_TypeDef*

C:\Users\Michael\Documents\Arduino\libraries\MH-Z19\src\MHZ19.cpp:746:12: note: in expansion of macro 'CRC'

746 | return CRC;

  |            ^~~

exit status 1

Fehler beim Kompilieren für das Board Generic STM32F1 series.

Question about the Calibration

Hey,

thank your for your nice Library and your Documentation about it. I bought this Sensor and I want to use it only indoors and my Question is about the Calibration. I thought that I need to turn of the auto-calibration, right?

But how can I calibrate this Sensor to have stable Values for a long time?

Is it possible to use your Calibration code with an simple button? I mean : I pressed the button outside the Sensor calibrates itself and then its done. Or needs the Sensor a longer Calibration Time?

Could you please explain to me if I disable the Auto-Calibration disabled that also the temperature Compensation?

My last question is about the Power-Consumption:

  • Could I power Off the Sensor to save Energy?

Thank you very much for answering my Questions..

Failed communication via UART (ESP32)

Hi everyone,
I'm using ESP32 with MHZ19B co2 sensor. I've changed the BasicUsage sketch to use HardwareSerial 2. After wiring everything the result was:
co2: 0
temperature: -17
error

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.