LamaPLC: MH-Z19 series of NDIR CO₂ sensors

MH-Z19 series of NDIR CO₂ sensors The MH-Z19 sensor is manufactured by Winsen Ltd., China, and uses the non-dispersive infrared (NDIR) principle to detect the presence of CO₂ in the air.

The MH-Z19 series of NDIR CO₂ sensors shares core technology but differs in operational parameters, including power consumption, sampling rate, and calibration cycles.

The MH-Z19C is generally considered the successor to the MH-Z19B, offering improved consistency and lower power usage.

FeatureMH-Z19MH-Z19BMH-Z19CMH-Z19DMH-Z19E
Working Voltage3.6~5.5V DC4.5~5.5V DC5.0±0.1V DC5.0±0.1V DC4.5V~5.5V DC
Average Current< 18mA< 60mA (@5V)< 40mA (@5V)< 40mA (@5V)< 85mA
Detection Range0-2000/5000 ppm0-5000/10000 ppm400-5000 ppm400-5000 ppm0-5000 ppm
Accuracy±(50ppm+5% reading)±(50ppm+3% reading)±(50ppm+5% reading)Not specified in general specs
Response Time (T90)< 60s< 120s< 120s< 120s< 90s
Preheat Time3 min3 min1 min1 min3 min
Sampling PeriodN/A5 seconds1 second1 secondN/A
Analog Output / CommunicationAnalog 0.4-2VAnalog 0.4-2VAnalog, UART/PWM only on some boardAnalog, UART/PWM only on some boardAnalog 0.4-2V

Key Differences and Features

  • MH-Z19B vs. MH-Z19C: The primary practical difference is the C version's faster sampling rate (1s vs. 5s) and lower power consumption, making it more responsive and efficient. The B version has two CO2 gas-receiving windows, while the C version has one.
  • MH-Z19E: This model is described as mid- to low-end, likely a cost-optimized variant with slightly different specifications, though comprehensive direct comparison data are less common than for the B and C models.
  • Common Features: All models use the same NDIR (Non-Dispersive Infrared) principle, feature a gold-plated gas chamber for stability and long life, and include built-in temperature compensation.
  • Output Modes: All listed variants support both UART (TTL-level, 3.3V) and PWM output modes, enabling flexible integration with microcontrollers such as Arduino or Raspberry Pi.

If you'd like to support the development of the site with the price of a coffee — or a few — please do so here.

Here's a handy tip: you can quickly save this page as a PDF by clicking “export to PDF” in the menu on the right side of the screen.

2026/02/14 22:38

The MH-Z19 units can be integrated into the Tasmota system. More details are available here: https://tasmota.github.io/docs/MH-Z19B/

Arduino and MH-Z19C, UART vs. Analog Output

FeatureUART (Digital)Analog (Voltage)
Data FormatDigital packet (exact PPM number)Voltage (0.4V to 2.0V)
PrecisionHigh: No signal loss or interferenceLower: Susceptible to “noise” and voltage drops
CalibrationAccessible via software commandsRequires manual hardware grounding (HD pin)
Extra DataProvides Temperature and Error CodesCO₂ levels only
Wiring4 wires (VCC, GND, TX, RX)3 wires (VCC, GND, Vout)
ProcessingRequires a library or serial parsingRequires analogRead() and math mapping

Why is UART usually better

  • Noise Immunity: Analog signals can fluctuate if your power supply is unstable or your wires are long. UART transmits bits, so the number 800 ppm always arrives as 800 ppm in the Winsen MH-Z19C Datasheet.
  • Resolution: The Arduino's analogRead() splits the 0-5V range into 1024 steps. Since the sensor only uses the 0.4V–2.0V range, you only get about 320 steps of resolution to represent 5000ppm. UART provides full 1 ppm resolution.
  • Advanced Features: Through UART commands, you can change the detection range (e.g., 2000ppm vs 5000ppm) or toggle Auto-Baseline Calibration (ABC).

See:

  • 1: Arduino and MH-Z19C, utilize the Analog input
  • 2: Arduino and MH-Z19C, utilize the UART cpmmunication

1: Arduino and MH-Z19C, utilize the Analog input

To read the MH-Z19C sensor's analog output with an Arduino, utilize its built-in ADC to measure the voltage from its analog pin. The sensor produces a voltage from 0.4V at 0 ppm up to 2.0V at 5000 ppm, which is scaled to the Arduino's analog input range of 0 to 1023.

