The

**MQ series are cheap gas sensors**.

They are resistive

**electro-chemical sensors**.

These sensors have a heating element and a resistance that react to gases.

Below a MQ135 sensor opened. Inside it looks like that.

To read the sensor's resistance, we measure the voltage drop of the sensor.

The method we use to measure resistance on the micro is by using the ADC, and a pull-up (or pull-down) resistor. Here http://electronics.stackexchange.com/a/70012 you can find a good explanation on the pull-down/up method on reading resistance.

Some people are asking me in my previous post about the MQ135 sensor, http://davidegironi.blogspot.it/2014/01/cheap-co2-meter-using-mq135-sensor-with.html how to obtain correlation function for other MQ series sensor, or other gas.

In this post I will explain a simple (to me) method of obtaining correlation function for any MQ series sensors that fit an exponential function.

An italian version of this article has been published in the may number of

**Elettronica In**(http://www.elettronicain.it/) magazine.

As a reference, let's consider the MQ135 sensor (again).

We will look at the "

*sensitivity characteristics of the MQ-135*" figure of the datasheet.

Notice that it's a log-log plot, this means that is has logarithmic scales on both axes.

Another thing to notice, is that the y-axis is for

*Rs/Ro*, it will be much clearer if we impose

*ppm*on the y-axis.

So as a first step, we will

**flip the axis**.

As a reference, above we will see a flip axis example

Now, let's take a look at a power function with different exponents.

Let's try to plot those function on a log-log scale.

You may notice that an exponential function flipped is again an exponential function, with different coefficient of course.

As you may see, the

**power function with a negative exponent**looks like the one we are searching for.

Summarizing, let's take the power function

*y=x^-2*and plot this on the log-log scale, with a 10 multiplier

We are searching for something like:

*y=a*x^b*

with b<0

Now, our purpose is to find out the value of the

*a*and

*b*constants, starting from the datasheet figure.

We can do this by performin a nonlinear regression. Specifically we need a

**power regression**.

First, we need to collect values from the datasheet figure.

*WebPlotDigitizer*is the tool we are going to use here: https://github.com/ankitrohatgi/WebPlotDigitizer. We can find few online tutorials that teach us how to use WePlotDigitalizer. I will try here to sum it up here:

1) extract the figure from the datasheet

2) load the figure on WebPlotDigitalizer

3) set axis, remember to se axis both as log

4) check out points from the curve of the gas you need to found

5) click on the view data button, and you get the points you need.

Now that we have found out the points of the curve from the datasheet, we need something to load with those points and perform a power regression.

You can use

*matlab*or you favorite math software tools. There are also other online tools you can use to perform power regressions. Here I will use an

