~~NOCACHE~~ ====== LamaPLC: MH-Z19 series of NDIR CO₂ sensors ====== {{ :sensor:mh_z19.png?140|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. ^Feature^MH-Z19^MH-Z19B^MH-Z19C^MH-Z19D^MH-Z19E| ^Working Voltage|3.6~5.5V DC|4.5~5.5V DC|5.0±0.1V DC|5.0±0.1V DC|4.5V~5.5V DC| ^Average Current|< 18mA|< 60mA (@5V)|< 40mA (@5V)|< 40mA (@5V)|< 85mA| ^Detection Range|0-2000/5000 ppm|0-5000/10000 ppm|400-5000 ppm|400-5000 ppm|0-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 Time|3 min|3 min|1 min|1 min|3 min| ^Sampling Period|N/A|5 seconds|1 second|1 second|N/A| ^Analog Output / Communication|Analog 0.4-2V|Analog 0.4-2V|Analog, **UART/PWM** only on some board|Analog, **UART/PWM** only on some board|Analog 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. {{page>:tarhal}} 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 ==== ^Feature^UART (Digital)^Analog (Voltage)| ^Data Format|Digital packet (exact PPM number)|Voltage (0.4V to 2.0V)| ^Precision|High: No signal loss or interference|Lower: Susceptible to //"noise"// and voltage drops| ^Calibration|Accessible via software commands|Requires manual hardware grounding (HD pin)| ^Extra Data|Provides **Temperature** and **Error Codes**|CO₂ levels only| ^Wiring|4 wires (VCC, GND, TX, RX)|3 wires (VCC, GND, Vout)| ^Processing|Requires a library or serial parsing|Requires 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 #include #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 ===== {{topic>sensor}} \\ {{tag>MH-Z19 MH-Z19D MH-Z19C MH-Z19B MH-Z19E NDIR CO₂ sensor Winsen UART PWM communication NDIR Non-Dispersive_Infrared Infrared IR temperature arduino code Tasmota}} This page has been accessed for: Today: {{counter|today}}, Until now: {{counter|total}}