World-class manufacturing

Understanding a Gas Sensor

image of gas sensor
Table of Contents

A Gas sensor’s working principle is serve to measure the concentration of gases in the environment. There are many different types depending on what you want to measure. In this case, the MQ-4 natural gas sensor can measure Liquefied Petroleum Gas (LPG), Methane (CH4), Hydrogen (H2), Carbon Monoxide (CO), alcohol, and smoke concentrations.

image of gas sensor
Gas Sensor

The sensor has a built in variable resistor that changes its value according to the concentration of gas. If the concentration is high, the resistance decreases. If the concentration is low, the resistance increases. Besides the built in resistor, it is necessary to include a load resistor. This resistor serves to adjust the sensor’s sensitivity and accuracy. The value can range anywhere from 2k Ohms to 47k Ohms. The higher the value, the more sensitive the sensor becomes.

The value depends on whether you want to measure high concentrations of gas or not. If you choose to measure high concentrations of gas, but choose a high value for the load resistor, then the readings won’t be very accurate. Lastly, there is another built-in resistor used for the heater of the sensor. The heater is used to provide the temperature that the sensor needs to work properly. In the end, we have a circuit like this:

image of sensor circuit
Figure 1: Sensor Circuit

Which can also be seen as this:

image of sensor circuit 2
Figure 2: Sensor Circuit

Where H, A, and B are the pins of the sensor.

image of sensor pinout
Figure 3: Sensor Pinout (Bottom View)

Even though the sensor has six pins in total, pins A and pins B are connected together, leaving us with four connections.

image of sensor pins combined
Figure 4: Sensor Pins combined

Between A and B there is the built-in resistor that varies depending on the gas concentration. Between H and H there is the built-in resistor for the heater.

How do we calculate gas concentrations from the variation of resistance? Here is where this data sheet comes in handy.

image of mq4 sensitivity characteristics
Figure 5: MQ-4 Sensitivity Characteristics

Figure 5 tells us the concentration of a gas in part per million (ppm) according to the resistance ratio of the sensor (RS/R0). RS is the resistance of the sensor that changes depending on the concentration of gas, and R0 is the resistance of the sensor at a known concentration without the presence of other gases, or in fresh air.

Calculations

We can derive a formula to find RS using Ohm’s Law:

V = I x R

Where V is voltage, I is current, and R is resistance. Looking back at the circuit from Figure 1, we can see that RS, which is the resistor between pins A and B, and RL are in series. Thus, we can simplify the circuit as shown below:

image of sensor circuit simplified
Figure 6: Sensor Circuit Simplified

Now we combine the two resistors in series

image of rs and rl combined
Figure 7: RS and RL combined

From Ohm’s Law, we can derive I as follows:

I = V / R

Which in our circuit is equal to:

I = VC / (RS+RL)

Going back to our original circuit from Figure 6, we can obtain the output voltage at the load resistor using the value obtained for I and Ohm’s Law.

V = I x R
VRL = [VC / (RS + RL)] x RL
VRL = (VC x RL) / (RS + RL)

So now we solve for RS:

VRL x (RS + RL) = VC x RL
(VRL x RS) + (VRL x RL) = VC x RL
(VRL x RS) = (VC x RL) – (VRL x RL)
RS = [(VC x RL) – (VRL x RL)] / VRL
RS = [(VC x RL) / VRL] – RL

This formula will help us find the values of the sensor resistance for different gases.

From the graph, we can see that the resistance ratio in fresh air is a constant:

RS / R0 = 4.4 ppm

To calculate R0 we will need to find the value of the RS in fresh air. This will be done by taking the analog average readings from the sensor and converting it to voltage. Then we will use the RS formula to find R0. We will show you how to do this in the Arduino IDE after the wiring setup.

Now let’s analyze the graph:

  1. The scale of the graph is log-log. This means that in a linear scale, the behavior of the gas concentration with respect to the resistance ratio is exponential.
  2. The data for gas concentration only ranges from 200 ppm to 10000 ppm.
  3. Even though the relation between resistance ratio and gas concentration may seem linear, in reality, it is not.

First of all, we will treat the lines as if they were linear. This way we can use one formula that linearly relates the ratio and the concentration. By doing so, we can find the concentration of a gas at any ratio value even outside of the graph’s boundaries. The formula we will be using is the equation for a line, but for a log-log scale. The formula for a line is:

y = mx + b

