Arduino library · Sensors

MQUnifiedsensor: MQ gas sensors in parts per million

A bare analogRead() of an MQ-2, MQ-135 or MQ-7 module only tells you "more gas" or "less gas". MQUnifiedsensor by Miguel Califa turns that reading into an estimate in parts per million by doing the sums from the sensor’s datasheet. The same library covers the whole MQ family; what changes per sensor and per gas is a pair of curve constants and the clean-air ratio.

Built in on Mokxi: #include <MQUnifiedsensor.h> and it builds, with nothing to install. Free, and no account needed.

What MQUnifiedsensor does

The sensor is a heated resistor that drops in resistance as gas reaches it. The module puts it over a load resistor, so the library works back from the voltage to the sensor’s resistance Rs. R0 is that resistance in clean air, found once by calibrate(); after that, the gas level comes from the ratio Rs / R0 through a power curve, ppm = a × (Rs/R0)^b. For LPG on an MQ-2, a is 574.25 and b is -2.222.

The example on this page reads the MQ-2 on A0 of an Uno, calibrates R0 from ten readings at start, then reports LPG in ppm every second while gas is let in. Mokxi’s mq2 part takes a warm-up just as a real one does (20 seconds unless you change it), and calibrating before the heater is warm gives an R0 that is too low. Treat the ppm figure as an estimate: the curves come from the datasheet’s graph and a cheap module is not a calibrated instrument.

Library Manager nameMQUnifiedsensor
AuthorMiguel Califa
Include#include <MQUnifiedsensor.h>
BoardsArduino Uno, Arduino Nano, Arduino Mega 2560, Arduino Leonardo, SparkFun Pro Micro, Arduino Micro, WCH CH32V003, Raspberry Pi Pico, Raspberry Pi Pico W, Seeed XIAO SAMD21, STM32, STM32 Nucleo-F411RE, Arduino Uno R4, ESP32 DevKit, ESP32-S3-DevKitC-1, ESP8266 NodeMCU, Arduino Pro Mini 3.3 V, Seeed XIAO ESP32-C3, Seeed XIAO ESP32-C6, ESP32-DevKitC V4, LOLIN32 Lite, Wemos D1 R32, Cheap Yellow Display, TTGO T-Display, Seeed XIAO ESP32-S3, Arduino Nano ESP32, Arduino Nano RP2040 Connect, Seeed XIAO RP2040, Waveshare RP2040-Zero, Arduino Uno R4 WiFi
In the simulatorSimulated: it runs against the part the way it does on the bench.
Parts it drivesGas sensor, MQ-2

Install it

It builds on Arduino Uno, Arduino Nano, Arduino Mega 2560, Arduino Leonardo, SparkFun Pro Micro, Arduino Micro, WCH CH32V003, Raspberry Pi Pico, Raspberry Pi Pico W, Seeed XIAO SAMD21, STM32, STM32 Nucleo-F411RE, Arduino Uno R4, ESP32 DevKit, ESP32-S3-DevKitC-1, ESP8266 NodeMCU, Arduino Pro Mini 3.3 V, Seeed XIAO ESP32-C3, Seeed XIAO ESP32-C6, ESP32-DevKitC V4, LOLIN32 Lite, Wemos D1 R32, Cheap Yellow Display, TTGO T-Display, Seeed XIAO ESP32-S3, Arduino Nano ESP32, Arduino Nano RP2040 Connect, Seeed XIAO RP2040, Waveshare RP2040-Zero, Arduino Uno R4 WiFi.

In Mokxi it is built in: #include <MQUnifiedsensor.h> and the sketch compiles, with no download, no zip and no Library Manager.

On a real board, install "MQUnifiedsensor" by Miguel Califa from the Arduino IDE’s Library Manager (Sketch, Include Library, Manage Libraries), or add MQUnifiedsensor to lib_deps in PlatformIO. Mokxi follows the calls of release 3.0.5, so a sketch written here builds there too.

What to know in the simulator: Mokxi has the MQ-2. The other MQ sensors read the same way, with their own a, b and clean-air ratio.

The calls you will use

In the order a sketch meets them.