Wiring Diagram

Connect the MH-Z19C to the Arduino as follows:

  • VCC pin to the 5V pin on the Arduino.
  • GND pin to a GND pin on the Arduino.
  • Analog Out pin to an analog input pin, such as A0.

Do not use the HD pin unless you intend to perform manual zero-point calibration (by connecting it to GND for 7 seconds in 400ppm air).

This code reads the analog voltage and converts it to ppm values within the standard 0-5000 ppm range, using a 0.4V-2.0V output:

/*
 * MH-Z19C Analog Reading Example
 * Reads the 0.4V-2.0V analog output and converts it to ppm.
 */
 
const int CO2_ANALOG_PIN = A0; // Connect the MH-Z19C Analog Out pin to A0
const int MIN_VOLTAGE_ADC = 82; // Approx. ADC value for 0.4V (0.4V / 5V * 1023)
const int MAX_VOLTAGE_ADC = 410; // Approx. ADC value for 2.0V (2.0V / 5V * 1023)
const int MIN_PPM = 0;           // Corresponds to 0.4V
const int MAX_PPM = 5000;        // Corresponds to 2.0V
 
void setup() {
  Serial.begin(9600);
  Serial.println("MH-Z19C Analog Reader Starting...");
  pinMode(CO2_ANALOG_PIN, INPUT);
}
 
void loop() {
  // Read the raw analog value (0-1023 range for 5V Arduino)
  int rawADCValue = analogRead(CO2_ANALOG_PIN);
 
  // Convert the raw ADC value to CO2 ppm using the map function
  long co2_ppm = map(rawADCValue, MIN_VOLTAGE_ADC, MAX_VOLTAGE_ADC, MIN_PPM, MAX_PPM);
 
  // Print the results to the Serial Monitor
  Serial.print("Raw ADC Value: ");
  Serial.print(rawADCValue);
  Serial.print(" | Estimated CO2 (ppm): ");
  // Constrain the value to the sensor's valid range
  if (co2_ppm < MIN_PPM) co2_ppm = MIN_PPM;
  if (co2_ppm > MAX_PPM) co2_ppm = MAX_PPM;
  Serial.println(co2_ppm);
 
  delay(2000); // Read every 2 seconds
}

Important Notes

  • Accuracy: According to experts at Wolles Elektronikkiste, the analog method may exhibit “significant deviations” compared with UART (serial) communication. For better precision, the serial interface is highly recommended.
  • Voltage Divider: If your Arduino runs at 3.3V, you may need to adjust the MIN_VOLTAGE_ADC and MAX_VOLTAGE_ADC values based on a 3.3V reference (e.g., using analogReference(EXTERNAL) with a precise 2.5V source or using the internal 1.1V reference, though this requires a voltage divider because the output goes up to 2V).
  • Warm-up: The sensor requires a 3-minute warm-up after power-on to ensure accurate readings.

2: Arduino and MH-Z19C, utilize the UART cpmmunication

To get the most accurate readings from the MH-Z19C, using the UART (Serial) interface is the gold standard. It allows you to read digital values directly, avoiding the voltage fluctuations of analog pins.

Wiring (UART)

Connect the sensor to your Arduino (e.g., Uno) using SoftwareSerial to keep the main USB port free for debugging:

  • VCC: 5V
  • GND: GND
  • TX (Sensor): Pin 10 (Arduino RX)
  • RX (Sensor): Pin 11 (Arduino TX)

Recommended Library

For a reliable setup, use the MH-Z19 Library by Jonathan T. available in the Arduino Library Manager.

#include <SoftwareSerial.h>
#include <MHZ19.h>
 
#define RX_PIN 10                                          // Sensor TX -> Arduino 10
#define TX_PIN 11                                          // Sensor RX -> Arduino 11
#define BAUDRATE 9600                                      
 
MHZ19 myMHZ19;                                             
SoftwareSerial mySerial(RX_PIN, TX_PIN);                   
 
void setup() {
  Serial.begin(9600);                                     // Device to PC
  mySerial.begin(BAUDRATE);                               // Device to Sensor
  myMHZ19.begin(mySerial);                                // Initialize library
 
  myMHZ19.autoCalibration(true);                          // Turn on Auto Calibration (ABC)
  Serial.println("Sensor warming up (3 mins recommended)...");
}
 
