MHZ19

From RevSpace
Revision as of 12:09, 22 October 2016 by Bertrik Sikken (talk | contribs)
Jump to navigation Jump to search
Project MHZ19
Mhz19.jpg
Some research into the MH-Z19 CO2 sensor
Status Initializing
Contact bertrik
Last Update 2016-10-22

Introduction

This page is about the MH-Z19 CO2 sensor and some experiments done with it.

This sensor gives a digital (serial) output of the CO2 concentration in air, in parts-per-million (ppm). It uses the optical measurement principle of measuring CO2, which should be much more accurate than the inexpensive electro-chemical sensors you can find. As far as I know, the optical measurement principle uses a broadband light-source to send some light through an air-sample. The sensor then looks at the relative intensity of the light at two different frequencies. The CO2 gas inside the air absorbs light strongly at very specific wavelengths, allowing a determination of the concentration (ppm) of CO2. This is then compensated for temperature (and pressure?) for increased accuracy. See also wikipedia for this measurement principle. A new measurement is started every 5 seconds, you can actually see a small amount of light coming out of the sensor while it's measuring.

The MH-Z19 is the cheapest optical CO2 sensor I could find on AliExpress, about E22,-.

Hardware and reference data

See the manufacturer MH-Z19 page.

Software

See this github repo for code using this sensor with an ESP8266 board (WeMos D1 mini). It publishes the CO2 concentration to topic "bertrik/co2" on test.mosquitto.org every 5 seconds.

It seems that support for this sensor was recently added to ESPEasy.

Extended commands

Normally, this sensor is read out using a command/response sequence over serial.

It appears that there are some additional command beyond just reading the CO2 concentration, these are mentioned in the MH-Z19B datasheet but not in the MH-Z19 datasheet:

  • some calibration commands, e.g. to let the sensor know when it's breathing pure nitrogen (0 ppm), or some reference gas with a known CO2 concentration (e.g. 400 ppm)
  • command 0x79 (ABC logic on/off), to enable/disable the ABC-algorithm (automatic baseline correction)
  • command 0x99 (sensor detection range setting), to set the measurement range of the sensor in steps of 1000 ppm

Some of these commands appear in the MHZ-19<bold>B</bold> datasheet, but appear to work a little differently for the MH-Z19.

command 0x99 (range)

Unlike what the MH-Z19B datasheet says, you can set the range using the following command (2000 ppm in this case):

0xFF 0x01 0x99 0x00 0x00 0x00 0x07 0xD0 0x8F

The 0x07 0xD0 bytes (index 6 and 7) set the range to 2000 ppm.

command 0x86 response frame

A response to command 0x86 typically looks like this:

HH LL TT SS U1 U2

where

  • HH/LL is the CO2 ppm value
  • TT is the temperature in degrees Celcius, plus 40
  • SS is some kind of status byte, this byte always has only one bit set!
  • U1/U2 is some unknown value, perhaps related to pressure?

Log of response at startup

Below is a log of the sensor response to the 0x86 measurement command while starting up. The first couple of measurement seem to be invalid.

RAW: 00 80 47 01 3A 98
RAW: 07 D0 47 01 3A 98
RAW: 00 05 47 01 3A 98
RAW: 01 2D 47 01 3A 98
RAW: 28 97 47 01 3A 98
RAW: 28 97 47 01 3A 98
RAW: 28 97 47 01 3A 98
RAW: 28 97 47 01 3A 98
RAW: 28 97 47 01 3A 98
RAW: 28 97 47 01 3A 98
RAW: 28 97 47 01 3A 98
RAW: 28 97 47 01 3A 98
RAW: 28 97 47 01 3A 98
RAW: 28 97 47 01 3A 98
RAW: 28 97 47 01 3A 98
RAW: 28 97 47 40 3A 98
RAW: 28 97 47 40 3A 98
RAW: 03 84 47 40 2B 43
RAW: 03 85 47 40 2B 19
RAW: 03 86 47 40 2A F9
RAW: 03 87 47 40 2A E1

The first measurement shows a ppm value of 128, a temperature of 31 degrees C, a "status" byte of 01 and the "unknown" value of 0x3a98 (= 15000). The second measurement shows a high ppm value of 2000 ppm (the max value within the ppm range). The third measurement shows a low ppm value of 5 ppm. The fourth measurement shows a ppm value of 301 ppm. The fifth measurement shows a very high ppm value of 10391. The final measurement shows a realistic indoors ppm value of 0x387 = 903 ppm. The "unknown value" (byte 4/5) typically settles down to 10500 or so.

So, it takes some time before the measurement stabilizes, proposed heuristic for a valid reading:

  • "status byte" has to be 0x40
  • "unknown value" has to be lower than 15000