Zbotic Logo Zbotic Logo
  • Home
  • Shop
  • Sale
  • 3D Print Service
  • PCB Service
  • B2B
  • Blogs
  • Contact Us
0 0

View Wishlist Add all to cart

0 0
0 Shopping Cart
Shopping cart (0)
Subtotal: ₹0.00

View cartCheckout

  • Shop
  • About Us
  • Contact Us
  • Reseller
  • Blogs
020 69134444
1800 209 0998
[email protected]
Help Desk
Facebook Twitter Instagram Linkedin YouTube
Zbotic Logo Zbotic Logo
0 0

View Wishlist Add all to cart

0 0
0 Shopping Cart
Shopping cart (0)
Subtotal: ₹0.00

View cartCheckout

All departments
  • 3D Print Service
  • 3D Printer
  • Batteries & Chargers
  • Development Boards
  • Drone Parts
  • EBike parts
  • Sensor Modules
  • Electronic Components
  • Electronic Modules
  • IoT and Wireless
  • Mechanical Parts and Workbench Tools
  • Motors & Drivers & Pumps & Actuators
  • DIY and Robot Kits
  • Show more
  • Home
  • Shop
  • Sale
  • 3D Print Service
  • PCB Service
  • B2B
  • Blogs
  • Contact Us
Return to previous page
Home Weather & Environmental Monitoring

CO2 Sensor MH-Z19: Indoor Air Quality Monitor Build

CO2 Sensor MH-Z19: Indoor Air Quality Monitor Build

March 11, 2026 /Posted byJayesh Jain / 0

CO2 Sensor MH-Z19: Indoor Air Quality Monitor Build

The MH-Z19 CO2 sensor is a NDIR (Non-Dispersive Infrared) sensor that accurately measures carbon dioxide concentration from 400-5000 ppm — essential data for indoor air quality monitoring in Indian offices, classrooms, and homes. CO2 is a direct indicator of ventilation adequacy and plays a significant role in productivity, cognitive performance, and COVID-19 aerosol risk mitigation. This guide builds a complete MH-Z19 indoor air quality monitor with Arduino, OLED display, and IoT connectivity, with specific guidance for India’s energy-efficient but often under-ventilated buildings.

Table of Contents

  1. CO2 and Indoor Air Quality in India
  2. MH-Z19 Sensor Specifications
  3. UART and PWM Wiring with Arduino
  4. Arduino Code: UART and PWM Reading
  5. Zero Calibration Procedure
  6. Complete Monitor with OLED and Alerts
  7. Ventilation Control Automation
  8. Frequently Asked Questions

CO2 and Indoor Air Quality in India

Outdoor CO2 concentration globally is approximately 420 ppm. Indoors, CO2 builds up from human respiration and can reach 2000-5000 ppm in under-ventilated spaces. The health and cognitive impacts:

  • 400-600 ppm: Outdoor level / ideal indoor — full cognitive performance
  • 600-1000 ppm: Good — typical well-ventilated office
  • 1000-1500 ppm: Moderate — noticeable impairment in complex decision-making (studies show 15% performance reduction)
  • 1500-2500 ppm: Poor — headaches, drowsiness, reduced concentration (common in Indian classrooms after 2 hours)
  • 2500-5000 ppm: Very Poor — significant cognitive impairment, WHO recommends immediate ventilation
  • >5000 ppm: Hazardous — occupational safety threshold (OSHA PEL)

Indian ASHRAE 62.1 equivalent: BIS IS 3103 recommends minimum 10 m³/hour/person ventilation, targeting CO2 below 1000 ppm above outdoor levels (~1420 ppm absolute). Many Indian offices and schools fail this standard in their AC-only (no fresh air exchange) operation — a common energy-saving measure that compromises air quality.

MH-Z19 Sensor Specifications

  • Principle: NDIR (Non-Dispersive Infrared) — gold standard for CO2 measurement
  • Measurement range: 0-5000 ppm (MH-Z19B) or 0-10000 ppm (MH-Z19C)
  • Accuracy: ±50 ppm + 3% of reading (±75 ppm at 1000 ppm)
  • Warm-up time: 3 minutes (readings stabilize after 3 min power-on)
  • Response time: T90 ≤120 seconds
  • Interfaces: UART (9600 baud) + PWM output + analog voltage (0.4-2V)
  • Supply: 3.6V – 5.5V, 40mA average, 150mA peak
  • Temperature range: 0-50°C (cover range for Indian indoor environments)
  • Auto-calibration: ABC (Automatic Baseline Correction) — assumes lowest reading each week is outdoor 400 ppm. Must be disabled in non-outdoor-facing deployments!
  • India price: ₹800-1500
