Gas sensor MQ-2 is used here with ATmega32 microcontroller to detect gas presence and display the level of the gas on LCD. MQ-2 gas sensor can detect LPG, smoke and hydrogen gas, butane, CO2, alcohol etc so you can use it in many projects. Here we will simply display the level of LPG gas and Smoke in PPM(Parts Per Million) on LCD.
Download the project Proteus File
You can download the project Proteus File from the free download link below.
Dwnload Gas Sensor MQ-2 with ATmega32 and LCD project filesShown below is picture of what it looks like when the circuit is completed on a breadboard.
MQ-2 Gas Sensor Module
Also in the picture you can see a potentiometer knob which is used to adjust the sensitivity of the sensor. Clockwise rotation will increase the sensitivity and counter clockwise rotation will decrease the sensitivity.
Circuit Diagram of Interfacing MQ-2 Gas Sensor with ATmega32 and LCD
Below is the wiring diagram for interfacing MQ2 gas sensor with ATmega32 and LCD. The MQ2 analog output pin is connected to the ADC0 pin which is on PORT A pin 0. From this pin we acquire the sensor signal and convert it to PPM value according the Datasheet of MQ2 sensor. For how to do this see the code provided below. The 16x2 LCD is connected to the Port.D of ATmega32. For this pin PD7 to pin PD2 are used.
Code of MQ-2 gas sensor with ATmega32 and LCD
The following are the codes used for this project. There is main.c file and c and header files for LCD, ADC module and MQ2 sensor.
main.c
#include <avr/io.h>
#include <util/delay.h>
#include <stdlib.h>
#include "lcd.h"
#include "adc.h"
#include "mq2.h"
float Ro=10; //Ro is initialized to 10 kilo ohms
int main(){
unsigned char Res[16], lpg[16], smoke[16];
lcdinit();
adcinit();
lcdstr("Calibrating...");
Ro = SensorCalibration(); //Please make sure the sensor is in clean air when you perform the calibration
dtostrf(Ro, 6, 2, Res);
lcdclear();
_delay_ms(2); //clearing takes around 1.64ms to execute
lcdstr("Calibration done...");
lcdgoto(3,2);
lcdstr("Ro=");
lcdstr("KOhm ");
_delay_ms(4000);
lcdclear();
_delay_ms(2); //clearing takes around 1.64ms to execute
lcdgoto(1,1);
lcdstr("LPG:");
lcdgoto(13,1);
lcdstr("PPM");
lcdgoto(1,2);
lcdstr("SMOKE:");
lcdgoto(13,2);
lcdstr("PPM");
while (1){
itoa(GetGasPercentage(ReadSensor()/Ro,LPG), lpg, 10);
lcdgoto(5,1);
lcdstr(lpg);
itoa(GetGasPercentage(ReadSensor()/Ro,SMOKE), smoke, 10);
lcdgoto(7,2);
lcdstr(smoke);
_delay_ms(2000);
lcdgoto(5,1);
lcdstr(" ");
lcdgoto(7,2);
lcdstr(" ");
}
return 0;
}
lcd.h
void lcdinit();
void lcdcmd(uint8_t);
void lcdchar(uint8_t);
void lcdstr(unsigned char *);
void latch(void);
void lcdgoto(uint8_t , uint8_t );
lcd.c
#include <avr/io.h>
#include <util/delay.h>
#include "lcd.h"
#define E (1<<PD3)
#define RS (1<<PD2)
void lcdinit(){
//initialize PORT D for LCD
DDRD |= (1<<PD2) | (1<<PD3) | (1<<PD4) | (1<<PD5) | (1<<PD6) | (1<<PD7);
_delay_ms(50);
PORTD &= ~E; //send low
_delay_ms(50); //delay for stable power
lcdcmd(0x33);
lcdcmd(0x32);
lcdcmd(0x28); // for using 4 pins
lcdcmd(0x0C); // display ON, Cursor OFF
lcdcmd(0x01); //clear LCD
lcdcmd(0x06); //shift cursor to right
_delay_us(1000);
}
void lcdcmd(unsigned char cmd){
PORTD = (PORTD & 0x0F) | (cmd & 0xF0); // send high nibble
PORTD &= ~RS; //send 0 to select command register
PORTD |= E; //send high
_delay_ms(50); //wait
PORTD &= ~E; //send low
PORTD = (PORTD & 0x0F) | (cmd<<4); //send low nibble
PORTD |= E; //send high
_delay_ms(50); //wait
PORTD &= ~E; //send low
}
void lcdchar(unsigned char data){
PORTD = (PORTD & 0x0F) | (data & 0xF0); // send high nibble
PORTD |= RS; //send 1 to select data register
PORTD |= E; //send high
_delay_ms(50); //wait
PORTD &= ~E; //send low
PORTD = (PORTD & 0x0F) | (data<<4); // send low nibble
PORTD |= E; //send high
_delay_ms(50); //wait
PORTD &= ~E; //send low
}
void lcdstr(unsigned char *str){
unsigned char k=0;
while(str[k] != 0){
lcdchar(str[k]);
k++;
}
}
void lcdgoto(unsigned char x, unsigned char y){
unsigned char firstcharadr[] = {0x80, 0xC0, 0x94, 0xD4};
lcdcmd(firstcharadr[y-1] + x-1);
_delay_us(100);
}
void lcdclear(){
lcdcmd(0x01);
_delay_ms(1);
}
adc.h
void adcinit();
int adcread(char);
adc.c
#include <avr/io.h>
#include <util/delay.h>
#include "adc.h"
void adcinit(){
//make PA0 an analog input
DDRA &= ~(1<<PA0);
//enable ADC module, set prescalar of 128 which gives CLK/128
ADCSRA |= (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);
//set the voltage reference using REFS1 and REFS0 bits and select the ADC channel using the MUX bits
ADMUX = 0b01000000; // set REFS1 = 0 |REFS0 = 1 (Vref as AVCC pin) | ADLAR = 0(right adjusted) | MUX4 to MUX0 is 0000 for ADC0
}
int adcread(char channel){
/* set input channel to read */
ADMUX = 0x40 | (channel & 0x07); // 0100 0000 | (channel & 0000 0100)
/* Start ADC conversion */
ADCSRA |= (1<<ADSC);
/* Wait until end of conversion by polling ADC interrupt flag */
while (!(ADCSRA & (1<<ADIF)));
/* Clear interrupt flag */
ADCSRA |= (1<<ADIF);
_delay_ms(1); /* Wait a little bit */
/* Return ADC word */
return ADCW;
}
mq2.h
#define RL_VALUE (10) //define the load resistance on the board, in kilo ohms
#define RO_CLEAN_AIR_FACTOR (9.83) //(Sensor resistance in clean air)/RO,which is derived from the chart in datasheet
#define LPG (0) // Gas identity no.
#define SMOKE (1)
int GetPercentage(float, float *);
int GetGasPercentage(float , int);
float ReadSensor();
float ResistanceCalculation(int);
float SensorCalibration();
mq2.c
#include <util/delay.h>
#include "adc.h"
#include "mq2.h"
float LPGCurve[3] = {2.3,0.20,-0.45}; //two points from LPG curve are taken point1:(200,1.6) point2(10000,0.26)
//take log of each point (lg200, lg 1.6)=(2.3,0.20) (lg10000,lg0.26)=(4,-0.58)
//find the slope using these points. take point1 as reference
//data format:{ x, y, slope};
float SmokeCurve[3] ={2.3,0.53,-0.43}; //two points from smoke curve are taken point1:(200,3.4) point2(10000,0.62)
//take log of each point (lg200, lg3.4)=(2.3,0.53) (lg10000,lg0.63)=(4,-0.20)
//find the slope using these points. take point1 as reference
//data format:{ x, y, slope};
// sensor and load resistor forms a voltage divider. so using analog value and load value
// we will find sensor resistor.
float ResistanceCalculation(int raw_adc){
return ( ((float)RL_VALUE*(1023-raw_adc)/raw_adc)); // we will find sensor resistor.
}
float SensorCalibration(){
int i; // This function assumes that sensor is in clean air.
float val=0;
for (i=0;i<50;i++){ //take multiple samples and calculate the average value
val += ResistanceCalculation(adcread(0));
_delay_ms(500);
}
val = val/50;
val = val/RO_CLEAN_AIR_FACTOR; //divided by RO_CLEAN_AIR_FACTOR yields the Ro according to the chart in the datasheet
return val;
}
float ReadSensor(){
int i;
float rs=0;
for (i=0;i<5;i++) { // take multiple readings and average it.
rs += ResistanceCalculation(adcread(0)); // rs changes according to gas concentration.
_delay_ms(50);
}
rs = rs/5;
return rs;
}
int GetGasPercentage(float rs_ro_ratio, int gas_id){
if ( gas_id == LPG ) {
return GetPercentage(rs_ro_ratio,LPGCurve);
}
else if( gas_id == SMOKE ) {
return GetPercentage(rs_ro_ratio,SmokeCurve);
}
return 0;
}
//Using slope,ratio(y2) and another point(x1,y1) on line we will find
// gas concentration(x2) using x2 = [((y2-y1)/slope)+x1]
// as in curves are on logarithmic coordinate, power of 10 is taken to convert result to non-logarithmic.
int GetPercentage(float rs_ro_ratio, float *curve){
return (pow(10,( ((log(rs_ro_ratio)-curve[1])/curve[2]) + curve[0])));
}
Result & Conclusion
Thus we have successfully used MQ-2 sensor with ATmega32 to display LPG and Smoke level on an LCD. By bringing butane gas near the sensor, the MQ-2 sensor has detected the gas and using the above code, we have displayed the gas and smoke level on the LCD. The following video demonstrates the working of MQ-2 gas sensor with ATmega32 microcontroller and LCD.
Further Work
One can easily modify the code to take action if certain level of gas is reached. For example, you can use DC Motor Control using ATmega32 to run a fan or you can use servo motor or Stepper Motor using ATmega32 to turn on/off supply regulator or open/close window to adjust the gas in the surrounding.
Recommended Tutorial
how can i download protues file
Hello I could not able find protues file
Pls give proper Proteus file this Proteus file goes to other websites
Can you give me all proteus file and tell me version of proteus on jadhavarjun263@gmail.com adress
The link for the proteus file is broken. Could you please provide with another link instead?
hello all,
The following is the link to download. Let me know if any problem downloading:
https://drive.google.com/file/d/1fYW_B82QC_yaxmzbO3hrwIHo2h0pqqIH/view?usp=sharing
can you please tell how to add buzzer to this model which buzzes after certain threshold of ppm? kindly reply
you need to connect the buzzer to some pin like PB0 for example, then in the GetGasPercentage() function or in the main function you can write code to turn on the buzzer when some gas percentage is exceeded.
Sir, can you please provide the code and proteus file for buzzer integrated with it, we are trying but it is not running. we have a deadline on 31th may. it would be very grateful if you respond.
can you please send the code how to interface buzzer to it it would be very helpful.
I have connected everything same as you but in hardwere lpg and somke stays always 0 it doesn't change value.... Please help me
post your picture of your hardware and probably we can help
Hey, what's the value for the crystal oscillator used in this project?
i used crystal with frequency is 4MHz, you can also use internal oscillator, no need for external crystal