Documentation

ShillehTek MQ-135 Air Quality Hazardous Gas Sensor Module for Arduino | ShillehTek Product Manual
Documentation / ShillehTek MQ-135 Air Quality Hazardous Gas Sensor Module for Arduino | ShillehTek Product Manual

ShillehTek MQ-135 Air Quality Hazardous Gas Sensor Module for Arduino | ShillehTek Product Manual

shillehtek

Overview

The MQ-135 is an air quality / hazardous gas sensor that responds to ammonia (NH3), nitrogen oxides (NOx), alcohol vapors, benzene, smoke, and carbon dioxide (CO2). It's the sensor of choice for general "indoor air quality" projects, simple smoke detectors, and bedroom / office monitors that just need to know "is the air getting worse?".

The breakout module includes the bare MQ-135 element along with an LM393 voltage comparator, a sensitivity-adjustment trimpot, and a clean 4-pin header (VCC, GND, DO, AO). The analog output (AO) gives you a continuous readout of gas concentration; the digital output (DO) goes LOW once the level crosses the threshold set by the on-board pot.

The MQ-135 needs to warm up — typically 24-48 hours on first use, then 1-3 minutes any time you re-power it — before readings stabilize. Once warm, it's stable enough for trend monitoring and simple alarms, though it's not a calibrated lab instrument.

At a Glance

Detects
NH3, NOx, smoke, CO2, alcohols
Operating Voltage
5V DC
Heater Current
~150 mA
Outputs
Analog + Digital
Warm-up Time
24-48 h (initial)
Pins
VCC, GND, DO, AO

Specifications

Parameter Value
Sensing Element MQ-135 metal-oxide semiconductor
Operating Voltage 5V DC
Heater Voltage 5V +/- 0.1V
Heater Power ~800 mW
Heater Current ~150 mA
Detected Gases NH3, NOx, alcohols, benzene, smoke, CO2
Detection Range 10 - 1000 ppm (gas-dependent)
Analog Output (AO) 0 - VCC, increases with gas concentration
Digital Output (DO) HIGH normally, LOW above threshold
Comparator LM393, threshold via on-board pot
Initial Warm-up 24-48 hours (first use)
Re-warm-up 1-3 minutes
Operating Temperature -20 degC to +50 degC
Dimensions ~32 x 20 mm

Pinout Diagram

MQ-135 air quality gas sensor module pinout diagram showing Pin 1 VCC (5V), Pin 2 GND, Pin 3 AO (analog output), and Pin 4 DO (digital output) with adjustable threshold via on-board trim pot

Wiring Guide

Arduino Wiring

The MQ-135's heater draws around 150 mA. Powering it from the Arduino's 5V rail is fine for a single sensor; if you stack multiple gas sensors, use an external 5V supply with a shared ground.

MQ-135 Pin Arduino Pin
VCC 5V
GND GND
AO A0 (analog input)
DO D2 (digital input, optional)
Tip: The sensor body gets warm during operation — that's normal. The heater is what makes the metal-oxide layer reactive to gases.

ESP32 Wiring

Power the heater from the ESP32's VIN (5V) pin. The analog output can swing close to 5V at high gas concentrations, so use a 2:1 divider before the ADC pin to protect the GPIO and stay in the 0-3.3V range.

MQ-135 Pin ESP32 Pin Details
VCC VIN (5V) Heater needs 5V
GND GND
AO GPIO 34 Through 2:1 divider
DO GPIO 35 3.3V logic; safe direct
Warning: AO can rise above 3.3V. Connecting it directly to an ESP32 GPIO can damage the chip. Use two 10k resistors in series to halve the voltage before the input.

Raspberry Pi Wiring

The Pi has no analog input. Use an external ADC like the ADS1115 to read AO, and a regular GPIO for DO. Power the heater from the Pi's 5V rail (or external 5V if powering many sensors).

Connection Pi Pin
MQ-135 VCC Pin 2 (5V)
MQ-135 GND Pin 6 (GND)
MQ-135 AO ADS1115 A0
MQ-135 DO Pin 11 (GPIO 17)
ADS1115 SDA Pin 3 (GPIO 2)
ADS1115 SCL Pin 5 (GPIO 3)

Raspberry Pi Pico Wiring

The Pico's 12-bit ADC reads up to 3.3V. Use a 2:1 divider on AO, just like with the ESP32, so the signal never exceeds 3.3V.

MQ-135 Pin Pico Pin Details
VCC VBUS (5V from USB)
GND GND
AO GP26 (ADC0) Through 2:1 divider
DO GP15

Code Examples

Arduino - Print Air Quality

