# Understanding a Gas Sensor

Gas Sensor

Gas sensors 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 gas sensor can measure Liquefied Petroleum Gas (LPG), Methane (CH4), Hydrogen (H2), Carbon Monoxide (CO), alcohol, and smoke concentrations.

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:

Figure 1: Sensor Circuit

Which can also be seen as this:

Figure 2: Sensor Circuit

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

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.

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.

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:

Figure 6: Sensor Circuit Simplified

Now we combine the two resistors in series

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 link:

Materials

Now that we have the necessary background, we can start working on the tutorial. 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:

Wiring

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

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 sensor Arduino Pro Mini A VCC B Pin A0 H VCC H GND

Connect a 10k ohm resistor from A0 to ground:

Connect the OLED to the Arduino as shown below:

 OLED Arduino Pro Mini SDA Pin 4 SCL Pin 5 RES Pin 11 GND GND VCC VCC

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.

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.0*10.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.0*10.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 <SPI.h> //Library for SPI interface
#include <Wire.h> //Library for I2C interface
#include <Adafruit_GFX.h> //Core graphic library for displays
#include <Adafruit_SSD1306.h> //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 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.0*10.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 <SPI.h> //Library for SPI interface
#include <Wire.h> //Library for I2C interface
#include <Adafruit_GFX.h> //Core graphic library for displays
#include <Adafruit_SSD1306.h> //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:

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.0*10.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.

This article was published by the Jaycon team. Learn more about how we can take your product design and hardware idea to the next level here.