Вы находитесь на странице: 1из 19

  

Gas Detection and PPM Measurement using PIC


Microcontroller and MQ Gas Sensors
EMBEDDED
BySourav Gupta Jan 21, 20201

MQ sensor with PIC microcontroller


MQ series Gas sensors are very common types of sensors used in Gas Detectors to detect or measure certain types of Gases.
These sensors are widely used in all Gas related devices like from simple Smoke Detectors to Industrial Air Quality Monitors. We
have already used these MQ gas sensors with Arduino to measure some harmful gases like Ammonia. In this article, we will learn
how to use these gas sensors with PIC Microcontrollers, to measure the PPM value of the gas and display it on a 16x2 LCD.

As mentioned earlier, there are different kinds of MQ series sensors available in the market and each sensor can measure different
types of gases as shown in the table below. For the sake of this article, we will be using the MQ6 Gas sensor with PIC that can be
used to detect the LPG gas presence and concentration. However, by using the same hardware and firmware other MQ series
sensors can also be used without major modification in the code and hardware part.

Sensor Detects

MQ-2 Methane, Butane, LPG, smoke


MQ-3 Alcohol, Ethanol, smoke

MQ-4 Methane, CNG Gas

MQ-5 Natural gas, LPG

MQ-6 LPG, butane gas

MQ-7 Carbon Monoxide

MQ-8 Hydrogen Gas

MQ-9 Carbon Monoxide, flammable gasses.

MQ131 Ozone

MQ135 Air Quality (Benzene, Alcohol, smoke)

MQ136 Hydrogen Sulfide gas

MQ137 Ammonia

MQ138 Benzene, Toluene, Alcohol, Acetone, Propane, Formaldehyde gas, Hydrogen

MQ214 Methane, Natural gas

MQ216 Natural gas, Coal gas

MQ303A Alcohol, Ethanol, smoke

MQ306A LPG, butane gas

MQ307A Carbon Monoxide


MQ309A Carbon Monoxide, flammable gasses

MG811 Carbon Dioxide (CO2)

AQ-104 Air quality

MQ6 Gas Sensor


The below image shows the MQ6 sensor pin diagram. However, the left image is a module-based MQ6 sensor for interfacing with
the microcontroller unit, the pin diagram of the module is also shown in that image.

Pin 1 is VCC, Pin 2 is the GND, Pin 3 is the Digital out (Logic low when gas is detected.) and Pin 4 is the Analog output. The pot is
used to adjust the sensitivity. It is not RL. The RL resistor is the right resistor of the DOUT LED.
Each MQ series sensor has a heating element and a sensing resistance. Depending on the concentration of the gas, the sensing
resistance gets changed and by detecting the changing resistance, the gas concentration can be measured. To measure the gas
concentration in PPM all MQ sensors provide a logarithmic graph which is very important. The graph provides an overview of the
gas concentration with the ratio of RS and RO.

How to measure PPM using MQ Gas sensors?


The RS is the sense resistance during the presence of a particular gas whereas the RO is the sense resistance in clean air without
any particular gas. The below logarithmic graph taken from the datasheet provides an overview of the gas concentration with the
sense resistance of the MQ6 sensor. The MQ6 sensor is used to detect LPG gas concentration. Therefore, the MQ6 sensor will
provide a particular resistance during the clean air condition where the LPG gas is unavailable. Also, the resistance will change
whenever the LPG gas is detected by the MQ6 sensor.
So, we need to plot this graph into our firmware similar to what we did in our Arduino Gas detector Project. The formula is to have 3
different data points. The first two data points are the starting of the LPG curve, in X and Y coordinates. The third data is the slope.

So, If we select the deep blue curve which is the LPG curve, the starting of the curve in X and Y coordinate is the 200 and 2. So, the
first data point from the logarithmic scale is (log200, log2) which is (2.3, 0.30).

Let’s make it as, X1 and Y1 = (2.3, 0.30). The ending of the curve is the second data point. By the same process described above,
X2 and Y2 are (log 10000, log0.4). Thus, X2 and Y2 = (4, -0.40). To get the slope of the curve, the formula is

=(Y2-Y1)/(X2-X1)

=(-0.40 - 0.30) / (4 - 2.3)

= (-0.70) / (1.7)

= -0.41

The graph we need can be given as

LPG_Curve = {starting X and starting Y, slope}