Critical Note: MH-Z19’s ABC (auto-calibration) assumes the sensor is near outdoor air for at least 1 hour per week. In permanently sealed air-conditioned Indian offices, CO2 never returns to 400 ppm — ABC will incorrectly recalibrate upward, causing all readings to shift low. Disable ABC for indoor-only installations.

UART and PWM Wiring with Arduino

/* MH-Z19B Wiring:
 *
 * MH-Z19B Pin  Color  Arduino
 * Vin (5V)     Red    5V
 * GND          Black  GND
 * TXD          Green  Pin 10 (SoftwareSerial RX)
 * RXD          Blue   Pin 11 (SoftwareSerial TX)
 * PWM          Yellow Optional: Any digital pin (alternate reading method)
 * AOUT         White  A0 (0.4-2V analog, ~30ppm accuracy)
 *
 * NOTE: MH-Z19 is 3.3V UART logic
 * For Arduino Uno 5V: Add 1kΩ resistor in series on RXD (to sensor)
 * TXD (from sensor) is fine — Arduino reads 3.3V as HIGH
 *
 * ESP32 (direct 3.3V connection):
 * TXD → ESP32 GPIO16 (UART2 RX)
 * RXD → ESP32 GPIO17 (UART2 TX)
 */

Arduino Code: UART and PWM Reading

// MH-Z19 CO2 Sensor - Arduino UART Interface
// Library: MHZ19 by Jonathan Dempsey (Library Manager)
// Or: Manual UART implementation (shown below for understanding)

#include <SoftwareSerial.h>

SoftwareSerial mhzSerial(10, 11); // RX (from sensor TXD), TX (to sensor RXD)

// Read CO2 via UART command
int readCO2_UART() {
  // Command: 0xFF 0x01 0x86 0x00×5 0x79 (checksum)
  byte cmd[] = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79};
  
  // Clear input buffer
  while (mhzSerial.available()) mhzSerial.read();
  
  mhzSerial.write(cmd, 9);
  delay(10);
  
  if (mhzSerial.available() < 9) return -1;
  
  byte response[9];
  for (int i = 0; i < 9; i++) {
    response[i] = mhzSerial.read();
  }
  
  // Verify: start byte = 0xFF, command = 0x86
  if (response[0] != 0xFF || response[1] != 0x86) return -1;
  
  // Verify checksum
  byte checksum = 0;
  for (int i = 1; i < 8; i++) checksum += response[i];
  checksum = 0xFF - checksum + 1; // Two's complement
  if (response[8] != checksum) {
    Serial.println("CO2 checksum error!");
    return -1;
  }
  
  // CO2 ppm = high byte × 256 + low byte
  int co2 = (response[2] < 0) {
    String category = getCO2Category(co2);
    Serial.print(co2); Serial.print(" ppm | "); Serial.println(category);
  }
  delay(5000); // Read every 5 seconds
}

String getCO2Category(int co2) {
  if (co2 < 600) return "Excellent";
  if (co2 < 1000) return "Good";
  if (co2 < 1500) return "Moderate - Open window";
  if (co2 < 2500) return "Poor - Ventilation needed!";
  if (co2 < 5000) return "Very Poor - Evacuate!";
  return "HAZARDOUS - Leave immediately!";
}

// PWM reading method (simpler, no UART needed):
int readCO2_PWM(int pwmPin) {
  // MH-Z19 PWM cycle: 1004ms total
  // CO2 (ppm) = 5000 × (Th - 2ms) / 1000ms
  // Where Th = HIGH time in milliseconds
  long th = pulseIn(pwmPin, HIGH, 1500000L); // 1.5s timeout
  if (th == 0) return -1;
  int co2 = 5000 * (th/1000L - 2) / 1000;
  return constrain(co2, 0, 5000);
}

Zero Calibration Procedure

Proper calibration is critical for accurate CO2 readings. The MH-Z19 factory calibration may drift over time. Re-calibrate annually:

// Calibration Steps:
// 1. Take the sensor outdoors (or near an open window)
// 2. Let it run for 15-20 minutes until stable
// 3. Verify serial readings approach 400-420 ppm
// 4. Only if readings are far off (>50 ppm from expected), run calibration:
//    forceCalibration400ppm();

