The MQ2 is a sensor that allows gas or smoke detector at concentrations of 300 ppm to 10,000 ppm. After calibration, the MQ-2 can detect various gases such as LPG, i-butane, propane, methane, alcohol, hydrogen and fumes. It is designed for indoor use at room temperature.
Supplied in 5V, it has an analog output and a potentiometer sensitivity adjustment. You can also find it with a Grove interface, including the SeeedStudio manufacturer for your Intel Edisson projects. You can buy MQ2 from €2.60
Hardware needed to test the MQ-2 on an Arduino
For this project, you will need the following materials:
- 1x Arduino Uno (or equivalent)
- 1x Breadboard (optional)
- 1x MQ-2 gas detector
- Some Dupont M/M or M/F cables if you do not use a breadboard
Circuit
You may encounter problems installing your MQ-2 on a breadboard. Indeed, manufacturers quite often solder angled connectors a little too far from the edge (to let the markings appear), which prevents the use of a breadboard. In this case, it is preferable to use Dupont M / F Jumpers.
Connect the 3 pins of the sensor to the Arduino (or ESP32 / ESP8266) by following the following wiring diagram
Connect the Vcc and GND pins of the sensor to the 5V and GND of the Arduino
Connect the Pin D0 of the sensor to the analog input A0 of the Arduino
Basic Arduino code, how to read MQ2 analog signal
Here is the code for testing your MQ-2. By default, the analog output of the MQ-2 is connected to input A0 of the Arduino.
const int mqxPin = A0; // La sortie analogique du détecteur MQx est reliée au Pin analogique A0 de l'Arduino
void setup()
{
Serial.begin(9600); // Initialise le port série à 9600 bps //
}
void loop()
{
Serial.println(analogRead(mqxPin));
delay(1000); // Imprime une mesure chaque seconde
}
How to determine the pollutant concentration with an MQ-2
To detect the presence of a pollutant (gas or smoke), we calculate the ratio between the initial resistance (R0) and the resistance (the analog signal read by the Arduino) that the MQ2 sends back at any time (Rs).
Knowing this ratio, we use the theoretical curve below to determine the quantity of each pollutant.
Here for example, the ratio Rs / R0 = 2, we read a smoke concentration of 800ppm on the red curve.
It is preferable to determine the R0 each time the sensor is turned on. In fact, the resistance of MQxx sensors can change over time because the active surface of the sensor can change (presence of dust, stabilization of the ceramic, etc.).
By measuring the temperature and the humidity level, the Rs / R0 ratio can be corrected, which improves detection accuracy.
In practice, the MQ2 sends an analog signal to the Arduino. This signal will be the value of Rs
Example of Arduino code to detect the presence of LPG, CO and smoke with an MQ2
To use the MQ2, there is no need to reinvent the wheel, we will use the code made available by Sandbox Electronics which allows the sensor to be calibrated to detect the presence of LPG, CO (carbon monoxide) or fumes in the surrounding atmosphere. .
Create an Arduino project and paste the code below.
The program begins by measuring the resistance on CALIBARAION_SAMPLE_TIMES samples (measurements). We wait for CALIBRATION_SAMPLE_INTERVAL between each measurement. By default, the initial calibration of R0 lasts 2.5 seconds (5 * 500 ms).
We can think of each curve as a straight line. The LPGCurve COCurve and SmokeCurve variables are used to determine the concentration of LPG, fumes and CO in the atmosphere, knowing the Rs / R0 ratio .
The MQGetGasPercentage () method allows you to find out the pollutant concentration. We must indicate the Rs / R0 ratio as well as the desired pollutant GAS_LPG, GAS_CO (carbon monoxide) or GAS_SMOKE.
To find out the presence of other gases, just add the corresponding curves in your code.
/*******************Demo for MQ-2 Gas Sensor Module V1.0*****************************
Support: Tiequan Shao: support[at]sandboxelectronics.com
Lisence: Attribution-NonCommercial-ShareAlike 3.0 Unported (CC BY-NC-SA 3.0)
Note: This piece of source code is supposed to be used as a demostration ONLY. More
sophisticated calibration is required for industrial field application.
Sandbox Electronics 2011-04-25
************************************************************************************/
/************************Hardware Related Macros************************************/
#define MQ_PIN (0) //define which analog input channel you are going to use
#define RL_VALUE (5) //define the load resistance on the board, in kilo ohms
#define RO_CLEAN_AIR_FACTOR (9.83) //RO_CLEAR_AIR_FACTOR=(Sensor resistance in clean air)/RO,
//which is derived from the chart in datasheet
/***********************Software Related Macros************************************/
#define CALIBARAION_SAMPLE_TIMES (50) //define how many samples you are going to take in the calibration phase
#define CALIBRATION_SAMPLE_INTERVAL (500) //define the time interal(in milisecond) between each samples in the
//cablibration phase
#define READ_SAMPLE_INTERVAL (50) //define how many samples you are going to take in normal operation
#define READ_SAMPLE_TIMES (5) //define the time interal(in milisecond) between each samples in
//normal operation
/**********************Application Related Macros**********************************/
#define GAS_LPG (0)
#define GAS_CO (1)
#define GAS_SMOKE (2)
/*****************************Globals***********************************************/
float LPGCurve[3] = {2.3,0.21,-0.47}; //two points are taken from the curve.
//with these two points, a line is formed which is "approximately equivalent"
//to the original curve.
//data format:{ x, y, slope}; point1: (lg200, 0.21), point2: (lg10000, -0.59)
float COCurve[3] = {2.3,0.72,-0.34}; //two points are taken from the curve.
//with these two points, a line is formed which is "approximately equivalent"
//to the original curve.
//data format:{ x, y, slope}; point1: (lg200, 0.72), point2: (lg10000, 0.15)
float SmokeCurve[3] ={2.3,0.53,-0.44}; //two points are taken from the curve.
//with these two points, a line is formed which is "approximately equivalent"
//to the original curve.
//data format:{ x, y, slope}; point1: (lg200, 0.53), point2: (lg10000, -0.22)
float Ro = 10; //Ro is initialized to 10 kilo ohms
void setup()
{
Serial.begin(9600); //UART setup, baudrate = 9600bps
Serial.print("Calibrating...\n");
Ro = MQCalibration(MQ_PIN); //Calibrating the sensor. Please make sure the sensor is in clean air
//when you perform the calibration
Serial.print("Calibration is done...\n");
Serial.print("Ro=");
Serial.print(Ro);
Serial.print("kohm");
Serial.print("\n");
}
void loop()
{
Serial.print("LPG:");
Serial.print(MQGetGasPercentage(MQRead(MQ_PIN)/Ro,GAS_LPG) );
Serial.print( "ppm" );
Serial.print(" ");
Serial.print("CO:");
Serial.print(MQGetGasPercentage(MQRead(MQ_PIN)/Ro,GAS_CO) );
Serial.print( "ppm" );
Serial.print(" ");
Serial.print("SMOKE:");
Serial.print(MQGetGasPercentage(MQRead(MQ_PIN)/Ro,GAS_SMOKE) );
Serial.print( "ppm" );
Serial.print("\n");
delay(200);
}
/****************** MQResistanceCalculation ****************************************
Input: raw_adc - raw value read from adc, which represents the voltage
Output: the calculated sensor resistance
Remarks: The sensor and the load resistor forms a voltage divider. Given the voltage
across the load resistor and its resistance, the resistance of the sensor
could be derived.
************************************************************************************/
float MQResistanceCalculation(int raw_adc)
{
return ( ((float)RL_VALUE*(1023-raw_adc)/raw_adc));
}
/***************************** MQCalibration ****************************************
Input: mq_pin - analog channel
Output: Ro of the sensor
Remarks: This function assumes that the sensor is in clean air. It use
MQResistanceCalculation to calculates the sensor resistance in clean air
and then divides it with RO_CLEAN_AIR_FACTOR. RO_CLEAN_AIR_FACTOR is about
10, which differs slightly between different sensors.
************************************************************************************/
float MQCalibration(int mq_pin)
{
int i;
float val=0;
for (i=0;i<CALIBARAION_SAMPLE_TIMES;i++) { //take multiple samples
val += MQResistanceCalculation(analogRead(mq_pin));
delay(CALIBRATION_SAMPLE_INTERVAL);
}
val = val/CALIBARAION_SAMPLE_TIMES; //calculate the average value
val = val/RO_CLEAN_AIR_FACTOR; //divided by RO_CLEAN_AIR_FACTOR yields the Ro
//according to the chart in the datasheet
return val;
}
/***************************** MQRead *********************************************
Input: mq_pin - analog channel
Output: Rs of the sensor
Remarks: This function use MQResistanceCalculation to caculate the sensor resistenc (Rs).
The Rs changes as the sensor is in the different consentration of the target
gas. The sample times and the time interval between samples could be configured
by changing the definition of the macros.
************************************************************************************/
float MQRead(int mq_pin)
{
int i;
float rs=0;
for (i=0;i<READ_SAMPLE_TIMES;i++) {
rs += MQResistanceCalculation(analogRead(mq_pin));
delay(READ_SAMPLE_INTERVAL);
}
rs = rs/READ_SAMPLE_TIMES;
return rs;
}
/***************************** MQGetGasPercentage **********************************
Input: rs_ro_ratio - Rs divided by Ro
gas_id - target gas type
Output: ppm of the target gas
Remarks: This function passes different curves to the MQGetPercentage function which
calculates the ppm (parts per million) of the target gas.
************************************************************************************/
int MQGetGasPercentage(float rs_ro_ratio, int gas_id)
{
if ( gas_id == GAS_LPG ) {
return MQGetPercentage(rs_ro_ratio,LPGCurve);
} else if ( gas_id == GAS_CO ) {
return MQGetPercentage(rs_ro_ratio,COCurve);
} else if ( gas_id == GAS_SMOKE ) {
return MQGetPercentage(rs_ro_ratio,SmokeCurve);
}
return 0;
}
/***************************** MQGetPercentage **********************************
Input: rs_ro_ratio - Rs divided by Ro
pcurve - pointer to the curve of the target gas
Output: ppm of the target gas
Remarks: By using the slope and a point of the line. The x(logarithmic value of ppm)
of the line could be derived if y(rs_ro_ratio) is provided. As it is a
logarithmic coordinate, power of 10 is used to convert the result to non-logarithmic
value.
************************************************************************************/
int MQGetPercentage(float rs_ro_ratio, float *pcurve)
{
return (pow(10,( ((log(rs_ro_ratio)-pcurve[1])/pcurve[2]) + pcurve[0])));
}
The other detectors of the MQ-xx family
The MQ-2 belongs to a family of sensors dedicated to gas detection. It is the most versatile detector, the others are specialized in one or two molecules. You can purchase them separately. It is very often found in sensor kits. You can use the same code as before to test them, you will have to adjust the calibration according to the chosen sensor.
- How to store data on a micro SD card. Arduino code compatible ESP32, ESP8266
- Getting started Arduino. Receive commands from the serial port (ESP32 ESP8266 compatible)
- C++ functions print•println•printf•sprintf for Arduino ESP32 ESP8266. Combine•format → serial port
- C++ String functions. concat•c_srt•indexOf•replace•subString… for Arduino, ESP32, ESP8266
- Get started with the I2C bus on Arduino ESP8266 ESP32. Wire.h library