When building an air quality monitor, understanding exactly how your chosen component translates chemical presence into electrical signals is the difference between a functional project and a paperweight. The MQ-135 is a staple for detecting volatile organic compounds (VOCs)—which the EPA identifies as a major indoor air pollutant—as well as ammonia and carbon dioxide. But because it outputs a resistance-based analog voltage rather than a clean digital packet, getting accurate parts-per-million (PPM) readings requires precise math, hardware conditioning, and an understanding of the sensor's physical quirks.
The Sensing Principle: How Metal Oxide Sensors React to Gases
The MQ-135 (and the broader MQ series manufactured by Hanwei Electronics) relies on a tin dioxide (SnO2) sensing layer housed inside a stainless steel mesh cap. In clean air, oxygen molecules adsorb onto the SnO2 surface, trapping electrons and creating a potential barrier that keeps the sensor's electrical resistance high—typically between 10kΩ and 40kΩ, depending on the specific module's load resistor.
When target gases like benzene, ammonia, or CO2 are introduced, they chemically react with the adsorbed oxygen. This reaction releases the trapped electrons back into the conduction band of the SnO2, drastically lowering the electrical resistance. The sensor module translates this resistance drop into a varying analog voltage via an onboard voltage divider, which your microcontroller reads via an ADC pin to determine the gas concentration.
Wiring the MQ-135 to an ESP32 (Pinout & Supply)
The most common mistake makers make with the MQ-135 is frying their microcontroller's ADC pin. The MQ-135 requires a 5V supply to power its internal heating element, which must reach roughly 300°C to catalyze the gas reaction. However, the ESP32 is a 3.3V logic device. If you connect a 5V module's analog output directly to an ESP32 GPIO, a high-concentration gas event will push 5V into a 3.3V pin, permanently damaging the silicon.
You must use a voltage divider on the analog output, or purchase a specific 3.3V logic-level MQ module. Below is the wiring schematic for a standard 5V module using a resistor divider.
| Module Pin | ESP32 Pin | Supply / Signal Range | Hardware Notes & Constraints |
|---|---|---|---|
| VCC | VIN (5V) | 4.8V to 5.2V | Heater draws ~150mA. Do not use the 3V3 pin. Ensure your USB source can supply the current. |
| GND | GND | 0V | Common ground is mandatory for accurate ADC referencing. |
| AOUT | GPIO 34 | 0V to 3.3V (Max) | Must pass through a voltage divider (e.g., 10kΩ series, 15kΩ to ground) to step 5V down to a safe 3.0V max. |
| DOUT | Not Used | Digital 5V/0V | Digital out is just a comparator threshold tied to a potentiometer. It is useless for PPM math; ignore it. |
The ESP32's ADC is notoriously non-linear at the extremes (near 0V and near 3.1V). As of 2026, the ESP32 Arduino Core v3.x includes the
analogReadMilliVolts() function. Always use this instead of the legacy analogRead(). It reads the factory-calibrated eFuse values to return true millivolts, bypassing the non-linear lookup table issues that plague older code examples.
Output Signal Math: Converting Raw ADC Readings to PPM
The analog output is not a direct representation of PPM. It is a voltage representing the ratio between the sensor's variable resistance ($R_s$) and the fixed load resistor ($R_L$) on the PCB. On most cheap breakout boards, $R_L$ is 1,000Ω (1kΩ). You must reverse-engineer the voltage divider to find $R_s$, then apply a logarithmic curve to estimate PPM.
Step 1: Convert ADC Reading to Voltage
Using analogReadMilliVolts(GPIO_34), you get a value between 0 and 3300mV. Because of our voltage divider (10kΩ and 15kΩ), we must scale this back up to find the actual voltage exiting the MQ-135 module ($V_{out}$).
V_module = V_esp32 * ((10000 + 15000) / 15000)
Step 2: Calculate Sensor Resistance ($R_s$)
The module itself is a voltage divider where $V_{cc}$ is 5V, $R_L$ is 1000Ω, and $V_{out}$ is the voltage we just calculated. Rearranging the standard voltage divider formula gives us the sensor's current resistance:
R_s = R_L * ((5.0 / V_module) - 1.0)
Step 3: Convert Resistance Ratio to PPM
Gas concentration correlates to the ratio of the sensor's resistance in target gas ($R_s$) to its resistance in clean air ($R_0$). According to the Espressif ADC documentation and Hanwei sensitivity curves, the relationship is logarithmic. For CO2 detection on an MQ-135, the standard approximation formula is:
PPM = a * (R_s / R_0) ^ b
Where a = 116.602 and b = -2.769. Note that these constants are derived from the datasheet's CO2 sensitivity curve; they will differ if you are targeting ammonia or benzene.
Interference, Calibration, and Burn-In Requirements
Metal oxide sensors are highly susceptible to environmental drift. You cannot simply wire up an MQ-135, flash the code, and expect accurate PPM readings on minute one.
- The Burn-In Period: Out of the box, the SnO2 layer contains manufacturing residues and trapped moisture. The sensor requires a continuous 24 to 48-hour 'burn-in' period where it is powered on in clean air to stabilize the baseline resistance. If you skip this, your $R_0$ calibration will be wildly inaccurate.
- Calibrating $R_0$: After the burn-in, take the sensor outside to a well-ventilated area away from traffic or exhaust. Measure the $R_s$ value. This stable value becomes your $R_0$ (clean air resistance). Hardcode this value into your firmware or save it to the ESP32's EEPROM/NVS.
- Humidity and Temperature Cross-Sensitivity: The SnO2 surface is highly reactive to water vapor. A spike in room humidity will lower the sensor's resistance, mimicking the presence of a target gas and causing false high-PPM alerts. For serious applications, you must pair the MQ-135 with a BME280 temperature/humidity sensor and apply a software compensation matrix to offset the humidity drift.
FAQ: How Sensors React to Environmental Changes
How do MQ gas sensors react to humidity and temperature shifts?
High humidity increases the conductivity of the SnO2 surface, causing the sensor's baseline resistance to drop. This makes the sensor 'think' there is more target gas present than there actually is. Temperature shifts alter the catalytic reaction rate on the sensor surface. To mitigate this, professional implementations use a lookup table to subtract a humidity-offset value from the final PPM calculation based on concurrent readings from a digital hygrometer.
Why do metal oxide sensors react to alcohol when calibrated for CO2?
The MQ-135 is a broad-spectrum sensor. While it is marketed for CO2 and VOCs, the SnO2 layer reacts to almost any reducing gas, including ethanol, isopropyl alcohol, and even citrus peel oils (limonene). If you clean your workbench with rubbing alcohol, the sensor will react to the fumes and spike the CO2 PPM reading. This cross-sensitivity is a fundamental limitation of metal oxide chemistry; if you need strict CO2 isolation without VOC interference, you must upgrade to an NDIR (Non-Dispersive Infrared) sensor like the MH-Z19B.
How long does it take for gas sensors to react to a sudden leak?
The physical reaction time of the SnO2 layer to a sudden introduction of gas is quite fast—typically under 10 seconds for the resistance to begin dropping. However, the 'recovery time' (how long it takes for the sensor to react to clean air and return to baseline after the gas dissipates) is much slower, often taking 30 to 60 seconds. The stainless steel mesh cap also acts as a physical diffusion barrier, slightly delaying the initial spike compared to bare-die MEMS sensors.