LPG_Curve = {2.3, 0.30, -0.41}

For other MQ sensors, get the above data from the datasheet and the Logarithmic graph plot. The value will differ based on the
sensor and gas measured. For this particular module, it has a digital pin that only provides information about gas present or not. For
this project, it is also used.
Required components
The required components for interfacing MQ sensor with PIC microcontroller are given below-

1. 5V power supply
2. Breadboard
3. 4.7k resistor
4. LCD 16x2
5. 1k resistor
6. 20Mhz crystal
7. 33pF capacitor - 2pcs
8. PIC16F877A microcontroller
9. MQ series sensor
10. Berg and other hookup wires.

Schematic
The schematic for this Gas sensor with a PIC project is pretty straight forward. The Analog pin is connected with the RA0 and the
digital one with the RD5 to measure the analog voltage provided by the Gas sensor module. If you are completely new to PIC, then
you might want to look into PIC ADC tutorial and PIC LCD tutorial to better understand this project.

The circuit is constructed in a breadboard. Once the connections were completed, my set-up looks like this, shown below.

MQ Sensor with PIC Programming


The main part of this code is the main function and other associated peripheral functions. The Complete program can be found at
the bottom of this page, the important code snippets are explained as follows

The below function is used for getting the sensor resistance value in free air. As the Analog channel 0 is used, it is getting data from
the analog channel 0. This is for calibrating the MQ Gas sensor.