void loop() {
  int co2 = myMHZ19.getCO2();                             // Request CO2 ppm
 
  if (myMHZ19.errorCode == RESULT_OK) {
    Serial.print("CO2 (ppm): ");
    Serial.println(co2);
 
    int temp = myMHZ19.getTemperature();                  // Request Temperature
    Serial.print("Temperature (C): ");
    Serial.println(temp);
  } else {
    Serial.print("Error Code: ");
    Serial.println(myMHZ19.errorCode);
  }
 
  delay(5000);                                            // Sensor refreshes every few seconds
}

Pro Tips for MH-Z19C

  • Logic Levels: The MH-Z19C uses 3.3V logic for TX/RX. While many Arduinos (like the Uno) can handle this, using a Logic-Level Converter is safer for long-term use.
  • Warm-up: The Official Datasheet from Winsen specifies a 1-minute preheat for the “C” model before readings stabilize.
  • ABC Logic: The Auto-Baseline Calibration (ABC) assumes the sensor sees “fresh air” (400ppm) at least once every 24 hours. If you are using this in a sealed lab, turn ABC off.

Sensor topics on lamaPLC

PageDateTags
2026/02/12 22:14, , , , , , , , ,
2026/02/14 22:31, , , , , , , , , ,
2026/03/21 19:20, , , , , , ,
2026/02/15 20:33, , , , , , , , ,
2026/02/14 23:38, , , , , , , , , , , ,
2026/02/14 22:24, , , , , , , , , , , , ,
2026/03/28 22:07, , , , , , ,
2026/02/15 20:40, , , , , , , , , , , , , ,
2026/02/14 23:36, , , , , , , ,
2026/02/14 23:37, , , , , , , , , , ,
2026/02/14 22:40, , , , , , , , , ,
2026/02/14 22:39, , , , , , , , , , ,
2026/02/14 23:39, , , , , , , , , , , , ,
2026/02/14 22:16, , , , , , , , , , , , ,
2026/03/21 22:25, , , , , , , , , , ,
2026/02/14 22:55, , , , ,
2026/02/14 18:19, , , , , , , , , , ,
2026/02/15 20:42, , , , , , , , ,
2026/02/14 18:11, , , , , , , ,
2026/02/15 20:44, , , , , ,
2025/05/31 21:32, , , , , , , ,
2026/02/14 19:29, , , , , , , , , , , , , ,
2026/03/21 20:45, , , , , , , , ,
2023/07/01 15:29, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,
2026/02/14 22:18, , , , , , , , , , , , , , , , , , , ,
2026/03/22 00:26, , , , , , , , ,
2026/02/14 22:19, , , ,
2026/02/14 22:09, , , , , , , , , , , , , , , ,
2026/02/14 21:54, , , , , , , , , , , , , , , , , , , , , , , , ,
2026/02/15 23:59, , , , , , , , , , ,
2026/03/28 18:02, , , , , , , , , , , , , , , ,
2026/02/14 23:58, , , , , , , , , , ,
2026/02/14 23:35, , , , ,
2026/02/14 22:24, , , ,
2026/02/14 23:38, , , , , , ,
2026/02/14 17:38, , , , , , , , , ,
2026/02/15 17:35, , , , , , , , , , ,
2026/02/15 20:20, , , , , , , , , , , , , , , , , ,
2026/03/22 01:24, , , , , , , , , , , ,
2026/02/14 21:17, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,
2026/02/15 16:39, , , , , , , ,
2026/02/14 22:23, , , , , , , ,
2025/09/23 16:59, , , , ,
2026/02/14 17:42, , , , , , ,
2026/02/14 22:33, , , , , ,
2026/02/14 22:33, , , , , , , , , , ,
2026/02/15 20:27, , , , , , , , , , , , , , , ,
2026/02/15 20:29, , , , , , , , , , , , , ,
2026/02/15 22:34, , , , , , , , , , , , , , , , , , , , , , , ,
2026/02/14 22:22, , , , , , , , , , , , ,
2023/06/24 22:43, , , , , ,
2026/02/14 22:21, , , , , , , , , , ,
2026/02/14 22:22, , , , , , , ,
2026/02/14 22:32, , , , ,
2026/02/14 23:00, , , , , , , , ,
2026/03/05 20:19, , , , , , , , , , , , , , , , ,
2026/02/14 17:49, , , , , ,
2025/12/10 17:50, , , ,
2025/11/09 17:38, , , , , , , ,


This page has been accessed for: Today: 8, Until now: 74