**R**(ref. https://en.wikipedia.org/wiki/R_(programming_language)) script I've write.

You just have to load the points values you have found out, and launch this R script. You can also launch it on http://www.r-fiddle.org/.

The script will find out the function coefficients (a and b), and print out the function found next to the graph points, just to check the function's accuracy.

Below the Rs/Ro vs ppm function, as seen on the datasheet.

Then the flipped function we are searching for

Then, the plot of both functions on linear scale axes:

Now we have to

**estimate the Ro coefficient**.

Ro estimation is quite simple

We just need to solve this equation for Ro

ppm=a*(Rs/Ro)^b

Ro=Rs* sqrt(a/ppm,b)=Rs*(a/ppm)^(1/b)

note: in my library here: http://davidegironi.blogspot.it/2014/01/cheap-co2-meter-using-mq135-sensor-with.html i simply Ro as Rs*sqrt(a/ppm,b) = Rs*exp(ln(a/ppm)/b), which is the same that Rs*(a/ppm)^b.

So given the function coefficients, we have to

**measure the resistance of the sensor at a know amount**of ppm for the gas we are investigating.

Now, just substitute the found function coefficients (a and b), the resisteance we have read (Rs in ohm) at the amount of gas (ppm) to the estimation Ro function

Ro=Rs*(a/ppm)^b

One last step is to provide the Rs/Ro limits we are going to use to validate the input for our solving function ppm=a*(Rs/Ro)^b

We know that Rs/Ro=(ppm/a)^(1/b)

So

min[Rs/Ro]=(max[ppm]/a)^(1/b)

max[Rs/Ro]=(min[ppm]/a)^(1/b)

By the datasheet figure we have to select the max and min Rs/Ro and ppm points.

Notice that we get the max Rs/Ro value for the min ppm point value.

Here you can find the

**R script to estimate correlation function coefficients, compute Ro, min and max Rs/Ro**(input: x/y axis limits, correlation function points, resistance of the sensor in ohm at a know amount of gas in ppm).

On gist: https://gist.github.com/davidegironi/b7be6b7cace6b475dd42c48c3e62fcf4

Above an implementation of the raw value to ppm conversion,

**sample sketch for Arduino**:

//sensor input PIN int mqInput = A1; //pull-down resistor value int mqR = 22000; //rO sensor value long rO = 41763; //min value for Rs/Ro float minRsRo = 0.358; //max value for Rs/Ro float maxRsRo = 2.428; //sensor a coefficient value float a = 116.6020682; //sensor b coefficient value float b = -2.769034857; void setup() { pinMode(mqInput, INPUT); Serial.begin(9600); } void loop() { int adcRaw = analogRead(mqInput); long rS = ((1024.0 * mqR) / adcRaw) - mqR; Serial.print("Rs: "); Serial.println(rS); float rSrO = (float)rS / (float)rO; Serial.print("Rs/Ro: "); Serial.println(rSrO); if(rSrO < maxRsRo && rSrO > minRsRo) { float ppm = a * pow((float)rS / (float)rO, b); Serial.print("ppm: "); Serial.println(ppm); } else { Serial.println("Out of range."); } delay(1000); }

You can find the temperature and humidity correlation function here: http://davidegironi.blogspot.com/2017/07/mq-gas-sensor-correlation-function.html

**Notes**

- read risk disclaimer
- excuse my bad english

This comment has been removed by the author.

ReplyDeleteThis comment has been removed by the author.

ReplyDeleteSir please correct me if I am wrong

ReplyDeletefirst we have to calculate the value of scaling factor and exponential by using the R script you gave then we need to find the value of Ro for our sensor so we need to write the equation you gave for Ro and Rs/Ro and upload it to arduino and wait until 24 hours. After that we have to see the value of Ro and Rs/Ro by defining it as constant and then we can calculate ppm value.Sir please correct me if I am wrong

Hello. It something like this. You can use the R script to get the "a" and "b" factor, and also the Ro value by reading the resistance of the sensor (heated up for a few hours) at a know value of ppm. Then you can upload all to Arduno. By datasheet the sensor did consisten readings after 24 hours although it may takes just an hours to get good reading to me.

DeleteExcuse, how you get the value of RO =41763 ? I still confuse

DeleteThis comment has been removed by a blog administrator.

DeleteHello, Ro value is derive by the "a" and "b" factors for you gas curve, and the know amount of gas "ppm" reading the sensor resistance "Rs", in other words solving the formula: Ro=Rs*(a/ppm)^(1/b).

DeleteHello Sir, can you explain how to find this values below ?

ReplyDelete//pull-down resistor value

int mqR = 22000;

//rO sensor value

long rO = 41763;

//min value for Rs/Ro

float minRsRo = 0.358;

//max value for Rs/Ro

float maxRsRo = 2.428;

//sensor a coefficient value

float a = 116.6020682;

//sensor b coefficient value

float b = -2.769034857;

Hello Raka, you can take a look at the blog description above and the related video, it's all there.

DeleteDear Davide,

ReplyDeleteI was wondering how you came to a known value of ppm for a gas (CO2/NH4 etc.). Did you leave your sensor outside/inside and find the relative/general values of the ppm from references like google or the internet. I understand there is some percentage in the air that stays relatively constant. Otherwise I would like to know how you knew exactly what amount of ppm you put into the sensor without using another sensor to measure it! :)

Thank you very much in advance,

Naomi

Hello, it really depends on which gas are you trying to measure. For CO2 it was quite simple https://www.co2.earth/, for other gases, you must have a calibrated sensor or a tricky way to get a know amount of gas.

DeleteThank you for the fast reply. I think for the scale of my project the ship for the other gases has sailed. after a little bit of googling I also come to the same website. Thanks for sharing the website. Have a great evening :)

DeleteHow to get the value of RO = 41763 ?

ReplyDeleteHello, look at my reply "June 13, 2017 at 7:51 PM".

DeleteThis comment has been removed by a blog administrator.

ReplyDeleteHi Davide,

ReplyDeleteHow did you determine the RL value of the sensor? In the datasheet it says its adjustable and the sensor I have does not have the 6 pins but is attached to a blue sort of board and has 4 pins. I have no clue on how to determine the RL or is this an exterior resister I can add myself to the A0 to the Ground?

Hello, Rl is the load resistor. As example in the MQ135 datasheet it is stated to chose a value between 10k to 47k). It's a pull down resistor, take a look at the schematics here http://davidegironi.blogspot.it/2014/01/cheap-co2-meter-using-mq135-sensor-with.html

DeleteHi, first of all thanks for this nice article!

ReplyDeleteI bought the following mq135 module: http://www.ebay.de/itm/MQ-135-MQ135-Air-Quality-Sensor-Hazardous-Gas-Detection-Module-For-Arduino-AVR-/172115034015?

I (kind of ;) ) understood all the calculations but I am not sure how to set up the values from the module.

Can you give me any help?

Thanks,

Pedro Scaff.

Hello and thank you. You can use the sketch provided in this post as a starting point.

DeleteHello sir, I want to ask, is the program code can be used for sensor MQ-7?

ReplyDeleteHello, yes. The MQ-7 follow the same principles of this sensor. You have just to built up the conversion points, and the compute factors for the sensor you are using and the gas you would like to trace.

DeleteBefore I apologize if my language is still wrong, I want to introduce myself first, I am chan heldo, I come from Indonesia. I have the final task to make a CO gas detector using MQ-7 sensor. But I am still confused in making arduino program code for the MQ-7 sensor. I hope you can help me in making the program code. thank you

DeleteSir, why after I follow the above steps, but does not appear the ppm value in view?

