How to use MQ-2 gas sensor for smoke detection?


Here’s a practical, no-nonsense guide to using an MQ-2 for smoke detection with Arduino.
What the MQ-2 is (and isn’t)
Detects: smoke/particulates via combustible gases (LPG/propane, H₂, CH₄, alcohol, etc.). Output is analog (resistance change).
Not a certified safety detector. For life safety, use a UL/EN-certified smoke alarm. MQ-2 is great for hobby / non-critical projects.
Hardware you’ll need
MQ-2 sensor (bare sensor or common breakout with LM393 + potentiometer).
Arduino Uno (or similar, 5 V ADC).
5 V power that can supply ≥200 mA (the heater draws ~150–180 mA). Prefer an external 5 V supply; tie grounds together.
Optional: buzzer/LED.
Pinout & wiring (typical breakout)
VCC → 5 V, GND → GND
A0 → A0 (Arduino analog input)
D0 (digital/threshold output from on-board comparator) → any digital pin (optional)
Use A0/analog for reliable detection & tuning. The D0 threshold is coarse.
If you have the bare sensor:
- It’s a resistive element + heater. Use a load resistor (RL ~ 5–20 kΩ) in series to form a divider:
5V ---[ MQ-2 (Rs) ]---+--- A0
|
[RL] 10k (start here)
|
GND
Warm-up & calibration
Burn-in: first use, let heater run for 24–48 h (datasheet practice) for stable baseline.
Each power-up: wait 3–5 min before trusting readings.
Baseline R0 (optional but useful):
In clean air, measure sensor resistance Rs and record it as R0.
With the divider above:
Rs=RL⋅(VCC/Vout−1)
where Vout is the voltage at A0.Use Rs/R0 ratio for robust thresholds: smoke ⇒ Rs drops ⇒ Rs/R0 decreases.
Simple “smoke present” detection (recommended start)
Idea: Smooth the analog value, compare to a threshold you find during tests (e.g., incense, match smoke).
// MQ-2 on A0, buzzer on D8 (optional)
const int PIN_MQ2 = A0;
const int PIN_BUZ = 8;
const int N = 20; // moving average length
float avg = 0;
float alpha = 2.0f / (N + 1); // EMA smoother
// Set after experiments:
// Lower threshold => more sensitive (more false positives)
int smokeThreshold = 520; // 0..1023 (adjust to your room & sensor)
void setup() {
pinMode(PIN_BUZ, OUTPUT);
digitalWrite(PIN_BUZ, LOW);
Serial.begin(115200);
// Warm-up notice
Serial.println("MQ-2 warming up 180s...");
for (int i = 0; i < 180; i++) { delay(1000); }
Serial.println("Ready.");
}
void loop() {
int raw = analogRead(PIN_MQ2); // 0..1023
if (avg == 0) avg = raw; // init EMA
avg = avg + alpha * (raw - avg);
// simple hysteresis to reduce chatter
static bool alarm = false;
const int H = 15; // hysteresis counts
if (!alarm && avg > smokeThreshold) {
alarm = true;
digitalWrite(PIN_BUZ, HIGH);
Serial.print("ALARM: ");
} else if (alarm && avg < smokeThreshold - H) {
alarm = false;
digitalWrite(PIN_BUZ, LOW);
Serial.print("Clear: ");
}
Serial.print("raw="); Serial.print(raw);
Serial.print(" avg="); Serial.print((int)avg);
Serial.print(" th="); Serial.println(smokeThreshold);
delay(50);
}
How to set smokeThreshold
:
Measure avg in clean air (after warm-up). Note the value (e.g., 400–480 with RL=10 k).
Expose to a small smoke source (incense/match at safe distance) and see the avg rise (often ≥550–700).
Pick a threshold between them with some margin (e.g., clean 460 → smoke 620 ⇒ threshold ≈ 520–560).
Going further: Rs/R0 & (rough) ppm estimation
The MQ-2 datasheet provides log-log curves of Rs/R0 vs ppm for various gases (smoke line ≈ “smoke/alcohol/LPG” family).
Procedure:
Find R0 in clean air (or per datasheet reference gas).
Compute Rs from A0 each sample; then ratio = Rs/R0.
Using two points from the datasheet’s smoke curve, fit a line in log-space:
log10(ratio)=m⋅log10(ppm)+b
⇒ppm=10(log10(ratio)−b)/m.
Because curves vary unit-to-unit and with humidity/temperature, treat ppm as order-of-magnitude, not exact.
Practical tips (to reduce false alarms)
Ventilation & placement: Avoid placing near kitchens directly over stoves; rising alcohol vapors trigger it.
Humidity/temperature affect readings; if possible, log values and use adaptive thresholds or add a temp/RH sensor for compensation.
Power: Don’t run the sensor heater from Arduino’s 5 V if powered via USB; use an external 5 V with common GND.
Settling: After power-on, ignore the first minutes; values drift as the heater stabilizes.
Filtering: Use moving average / EMA (as above) and a time window (e.g., must exceed threshold for ≥2–5 s) before alarm.
Digital D0 pin on LM393 boards: convenient but coarse. Prefer A0 and your own logic.
Safety: Treat this as an indicator, not a certified alarm.
Troubleshooting
No change with smoke: wrong wiring, RL too high/low, not warmed up, bad airflow.
Always high: sensor saturated (too close to source) or threshold too low.
Noisy readings: add averaging, keep wires short, separate sensor power from noisy loads, decouple 5 V near the module (e.g., 100 nF + 10 µF).
Subscribe to my newsletter
Read articles from ampheo directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