// Important for India:
// - Don't calibrate during Diwali (firecrackers → elevated CO2/particulates)
// - Don't calibrate during winter fog inversion (Delhi Dec-Jan)
//   when even outdoor CO2 spikes to 450-500 ppm due to trapped emissions
// - Morning 5-6 AM typically has lowest outdoor CO2 (photosynthesis starts)
// - Best calibration time: Clean monsoon morning after heavy rain

Recommended Product

5V Active Buzzer Module for Arduino
Pair with MH-Z19 for audible CO2 alerts — buzzer triggers when CO2 exceeds 1000 ppm in classrooms and offices to prompt ventilation action.
Category: Audio & Sound Modules

Complete Monitor with OLED and Alerts

// Complete CO2 Monitor: MH-Z19 + DHT22 + SSD1306 OLED
#include <SoftwareSerial.h>
#include <Wire.h>
#include <U8g2lib.h>
#include <DHT.h>

SoftwareSerial mhzSerial(10, 11);
U8G2_SSD1306_128X64_NONAME_F_HW_I2C oled(U8G2_R0);
DHT dht(4, DHT22);

#define BUZZER_PIN 8
#define LED_GREEN  5
#define LED_YELLOW 6
#define LED_RED    7

void setup() {
  mhzSerial.begin(9600);
  oled.begin();
  dht.begin();
  pinMode(BUZZER_PIN, OUTPUT);
  pinMode(LED_GREEN, OUTPUT);
  pinMode(LED_YELLOW, OUTPUT);
  pinMode(LED_RED, OUTPUT);
  delay(30000); // 30s initial warm-up
}

void loop() {
  int co2 = readCO2_UART();
  float temp = dht.readTemperature();
  float hum = dht.readHumidity();
  
  // Update LED indicator
  digitalWrite(LED_GREEN, co2 = 1000 && co2 = 1500 ? HIGH : LOW);
  
  // Buzzer alert for poor air quality
  if (co2 >= 2000) {
    tone(BUZZER_PIN, 880, 200); // Short beep every cycle
  }
  
  // OLED display
  oled.clearBuffer();
  oled.setFont(u8g2_font_logisoso28_tr);
  char co2Str[10];
  sprintf(co2Str, "%d", co2);
  oled.drawStr(0, 35, co2Str);
  oled.setFont(u8g2_font_6x10_tr);
  oled.drawStr(75, 30, "ppm CO2");
  
  char tempHum[25];
  sprintf(tempHum, "%.1fC  %.0f%%", temp, hum);
  oled.drawStr(0, 50, tempHum);
  oled.drawStr(0, 63, getCO2Category(co2).c_str());
  oled.sendBuffer();
  
  delay(5000);
}

Ventilation Control Automation

// Automatic ventilation control based on CO2 level
// Controls a exhaust fan relay
#define FAN_RELAY_PIN 3
#define CO2_HIGH_THRESHOLD 1200 // Turn fan ON above this
#define CO2_LOW_THRESHOLD  900  // Turn fan OFF below this (hysteresis)

bool fanRunning = false;

void controlVentilation(int co2) {
  if (!fanRunning && co2 > CO2_HIGH_THRESHOLD) {
    fanRunning = true;
    digitalWrite(FAN_RELAY_PIN, HIGH); // Fan ON
    Serial.println("Ventilation FAN ON");
  } else if (fanRunning && co2 < CO2_LOW_THRESHOLD) {
    fanRunning = false;
    digitalWrite(FAN_RELAY_PIN, LOW); // Fan OFF
    Serial.println("Ventilation FAN OFF");
  }
}
// Connect relay to exhaust fan, window actuator, or HVAC fresh air damper

Recommended Product

8-Channel Solid State Relay Module for Arduino
Control exhaust fans, HVAC dampers, and fresh air systems based on CO2 readings — build a complete automated ventilation control system for offices and classrooms.
Category: Industrial Automation

Frequently Asked Questions

Q: Why does my MH-Z19 read 400 ppm even in a crowded room?

A: ABC (Automatic Baseline Correction) is likely enabled and incorrectly calibrating. If ABC is on and the sensor never experiences true outdoor 400 ppm air, it slowly shifts its zero point — making a 1500 ppm reading appear as 400 ppm. Solution: Disable ABC with the command in the code above, then perform a proper outdoor zero calibration.

Q: Is MH-Z19 accurate enough for COVID-19 ventilation assessment?