DeleteHello, at first you have to check it out the factor you have found by simply reading the resistence of the sensor with a multimeter and applying the conversion formula with the factor values found. For CO and MQ-7 of course you can not use the a,b Ro value that I provide as sample, but you have to find your how using the method of this blog post.

DeleteHi Sinaga, hi Davide,

DeleteI just worked through the MQ-7 and I got the values for MQ-7 CO (not the heater/RL values, I used a module that already does this part). I didn't do a power regression since there were two points that were exactly marked on the data sheet. Here is the octave/matlab code and the final equation:

% Inverting x and y axis, points on data sheet: `p0 = (0.09, 4000)` `p1 = (1, 100)`

% the x axis represents the ratio Rs/R0

% the y axis represents the ppm CO concentration

% https://en.wikipedia.org/wiki/Log%E2%80%93log_plot

% a straight line on a log-log plot can be represented as a power function

% where the slope m = log(y1,y0)/log(x1/x0)

% and the equation for Y = a * (x^m)

% for the point (1,100) we have a = 100

% octave code for the slope m

x = [0.09, 4000]

y = [1, 100]

m = log(y(2),y(1))/log(x(2)/x(1))

% our final equation for CO ppm concentration is

% ppm = 100 * (Rs/R0)^-1.53

% from data sheet: Rs/Ro = (Vcc - VRL) / VRL

Thanks for this post, Davide, it has been very helpful for my bachelor thesis :). I also used this post as a helper, and I guess I corrected the value he found there a little bit ;): http://forum.arduino.cc/index.php?topic=294085.0

This comment has been removed by the author.

Deleteand complementary from the post on the arduino forum I mentioned above:

DeleteRs = RL * (VCC / VRL - 1)

ppmCO = 100 * (RL/Ro * (VCC/VRL - 1))^-1.53

Hello Pedro. Thank you for your feedback and thank you for sharing your results here. Congratulations for your thesis.

DeleteHi pedro, thanks for your response Have you ever designed a tool using the MQ-7 sensor? Can you help me to complete my task? and Can you give me your email? Or you can chat with me at sinagabonor2320@gmail.com. Sorry if my language is still wrong

DeleteThis comment has been removed by the author.

ReplyDeleteHi,

ReplyDeleteI am having hard time for converting analog data from Aurdino sensor to ppm. I am using MQ131 ozone sensor. Can I apply same steps shown in this blog for MQ 131 sensor?

Hello, yes you can apply all the proposed steps, but for calibration you have to know the O3 ppm and of course the resistance of the sensor.

DeleteHi Davide,

DeleteDo we measure the resistance between "ground pin" and "analog pin" in the sensor to get "mres" if we know the value of ozone ppm?

Hello, power up the sensor header (one Hpin to GND, the other to VCC), then read with a multimeter the value between A and B pin. Start with a multimeter and a spreadsheet, then you can go through a microcontroller.

DeleteHi Davide, I am working with ozone sensor and i could not understand how "long rS = ((1024.0 * mqR) / adcRaw) - mqR;" came in the formula. I am using the same formula as in your blog, just changing the values and I am not sure if it is correct because it does not match with the photometric ozone analyser that we have in our university. I was wondering if you can explain "long rS = ((1024.0 * mqR) / adcRaw) - mqR;" line in the formula.

DeleteHello, that is the ADC raw value to resistance value conversion formula for a 10bit adc. Take a look here: https://learn.adafruit.com/thermistor/using-a-thermistor it may help.

DeleteHi Davide,

ReplyDeleteI am working with MQ-4 sensor. In your video at 3:08, you mentioned a value of 26954 ohm at 392 ppm. Where did you get that value?

How can I get this value for MQ-4 sensor to calculate methane in ppm. You help would be highly appreciated.

Hello, you have to measure the resistance of the sensor between A and B pin when it's in a know amount of gas. In my example it was in 392ppm of CO2, and i measure 26954ohm. You have to put your sensor in a know amount of methane and measure the resistance of it, please be carefull with CH4.

DeleteIf We use the values obtained from graph provided with datasheet with the help of WebPlotDigitilizer, Will it not be sufficient to get ppm value with marginal accuracy?

DeleteHello, it depends on what you mean with sufficient. Also it depends on the gas you are trying to measure. Let's say you get a relistic idea of what it could be the gas amount in ppm :)

DeleteDear David,

ReplyDeleteI was trying to reproduce your project for measuring CO2. I followed the same process you explain on the video, i've got the following values:

rO = 42842; a = 111.336; b = -2.716215;

which are sufficiently close to those you're reporting.

The problem is that i am obtaining Rs/Ro values around 7 and they continue incresing (now they are around 20) thus going further from the maxRsRo = 2.428. Of course the result is an "out of range" message.

However, i also performed the same process using the values of r0, a and b that you are using.

What are the chances that I am doing wrong?

Thank you in advance for your help.

Hello, at first connect you sensor and measure the resistance of the sensor using a multimeter. Then check that your resistance value measured on your micro is almost the same. You should get a resistance value on range, if not it could be your sensor. A valid resistance should be something around 30K.

Delete