MH-Z14 / MH-Z19 CO2 sensor
Moderators: grovkillen, Stuntteam, TD-er
MH-Z14 / MH-Z19 CO2 sensor
Hi,
I'm planning to create a CO2 sensor using an MH-Z19 sensor module.
As far as I can see this sensor module is not supported yet by ESPEasy and I'd like to add it if possible.
It uses a 8N1 3.3V serial connection to receive a measurement command and send back the result.
As far as I can tell, this sensor has a serial format compatible with the MH-Z14 CO2 sensor module.
Is anyone else already working on this, or can I go ahead and try adding support for it?
Regards, Bertrik
I'm planning to create a CO2 sensor using an MH-Z19 sensor module.
As far as I can see this sensor module is not supported yet by ESPEasy and I'd like to add it if possible.
It uses a 8N1 3.3V serial connection to receive a measurement command and send back the result.
As far as I can tell, this sensor has a serial format compatible with the MH-Z14 CO2 sensor module.
Is anyone else already working on this, or can I go ahead and try adding support for it?
Regards, Bertrik
Re: MH-Z14 / MH-Z19 CO2 sensor
I've been looking a bit into doing serial port communication on the ESP.
Apparently you can call Serial.swap() to swap the serial port to pins GPIO15(TX) and GPIO13(RX).
I plan to use this mechanism to talk to the MH-Z19. So I'll connect the sensor to GPIO15 and GPIO13 and it won't interfere with normal debug serial port output.
Just before and after communication with the MH-Z19, the serial port is swapped to GPIO15/13 and back, so we can communicate with the sensor but other debug output still appears the normal way.
I have some code already to send the serial command and receive the sensor serial response, now I'll just have to wait for the actual sensor to arrive to try it.
Apparently you can call Serial.swap() to swap the serial port to pins GPIO15(TX) and GPIO13(RX).
I plan to use this mechanism to talk to the MH-Z19. So I'll connect the sensor to GPIO15 and GPIO13 and it won't interfere with normal debug serial port output.
Just before and after communication with the MH-Z19, the serial port is swapped to GPIO15/13 and back, so we can communicate with the sensor but other debug output still appears the normal way.
I have some code already to send the serial command and receive the sensor serial response, now I'll just have to wait for the actual sensor to arrive to try it.
Re: MH-Z14 / MH-Z19 CO2 sensor
I have written a plugin for reading CO2 sensor from SenseAir.
I checked the data sheet for the sensor you mentioned but they don't have the same protocol, but very similar.
Take a look in ESPPlayground, maybe there should only be one plugin with support for different brands and models?
I checked the data sheet for the sensor you mentioned but they don't have the same protocol, but very similar.
Take a look in ESPPlayground, maybe there should only be one plugin with support for different brands and models?
Re: MH-Z14 / MH-Z19 CO2 sensor
Interesting info, I was wondering about the SenseAir S8 a bit because it seems to have a form factor and pinout identical to the MH-Z19. The S8 is a more expensive though (like E75,- for the S8 vs E25,- for the MH-Z19).
I now guess this is because they developed a more advanced firmware inside the sensor, which for example does things like automatic background calibration algorithm.
This may also explain why the communication protocol is different (e.g. using CRC instead of a simple checksum).
Personally, I would consider it like a different kind of sensor because of this.
I see you use software serial in your driver.
This makes it a lot more flexible than my proposal for using Serial.swap() with respect to which pins can be used.
I just have a bit of mistrust in software serial, but at low data rates it may not make any difference.
I now guess this is because they developed a more advanced firmware inside the sensor, which for example does things like automatic background calibration algorithm.
This may also explain why the communication protocol is different (e.g. using CRC instead of a simple checksum).
Personally, I would consider it like a different kind of sensor because of this.
I see you use software serial in your driver.
This makes it a lot more flexible than my proposal for using Serial.swap() with respect to which pins can be used.
I just have a bit of mistrust in software serial, but at low data rates it may not make any difference.
Re: MH-Z14 / MH-Z19 CO2 sensor
Yes, it's probably best to keep these as separate plugins. My intention is to continue to develop the SenseAir plugin to more data of the S8-sensor and also support more variants of sensors from SenseAir.
Myself and colleagues have run the SenseAir plugin for several weeks and I have not had any problem and have not heard of problems so SoftSerial seams to be okay for this application.
Myself and colleagues have run the SenseAir plugin for several weeks and I have not had any problem and have not heard of problems so SoftSerial seams to be okay for this application.
Re: MH-Z14 / MH-Z19 CO2 sensor
Cool! I'm keen to build a device to monitor CO2 around the house
. I'm following this topic!

