Complete Tutorial: Indoor Air Quality & Pollution Monitoring
The MQ-135 is an air quality sensor designed for detecting harmful gases in the air. It's commonly used in indoor air quality monitors, pollution detection systems, and HVAC control applications.
| Parameter | Specification |
|---|---|
| Operating Voltage | 5V DC |
| Heater Current | ~150mA |
| Load Resistance | 20kΩ (adjustable) |
| Preheat Time | 24+ hours for accurate calibration |
| Output Type | Analog (AO) + Digital (DO) |
| Detection Range | 10-1000 ppm (varies by gas) |
Like other MQ sensors, the MQ-135 uses a tin dioxide sensing element:
For accurate readings, the sensor needs a 24-48 hour burn-in period when first used. Run it continuously in clean air to stabilize the baseline.
| MQ-135 Pin | Description | Arduino | ESP32 |
|---|---|---|---|
| VCC | Power (5V) | 5V | VIN/5V |
| GND | Ground | GND | GND |
| AO | Analog Output | A0 | GPIO 34 |
| DO | Digital Output | Pin 2 | GPIO 13 |
Figure 1: MQ-135 sensor wiring with Arduino
const int sensorPin = A0;
void setup() {
Serial.begin(115200);
Serial.println("MQ-135 Air Quality Sensor");
Serial.println("Warming up (2 minutes)...");
delay(120000); // 2 minute warm-up
Serial.println("Ready!");
}
void loop() {
int rawValue = analogRead(sensorPin);
float voltage = rawValue * (5.0 / 1023.0);
Serial.print("Raw: ");
Serial.print(rawValue);
Serial.print(" | Voltage: ");
Serial.print(voltage, 2);
Serial.print("V | Air Quality: ");
if (rawValue < 150) {
Serial.println("Excellent");
} else if (rawValue < 300) {
Serial.println("Good");
} else if (rawValue < 500) {
Serial.println("Moderate");
} else if (rawValue < 700) {
Serial.println("Poor");
} else {
Serial.println("Hazardous!");
}
delay(2000);
}
const int sensorPin = A0;
// Baseline value in clean air (calibrate this!)
const int cleanAirValue = 120;
void setup() {
Serial.begin(115200);
Serial.println("MQ-135 AQI Monitor");
Serial.println("Calibrating...");
delay(60000);
}
void loop() {
int rawValue = analogRead(sensorPin);
// Calculate a relative pollution index
float ratio = (float)rawValue / cleanAirValue;
int aqi = (ratio - 1.0) * 100;
if (aqi < 0) aqi = 0;
if (aqi > 500) aqi = 500;
Serial.print("Raw: ");
Serial.print(rawValue);
Serial.print(" | AQI: ");
Serial.print(aqi);
Serial.print(" | Category: ");
if (aqi <= 50) {
Serial.println("Good (Green)");
} else if (aqi <= 100) {
Serial.println("Moderate (Yellow)");
} else if (aqi <= 150) {
Serial.println("Unhealthy for Sensitive (Orange)");
} else if (aqi <= 200) {
Serial.println("Unhealthy (Red)");
} else if (aqi <= 300) {
Serial.println("Very Unhealthy (Purple)");
} else {
Serial.println("Hazardous (Maroon)");
}
delay(2000);
}
| Sensor | Best For | Interface |
|---|---|---|
| MQ-135 | General air quality, NH3, CO2 | Analog |
| CCS811 | eCO2 and TVOC (calibrated) | I2C |
| BME680 | Gas + Temp + Humidity + Pressure | I2C |
| PMS5003 | Particulate matter (PM2.5) | UART |
For precise CO2 measurements, consider dedicated CO2 sensors like MH-Z19 or SCD30.