Skip to content
cropped-image.webp

cropped-banner-promo-full-yellow.jpg

Connect with Us

  • Facebook
  • Twitter
  • Linkedin
  • VK
  • Youtube
  • Instagram
Primary Menu
  • Home
  • Blog
Light/Dark Button
Watch Video
  • Home
  • The Lab
  • ESP32 Air Quality Monitor with MQ Sensors
  • The Lab

ESP32 Air Quality Monitor with MQ Sensors

Friday February 19, 2026 (Last updated: February 20, 2026) 4 minutes read

Difficulty: Intermediate
Time Required: 2 hours
Cost: $15-20
ESP Board: ESP32

What You’ll Need

Component Approximate Cost Where to Buy
ESP32 Dev Board $5-8 Amazon
MQ-135 Sensor $2-4 Amazon
DHT22 Sensor $3-5 Amazon
OLED Display (Optional) $2-4 Amazon
Jumper Wires $2 Amazon

Circuit Diagram

ESP32 Pin Component Notes
3.3V MQ-135 VCC Power
GND MQ-135 GND Ground
GPIO 34 MQ-135 AOUT Analog output
3.3V DHT22 VCC Power
GND DHT22 GND Ground
GPIO 4 DHT22 DATA Data pin

Step 1: Install Libraries

  • DHT sensor library – Adafruit GitHub
  • Adafruit Unified Sensor – Required dependency

Step 2: The Complete Code

/*********************************************************************
 * ESP32 Air Quality Monitor with MQ Sensors
 * 
 * Measures: CO2, Smoke, NH3, Temperature, Humidity
 * Hardware: ESP32, MQ-135, DHT22
 * 
 * Libraries Required:
 * - DHT sensor library (Adafruit)
 * - Adafruit Unified Sensor
 *********************************************************************/

#include 
#include 
#include "DHT.h"

// ============== DHT CONFIGURATION ==============
#define DHTPIN 4        // GPIO 4
#define DHTTYPE DHT22

DHT dht(DHTPIN, DHTTYPE);

// ============== MQ-135 CONFIGURATION ==============
#define MQ135_PIN 34    // GPIO 34 (ADC)

// Calibration values
#define RLOAD 10.0       // Load resistance in kOhms
#define RZERO 76.63      // Calibration resistance
#define CO2_RZERO 76.63
#define CO2_SCALINGFACTOR 116.6020682
#define CO2_EXPONENT -2.769034857

// ============== WIFI CONFIGURATION ==============
const char* wifi_ssid = "YOUR_WIFI_NAME";
const char* wifi_password = "YOUR_WIFI_PASSWORD";

// ============== THINGSPEAK CONFIGURATION ==============
String apiKey = "YOUR_THINGSPEAK_API_KEY";
String server = "http://api.thingspeak.com/update";

// ============== DISPLAY CONFIGURATION ==============
#define BAUD_RATE 115200
#define READ_INTERVAL 5000  // 5 seconds

unsigned long lastRead = 0;

// ============== SETUP ==============
void setup() {
  Serial.begin(BAUD_RATE);
  Serial.println(F("\n======================================"));
  Serial.println(F("ESP32 Air Quality Monitor Starting..."));
  Serial.println(F("======================================"));
  
  // Initialize DHT sensor
  dht.begin();
  
  // Configure ADC
  analogReadResolution(12);  // 12-bit ADC (0-4095)
  
  // Connect to WiFi
  connectToWiFi();
  
  Serial.println(F("Setup complete!"));
  Serial.println(F("Reading air quality data...\n"));
}

// ============== MAIN LOOP ==============
void loop() {
  if (millis() - lastRead > READ_INTERVAL) {
    lastRead = millis();
    readSensors();
  }
}

// ============== FUNCTIONS ==============

void readSensors() {
  // Read DHT22 data
  float temperature = dht.readTemperature();    // Celsius
  float humidity = dht.readHumidity();           // Percentage
  
  // Read MQ-135 data
  int sensorValue = analogRead(MQ135_PIN);
  float voltage = sensorValue * (3.3 / 4095.0);
  
  // Calculate CO2 equivalent
  float co2 = calculateCO2(sensorValue);
  
  // Calculate resistance
  float resistance = calculateResistance(sensorValue);
  
  // Print to Serial
  Serial.println(F("========== AIR QUALITY DATA =========="));
  Serial.print(F("Temperature: ")); Serial.print(temperature, 1); Serial.println(F(" C"));
  Serial.print(F("Humidity: ")); Serial.print(humidity, 1); Serial.println(F(" %"));
  Serial.print(F("Sensor Value: ")); Serial.println(sensorValue);
  Serial.print(F("Voltage: ")); Serial.print(voltage, 3); Serial.println(F(" V"));
  Serial.print(F("Resistance: ")); Serial.print(resistance, 1); Serial.println(F(" kOhms"));
  Serial.print(F("CO2: ")); Serial.print(co2, 0); Serial.println(F(" ppm"));
  Serial.println(F("=====================================\n"));
  
  // Send to ThingSpeak
  sendToThingSpeak(temperature, humidity, co2);
}

float calculateResistance(int rawValue) {
  // Calculate sensor resistance
  float voltage = rawValue * (3.3 / 4095.0);
  return (3.3 - voltage) / voltage * RLOAD;
}

