MQ-2 Gas Sensor with Arduino and LCD

 Here we will show how to use MQ-2 gas sensor with Arduino and LCD. This project will be helpful to you if you need or want to monitor gas leakage. For example you can use it as a domestic gas leakage detector(in Kitchen) or as industrial combustible gas detector or as a portable gas detector. In this example we will only display the detected gas(LPG, CO2, Smoke) level on LCD and on the serial monitor to demonstrates how it works. But you can also modify the project that when certain level of gas is reached, some action is taken. For example you can make use of DC motor with Arduino to run a fan or you can use servo motor to open door or window for environment temperature control or use a stepper motor with Arduino to control supply of gas.

MQ-2 Gas Sensor Module Working Mechanism

The MQ-2 gas sensor can detect LPG, Propane, Hydrogen, Methane, Alcohol and smoke. It works by sensing the conductivity of the surroundings space and outputs voltage proportional to the conductivity. Internally it contains Tin Dioxide (SnO2) sensitive layer, heater circuit and measuring electrodes. The SnO2 conductivity is low in clean air but in presence of gas, its conductivity increases proportional to the gas concentration. This in turn proportional increases/decreases output voltage at it's analog output pin. The sensor resistor(Rs) resistance, which is reciprocal of the sensor conductivity is used for outputting the sensor value. 


The MQ-2 module has protection resistor and potentiometer. These two resistor together forms a series load resistor(Rl). The potentiometer is used to adjust the sensitivity. The load resistor(Rl) and the sensor resistor(Rs) form a voltage divider. The output voltage is taken from this voltage divider.

The module has four pins as shown in the MQ-2 pin out figure. The first pin is continuous analog output pin which can be read by the ADC module of a microcontroller. The second pin is digital output pin which can be configured to output high signal when certain level of gas is reached. When the digital output is high, a LED on the module will turn ON. The third pin is the ground pin and the fourth pin the power supply Vcc pin.

In the MQ-2 pin-out picture you can also see the potentiometer knob which is used to vary the sensitivity of the gas sensor.



Wiring Diagram of MQ2 Gas Sensor with Arduino and LCD

The following diagram shows the wiring diagram of Arduino, 16x2 LCD with MQ-2 gas sensor. The Arduino pins 13 to 8 are used for LCD. The MQ-2 gas sensor analog output pin(A0) is connected to the A0 ADC pin of the Arduino. 

schematic of MQ2 Arduino LCD

Below picture shows MQ-2 gas sensor with Arduino and LCD on a breadboard. 

MQ-2 Gas Sensor with Arduino and LCD


Arduino Code for MQ-2 Gas Sensor and LCD

Below is the program code for detecting gas using MQ2 gas sensor and displaying the PPM values on the LCD.

#include <LiquidCrystal.h>


/**********************************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
#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 
#define         GAS_LPG                      (0)
#define         GAS_CO                       (1)
#define         GAS_SMOKE                    (2)

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
/**********************************MACROS END**********************************************/


LiquidCrystal lcd(13, 12, 11, 10, 9, 8);            //16x2 LCD Pin configuration


void setup()
{
  //send to serial port
  Serial.begin(9600);                               //UART setup, baudrate = 9600bps
  Serial.print("Calibrating...\n");

  //send to LCD
  lcd.begin(16, 2);
  lcd.print("Calibrating...");

  Ro = MQCalibration(MQ_PIN);                       //Calibrating the sensor. Please make sure the sensor is in clean air
  //send to serial port
  Serial.print("Calibration is done...\n");
  Serial.print("Ro=");
  Serial.print(Ro);
  Serial.print("kohm");
  Serial.print("\n");

  //send to LCD
  lcd.clear();
  lcd.print("Calibration done...");
  lcd.setCursor(2, 1);
  lcd.print("Ro=");
  lcd.print(Ro);
  lcd.print("KOhm");
  delay(3000);
  lcd.clear();
}

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");

  //send to LCD
  lcd.setCursor(0, 0);
  lcd.print("LPG:");
  lcd.print(MQGetGasPercentage(MQRead(MQ_PIN) / Ro, GAS_LPG) );
  lcd.print("     ");
  lcd.setCursor(9, 0);
  lcd.print("CO:");
  lcd.print(MQGetGasPercentage(MQRead(MQ_PIN) / Ro, GAS_CO) );
  lcd.print("       ");
  lcd.setCursor(0, 1);
  lcd.print("SMOKE:");
  lcd.print(MQGetGasPercentage(MQRead(MQ_PIN) / Ro, GAS_SMOKE) );
  lcd.setCursor(11, 1);
  lcd.print("(PPM)" );
  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])));
}


Results & Video demonstration

Below video demonstrates how the MQ-2 gas sensor works with Arduino and LCD. Also provided is the serial monitor output. As the lighter liquid gas which is butane is brought near the gas sensor, the LPG level, CO and smoke level increases. This demonstrates that the gas sensor and the arduino code provided above works.

On the serial monitor you will see the level of gas displayed.

serial monitor display of gas level by mq2

Recommended Tutorials

 In this tutorial we used Arduino board with MQ2 gas sensor. The tutorial Gas Sensor MQ-2 with ATmega32 and LCD is same except it uses ATmega32A microcontroller. Another similar sensor is MQ-3 sensor which is alcohol sensor. The tutorial  MQ3 Alcohol Analyzer with Arduino explains how to use the MQ3 alcohol sensor with Arduino.

 Further Work

Next you can enhance your project to include other sensor in your gas sensor project. You might want to include temperature and humidity sensor. The DHT11 sensor is easy to use and you can find details and source code in the tutorial LCD Display of Temperature and Humidity using DHT11 & Arduino with Code. In case you are only interested in temperature control with gas sensor then you can use the simple LM35 temperature sensor. This can be helpful in industrial application and research work where gas and temperature have to be monitored. The LM35 Temperature Sensor with Arduino and LCD tutorial explains how you can use LM35 temperature sensor and source code is also provided.

Post a Comment

Previous Post Next Post