Re: MH-Z14 / MH-Z19 CO2 sensor
My MH-Z19 arrived yesterday. I notice that it reacts very quickly (usually within 10 ms) to a command, but that the measurement data is only updated every 5 seconds (you can also see a glowing light inside the sensor every 5 seconds). I also saw that it seems to output more than just temperature and co2 level: one of the returned bytes always has just one bit set. Could this be some kind of sensor status register? Two of the other returned bytes appear to be some other number. Just after power-up, it always outputs a value of 400 ppm, then jumps around and takes a few minutes to stabilize to the final value. During this time the mystery number is 15000 decimal, which seems to stabilize to a value of about 10606 after some time, I wonder about the meaning of this number, perhaps an estimate of air pressure?
The code I'm using to play with the sensor is at https://github.com/bertrik/mhz19
The code I'm using to play with the sensor is at https://github.com/bertrik/mhz19
Re: MH-Z14 / MH-Z19 CO2 sensor
Hello,
Interesting, can anybody maybe help to make this work with the following 2 sensors on a ESP12E working with ESPEasy?
• MQ-2 MQ2 Smoke Gas LPG Butane Hydrogen Gas Sensor
• MQ-7 Carbon Monoxide CO Gas Alarm Sensor
Thanks for your time
Interesting, can anybody maybe help to make this work with the following 2 sensors on a ESP12E working with ESPEasy?
• MQ-2 MQ2 Smoke Gas LPG Butane Hydrogen Gas Sensor
• MQ-7 Carbon Monoxide CO Gas Alarm Sensor
Thanks for your time
Re: MH-Z14 / MH-Z19 CO2 sensor
Replying to myself again:
My brother e-mailed the manufacturer. Apparently you can change the 0-2000ppm variant of the MH-Z19 into a 0-5000ppm variant (and vice versa)
You can find the command to change the measurement range at: https://revspace.nl/MHZ19#command_0x99_.28range.29
I tried various other command codes and several of them seem to return data or have some kind of effect. I'd like to find the setting for the alarm output, but I'm a bit afraid of accidentally destroying calibration data or something like that.
My brother e-mailed the manufacturer. Apparently you can change the 0-2000ppm variant of the MH-Z19 into a 0-5000ppm variant (and vice versa)
You can find the command to change the measurement range at: https://revspace.nl/MHZ19#command_0x99_.28range.29
I tried various other command codes and several of them seem to return data or have some kind of effect. I'd like to find the setting for the alarm output, but I'm a bit afraid of accidentally destroying calibration data or something like that.
Re: MH-Z14 / MH-Z19 CO2 sensor
I just ordered one as I need to measure CO2 for my Hydroponic greenhouse 

Re: MH-Z14 / MH-Z19 CO2 sensor
hi guys,
feedback, just built the co2 sensor with mhz19. so far (2 days) working fine with the code from playground. I set the power to 3.6V and power both the sensor and esp from one supply. thanks a lot to the developers.
feedback, just built the co2 sensor with mhz19. so far (2 days) working fine with the code from playground. I set the power to 3.6V and power both the sensor and esp from one supply. thanks a lot to the developers.
- ThinkPadNL
- New user
- Posts: 7
- Joined: 18 Jan 2017, 08:00
Re: MH-Z14 / MH-Z19 CO2 sensor
A few days ago i received a MH-Z19. Unfortunately, i cannot get it working with the plugin.
I know the sensor is fine, because with this code it works great.
In both code i have the wires connected to the same pins (D3 and D6). I tested under ESPEasy if these were assigned to the correct GPIOs and it was (connected my multimeter to these pins and made them high/low in ESPEasy and my multimeter showed accordingly). So i am 100% confident that i have the MH-Z19 connected to the correct GPIO's that i defined in when selecting the sensor under 'Devices'.
Does anyone know how to get it working?
I know the sensor is fine, because with this code it works great.
In both code i have the wires connected to the same pins (D3 and D6). I tested under ESPEasy if these were assigned to the correct GPIOs and it was (connected my multimeter to these pins and made them high/low in ESPEasy and my multimeter showed accordingly). So i am 100% confident that i have the MH-Z19 connected to the correct GPIO's that i defined in when selecting the sensor under 'Devices'.
Does anyone know how to get it working?
Re: MH-Z14 / MH-Z19 CO2 sensor
I received mine last week and made it work without problems.ThinkPadNL wrote:A few days ago i received a MH-Z19. Unfortunately, i cannot get it working with the plugin.
I know the sensor is fine, because with this code it works great.
In both code i have the wires connected to the same pins (D3 and D6). I tested under ESPEasy if these were assigned to the correct GPIOs and it was (connected my multimeter to these pins and made them high/low in ESPEasy and my multimeter showed accordingly). So i am 100% confident that i have the MH-Z19 connected to the correct GPIO's that i defined in when selecting the sensor under 'Devices'.
Does anyone know how to get it working?
I'm using for communication D5 and D6

DIY CO2 monitor with ESP Easy at https://emariete.com/medidor-casero-co2/
ESP Easy related info at my blog: https://emariete.com/tag/espeasy/
ESP Easy related info at my blog: https://emariete.com/tag/espeasy/
Re: MH-Z14 / MH-Z19 CO2 sensor
Mariete wrote:I received mine last week and made it work without problems.ThinkPadNL wrote:A few days ago i received a MH-Z19. Unfortunately, i cannot get it working with the plugin.
I know the sensor is fine, because with this code it works great.
In both code i have the wires connected to the same pins (D3 and D6). I tested under ESPEasy if these were assigned to the correct GPIOs and it was (connected my multimeter to these pins and made them high/low in ESPEasy and my multimeter showed accordingly). So i am 100% confident that i have the MH-Z19 connected to the correct GPIO's that i defined in when selecting the sensor under 'Devices'.
Does anyone know how to get it working?
I'm using for communication D5 and D6
Thanks! Received mine on Saturday and it took me a steep dive in downloading the Arduino IDE, plugins, libraries, compiling sketches, but failed to get it to work. Your screenshot was the missing link

PS. TX on sensor to D5 on Wemos, RX on sensor to D6 on Wemos. Got CRC error the other way around.
PPS. Selecting air quality sensor as virtual sensor did not work for me, had to select custom sensor. Otherwise value remained 0 PPM in Domoticz
- ThinkPadNL
- New user
- Posts: 7
- Joined: 18 Jan 2017, 08:00
Re: MH-Z14 / MH-Z19 CO2 sensor
Thanks for responding with the screenshot.
I will try again with Wemos D1 Mini when i have received that one. The sensor is now connected to a NodeMCU.
I will try again with Wemos D1 Mini when i have received that one. The sensor is now connected to a NodeMCU.
- ThinkPadNL
- New user
- Posts: 7
- Joined: 18 Jan 2017, 08:00
Re: MH-Z14 / MH-Z19 CO2 sensor
So today i have received a Wemos D1 Mini.
I downloaded the latest ESPEasy from here (download the repo as .zip), extracted it and added the _P149_MHZ19.ino to the other .ino files.
Then opened ESPEasy.ino from the Arduino IDE, which also loaded the other .ino files in the tabs. Compiled it for Wemos D1 Mini and flashed it.
Then configured the device:

But the ppm stays zero all the time:

I don't know what i am doing wrong. The MH-Z19 is working fine with a different sketch.
Pin 'Tx' from CO2 is connected to 'D5' on Wemos
Pin 'Rx' from CO2 is connected to 'D6' on Wemos
Pin 'Vin' from CO2 is connected to '5V' on Wemos
Pin 'GND' from CO2 is connected to 'G' on Wemos
Why doesn't it work?
I downloaded the latest ESPEasy from here (download the repo as .zip), extracted it and added the _P149_MHZ19.ino to the other .ino files.
Then opened ESPEasy.ino from the Arduino IDE, which also loaded the other .ino files in the tabs. Compiled it for Wemos D1 Mini and flashed it.
Then configured the device:

But the ppm stays zero all the time:

I don't know what i am doing wrong. The MH-Z19 is working fine with a different sketch.
Pin 'Tx' from CO2 is connected to 'D5' on Wemos
Pin 'Rx' from CO2 is connected to 'D6' on Wemos
Pin 'Vin' from CO2 is connected to '5V' on Wemos
Pin 'GND' from CO2 is connected to 'G' on Wemos
Why doesn't it work?
Re: MH-Z14 / MH-Z19 CO2 sensor
The sketch you linke (which seems to work) uses D1 and D2, did you try those 2 pins?
Another thought is that maybe TX and RX are swapped, did you try to swap either the wires or the PIN configuration in ESPEasy?
Another thought is that maybe TX and RX are swapped, did you try to swap either the wires or the PIN configuration in ESPEasy?
My TINDIE Store where you can find all ESP8266 boards I manufacture --> https://www.tindie.com/stores/GiovanniCas/
My Wiki Project page with self-made PCB/devices --> https://www.letscontrolit.com/wiki/inde ... :Papperone
My Wiki Project page with self-made PCB/devices --> https://www.letscontrolit.com/wiki/inde ... :Papperone
- ThinkPadNL
- New user
- Posts: 7
- Joined: 18 Jan 2017, 08:00
Re: MH-Z14 / MH-Z19 CO2 sensor
Thanks for your reaction. I also tried pins D1 and D2 (after disabling SDA/SCL on them in the 'Hardware' tab) but that didn't make any difference.
I also tried reversing RX/TX for D1/D2 and D5/D6 but still no luck.
I don't use Domoticz, but MQTT (Mosquitto) and configured the Wemos for 'OpenHAB MQTT'. But as the 'Devices' page also stays on 0.00 ppm i think it is something with the readout of the sensor. But what??
Is the method for flashing ESPEasy + this MH-Z19 plugin to the Wemos correct?
Edit: It works! The solution was that i had to fill in a value in the field 'IDX / Var'. But i don't even use Domoticz, only MQTT and had already changed the 'Protocol' on the 'Main' page to 'OpenHAB MQTT'. Not funny, another hour of my life gone that i don't get back
I also tried reversing RX/TX for D1/D2 and D5/D6 but still no luck.
I don't use Domoticz, but MQTT (Mosquitto) and configured the Wemos for 'OpenHAB MQTT'. But as the 'Devices' page also stays on 0.00 ppm i think it is something with the readout of the sensor. But what??
Is the method for flashing ESPEasy + this MH-Z19 plugin to the Wemos correct?
Edit: It works! The solution was that i had to fill in a value in the field 'IDX / Var'. But i don't even use Domoticz, only MQTT and had already changed the 'Protocol' on the 'Main' page to 'OpenHAB MQTT'. Not funny, another hour of my life gone that i don't get back