MQUnifiedsensor MQ2(Board, Voltage_Resolution, ADC_Bit_Resolution, Pin, Type)

The sensor on an analog pin: a board name for messages, the ADC reference voltage (5), its bits (10 on an Uno, 12 on an ESP32), the pin and the sensor name.

MQ2.setRegressionMethod(1)

Method 1 is the exponential curve ppm = a × ratio^b that the published constants are for. Method 2 is the linear log form.

MQ2.setA(574.25)

The curve’s a constant for the gas you want. Pair it with setB(); each gas on each sensor has its own pair.

MQ2.init()

Sets the analog pin up for reading. Call it after the constants and before the first update().

MQ2.calibrate(RatioMQ2CleanAir)

Returns R0 from the current reading, given the datasheet’s clean-air ratio (9.83 for the MQ-2). Average several and pass the result to setR0().

float r0 = 0;
for (int i = 0; i < 10; i++) {
  MQ2.update();
  r0 += MQ2.calibrate(9.83);
}
MQ2.setR0(r0 / 10);

MQ2.update()

Reads the analog pin once. readSensor() works from the last update, so call this first each time.

MQ2.readSensor()

The gas level in ppm from the latest reading and R0, never below 0.

MQ2.setRL(10)

The module’s load resistor in kilohms, 10 unless yours differs. Some MQ-2 boards fit 1 k, which shifts every reading.

Example: LPG in ppm from an MQ-2, calibrated in clean air

On the Arduino Uno R3. It runs in the browser exactly as printed.

sketch.ino · Arduino Uno R3
#include <MQUnifiedsensor.h>

#define Board ("Arduino UNO")
#define Pin (A0)
#define Type ("MQ-2")
#define Voltage_Resolution (5)
#define ADC_Bit_Resolution (10)
#define RatioMQ2CleanAir (9.83)

MQUnifiedsensor MQ2(Board, Voltage_Resolution, ADC_Bit_Resolution, Pin, Type);

void setup() {
  Serial.begin(9600);
  MQ2.setRegressionMethod(1);  // ppm = a * ratio^b
  MQ2.setA(574.25);
  MQ2.setB(-2.222);  // LPG
  MQ2.init();
  float calcR0 = 0;
  for (int i = 1; i <= 10; i++) {
    MQ2.update();
    calcR0 += MQ2.calibrate(RatioMQ2CleanAir);
  }
  MQ2.setR0(calcR0 / 10);
  Serial.print("R0 ");
  Serial.println(MQ2.getR0());
}

void loop() {
  MQ2.update();
  Serial.print("LPG ppm ");
  Serial.println(MQ2.readSensor());
  delay(1000);
}

Wiring

  • Arduino Uno R3 A0 to Gas sensor, MQ-2 AO
  • Arduino Uno R3 5V to Gas sensor, MQ-2 VCC
  • Arduino Uno R3 GND to Gas sensor, MQ-2 GND

Open it in the editor, wired and ready to run

Common errors and how to fix them

R0 comes out as inf or the ppm reads 0 forever

The analog reading was 0 during calibration, so the sums divided by zero. Check that AO, not DO, goes to the analog pin, that the module has 5 V, and that Pin in the constructor matches the wire.

The ppm is huge right after power on and falls over a minute

The heater is still warming up. Wait at least 20 seconds (a day for a brand new sensor, by the datasheet) before calibrating, and do the calibration in air you know to be clean.

Readings are about four times too high on an ESP32

The ESP32 reads 12 bits and 3.3 V. Set ADC_Bit_Resolution to 12 and Voltage_Resolution to 3.3, and call setVCC(5) if the sensor itself runs from 5 V through a divider.

Questions and answers

Where do I find a and b for another gas?

From the sensitivity graph in the sensor’s datasheet. The library’s own examples list pairs for common gases on each MQ sensor, such as CO and alcohol on the MQ-2.

Projects that use MQUnifiedsensor

Built-in projects that include it. Each page has the full sketch and opens in the editor, already wired.

Try MQUnifiedsensor without installing anything

Open the example, change the sketch, and keep your version in a free account.