mq135_arduino.ino
// MQ-135 - Print analog air quality reading on Arduino
// Allow 1-3 minutes warm-up after powering on for stable values.

const int aoPin = A0;
const int doPin = 2;

void setup() {
  Serial.begin(9600);
  pinMode(doPin, INPUT);
  Serial.println("MQ-135 warming up... wait at least 1 minute.");
}

void loop() {
  int raw = analogRead(aoPin);
  float volts = raw * 5.0 / 1023.0;

  Serial.print("Raw=");   Serial.print(raw);
  Serial.print("  V=");   Serial.print(volts, 2);
  Serial.print("  DO=");  Serial.print(digitalRead(doPin));
  if (digitalRead(doPin) == LOW) Serial.print("  [ALARM]");
  Serial.println();

  delay(500);
}

Raspberry Pi Pico - MicroPython

mq135_pico.py
# MQ-135 on Raspberry Pi Pico (MicroPython)
# AO -> 2:1 divider -> GP26 (ADC0); DO -> GP15

from machine import ADC, Pin
import time

ao = ADC(26)
do = Pin(15, Pin.IN)

print("Warming up MQ-135 - wait 1-3 minutes for stable values")

while True:
    raw = ao.read_u16()              # 0 - 65535
    v_pin  = raw * 3.3 / 65535       # voltage at the GPIO
    v_real = v_pin * 2               # un-divide the 2:1 divider
    print("Raw={:5d}  Vreal={:.2f} V  DO={}".format(raw, v_real, do.value()))
    time.sleep(0.5)

Raspberry Pi (Python + ADS1115)

mq135_rpi.py
#!/usr/bin/env python3
# MQ-135 + ADS1115 on Raspberry Pi
# pip install adafruit-circuitpython-ads1x15 RPi.GPIO

import time
import board, busio
import RPi.GPIO as GPIO
from adafruit_ads1x15.ads1115 import ADS1115
from adafruit_ads1x15.analog_in import AnalogIn

DO_PIN = 17
GPIO.setmode(GPIO.BCM)
GPIO.setup(DO_PIN, GPIO.IN)

i2c = busio.I2C(board.SCL, board.SDA)
ads = ADS1115(i2c)
ao  = AnalogIn(ads, 0)

try:
    while True:
        v = ao.voltage
        d = "ALARM" if GPIO.input(DO_PIN) == 0 else "OK"
        print("AO={:.3f} V    DO={}".format(v, d))
        time.sleep(0.5)
except KeyboardInterrupt:
    GPIO.cleanup()

Frequently Asked Questions

Why are my readings unstable for the first day?
Brand-new MQ-series sensors need 24-48 hours of continuous power to "burn in" the metal-oxide layer. After that initial warm-up, expect 1-3 minutes whenever you re-power. Without burn-in your readings will drift downward steadily and won't track gas levels reliably.
Can the MQ-135 give me a calibrated CO2 reading in ppm?
Not accurately. The MQ-135 responds to many gases, not just CO2, so a "ppm" calculation assumes a single dominant gas in clean air — rarely true. Use it for trend monitoring and threshold alarms. For lab-grade CO2 readings, use a true NDIR sensor like the SCD30 or MH-Z19.
What does the on-board pot do?
It sets the threshold for the DO (digital) output. When the analog level rises above the pot setting, the LM393 comparator drives DO LOW and lights the on-board indicator LED. Turn the pot clockwise to make the alarm trigger at higher levels (less sensitive); counter-clockwise to make it more sensitive.
My Arduino keeps resetting when I power the MQ-135 — why?
The heater pulls a brief inrush current that can dip the 5V rail enough to reset a USB-powered Arduino. Use a powered USB hub or an external 5V supply with a 100 uF cap close to the sensor's VCC pin to keep the rail stable.
Can I use this in a battery-powered project?
It's not ideal. The heater draws ~150 mA continuously, which drains a typical 18650 battery in about 17-18 hours. If you must run on battery, sleep the microcontroller and use a MOSFET to power-cycle the sensor periodically — accepting the warm-up time on each wake.
Does the MQ-135 detect carbon monoxide (CO)?
Only weakly. The MQ-135 is biased toward NH3, NOx, alcohols, benzene, smoke, and CO2. For carbon monoxide, use the MQ-7 (CO-specific) or MQ-9 (CO and methane). Do not rely on the MQ-135 as a CO safety alarm.
Why does breathing on the sensor make AO jump?
Exhaled breath contains CO2, water vapor, ethanol from food, and other reactive gases — all of which the MQ-135 picks up. It's actually a great way to confirm the sensor is alive: blow on it gently and watch the analog reading climb.

Related Tutorials