Code: Select all
mqtt@mqtt-vm:~$ mosquitto_sub -v -t /WemosCO2/# | xargs -d$'\n' -L1 sh -c 'date "+%D %T.%3N $0"'
01/24/17 20:09:55.805 /WemosCO2/CO2/PPM 671.00
01/24/17 20:10:25.834 /WemosCO2/CO2/PPM 669.00
01/24/17 20:10:55.864 /WemosCO2/CO2/PPM 671.00
01/24/17 20:11:25.895 /WemosCO2/CO2/PPM 666.00
01/24/17 20:11:55.925 /WemosCO2/CO2/PPM 662.00
01/24/17 20:12:25.955 /WemosCO2/CO2/PPM 648.00
Re: MH-Z14 / MH-Z19 CO2 sensor
Hello,
Last week my long-awaited C02-sensor arrived, a nice and tiny "golden" box with an Ndir based MH-Z19 0-2000 Ppm inside.
Made me an new esp-easy-version with the required mh-z19 plugin inside, followed the info on the forum and
with some fiddeling i got reasonable PPm values on the internal Easy logging and within Domoticz overhere, me happy..
It was very bad wet and stormy weather here yesterday, so i could not "calibrate" the sensor in outside air
which should be somewhere around 400 Ppm Co2 as i interpreted al the mentioned figures right.
This is where things got a bit wild overhere .. i see many large variations with a 1 minute sample interval
from around 400 up to double values or more, there is almost mo wind, sensor is in free air in my backyard.
is this normal ? could there be that much difference in outside air ?
Anyone has same behaviour seen with this sensor .. ? Or a solution ?
Peter
Last week my long-awaited C02-sensor arrived, a nice and tiny "golden" box with an Ndir based MH-Z19 0-2000 Ppm inside.
Made me an new esp-easy-version with the required mh-z19 plugin inside, followed the info on the forum and
with some fiddeling i got reasonable PPm values on the internal Easy logging and within Domoticz overhere, me happy..
It was very bad wet and stormy weather here yesterday, so i could not "calibrate" the sensor in outside air
which should be somewhere around 400 Ppm Co2 as i interpreted al the mentioned figures right.
This is where things got a bit wild overhere .. i see many large variations with a 1 minute sample interval
from around 400 up to double values or more, there is almost mo wind, sensor is in free air in my backyard.
is this normal ? could there be that much difference in outside air ?
Anyone has same behaviour seen with this sensor .. ? Or a solution ?
Peter
- ThinkPadNL
- New user
- Posts: 7
- Joined: 18 Jan 2017, 08:00
Re: MH-Z14 / MH-Z19 CO2 sensor
Have a look here: https://gathering.tweakers.net/forum/li ... 5#50345695
It seems the module is very sensitive to infrared light, so you should cover it from direct sunlight.
Also airflow is something that can influent the readings badly.
It seems the module is very sensitive to infrared light, so you should cover it from direct sunlight.
Also airflow is something that can influent the readings badly.
Re: MH-Z14 / MH-Z19 CO2 sensor
Yes,ThinkPadNL wrote:Have a look here: https://gathering.tweakers.net/forum/li ... 5#50345695
It seems the module is very sensitive to infrared light, so you should cover it from direct sunlight.
Also airflow is something that can influent the readings badly.
That is exactly what was happening, it was on the table in full sunlight, i did spend some time with a modified cardboard box
with a kind of labyrinth which will let air flow through but almost no light and it was much more stable then ..
Even with the box inside the house it is quite sensible, but not as wild as it was in the direct sunlight , thanks ..
Peter
Re: MH-Z14 / MH-Z19 CO2 sensor
maybe a tip what could help as I never had issues with light
I ordered one of these cheap smoke detectors off ebay, removed the crap and installed the ESP and MHZ19 into it.. working fine.
http://www.ebay.com/itm/Fire-Smoke-Sens ... pFsJv_PcRA
I ordered one of these cheap smoke detectors off ebay, removed the crap and installed the ESP and MHZ19 into it.. working fine.
http://www.ebay.com/itm/Fire-Smoke-Sens ... pFsJv_PcRA
Re: MH-Z14 / MH-Z19 CO2 sensor
I have set up an ESP unit with several sensors, of which one is a Senseair S8. Works great, but when I try to link it to an "Air quality" device in Domoticz, it does not feed any values. In Domoticz it stays on zero.tedenda wrote: ↑03 Aug 2016, 00:51 Yes, it's probably best to keep these as separate plugins. My intention is to continue to develop the SenseAir plugin to more data of the S8-sensor and also support more variants of sensors from SenseAir.
Myself and colleagues have run the SenseAir plugin for several weeks and I have not had any problem and have not heard of problems so SoftSerial seams to be okay for this application.
I then defined a "user-defined" device, and linked the S8 to that idx. Values come in just great.
As a workaround I now use a script that copies those values from the user-defined into the air quality, but that is a workaround not really a solution to the problem.
Where should I report this bug for plugin P052?
Re: MH-Z14 / MH-Z19 CO2 sensor
It's not a bug, at least not in ESPEasy. Domoticz doesn't provide a standard device for this purpose...manjh wrote: ↑17 Aug 2017, 06:37 I have set up an ESP unit with several sensors, of which one is a Senseair S8. Works great, but when I try to link it to an "Air quality" device in Domoticz, it does not feed any values. In Domoticz it stays on zero.
I then defined a "userdefined" device, and linked the S8 to that idx. Values come in just great.
As a workaround I now use a script that copies those values from the user-defined into the air quality, but that is a workaround not really a solution to the problem.
Where should I report this bug for plugin P052?
Re: MH-Z14 / MH-Z19 CO2 sensor
Hello, maybe nobody will kill me for asking this here.
Anyone tried to get the MHZ19B working as standalone INO file wihout ESPEasy?
I'm experiencing zero responses from MHZ19B after certain period of time (cca 45-60minutes). The only solution is to power cycle the ESP8266 together with MHZ19B. Simple reset of ESP8266 does not help
With ESPEasy (using same hardware, just different program) the sensor is working fine forever, so I must be missing something in the code.
Could anybody help me with this, please? I would like to ise the ESPEasy code from Dmitry to read MHZ19B without using ESPEasy. The reason is that I need HTTPS support and I'm using custom 433MHz signal decoding from my meteo station, which is hard to implement for me (and no reason to do it) into ESPEasy.
If someone could do me a favor and waste some time to help me, I will paste my short code (and wiring and details) here or anywhere else. Please let me know.
Thanks
Anyone tried to get the MHZ19B working as standalone INO file wihout ESPEasy?
I'm experiencing zero responses from MHZ19B after certain period of time (cca 45-60minutes). The only solution is to power cycle the ESP8266 together with MHZ19B. Simple reset of ESP8266 does not help
With ESPEasy (using same hardware, just different program) the sensor is working fine forever, so I must be missing something in the code.
Could anybody help me with this, please? I would like to ise the ESPEasy code from Dmitry to read MHZ19B without using ESPEasy. The reason is that I need HTTPS support and I'm using custom 433MHz signal decoding from my meteo station, which is hard to implement for me (and no reason to do it) into ESPEasy.
If someone could do me a favor and waste some time to help me, I will paste my short code (and wiring and details) here or anywhere else. Please let me know.
Thanks
Re: MH-Z14 / MH-Z19 CO2 sensor
You better have a look at the way the bytes are parsed from the serial port.
That seems rather elaborate, but the key is that you sometimes loose sync and have to find the right 'sync' again by throwing away some bytes and check the checksum.
That seems rather elaborate, but the key is that you sometimes loose sync and have to find the right 'sync' again by throwing away some bytes and check the checksum.
Re: MH-Z14 / MH-Z19 CO2 sensor
So that's the shift about in espeasy sources? I will take espeasy sources and try to adapt it so it can be used in standalone program. I don't want to soil this thread with out of topic things but I'm quite helpless 
God help me haha
thanks!
EDIT: got it, sorry for going off topic. Since I already have this comment here, I'll paste the function with shifting. thanks!
// mhz19uart is softwareserial
God help me haha
EDIT: got it, sorry for going off topic. Since I already have this comment here, I'll paste the function with shifting. thanks!
// mhz19uart is softwareserial
Code: Select all
int readCO2() {
byte command[9] = {0xFF,0x01,0x86,0x00,0x00,0x00,0x00,0x00,0x79};
byte uartReturn[9];
mhz19uart.write(command, 9); //request co2value CO2
while (mhz19uart.available() && (unsigned char)mhz19uart.peek() != 0xFF) { // read byte after byte until we get the beginning 0xFF
mhz19uart.read();
shifts++; // count the shifts so we can see how much it happens
}
memset(uartReturn, 0, 9); // pre-fill uartReturn array with zeroes
mhz19uart.readBytes(uartReturn, 9); // read the response from serial
if (uartReturn[8] == checksum(uartReturn) && uartReturn[1] == 0x86) { // if CRC is correct and second byte contains command sent previously
int co2value = (int)uartReturn[2]*256+(int)uartReturn[3]; // calculate ppm value from high and low bytes
return co2value;
} else {
return -1; // return error - crc or wrong data returned
}
}
Re: MH-Z14 / MH-Z19 CO2 sensor
i am measering always 5000 ppm, temperature values are ok.
What is the problem?
What is the problem?
Re: MH-Z14 / MH-Z19 CO2 sensor
@Barb232 Paste the code
Re: MH-Z14 / MH-Z19 CO2 sensor
The sensor outputs always the max range value when it boots.
So if you're getting this value over and over again, the sensor is rebooting over and over again.
Try to improve the power supply to the sensor and use it on 5V, not 3V3.
So if you're getting this value over and over again, the sensor is rebooting over and over again.
Try to improve the power supply to the sensor and use it on 5V, not 3V3.
Re: MH-Z14 / MH-Z19 CO2 sensor
// same problem with espeasy software !!!!
// always 5000 ppm
#include <stdio.h>
#include "Arduino.h"
#include "mhz19.h"
#include "SoftwareSerial.h"
#include <ESP8266WiFi.h>
#include <WiFiManager.h>
#include <PubSubClient.h>
#define PIN_RX D3
#define PIN_TX D4
#define MQTT_HOST "192.168.178.67"
#define MQTT_PORT 1883
#define MQTT_TOPIC "/fhem/sensors/co2/mhz19"
#define MQTT_TOPIC2 "/fhem/sensors/co2/temp"
SoftwareSerial sensor(PIN_RX, PIN_TX);
WiFiManager wifiManager;
WiFiClient wifiClient;
PubSubClient mqttClient(wifiClient);
static char esp_id[16];
static bool exchange_command(uint8_t cmd, uint8_t data[], int timeout)
{
// create command buffer
uint8_t buf[9];
int len = prepare_tx(cmd, data, buf, sizeof(buf));
// send the command
sensor.write(buf, len);
// wait for response
long start = millis();
while ((millis() - start) < timeout) {
if (sensor.available() > 0) {
uint8_t b = sensor.read();
if (process_rx(b, cmd, data)) {
return true;
}
}
}
return false;
}
static bool read_temp_co2(int *co2, int *temp)
{
uint8_t data[] = {0, 0, 0, 0, 0, 0};
bool result = exchange_command(0x86, data, 3000);
if (result) {
*co2 = (data[0] << 8) + data[1];
*temp = data[2] - 40;
#if 1
char raw[32];
sprintf(raw, "RAW: %02X %02X %02X %02X %02X %02X", data[0], data[1], data[2], data[3], data[4], data[5]);
Serial.println(raw);
#endif
}
return result;
}
static void mqtt_send(const char *topic, int value, const char *unit)
{
if (!mqttClient.connected()) {
mqttClient.setServer(MQTT_HOST, MQTT_PORT);
mqttClient.connect(esp_id);
}
if (mqttClient.connected()) {
char string[64];
snprintf(string, sizeof(string), "%d %s", value, unit);
Serial.print("Publishing ");
Serial.print(string);
Serial.print(" to ");
Serial.print(topic);
Serial.print("...");
int result = mqttClient.publish(topic, string, true);
Serial.println(result ? "OK" : "FAIL");
}
}
void setup()
{
Serial.begin(115200);
Serial.println("MHZ19 ESP reader\n");
sprintf(esp_id, "%08X", ESP.getChipId());
Serial.print("ESP ID: ");
Serial.println(esp_id);
sensor.begin(9600);
Serial.println("Starting WIFI manager ...");
wifiManager.autoConnect("ESP-MHZ19");
}
void loop()
{
int co2, temp;
if (read_temp_co2(&co2, &temp)) {
Serial.print("CO2:");
Serial.println(co2, DEC);
Serial.print("TEMP:");
Serial.println(temp, DEC);
mqtt_send(MQTT_TOPIC, co2, "");
mqtt_send(MQTT_TOPIC2, temp, "");
}
delay(5000);
}
// always 5000 ppm
#include <stdio.h>
#include "Arduino.h"
#include "mhz19.h"
#include "SoftwareSerial.h"
#include <ESP8266WiFi.h>
#include <WiFiManager.h>
#include <PubSubClient.h>
#define PIN_RX D3
#define PIN_TX D4
#define MQTT_HOST "192.168.178.67"
#define MQTT_PORT 1883
#define MQTT_TOPIC "/fhem/sensors/co2/mhz19"
#define MQTT_TOPIC2 "/fhem/sensors/co2/temp"
SoftwareSerial sensor(PIN_RX, PIN_TX);
WiFiManager wifiManager;
WiFiClient wifiClient;
PubSubClient mqttClient(wifiClient);
static char esp_id[16];
static bool exchange_command(uint8_t cmd, uint8_t data[], int timeout)
{
// create command buffer
uint8_t buf[9];
int len = prepare_tx(cmd, data, buf, sizeof(buf));
// send the command
sensor.write(buf, len);
// wait for response
long start = millis();
while ((millis() - start) < timeout) {
if (sensor.available() > 0) {
uint8_t b = sensor.read();
if (process_rx(b, cmd, data)) {
return true;
}
}
}
return false;
}
static bool read_temp_co2(int *co2, int *temp)
{
uint8_t data[] = {0, 0, 0, 0, 0, 0};
bool result = exchange_command(0x86, data, 3000);
if (result) {
*co2 = (data[0] << 8) + data[1];
*temp = data[2] - 40;
#if 1
char raw[32];
sprintf(raw, "RAW: %02X %02X %02X %02X %02X %02X", data[0], data[1], data[2], data[3], data[4], data[5]);
Serial.println(raw);
#endif
}
return result;
}
static void mqtt_send(const char *topic, int value, const char *unit)
{
if (!mqttClient.connected()) {
mqttClient.setServer(MQTT_HOST, MQTT_PORT);
mqttClient.connect(esp_id);
}
if (mqttClient.connected()) {
char string[64];
snprintf(string, sizeof(string), "%d %s", value, unit);
Serial.print("Publishing ");
Serial.print(string);
Serial.print(" to ");
Serial.print(topic);
Serial.print("...");
int result = mqttClient.publish(topic, string, true);
Serial.println(result ? "OK" : "FAIL");
}
}
void setup()
{
Serial.begin(115200);
Serial.println("MHZ19 ESP reader\n");
sprintf(esp_id, "%08X", ESP.getChipId());
Serial.print("ESP ID: ");
Serial.println(esp_id);
sensor.begin(9600);
Serial.println("Starting WIFI manager ...");
wifiManager.autoConnect("ESP-MHZ19");
}
void loop()
{
int co2, temp;
if (read_temp_co2(&co2, &temp)) {
Serial.print("CO2:");
Serial.println(co2, DEC);
Serial.print("TEMP:");
Serial.println(temp, DEC);
mqtt_send(MQTT_TOPIC, co2, "");
mqtt_send(MQTT_TOPIC2, temp, "");
}
delay(5000);
}
Re: MH-Z14 / MH-Z19 CO2 sensor
I am using 5V (external USB plug).
it boots with 410 and after a few measurements it runs into 5000
i am putting a case over it to prevent sunlight
it boots with 410 and after a few measurements it runs into 5000
i am putting a case over it to prevent sunlight
Re: MH-Z14 / MH-Z19 CO2 sensor
other question: is the espeasy with this sensor now ok? I read in the documentation, that there are memory problems and i should use custom espeasy firmware.
Re: MH-Z14 / MH-Z19 CO2 sensor
Where is that warning?
ESPeasy is running just fine with the MH-Z19 sensor for almost half a year now.
Maybe you should add some capacitor to the power pins of the sensor. It may take up to 200 mA peak. The ESP module itself may also require quite some peak.
And some cheap USB chargers don't really output what is being written on the case.
Also the USB cable itself may cause quite some voltage drop during peak currents.
Like I said, it only outputs the max. value during startup of the sensor.
Re: MH-Z14 / MH-Z19 CO2 sensor
TD-er wrote: ↑28 Mar 2018, 19:45Where is that warning?
ESPeasy is running just fine with the MH-Z19 sensor for almost half a year now.
here:
https://www.letscontrolit.com/wiki/inde ... _MH-Z19%22
Re: MH-Z14 / MH-Z19 CO2 sensor
ESPEasy works fine even with the MH-Z19B version of the sensor, no problem here.
I'd say this:
- don't enable wifi, just test the sensor with a simple sketch without wifi (wifi won't consume power so powering the sensor will be more stable)
- calibrate the sensor (leave it outdoors for 30 minutes and upload the sketch which does zero point calibration in setup() once or twice
- if above does not help, have a look at the cabling and power requirements
apart from your problem, I see two things in your code:
1. is the shift I had problem with lately. sometimes you won't get the 0xFF as the first bit after sending command and you have to wait for it (look at my function few comments above). You are also not checking for the checksum, try to implement it. 1st byte of the answer should be 0xFF, 2nd is 0x86 and the checksum is the 9th byte. This way you will get only valid responses
2. is the delay(5000), I would do it using millis() instead just like you have it in the static bool exchange_command() function
I'd say this:
- don't enable wifi, just test the sensor with a simple sketch without wifi (wifi won't consume power so powering the sensor will be more stable)
- calibrate the sensor (leave it outdoors for 30 minutes and upload the sketch which does zero point calibration in setup() once or twice
- if above does not help, have a look at the cabling and power requirements
apart from your problem, I see two things in your code:
1. is the shift I had problem with lately. sometimes you won't get the 0xFF as the first bit after sending command and you have to wait for it (look at my function few comments above). You are also not checking for the checksum, try to implement it. 1st byte of the answer should be 0xFF, 2nd is 0x86 and the checksum is the 9th byte. This way you will get only valid responses
2. is the delay(5000), I would do it using millis() instead just like you have it in the static bool exchange_command() function
Re: MH-Z14 / MH-Z19 CO2 sensor
ok, thank you. i will try that.
Re: MH-Z14 / MH-Z19 CO2 sensor
also try reading via PWM to see if the sensor has bad values, this code is working for me, just change the PWM pin.
Code: Select all
int pwm_pin=D8; // put the input pin here
int prevupdate=0;
int updateseconds=5;
int pwmvalue=0;
unsigned long tmptime=0;
int calibrateafter=300; //minutes
boolean timerExpired(unsigned long whenms){
if(abs(millis()-whenms)>0) { return true; }else{ return false; }
}
int read_pwm_value() {
int th = 0;
int range=5000;
double ppm = 0;
do {
th = pulseIn(pwm_pin , HIGH, 1004000) / 1000;
ppm = range / 1000 * (th - 2);
} while (th == 0);
return (int) ppm;
}
void setup() {
Serial.begin(115200);
pinMode(pwm_pin,INPUT);
Serial.println("Starting...");
}
void loop() {
// put your main code here, to run repeatedly:
if((abs(millis()-prevupdate)) > updateseconds*1000){
Serial.print("reading PWM value... ");
tmptime=millis();
pwmvalue=read_pwm_value();
Serial.println(String(pwmvalue)+" and reading took "+String(millis()-tmptime)+"ms");
prevupdate=millis();
}
}
Re: MH-Z14 / MH-Z19 CO2 sensor
same problem with pwm
Code: Select all
395 and reading took 15795ms
reading PWM value... 405 and reading took 14056ms
reading PWM value... 405 and reading took 13051ms
reading PWM value... 405 and reading took 12048ms
reading PWM value... 2525 and reading took 1932ms
reading PWM value... 4990 and reading took 12047ms
reading PWM value... 4990 and reading took 12048ms
reading PWM value... 4990 and reading took 13051ms
reading PWM value... 4990 and reading took 12047ms
Re: MH-Z14 / MH-Z19 CO2 sensor
snip
- calibrate the sensor (leave it outdoors for 30 minutes and upload the sketch which does zero point calibration in setup() once or twice
snip
where can i find this sketch?
- calibrate the sensor (leave it outdoors for 30 minutes and upload the sketch which does zero point calibration in setup() once or twice
snip
where can i find this sketch?
- grovkillen
- Core team member
- Posts: 3621
- Joined: 19 Jan 2017, 12:56
- Location: Hudiksvall, Sweden
- Contact:
Re: MH-Z14 / MH-Z19 CO2 sensor
I removed the warning on the wiki... haven't looked into that until you noticed it.
ESP Easy Flasher [flash tool and wifi setup at flash time]
ESP Easy Webdumper [easy screendumping of your units]
ESP Easy Netscan [find units]
Official shop: https://firstbyte.shop/
Sponsor ESP Easy, we need you

ESP Easy Webdumper [easy screendumping of your units]
ESP Easy Netscan [find units]
Official shop: https://firstbyte.shop/
Sponsor ESP Easy, we need you



Re: MH-Z14 / MH-Z19 CO2 sensor
yeah so try calibrating it then.
you can use my test sketch which I put together from various sources around github. Disables ABC and performs calibration after 30 minutes, then it starts reading from serial.
Not sure if you should disable ABC at every start of your program or it remains disabled forever or until you enable it again. can somebody answer?
you can use my test sketch which I put together from various sources around github. Disables ABC and performs calibration after 30 minutes, then it starts reading from serial.
Not sure if you should disable ABC at every start of your program or it remains disabled forever or until you enable it again. can somebody answer?
Code: Select all
#include <SoftwareSerial.h>
#include <SPI.h>
#include <Wire.h>
#define INTERVAL 5000
#define MH_Z19_RX D5 //RX
#define MH_Z19_TX D7 //TX
byte mhzResp[9]; // 9 bytes bytes response
byte mhzCmdReadPPM[9] = {0xFF,0x01,0x86,0x00,0x00,0x00,0x00,0x00,0x79};
byte mhzCmdCalibrateZero[9] = {0xFF,0x01,0x87,0x00,0x00,0x00,0x00,0x00,0x78};
byte mhzCmdABCEnable[9] = {0xFF,0x01,0x79,0xA0,0x00,0x00,0x00,0x00,0xE6};
byte mhzCmdABCDisable[9] = {0xFF,0x01,0x79,0x00,0x00,0x00,0x00,0x00,0x86};
byte mhzCmdReset[9] = {0xFF,0x01,0x8d,0x00,0x00,0x00,0x00,0x00,0x72};
byte mhzCmdMeasurementRange1000[9] = {0xFF,0x01,0x99,0x00,0x00,0x00,0x03,0xE8,0x7B};
byte mhzCmdMeasurementRange2000[9] = {0xFF,0x01,0x99,0x00,0x00,0x00,0x07,0xD0,0x8F};
byte mhzCmdMeasurementRange3000[9] = {0xFF,0x01,0x99,0x00,0x00,0x00,0x0B,0xB8,0xA3};
byte mhzCmdMeasurementRange5000[9] = {0xFF,0x01,0x99,0x00,0x00,0x00,0x13,0x88,0xCB};
int shifts=0,co2ppm;
long previousMillis = 0;
SoftwareSerial co2Serial(MH_Z19_RX, MH_Z19_TX); // define MH-Z19
byte checksum(byte response[9]){
byte crc = 0;
for (int i = 1; i < 8; i++) {
crc += response[i];
}
crc = 255 - crc + 1;
return crc;
}
void disableABC() {
co2Serial.write(mhzCmdABCDisable, 9);
}
void enableABC() {
co2Serial.write(mhzCmdABCEnable, 9);
}
void setRange5000() {
co2Serial.write(mhzCmdMeasurementRange5000, 9);
}
void calibrateZero(){
co2Serial.write(mhzCmdCalibrateZero, 9);
}
int readCO2() {
byte cmd[9] = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79};
byte response[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();
shifts++;
}
memset(response, 0, 9);
co2Serial.readBytes(response, 9);
for (int i=0; i<9; i++) {
Serial.print(" 0x");
Serial.print(response[i], HEX);
}
Serial.println(" Response OK. Shifts="+String(shifts));
if (response[1] != 0x86)
{
Serial.println(" Invalid response from co2 sensor!");
return -1;
}
if (response[8] == checksum(response)) {
int responseHigh = (int) response[2];
int responseLow = (int) response[3];
int ppm = (256 * responseHigh) + responseLow;
return ppm;
} else {
Serial.println("CRC error!");
return -1;
}
}
void setup() {
Serial.begin(115200);
unsigned long previousMillis = millis();
co2Serial.begin(9600); //Init sensor MH-Z19(14)
delay(500);
disableABC();
//setRange5000();
delay(1800000);
calibrateZero();
Serial.println("Zero was calibrated");
}
void loop() {
unsigned long currentMillis = millis();
if (abs(currentMillis - previousMillis) > INTERVAL)
{
previousMillis = currentMillis;
Serial.print("Requesting CO2 concentration...");
co2ppm=-999;
co2ppm = readCO2();
Serial.println(" PPM = " + String(co2ppm));
//if(calibrated) { Serial.println("Zero was calibrated."); }
}
}
Re: MH-Z14 / MH-Z19 CO2 sensor
i will do this tomorrow, thank you
Re: MH-Z14 / MH-Z19 CO2 sensor
Just be very careful with the calibration commands.
The 400ppm calibration should be done in the same environment (temp/humidity) as the room it is being operated in.
And make sure you do not run it more than once per minute or so.
I've ruined one of my sensors by running it too fast in succession and that sensor is totally useless now since the 0 ppm level is now above 400 ppm.
Just have a thorough look at the code of the plugin of ESPeasy, or the same code, but more compact, in Tasmota.
The 400ppm calibration should be done in the same environment (temp/humidity) as the room it is being operated in.
And make sure you do not run it more than once per minute or so.
I've ruined one of my sensors by running it too fast in succession and that sensor is totally useless now since the 0 ppm level is now above 400 ppm.
Just have a thorough look at the code of the plugin of ESPeasy, or the same code, but more compact, in Tasmota.
Re: MH-Z14 / MH-Z19 CO2 sensor
the manufacturer says the sensor should be calibrated by calling calibration at least 20 minutes after operating the sensor in outdoor air, as far as I understood. why to calibrate it indoors?
Re: MH-Z14 / MH-Z19 CO2 sensor
The thing is that (at least here in Holland) the air outside is much colder and therefore higher relative humidity.
What they mean is that you should perform calibration in about 400 ppm CO2 concentration.
That's outside, when you're not among lots of people or in the city.
When you need to do recalibration, it is probably because the sensor did not experience well ventilated air in the last few days and then it is quite useless to do the calibration in the same room.
But you have to take into account the temperature and humidity and make sure no IR light enters the sensor (sunlight)
Re: MH-Z14 / MH-Z19 CO2 sensor
That makes sense, thanks
Re: MH-Z14 / MH-Z19 CO2 sensor
Finally, it works.
i downloaded the document
http://www.winsen-sensor.com/d/files/in ... ver1_0.pdf
And i tried the method 8a (manual calibration)
I soldered a button between GND and HD and pressed the button for 7 seconds
waited 20 min with open window
Results: values 395 ppm
Lets wait and see
photo follows
using espeasy
what is the meaning of U?
a few minutes later ...
btw: i want to make a traffic light
red: ?
yellow: ?
green: ?
and how can i do that with a gpio LED rgb? rules
what value-ranges should i use?
/robin
i downloaded the document
http://www.winsen-sensor.com/d/files/in ... ver1_0.pdf
And i tried the method 8a (manual calibration)
I soldered a button between GND and HD and pressed the button for 7 seconds
waited 20 min with open window
Results: values 395 ppm
Lets wait and see
photo follows
using espeasy
Code: Select all
44042105 : MHZ19: PPM value: 395 Temp/S/U values: 21/0/0.00
44042105 : EVENT: co2sensor#PPM=395.00
44042107 : EVENT: co2sensor#Temperature=21.00
44042108 : EVENT: co2sensor#U=0.00
a few minutes later ...
Code: Select all
Log
285758 : EVENT: co2sensor#Temperature=21.00
285759 : EVENT: co2sensor#U=0.00
296021 : MHZ19: PPM value: 588 Temp/S/U values: 21/0/0.00
296022 : EVENT: co2sensor#PPM=588.00
296046 : EVENT: co2sensor#Temperature=21.00
296047 : EVENT: co2sensor#U=0.00
301398 : WD : Uptime 5 ConnectFailures 0 FreeMem 18664
306850 : MHZ19: PPM value: 540 Temp/S/U values: 21/0/0.00
306851 : EVENT: co2sensor#PPM=540.00
306875 : EVENT: co2sensor#Temperature=21.00
306875 : EVENT: co2sensor#U=0.00
316871 : MHZ19: PPM value: 497 Temp/S/U values: 21/0/0.00
316871 : EVENT: co2sensor#PPM=497.00
316895 : EVENT: co2sensor#Temperature=21.00
316896 : EVENT: co2sensor#U=0.00
327697 : MHZ19: PPM value: 459 Temp/S/U values: 21/0/0.00
327698 : EVENT: co2sensor#PPM=459.00
327725 : EVENT: co2sensor#Temperature=21.00
327726 : EVENT: co2sensor#U=0.00
331398 : WD : Uptime 6 ConnectFailures 0 FreeMem 18664
red: ?
yellow: ?
green: ?
and how can i do that with a gpio LED rgb? rules
what value-ranges should i use?
/robin
Re: MH-Z14 / MH-Z19 CO2 sensor
Not able to help you with espeasy since I'm not using it, but you need to keep the window open for half an hour and after that calibrate, otherwise you will calibrate to wrong value
Re: MH-Z14 / MH-Z19 CO2 sensor
yes, i did this
Who is online
Users browsing this forum: Ahrefs [Bot] and 21 guests