float SensorCalibration(){

int count; // This function will calibrate the sensor in free air

float val=0;

for (count=0;count<50;count++) { //take multiple samples and calculate the average value

val += calculate_resistance(ADC_Read(0));

__delay_ms(500);

val = val/50;

val = val/RO_VALUE_CLEAN_AIR; //divided by RO_CLEAN_AIR_FACTOR yields the Ro

return val;

Below Function is used to read the MQ sensor analog values and average it to calculate the Rs value

float read_MQ()

int count;

float rs=0;
for (count=0;count<5;count++) { // take multiple readings and average it.

rs += calculate_resistance(ADC_Read(0)); // rs changes according to gas concentration.

__delay_ms(50);

rs = rs/5;

return rs;

The below function is used to calculate the resistance from the voltage divider resistor and the load resistance.

float calculate_resistance(int adc_channel)

{ // sensor and load resistor forms a voltage divider. so


using analog value and load value

return ( ((float)RL_VALUE*(1023-adc_channel)/adc_channel)); // we will find sensor resistor.

The RL_VALUE is defined at the starting of the code like shown below

#define RL_VALUE (10) //define the load resistance on the board, in kilo-ohms

Change this value after checking the onboard load resistance. It can be different in other MQ sensor boards. To plot the available
data into the log scale, the below function is used.

int gas_plot_log_scale(float rs_ro_ratio, float *curve)

return pow(10,(((log(rs_ro_ratio)-curve[1])/curve[2]) + curve[0]));

The curve is the LPG curve defined in above of the code that is previously calculated in our article above.

float MQ6_curve[3] = {2.3,0.30,-0.41}; //Graph Plot, change this for particular sensor

Finally, the main function inside which we measure the analog value, calculate the PPM and display it on the LCD is given below

void main() {

system_init();

clear_screen();

lcd_com(FIRST_LINE);

lcd_puts("Calibrating....");

Ro = SensorCalibration();

//clear_screen();
lcd_com(FIRST_LINE);

lcd_puts("Done! ");

//clear_screen();

lcd_com(FIRST_LINE);

lcd_print_number(Ro);

lcd_puts(" K Ohms");

__delay_ms(1500);

gas_detect = 0;

while(1){

if(gas_detect == 0){

lcd_com(FIRST_LINE);

lcd_puts("Gas is present ");

lcd_com(SECOND_LINE);

lcd_puts ("Gas ppm = ");

float rs = read_MQ();

float ratio = rs/Ro;

lcd_print_number(gas_plot_log_scale(ratio, MQ6_curve));

__delay_ms(1500);

clear_screen();

else{

lcd_com(FIRST_LINE);

lcd_puts("Gas not present ");

First, the sensor’s RO is measured in clean air. Then the digital pin is read to check whether the gas is present or not. If the gas is
present, the gas is measured by the provided LPG curve.

I have used a lighter to check if the PPM value is changing when the gas is detected. These cigar lighters have LPG gas inside
them, which when released in the air will be read by our sensor and the PPM value on the LCD changes as shown below.
The complete working can be found in the video given at the bottom of this page. If you have any questions please leave them in
the comment section, or use our forums for other technical questions.

Code
#include <xc.h>
#include <stdint.h>
#include <math.h>
#include "supporing_cfile/lcd.h"
#include "supporing_cfile/adc.h"
#pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = ON       // Power-up Timer Enable bit (PWRT enabled)
#pragma config BOREN = ON       // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = OFF        // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used
for programming)
#pragma config CPD = OFF        // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF        // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON
control)
#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)
/*
 Program Flow related definition
 */
#define gas_detect   PORTDbits.RD5
#define gas_Detect_Pin_Direction  TRISDbits.TRISD5
#define FIRST_LINE 0x80
#define SECOND_LINE 0xC0
#define RL_VALUE (10)     //define the load resistance on the board, in kilo ohms
#define RO_VALUE_CLEAN_AIR (9.83)  //(Sensor resistance in clean air)/RO,
                                    //which is derived from the chart in datasheet
float MQ6_curve[3]  = {2.3,0.30,-0.41};   //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 Ro =  0;                 //Ro is initialized to 10 kilo ohms
#define _XTAL_FREQ 20000000 //20 Mhz
// System related definitions
void system_init(void);
void introduction_screen(void);
void clear_screen(void);
//int   GetPercentage(float rs_ro_ratio, float *pcurve);
int   gas_plot_log_scale(float rs_ro_ratio, float *curve);
float read_mq();
float calculate_resistance(int raw_adc);
float SensorCalibration();
void main() {  
     system_init();
     clear_screen();
     lcd_com(FIRST_LINE);
     lcd_puts("Calibrating....");
     Ro = SensorCalibration();
     //clear_screen();
     lcd_com(FIRST_LINE);     
     lcd_puts("Done!          ");
     //clear_screen();
     lcd_com(FIRST_LINE);
     lcd_print_number(Ro);
     lcd_puts(" K Ohms");
     __delay_ms(1500);
     gas_detect = 0;
 while(1){
     if(gas_detect == 0){         
         lcd_com(FIRST_LINE);
         lcd_puts("Gas is present  ");
         lcd_com(SECOND_LINE);
         lcd_puts ("Gas ppm = ");
         float rs = read_mq();
         float ratio = rs/Ro;
        lcd_print_number(gas_plot_log_scale(ratio, MQ6_curve));
         __delay_ms(1500);
        clear_screen();
     }
     else{
         lcd_com(FIRST_LINE);
         lcd_puts("Gas not present  ");
         //lcd_com(SECOND_LINE);
        // lcd_print_number(gas_plot_log_scale(read_mq()/Ro, MQ6_curve));
     }
  }
}
 void system_init(){
     TRISB = 0; // LCD pins set to out. 
     gas_Detect_Pin_Direction = 1; //Configure RD0 as input
     lcd_init();
     ADC_Init();
     introduction_screen();
     //dht11_init();
 } 
 /*
 This Function is for Clear screen without command.
 */
void clear_screen(void){
    lcd_com(FIRST_LINE);
    lcd_puts("                ");
    lcd_com(SECOND_LINE);
    lcd_puts("                "); 
}
 /*
 This Function is for playing introduction.
 */
void introduction_screen(void){
    lcd_com(FIRST_LINE);
    lcd_puts("Welcome to");
    lcd_com(SECOND_LINE);
    lcd_puts("circuit Digest");
    __delay_ms(1000);
    __delay_ms(1000);
    clear_screen();
    lcd_com(FIRST_LINE);
    lcd_puts("MQ6 Sensor");
    lcd_com(SECOND_LINE);
    lcd_puts("with PIC16F877A");
    __delay_ms(1000);
    __delay_ms(1000);
}
/*
 * Sensor Related Functions
 */
float SensorCalibration(){
  int count;                                   // This function assumes that sensor is in clean air.
  float val=0;
  for (count=0;count<50;count++) {                   //take multiple samples and calculate the average value   
    val += calculate_resistance(ADC_Read(0));
    __delay_ms(500);
 }
  val = val/50;                  
  val = val/RO_VALUE_CLEAN_AIR;                        //divided by RO_CLEAN_AIR_FACTOR yields the Ro 
                                                        //according to the chart in the datasheet 
  return val; 
}
float read_mq()
{
  int count;
  float rs=0;
  for (count=0;count<5;count++) {                                 // take multiple readings and average it.
    rs += calculate_resistance(ADC_Read(0));   // rs changes according to gas concentration.
    __delay_ms(50);
  } 
  rs = rs/5;
  return rs;  
}
float calculate_resistance(int adc_channel)
{                                                         // sensor and load resistor forms a voltage divider. so using analog value and load value 
  return ( ((float)RL_VALUE*(1023-adc_channel)/adc_channel));     // we will find sensor resistor.
}
int gas_plot_log_scale(float rs_ro_ratio, float *curve)
{
    return pow(10,(((log(rs_ro_ratio)-curve[1])/curve[2]) + curve[0]));  
}

Video
TAGS
 PIC
 PIC16F877A
 GAS SENSOR
 GAS DETECTOR
 PIC MICROCONTROLLER





Get Our Weekly Newsletter!


Subscribe below to receive most popular news, articles and DIY projects from Circuit Digest

Email Address *

Name
Country                                                                                        
                                                                                              
                                                                     

Subscribe

RELATED CONTENT
PIC IoT WG Development Board Review – What’s new and How to Get Started with it

Interfacing DHT11 with PIC16F877A for Temperature and Humidity Measurement

DAC MCP4921 Interfacing with PIC Microcontroller PIC16F877A

Robotic Arm Control using PIC Microcontroller

Rotary Encoder Interfacing with PIC Microcontroller


IoT based Web controlled Home Automation using PIC Microcontroller and Adafruit IO

Generating PWM signals on GPIO pins of PIC Microcontroller

Heart Beat Monitoring using PIC Microcontroller and Pulse Sensor


 PREVIOUS POST
Interfacing ADXL345 Accelerometer with Arduino UNO
NEXT POST 
Arduino Solenoid Door Lock using RFID

COMMENTS

egealtay
Apr 17, 2020

o Log in or register to post comments

Gas detection PPM  this project is not working  can you help me.

LOG IN OR REGISTER TO POST COMMENT



Tubing Products
Heat shrink tubing provides insulation, protection, environmental sealing, and strain relief.


zSFP+ Stacked Interconnects
zSFP+ stacked interconnects are designed to save space and transfer data rates up to 56 Gbps PAM-4.


Expanded Line of VAL-U-LOK Connectors
VAL-U-LOK connectors offer a higher 13 A maximum current rating on 4.2 mm centerline spacing.


M12 X-Coded Ruggedized Connectors
The extremely ruggedized M12 connectors are designed for field assembly in the railway industry.


ELCON Micro Wire-to-Board Power Solutions
ELCON Micro power solutions provide a high current up to 12.5 A per pin in a 3.0 mm footprint.


LGA 4189 Socket and Hardware
LGA 4189 socket and hardware enable Intel® next-gen CPUs for fast turnaround time for prototypes.


STRADA Whisper R Backplane Connectors
STRADA Whisper R backplane connectors minimize skew with noise isolation and 360° grounding design.


TE 5G Networks
TE offers a full spectrum of ultra-compact, impossibly powerful solutions for 5G connectivity.
 NEWS
 ARTICLES
 PROJECTS

M5Stack ATOM - Smallest ESP32 Development Board for Portable Embedded and IoT Projects

Compact Non-Invasive Sensor Chip Developed to Record Multiple Heart and Lung Signals
New Family of QCS-AX2 Chipsets with 6GHz spectrum band for High throughput Wi-Fi 6E Applications

Digi-Key Electronics Announces Global Distribution Partnership with Fingerprint Cards AB

New Surface Mount DC-DC converters with Chiplet SiP technology for Reducing Package Size and Cost

FEATURED
PRODUCTS


Start your automotive design today with TI mmWave sensors
From long-range radar and lane-change assist to vital sign monitoring and child detection, TI mmWave sensors can be the primary sensing product in...

Kick-start your Wi-Fi development
Ramp to production in as little as 6 months with the newest SimpleLink™ Wi-Fi® LaunchPad™ development kits.


The CLB can customize what you need within your design.
Integrate custom logic and augment peripheral capability with C2000™ MCUs configurable logic block (CLB) peripheral.

Вам также может понравиться