float calculateCO2(int rawValue) {
  // Calculate CO2 concentration using MQ-135
  float resistance = calculateResistance(rawValue);
  float ratio = resistance / RZERO;
  float co2 = CO2_SCALINGFACTOR * pow(ratio, CO2_EXPONENT);
  return co2;
}

void sendToThingSpeak(float temp, float hum, float co2) {
  if (WiFi.status() == WL_CONNECTED) {
    HTTPClient http;
    String url = server + "?api_key=" + apiKey;
    url += "&field1=" + String(temp);
    url += "&field2=" + String(hum);
    url += "&field3=" + String(co2);
    
    http.begin(url);
    int httpCode = http.GET();
    
    if (httpCode > 0) {
      Serial.println(F("Data sent to ThingSpeak"));
    } else {
      Serial.println(F("ThingSpeak connection failed"));
    }
    
    http.end();
  }
}

void connectToWiFi() {
  Serial.print(F("Connecting to WiFi"));
  WiFi.begin(wifi_ssid, wifi_password);
  
  int attempts = 0;
  while (WiFi.status() != WL_CONNECTED && attempts < 20) {
    delay(500);
    Serial.print(F("."));
    attempts++;
  }
  
  if (WiFi.status() == WL_CONNECTED) {
    Serial.println(F(" Connected!"));
    Serial.print(F("IP: ")); Serial.println(WiFi.localIP());
  } else {
    Serial.println(F(" Connection failed!"));
  }
}

// ============== END OF CODE ==============

Step 3: Calibration (Important)

MQ-135 sensors need 24-48 hours to burn in, then calibrate:

  1. Power on and leave in clean air for 24 hours
  2. Note the RZERO value from serial monitor
  3. Update #define RZERO 76.63 with your value
  4. Upload calibrated code

Troubleshooting

Problem Solution
DHT22 reading NaN Check wiring; add 10K pull-up resistor
CO2 reading too high Recalibrate sensor; check power supply stability
Analog readings unstable Add 100nF capacitor between VCC and GND
ThingSpeak not updating Verify API key; check field numbers

Official Documentation

  • DHT Sensor Library - Official GitHub
  • MQ135 Library - Reference code
  • ThingSpeak - IoT platform

Frequently Asked Questions

Q: How accurate is MQ-135 for CO2?

A: It's a metal oxide sensor that detects various gases. CO2 readings are estimates, not lab-grade measurements.

Q: How often should I recalibrate?

A: Every 2-3 months, or when readings seem consistently off.

Q: Can I use this outdoors?

A: Protect from rain and direct sunlight. Use a weatherproof enclosure.

About The Author

Friday

See author's posts

Post navigation

Previous: ESP8266 Home Automation Relay with Blynk App
Next: ESP32 Smart Plant Watering System

Related Stories

  • The Lab

Raspberry Pi Pico vs ESP32: Which Should You Choose? 2026

Friday March 4, 2026
  • The Lab

ESP32-C3 vs ESP32-S3: Detailed Comparison 2026

Friday March 4, 2026
  • The Lab

STM32 vs ESP32: Battle of the Microcontrollers 2026

Friday March 3, 2026

Connect with Us

  • Facebook
  • Twitter
  • Linkedin
  • VK
  • Youtube
  • Instagram

Trending News

7 Best Shopify Alternatives for Dropshipping in 2026 1
  • Latest News

7 Best Shopify Alternatives for Dropshipping in 2026

Friday March 4, 2026
ESP32-C3 vs ESP32-S3: Detailed Comparison 2026 2
  • The Lab

ESP32-C3 vs ESP32-S3: Detailed Comparison 2026

Friday March 4, 2026
Raspberry Pi Pico vs ESP32: Which Should You Choose? 2026 3
  • The Lab

Raspberry Pi Pico vs ESP32: Which Should You Choose? 2026

Friday March 4, 2026
STM32 vs ESP32: Battle of the Microcontrollers 2026 4
  • The Lab

STM32 vs ESP32: Battle of the Microcontrollers 2026

Friday March 3, 2026
Arduino Mega vs ESP32: Processing Power Face-off 2026 5
  • The Lab

Arduino Mega vs ESP32: Processing Power Face-off 2026

Friday March 3, 2026

You May Have Missed

  • Latest News

7 Best Shopify Alternatives for Dropshipping in 2026

Friday March 4, 2026
  • The Lab

ESP32-C3 vs ESP32-S3: Detailed Comparison 2026

Friday March 4, 2026
  • The Lab

Raspberry Pi Pico vs ESP32: Which Should You Choose? 2026

Friday March 4, 2026
  • The Lab

STM32 vs ESP32: Battle of the Microcontrollers 2026

Friday March 3, 2026
CoreEcom provides honest, research-backed reviews and essential guides. We filter the noise to help global consumers find quality products that deliver real value, ensuring every purchase is a smart investment.

Categories

Buyer's Manuals Deep Reviews Editor's Choice Latest News Setup Guides The Lab

Quick Links

  • About
  • Editorial Standards
  • Privacy
  • Impressum
  • Contact
  • Facebook
  • Twitter
  • Linkedin
  • VK
  • Youtube
  • Instagram
Copyright © Growthscout 2026 All rights reserved. | ReviewNews by AF themes.