I am new to Arduino and electronics in general.I am working on MQ 7 Gas sensor to test Carbon monoxide level. But the issue is i still can't grasp the concept of converting analog readings to PPM. I tried to follow this ,but some parts, are very clear especially R0 = RS_air/(26+(1/3))

So far with my code below the ratio I get is between 20 and 30. Can someone help me complete the PPM calculation or point me in the right direction.Here is the Data sheet

Thank you in advance

int gasAnalogPin = A0;

void setup() {

  pinMode(gasAnalogPin, INPUT);


void loop() {

 float sensor_volt;
 float RS_air;
 float R0; 
 float sensorValue = 0;

  // A) preparation
    // turn the heater fully on
    analogWrite(gasAnalogPin, HIGH); 
    // heat for 1 min

    // now reducing the heating power: turn the heater to approx 1,4V
    analogWrite(gasAnalogPin, 286.72); // 255x1400/5000
     // heat for 90 sec

  // B) reading    
    // CO2 via MQ7
    analogWrite(gasAnalogPin, HIGH); 
    delay(50); // Getting an analog read apparently takes 100uSec

  for(int i = 0; i <= 100; i++){
    sensorValue = sensorValue + analogRead(gasAnalogPin);

 sensorValue = sensorValue/100.0; //get the avarage value
 sensor_volt = sensorValue/1024*5.0;
 RS_air = (5.0-sensor_volt)/sensor_volt;
 R0 = RS_air/(26+(1/3)); // Not sure how they came up with this ?

 float RS_gas = 0;
 float ratio = 0;

  sensor_volt = 0;
  sensorValue = 0;
  sensor_volt = 0;

  sensorValue = analogRead(gasAnalogPin);
  sensor_volt = sensorValue/1024*5.0;
  RS_gas = (5.0-sensor_volt)/sensor_volt;
  ratio = RS_gas/R0; //Replace R0 with the value found using the sketch above

  Serial.print("PPM:"); // How to calculate PPM?

  • \$\begingroup\$ One bug I see - you should set sensorValue to zero before reading the sensor 100 times. \$\endgroup\$ – Peter Bennett Jul 30 '18 at 23:34
  • \$\begingroup\$ Thank you for pointing that out , That was because of copy paste/editing .I corrected it. \$\endgroup\$ – sparks Jul 31 '18 at 0:04

You misunderstood the referenced article. The two code snippets are not supposed to work together in a loop.

First code is control. It reads sensor 100 times, calculates average and prints it out. This should be done in normal air conditions, i.e. with detectable gas concentrations at their safe levels. You take the printed value and place it into second code.

The second code is what actually supposed to run continuously in a loop. It reads sensor and compares it to previously obtained control value. This gives you current gas concentration relative to normal conditions.

Note, that better way to do this is to replace analogRead in the second code with inner loop, similar to the first, to get an average of 10-50 consecutive readings instead of a single read.


In order to calculate current PPM you need to find sensor resistance RS first. Normally it is done by simple formula for voltage divider: RS/RL = (V-Vs)/Vs, where RL is load resistor. When measured in clean air the calculated RS becomes R0. The first code uses this equation, however I have no idea why they divide this by some constant. IMHO the formula for ratio should be simple RS/R0 = RS_gas/RS_air. I suspect it is supposed to represent the gain of OP Amp used in their circuit somehow, but it would be pointless since the constant should be present in second code too, where they would cancel each other.

Regarding PPM calculation, first thing you should notice is that the relationship between RS/R0 and PPM is given on log-log scale. The second thing is that the graph in this scale is approximately linear. There are several methods to deal with this.

You can take the graph from datasheet and plot it on linear scale. The result would be exponential curve and you can use various tools to find exponential fit for it. This article has examples of exponential approximation and a code for some sensors.

You can also treat the graph as straight line y = ax + b but substitute x and y for their logarithms: log(y) = a * log(x) + b. Then you can use points on the graph in datasheet to find out slope (a) and offset (b). This seems to be exactly what the author of the referenced article is doing (although I am not sure the resulting formula is correct).

Finally, it seems the article is missing very important part of the functionality - the variable voltage supply. The circuit is supposed to switch between 1.5V and 5V for sensor to operate properly, according to datasheet. The measurements are done at low voltage, then it is heated up to clean adsorbed gases.

  • \$\begingroup\$ Thank you for the response .Yes i am aware of that.The snippets above is just example but my question is how do i complete calculating the PPM as you can see it is not complete.Also a bit of theory on the calculation works would help because in the articles and data sheets they dont bother explain in details. Thanks \$\endgroup\$ – sparks Jul 31 '18 at 0:22
  • \$\begingroup\$ @sparks I've added some explanations, although some things in those code snippets look weird to me. I could be missing some things there... or it could be buggy code. \$\endgroup\$ – Maple Jul 31 '18 at 2:13
  • \$\begingroup\$ Thank you @Maple. That was very helpful.That gave me a starting point.I will play with it again this coming weekend. \$\endgroup\$ – sparks Jul 31 '18 at 23:52

It's tempting to assume that the manufacturers datasheet gives you the solution in the form of a logarithmic response function from which you can derive an algorithm, but it doesn't. A common use of these sensors is in an alarm type of situation where the system integrator just needs to know when the sensor reaches ONE predetermined PPM level. Therefore it's pretty easy to characterize the sensor output by exposing the sensor to that PPM level repeatedly and measuring the output.

Converting sensor output to PPM is somewhat complicated and requires a deep understanding of the response characteristics of the sensor and almost always requires calibration. Sadly, the manufacturer's datasheets for those types of sensors do not typically provide enough information and you need to characterize the sensor response by exposing the sensor to different concentrations of the analyte (gas), measuring the output (be it voltage, resistance, etc) and running a regression analysis to determine the function. This is not a simple matter with MOS sensors. Two sensors from the same manufacturer can have very different responses to the same analyte concentration. Different pulse widths, heater voltages and load resistors can affect the output. Precision of the passives used is also important. The sensors also require temperature and relative humidity compensation to adequately convert the output to PPM.

To convert the sensor output to PPM you need to characterize the transducer by exposing it to known concentrations of the analyte, measure the output of the sensor at each concentration and develop a best fit algorithm. You need to be aware of integration time (i.e. how long does it take for the sensor to respond to exposure to the analyte). How many concentration levels you choose is dependent upon your requirements. You need to iterate this process several times to ensure repeatability OR to develop a known error margin. You need to then measure the temperature and relative humidity response characteristics or use the manufacturer's figures as a "best guess" and apply these offsets in firmware by having an on board T+RH sensor to generate compensation function inputs. Other methods to generate a PPM value include regression analysis with data from other, collocated, calibrated instruments. You also need to be aware of cross sensitivities, drift and sensor degradation. Drift and response degradation are why sensors need to be bump tested periodically, calibrated at regular intervals or discarded after a period of time.

Then, the low resolution linear ADC in the arduino presents a non trivial problem when measuring logarithmic output from a sensor like this.

However, you haven't really provided enough information to answer the question. You need to provide requirements like sensitivity, resolution, range, etc.


I also read the article in your link. There are many mistakes. MQ7 need to vary heating cycle so sensor need to be modified. Please read this link.


Then, you have to send PWM to control heater voltage. I also do not understand the equation R0 = RS_air/(26+(1/3)). [RL is ignore in all equations because it will be cancel each other when find ratio.] R0 should be R0=RS_air/x. x is ratio from graph. If you see in graph R0 is RS_Air value at 100ppm CO. So at 100ppm RS/R0=1 because it has same value. We do not have laboratory to set 100 ppm of CO to find real R0 value. At clean air, estimate that no CO, we can measure RS and convert to R0=RS/x. But why they say (26+1/3), it should be around 4-5. Also log10(0.09) has minus value and ppm = 100 * pow(log10(40)/log10(0,09), ratio) seem incorrect.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.