Measuring CO2 using MH-Z19B and D1 mini pro
(Updated: )
In this article I describe how to measure CO2 levels using an MH-Z19B CO2 sensor (winsen-sensor.com) connected to D1 mini pro (wemos.cc) and push these somewhere over wifi.
CO2 sensor ¶
There are numerous CO2 sensors available, a non-exhaustive follows here:
- NetAtmo Home Coach (netatmo.com) (100 EUR) - measures VOC (volatile organic compounds) as proxy for CO2, not CO2 directly. It’s also relatively expensive
- S8 SenseAir (senseair.com) - similar to MH-Z19, but more expensive
- MH-Z14 (winsen-sensor.com) - appears to be an older version of MH-Z19
- CCS811 VOC (ams.com) - appears to measure only VOC
- Voltcraft CO-100 (revspace.nl) - could be used as well
- AirBeam (takingspace.org) - great device that does almost everything I want, but quite expensive at $250
- Airquality (mysensors.org) Regarding the MH-Z19, there are two versions (see also this GitHub thread (github.com) and this GoT post (tweakers.net)):
- MH-Z19 (winsen-sensor.com), sometimes also denoted as MH-Z19A: original version, with a less optimal auto-calibration function
- MH-Z19B (winsen-sensor.com): improved version which you want
Connecting MH-Z19B ¶
The MH-Z19B requires 5V to operate. I’ve connected the sensor as follows (based on this article (esp8266-server.de) and this pinout (escapequotes.net)):
- MH-Z19B-GND: connect to ground
- MH-Z19B-Vin: connect to 5V
- MH-Z19B-Rx: connect to pin 5 / SCL = D1 (for UART)
- MH-Z19B-Tx: connect to pin 4 / SDA = D2 (for UART)
- MH-Z19B-PWM: connect to pin 16 / SLEEP = D0 (for PWM)
Reading data ¶
I used the “MH-Z CO2 Sensors” library by Tobias Schürg (github.com) to read out the sensor. You can install this in the Arduino IDE via the library manager.
In the example program, I updated the pins using the above connection:
// pin for uart reading
#define CO2_IN D0
// pin for pwm reading
#define MH_Z19_RX D2
#define MH_Z19_TX D1
Once updated, compile and upload the program to the D1 mini and open the serial monitor (at the right baud rate) to read the CO2 values. Once everything is correct, you should see something like (in this case with debugging turned on):
-- read CO2 uart ---
>> Sending CO2 request.
<< FF 86 9 B9 3D 0 7C 0 FF
getCheckSum()
# PPM UART: 2489
# Temperature? 17
Status OK: 0
PPMuart: 2489, Temperature: 17
One issue I have is that the sensor reports values that are way too high indoors (2500 to 5000 ppm) , which might be because of ABC not working, or the sensor being broken (or maybe I’m not as alive as I feel ).