A: Yes — CO2 monitoring for ventilation adequacy (target <1000 ppm) matches well with aerosol infection risk. At CO2 levels below 700 ppm, outdoor-level ventilation significantly dilutes aerosols. At >1500 ppm, risk increases substantially. MH-Z19’s ±75 ppm accuracy at 1000 ppm is sufficient for making ventilation decisions. Several Indian states have recommended CO2 monitoring for post-COVID school and office reopening.

Q: How long does the MH-Z19 last?

A: Rated for 5 years / 30,000 hours continuous operation. The infrared source (typically a blackbody IR emitter) gradually weakens over time, causing the sensor to drift high. Some users report accurate readings at 8-10 years with recalibration. In dusty Indian environments, the optical path can get contaminated — clean with dry nitrogen annually for best longevity.

Q: Can I use MH-Z19 in the kitchen to detect CO2?

A: NDIR CO2 sensors like MH-Z19 are NOT suitable for kitchens — they cannot detect methane (LPG, CNG used in Indian kitchens), CO (carbon monoxide from incomplete combustion), or smoke. For kitchen safety, use an MQ-2 (LPG/smoke) or CO detector module. CO2 sensors measure ventilation quality, not combustion gas leaks.

Q: What’s the difference between MH-Z19, MH-Z19B, and MH-Z19C?

A: MH-Z19B: Original version (0-5000 ppm range), common in India. MH-Z19C: Updated version with same specs but improved temperature compensation algorithm and 0-10000 ppm option. Both use identical UART protocol and wiring. Prefer MH-Z19B/C over the original MH-Z19 which had a known firmware bug that caused incorrect readings in some batches.

Shop Air Quality Sensors at Zbotic.in
Tags: air quality India, CO2 monitor Arduino, CO2 Sensor, indoor air quality, MH-Z19, NDIR CO2 sensor, ventilation monitoring
Share Post
  • Facebook
  • Linkedin
  • Whatsapp
Irrigation Pump Controller: Fl...
blog irrigation pump controller float switch and timer relay 599791
blog iot health monitor for final year project complete guide 599801
IoT Health Monitor for Final Y...

Related posts

Svg%3E
Read more

Climate Education Kit: Build and Learn About Weather

April 1, 2026 0
Table of Contents Weather Education in Indian Schools Designing a STEM Weather Kit Sensor Experiments for Students Curriculum-Aligned Activities Arduino... Continue reading
Svg%3E
Read more

Citizen Science Weather: Contribute Data to IITM Pune

April 1, 2026 0
Table of Contents Citizen Science Weather in India Data Quality Standards for Contribution Setting Up a WMO-Compatible Station Calibration and... Continue reading
Svg%3E
Read more

Weather Station Network: Multiple Stations with Gateway

April 1, 2026 0
Table of Contents Why Build a Weather Station Network LoRa Communication for Sensor Nodes Gateway Design with Raspberry Pi Sensor... Continue reading
Svg%3E
Read more

Cyclone Tracker Display: Real-Time IMD Data on Screen

April 1, 2026 0
Table of Contents Cyclone Tracking in India IMD Cyclone Data Sources ESP32 and TFT Display Setup Fetching and Parsing Cyclone... Continue reading
Svg%3E
Read more

Monsoon Onset Predictor: Historical Data Analysis India

April 1, 2026 0
Table of Contents Understanding Monsoon Onset in India Key Indicators for Monsoon Prediction Sensor Package for Monsoon Monitoring Collecting Baseline... Continue reading

Add comment Cancel reply

Your email address will not be published. Required fields are marked

Facebook Twitter Instagram Pinterest Linkedin Youtube

Get the latest deals and more.

Download on Google Play Download on the App Store

Call us: 020 69134444 / 1800 209 0998

Monday - Saturday 09:30 AM - 06:00 PM
For Technical Supports Email: [email protected]
For Sales / Enquiries Email: [email protected]

  • My Account

    • Cart

    • Wishlist

    • Checkout

    • My Orders

    • Track Order

    • My Account

  • Information

    • FAQs

    • Blogs

    • Career

    • About Us

    • Contact Us

    • Payment Options

  • Policies

    • Privacy Policy

    • Terms & Conditions

    • GST Input Tax Credit

    • Shipping Return Policy

    • E-Waste Collection Points

    • Our Sitemap

© Zbotic.in is registered trademark of Moxie Supply Pvt Ltd – All Rights Reserved
Login
Use Phone Number
Use Email Address
Not a member yet? Register Now
Reset Password
Use Phone Number
Use Email Address
Register
Already a member? Login Now