My experiences with the MH-Z19 NDIR CO2 sensor
Warning: I just destroyed my MH-Z19 sensor when soldering, I was changing connectors with lead free solder, iron set to 380 C. I had to heat for a little while to remove the old header. Now the sensor only gives a very low value, both on PWM and serial output.
Before destroying the device, I was getting strange values around 900 ppm when I should have been getting around 400 ppm. PWM and serial values were consistent but wrong.
My guess is that the firmware in the device for some reason thought it had a 2000 ppm range instead of 5000. Scaling the 900 ppm by 2000 / 5000 gives 360 ppm. I tried playing with the reserved "SR" pin (thinking it might mean "set range", but with no success.
Maybe I'll open my sensor up to see how it works on the inside. In any case, I'll order another sensor.
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.
I am having similar issues using MH Z19B via PWM. Over long time run it shows normal CO2 ppm and sometimes bounces to double value of ppm ( compared with Testo CO2 meter ) with no changes in program nor restart of the system. I also suspect the sensor to change range with no reason and was also to check pwm ratio measurement procedure ( which is the typical one found on internet but using unsigned long ).
Done a quick check today, and it looks like pulseIn function does not always work fine in my code.
I've replaced the measurement bit, wiring the sensor on pin 2 ( int 0 ) for an Arduino and used the following code :
// I have not displayed the usual setup for pin IO configuration and interruption 0 raising triggering first time.
// Reading of measurement also does require to reset bRu to true for next measurement sequence.
unsigned long prev = 0L;
unsigned long th = 0L;
unsigned long tl = 0L;
bool bHi = false;
bool bLo = false;
bool bRu = true;
void falling();
void rising();
void rising() {
attachInterrupt(0, falling, FALLING);
if (!bRu) return;
if ((bHi==false)&&(bLo==false)) { prev = micros(); bHi = true; bLo = false; }
if ((bHi==false)&&(bLo==true )) { tl = micros()-prev; bRu = false; bHi = false; bLo = false; }
}
void falling() {
attachInterrupt(0, rising, RISING);
if (!bRu) return;
if ((bHi==true )&&(bLo==false)) { th = micros()-prev; prev = micros(); bHi = false; bLo = true;};
}
it has two benefits. First it's no longer a blocking code ( for open loop code, much better timings are obtained like this ) and second it seems the readings are stable and aligned to what I'm using for comparison.
Hope it can help
Are you sure? yes | no
Thanks for the link. Very interesting!
I've not spent any more time on this, but I'll let you know when I have pictures.
Are you sure? yes | no
There seems to be a way of setting the range by a serial command: https://revspace.nl/MHZ19
Do you have photos of the interior of the sensor?
Are you sure? yes | no