Where:

y: X value
x: X value
m: Slope of the line
b: Y intercept

For a log-log scale, the formula looks like this:

log(y) = m*log(x) + b

Note: the log is base 10.

Okay, let’s find the slope. To do so, we need to choose 2 points from the graph. In our case, we chose the points (200,2.6) and (10000,0.75) from the LPG line. The formula to calculate m is the following:

m = [log(y) – log(y0)] / [log(x) – log(x0)]

If we apply the logarithmic quotient rule we get the following:

m = log(y/y0) / log(x/x0)

Now we substitute the values for x, x0, y, and y0:

m = log(0.75/2.6) / log(10000/200)
m = -0.318

Now that we have m, we can calculate the y intercept. To do so, we need to choose one point from the graph (once again from the LPG line). In our case, we chose (5000,0.9)

log(y) = m*log(x) + b
b = log(y) – m*log(x)
b = log(0.9) – (-0.318)*log(5000)
b = 1.13

Now that we have m and b, we can find the gas concentration for any ratio with the following formula:

log(x) = [log(y) – b] / m

However, in order to get the real value of the gas concentration according to the log-log plot we need to find the inverse log of x:

x = 10 ^ {[log(y) – b] / m}

If you are not sure how logarithms work, you can refer to this guide.

Materials

Now that we have the necessary background, we can start working on building the gas sensor using Arduino. We will calculate the gas concentration of LPG (butane) in the air and display it on an OLED screen. If the concentration is too high, a red LED will be turned on, and a buzzer will be activated. These are the materials required for this project:

  • Arduino Pro Mini
  • 330 Ohm Resistor
  • 10 Kohm Resistor
  • Red LED
  • Buzzer
  • Wires
  • Methane Gas Sensor MQ-4
  • 5V FTDI Basic USB to Serial Converter
  • USB 2.0 Cable (A to Mini B)
  • Protoboard
  • 0.91” Monochrome OLED Display

Wiring

Solder some wires to the gas pins and add heat shrinking tubing:

image of wiring

In our case, the orange wires represent A, the blue wires represent B, and the red wires represent H. If you want, you can make the blue wires A and the orange wires B, there is no polarity in these pins.

Wire the sensor to the Arduino as follows:

Gas sensorArduino Pro Mini
AVCC
BPin A0
HVCC
HGND

Connect a 10k ohm resistor from A0 to ground:

image of conec 10ohm resistor from a0 to ground

Connect the OLED to the Arduino as shown below:

image of connect the oled to the arduino as shown below 1
image of connect the oled to the arduino as shown below 2
OLEDArduino Pro Mini
SDAPin 4
SCLPin 5
RESPin 11
GNDGND
VCCVCC

Connect anode side of LED to Arduino’s pin 10 and cathode side to a 330 ohm resistor. Connect the other end of the 330 ohm resistor to GND.

image of Connect anode side of LED to Arduino’s pin 10 and cathode side to a 330 ohm resistor
Connect the other end of the 330 ohm resistor to GND

Connect positive side of buzzer to Arduino’s pin 9. The positive side is marked by “+” on the buzzer. Connect the negative side of the buzzer to GND.

Connect positive side of buzzer to Arduino’s pin 9
Connect the negative side of the buzzer to GND

Code to Calculate R0

Code to Calculate R0
void setup() {
Serial.begin(9600); //Baud rate
}

void loop() {
float sensor_volt; //Define variable for sensor voltage
float RS_air; //Define variable for sensor resistance
float R0; //Define variable for R0
float sensorValue; //Define variable for analog readings
for(int x = 0 ; x < 500 ; x++) //Start for loop
{
sensorValue = sensorValue + analogRead(A0); //Add analog values of sensor 500 times
}
sensorValue = sensorValue/500.0; //Take average of readings
sensor_volt = sensorValue(5.0/1023.0); //Convert average to voltage RS_air = ((5.010.0)/sensor_volt)-10.0; //Calculate RS in fresh air
R0 = RS_air/4.4; //Calculate R0

Serial.print(“R0 = “); //Display “R0”
Serial.println(R0); //Display value of R0
delay(1000); //Wait 1 second
}

Code Explanation

void setup() {
Serial.begin(9600); //Baud rate
}

The setup section starts serial communication at 9600 bits per second.

