MH-Z19B CO2 sensor

To keep a healthy environment at home or at the workplace, one of the important things to control is the carbon dioxide (CO2) level.

It’s measured in ppm (parts per million), indicating how many parts of CO2 there are in one million parts of air. As a reference:

  • Less than 1000 ppm are healthy levels
  • Between 1000 ppm and 2000 ppm, we need to reduce the CO2 levels
  • Levels greater than 2000 ppm are associated with headaches, sleepiness, poor concentration, loss of attention…

To reduce the CO2 level, we need to ventilate the room. It can be manually done (opening the windows) or it can be automated with a ventilation system.

To measure it we need a proper CO2 sensor, and one of the most reliables sensors is the MH-Z19B. It is not cheap for the Aliexpress standards (it costs around 20 EUR), but other cheap sensors announced as “air quality” sensors or “eCO2” sensors are not really measuring the CO2 level (i.e. the MQ135).

I bought this MH-Z19B from Aliexpress and hooked it to an ESP32-WROOM-32 board. This board is going to be also purposed as a temperature and humidity sensor, so I also attached a DHT22 sensor. I bought this DHT22 sensor but it is not an original one, and the measures do not seem very correct, so I ordered again an original AM2302 (=DHT22). The MH-Z19B includes a temperature sensor, but it’s mainly used for calibration and it lacks precision, as it does not report decimals. I’m also using an expansion board to simplify the connections.

The ESP32-WROOM-32 on the expansion board connected to the MH-Z19B (gold) and to the DHT22 (red)
  • The jumper in the expansion board needs to be set to 5V (because both of these sensors need 5V).
  • Connected VCC and GND of both sensors to the expansion board
  • Connected the RX and TX of the MH-Z19B to the TX and RX (GPIO1 and GPIO3) of the ESP
  • Connected GPIO16 to the DAT of the DHT22

Finally, I installed ESPHome to the board with this configuration:

devicename: co2sensor
friendly_name: CO2 sensor

name: ${devicename}
friendly_name: ${friendly_name}
platform: ESP32
board: nodemcu-32s


password: ""

password: ""

ssid: !secret wifi_ssid
password: !secret wifi_password
reboot_timeout: 90s
ssid: ${friendly_name} Hotspot
password: !secret wifi_password


port: 80


- platform: homeassistant
id: homeassistant_time

rx_pin: GPIO3
tx_pin: GPIO1
baud_rate: 9600

- platform: uptime
name: Uptime
- lambda: return x / 60.0;
unit_of_measurement: minutes

- platform: wifi_signal
name: "WiFi signal sensor"
update_interval: 60s

- platform: dht
model: DHT22
pin: GPIO16
id: "dht22_temperature"
name: "DHT22 Temperature"
id: "dht22_humidity"
name: "DHT22 Humidity"
update_interval: 60s

- platform: mhz19
id: "mhz19_co2"
name: "MH-Z19 CO2"
id: "mhz19_temperature"
name: "MH-Z19 Temperature"
update_interval: 60s
automatic_baseline_calibration: false

And It’s working nicely, this is the ESPHome web interface:

Keeping the CO2 levels under control is helping me create a healthier workplace environment and improve performance.