Preview build — page text is a draft awaiting human review. Code badges come from real compiles. The flasher is real but not yet hardware-tested; the Playground is still a preview.

MQ-2 gas sensor with ESP32 DevKit V1 — 5 V heater, divided AO

Run an MQ-2 LPG/smoke module on an ESP32 DevKit V1: heater on VIN, AO through a 10 kΩ / 20 kΩ divider to ADC1 pin D34, and an alarm from a clean-air baseline.

Arduino C++Verified — core esp32 3.3.12, 3 Nov 2026Compile-only

Community draft — report a mistake

The MQ-2 detects LPG, smoke and other combustible gases with a heated tin-oxide element. Its output voltage rises as gas reaches it, which makes it the usual sensor for kitchen gas-leak and smoke projects.

The ESP32 DevKit V1 needs two changes compared with an Uno: the heater runs from VIN (5 V), and the analog output goes through a 10 kΩ / 20 kΩ divider into D34, an ADC1 pin that still works once Wi-Fi is on. The sketch warms the heater for a minute, records a clean-air baseline, and lights the blue LED when the reading rises well above it.

Use it to learn and to experiment. For a real cylinder in a real kitchen, fit a certified LPG detector as well.

Wiring

ESP32 DevKit V1Only the pins used are shown · 3.3 V logicMQ-2 gas sensor module10k│20kD34GNDVINVCCGNDDO (not connected)AO
Also needed: 10 kΩ and 20 kΩ resistors (or 10 kΩ + two 10 kΩ in series).
Every connection
ESP32 DevKit V1MQ-2 gas sensor moduleWireNotes
VINVCCredThe heater needs 5 V and about 150 mA — VIN carries USB 5 V. 3V3 won’t heat it properly.
GNDGNDblack
D34AOyellowVia 10 kΩ / 20 kΩ divider — 10 kΩ from AO to D34, 20 kΩ from D34 to GND: 5 V at AO becomes 3.33 V at the pin. The sketch multiplies back by 1.5.

5 V (heater: about 150 mA) part, 3.3 V board. The heater needs 5 V. AO can reach about 5 V, so on ESP32 and Pico feed AO through a 10 kΩ / 20 kΩ divider (or similar) to stay under 3.3 V. DO is driven by the comparator from VCC — divide it too on 3.3 V boards.

Board quirks

  • AO can reach about 5 V in heavy gas, which is above the ESP32’s 3.3 V limit. The divider is not optional on this board. Use 10 kΩ / 20 kΩ rather than 1 kΩ / 2 kΩ: the module’s load resistor is only a few kΩ, and a low-value divider would pull its reading down.
  • D34 is on ADC1, so readings keep working when you later add Wi-Fi alerts. ADC2 pins (D4, D13, D25–D27…) return nothing while Wi-Fi is on. D34 is input-only, which is all an analog input needs.
  • analogReadMilliVolts() uses the chip’s factory calibration (core 3.x). With the default 11 dB attenuation the useful range is roughly 0.15–3.1 V; above that the reading flattens. The divider keeps a 4.5 V AO at 3.0 V, inside the good part.
  • DO is the comparator output and swings to 5 V. The sketch doesn’t use it; if you want it, it needs its own divider.
  • A new sensor needs 24–48 hours of powered burn-in before readings settle, and a few minutes of warm-up at every power-on. Readings are relative — the MQ-2 reacts to LPG, smoke, alcohol, methane and hydrogen alike, so treat it as “something changed”, never as calibrated ppm or a certified LPG alarm.

Code

mq2-esp32.inoArduino C++Open in PlaygroundOpen in PlaygroundFlash
// MQ-2 gas/smoke module on an ESP32 DevKit V1.
// VCC → VIN (5 V heater), GND → GND, AO → 10 kΩ → D34 (GPIO34), 20 kΩ from D34 to GND.
// The divider scales AO (0–~5 V) to 2/3 so the ESP32 pin stays under 3.3 V.
// Indicative only — this is not a certified gas or smoke alarm.

constexpr uint8_t MQ_PIN = 34;        // ADC1_CH6: works with Wi-Fi on, input-only
constexpr uint8_t LED_PIN = 2;        // on-board blue LED
constexpr float DIVIDER = 1.5f;       // (10 kΩ + 20 kΩ) / 20 kΩ
constexpr float RISE_ALARM_V = 0.6f;  // alarm when AO rises this far above clean-air baseline

float baselineV = 0;

float readAoVolts() {
  uint32_t sum = 0;
  for (int i = 0; i < 16; i++) sum += analogReadMilliVolts(MQ_PIN);  // calibrated mV at the pin
  return (sum / 16.0f) / 1000.0f * DIVIDER;                          // volts at the module's AO
}

void setup() {
  Serial.begin(115200);
  pinMode(LED_PIN, OUTPUT);
  Serial.println("MQ-2 on GPIO34 — heater warming up (60 s)");
  for (int s = 60; s > 0; s -= 10) {
    Serial.printf("  %d s…\n", s);
    delay(10000);
  }
  float sum = 0;
  for (int i = 0; i < 10; i++) {
    sum += readAoVolts();
    delay(500);
  }
  baselineV = sum / 10;
  Serial.printf("Clean-air baseline: AO %.2f V\n", baselineV);
}

void loop() {
  float v = readAoVolts();
  bool alarm = v > baselineV + RISE_ALARM_V;
  digitalWrite(LED_PIN, alarm);
  Serial.printf("AO %.2f V  (+%.2f V over baseline)%s\n", v, v - baselineV, alarm ? "  GAS/SMOKE DETECTED" : "");
  delay(1000);
}

Expected serial output

Serial Monitor · 115200Output
MQ-2 on GPIO34 — heater warming up (60 s)
  60 s…
  50 s…
Clean-air baseline: AO 0.74 V
AO 0.75 V  (+0.01 V over baseline)
AO 1.92 V  (+1.18 V over baseline)  GAS/SMOKE DETECTED

Common errors

AO reads 0 V all the time

The heater isn’t powered (the module’s power LED is off), or the divider is wired the wrong way round: 10 kΩ goes between AO and D34, 20 kΩ between D34 and GND.

Reading keeps climbing for hours

Normal during burn-in of a new sensor. Leave it powered for a day, then take the baseline again (press EN to restart the sketch).

ESP32 resets when the MQ-2 is plugged in

The cold heater draws a surge on top of the ESP32’s own current. Use a good USB cable and port, or feed the MQ-2 from a separate 5 V supply with its GND joined to the ESP32’s GND.

↑↓ to move · Enter to open