void loop() {
float sensor_volt; //Define variable for sensor voltage
float RS_air; //Define variable for sensor resistance in air
float R0; //Define variable for R0
float sensorValue; //Define variable for analog readings

Here we are defining the variables that will be used to calculate R0.

for(int x = 0 ; x < 500 ; x++) //Start for loop
{
sensorValue = sensorValue + analogRead(A0); //Add analog values of sensor 500 times
}

The “for loop” is used to add 500 samples of the analog readings from the sensor.

sensorValue = sensorValue/500.0; //Take average of readings
sensor_volt = sensorValue(5.0/1023.0); //Convert average to voltage RS_air = ((5.010.0)/sensor_volt)-10.0; //Calculate RS in fresh air
R0 = RS_air/4.4; //Calculate R0

In this section, we calculate the average of the analog readings. Then we convert the value to voltage (the value will range from 0-5V). This voltage represents Vout in Figure 2. Next we calculate RS in fresh air using the formula derived in the Calculations section. Lastly we calculate R0 based on the value of RS and the ratio constant obtained from the graph.

Serial.print(“R0 = “); //Display “R0”
Serial.println(R0); //Display value of R0
delay(1000); //Wait 1 second

Once we find R0, we display its value in the serial monitor. Let the code run for some time until the sensor stabilizes. Also, take note of the value since it will be used in the next code.

Code to Calculate Gas Concentration

include //Library for SPI interface
include //Library for I2C interface
include //Core graphic library for displays
include //Library for OLED display

define OLED_RESET 11 //Reset pin
Adafruit_SSD1306 display(OLED_RESET); //Set Reset pin for OLED display

int led = 10; //LED pin
int buzzer = 9; //Buzzer pin
int gas_sensor = A0; //Sensor pin
float m = -0.318; //Slope
float b = 1.133; //Y-Intercept
float R0 = 11.820; //Sensor Resistance in fresh air from previous code

void setup() {
Serial.begin(9600); //Baud rate
display.begin(SSD1306_SWITCHCAPVCC, 0x3C); //Initialize screen
display.setTextColor(WHITE); //Set text color
display.setTextSize(3); //Set text size
pinMode(led, OUTPUT); //Set LED as output
digitalWrite(led, LOW); //Turn LED off
pinMode(buzzer, OUTPUT); //Set buzzer as output
digitalWrite(buzzer, LOW); // Turn buzzer off
pinMode(gas_sensor, INPUT); //Set gas sensor connection as input
}

void loop() {
display.clearDisplay(); //Clear display
display.setCursor(0,5); //Place cursor in (x,y) location
float sensor_volt; //Define variable for sensor voltage
float RS_gas; //Define variable for sensor resistance
float ratio; //Define variable for ratio
float sensorValue = analogRead(gas_sensor); //Read analog values of sensor
sensor_volt = sensorValue(5.0/1023.0); //Convert analog values to voltage RS_gas = ((5.010.0)/sensor_volt)-10.0; //Get value of RS in a gas
ratio = RS_gas/R0; // Get ratio RS_gas/RS_air

double ppm_log = (log10(ratio)-b)/m; //Get ppm value in linear scale according to the the ratio value
double ppm = pow(10, ppm_log); //Convert ppm value to log scale
double percentage = ppm/10000; //Convert to percentage
display.print(percentage); //Load screen buffer with percentage value
display.print(“%”); //Load screen buffer with “%”
display.display(); //Flush characters to screen

if(ppm>2000){ //Check if ppm value is greater than 2000
digitalWrite(led, HIGH); //Turn LED on
digitalWrite(buzzer, HIGH); //Turn buzzer on } else{ //Case ppm is not greater than 2000 digitalWrite(led, LOW); //Turn LED off digitalWrite(buzzer, LOW); //Turn buzzer off } }

Code Explanation

include //Library for SPI interface
include //Library for I2C interface
include //Core graphic library for displays
include //Library for OLED display
define OLED_RESET 11 //Reset pin
Adafruit_SSD1306 display(OLED_RESET); //Set Reset pin for OLED display

We start by including the libraries required for I2C and SPI communication (OLED displays use either SPI or I2C interface). We also include the libraries required to control the OLED display. You can download such libraries here and here.

Then we assign an Arduino pin to reset the OLED screen, and let the SSD1306 library know what pin we are using.

int led = 10; //LED pin
int buzzer = 9; //Buzzer pin
int gas_sensor = A0; //Sensor pin
float m = -0.318; //Slope
float b = 1.133; //Y-Intercept
float R0 = 11.820; //Sensor Resistance in fresh air

Here we assign the corresponding Arduino’s pins to the LED, buzzer, and sensor. We also define our slope, y-intercept, and R0. R0 is the value obtained from the previous code.

void setup() {
Serial.begin(9600); //Baud rate
display.begin(SSD1306_SWITCHCAPVCC, 0x3C); //Initialize screen
display.setTextColor(WHITE); //Set text color
display.setTextSize(3); //Set text size
pinMode(led, OUTPUT); //Set LED as output
digitalWrite(led, LOW); //Turn LED off
pinMode(buzzer, OUTPUT); //Set buzzer as output
digitalWrite(buzzer, LOW); // Turn buzzer off
pinMode(gas_sensor, INPUT); //Set gas sensor as input
}

In the setup section, we initialize the OLED screen and set the color and size of the text that will be displayed on our screen. We also set the buzzer and LED as outputs and turned them off. Lastly we set the sensor as input.

void loop() {
display.clearDisplay(); //Clear display
display.setCursor(0,5); //Place curson in (x,y) location
float sensor_volt; //Define variable for sensor voltage
float RS_gas; //Define variable for sensor resistance
float ratio; //Define variable for ratio
float sensorValue = analogRead(gas_sensor); //Read analog values of sensor
sensor_volt = sensorValue(5.0/1023.0); //Convert analog values to voltage RS_gas = ((5.010.0)/sensor_volt)-10.0; //Get value of RS in a gas
ratio = RS_gas/R0; // Get ratio RS_gas/RS_air

In the loop, we erase everything that the screen is displaying. Then we set the cursor at the beginning of the screen and somewhat centered in the y-axis. Next we define the variables that will be used to calculate RS in the presence of a gas. Then we read the analog values obtained from the sensor, convert them to voltage, calculate RS using the derived formula, and find the resistance ratio.

double ppm_log = (log10(ratio)-b)/m; //Get ppm value in linear scale according to the the ratio value
double ppm = pow(10, ppm_log); //Convert ppm value to log scale
double percentage = ppm/10000; //Convert to percentage
display.print(percentage); //Load screen buffer with percentage value
display.print(“%”); //Load screen buffer with “%”
display.display(); //Flush characters to screen

Once we have the ratio, we find its corresponding value of gas concentration according to the graph. Then we convert the concentration to percentage using the following formula:

x(%) = x(ppm) / 10000

Once we have the percentage, we display it on our screen.

if(ppm>2000){ //Check if ppm value is greater than 2000
digitalWrite(led, HIGH); //Turn LED on
digitalWrite(buzzer, HIGH); //Turn buzzer on
}
else{ //Case ppm is not greater than 2000
digitalWrite(led, LOW); //Turn LED off
digitalWrite(buzzer, LOW); //Turn buzzer off
}

According to this document, exposure to 2000 ppm of LPG gas is immediately dangerous to life and health. In this section, we are constantly checking if there is more than 2000 ppm of LPG in the air. If the case is true, then we turn on the LED and buzzer to alert that there is a high concentration of LPG.

Results

The percentage readings obtained are only approximations of the real values. If you want to get more accurate results, then you can do the following:

  • Since the heater of the sensor draws a lot of current and the sensor needs 5V to work properly, it is better if you use an external power supply that assures you a voltage input of 5V with enough current for the heater (The Arduino provided a little less than 4.6V when tested). The Arduino Mini Pro has an internal 5V regulator, so you can connect an external power supply (no more than 12V) to the Raw pin. Alternatively, this tutorial shows you how to setup a 5V regulated power supply:
  • When getting the R0 value, do it in a clean environment where no other gases are present.
  • The datasheet recommends to calculate R0 in an environment that has 10000 ppm of methane. If you can simulate such environment, calculate R0 under these conditions.
  • Let the sensor preheat for a good amount of time (48 hours according to the datasheet), so that the readings stabilize. The longer it preheats, the more accurate readings you will get.

Related Post

Top 15 Design Software for 3D Printing

Explore top 3D printing software, perfecting your manufacturing with Jaycon.

Clear Plastic Molding: Material and Design Guide

Dive into the world of clear plastic molding. Learn the best materials and design…

Raspberry Pi vs Arduino: Which One Should You Choose?

Introduction Raspberry Pi and Arduino are two popular platforms in the maker world. The…