Go Down

Topic: How can I convert AnalogRead to something useful? (Read 11 times) previous topic - next topic

cronus

Hi,

I am using an MQ-7 CO sensor, and I have wired it as recommended in
http://www.parallax.com/Portals/0/Downloads/docs/prod/sens/MQ-7.pdf

I am using an RL of 20k ohm, and having implemented the variable voltage for the heater using PWM, I am getting readings of sorts from the analog read (typically around 950).

How can I go about converting this into ppm, as per the datasheet? I can't figure out what it is expecting me to do.

Regards,


robtillaart

#1
Mar 20, 2011, 12:06 pm Last Edit: Mar 20, 2011, 01:01 pm by robtillaart Reason: 1
No experience myself but a little google resulted in:

- http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1282621823
- http://thesis.jmsaavedra.com/prototypes/software/mq-7-breakout-arduino-library/

The datasheet is not the most clear one I've seen. This is what I understand:
- The MQ7 is not easiest sensor
- it is temperature and humdity sensitive  (but in a first experiment this may be ignored)
- you need to calibrate it before it can be used.
- the reference is 100 PPM (but it uses a 10K for RL)
- you should read a value at the end of the 1.4Volt modus when it peaks. (point b page 3)

That all said I come to something like:

The formula  Rs\RL = (Vc-VRL) / VRL can be rewritten to Rs = RL * (Vc-VRL) / VRL
Vc = 5 Volts (I assume)

bringing this into the formula:

float Vrl = 5.0 * analogRead(A1) / 1023;
float Rs = 20K * ( 5.0 - Vrl) / Vrl;

So now you have a formula to make the reference measurement Ro.

If you make a measurement Rs then you can calculate the ratio Rs/Ro which can be looked up the diagram in the datasheet. To do this automagically you need to create a lookup table. The Rs/R0 varies from 0.05 - 1.5. As floats cannot be used as an index for a lookup table you better multiply them with 20 giving the values 1..30. The table is filled with PPM values.

This results in code something like below. (not complete, only indicative code, no guarantees, all disclaimers apply :)
Code: [Select]

float Ro = xxx.yyy;

void setup()
{
}

void loop()
{
 waitForTheRightMoment();  // to be elabotated.

 float Vrl = 5.0 * analogRead(A1) / 1023;
 float Rs = 20K * ( 5.0 - Vrl) / Vrl;
 int ratio = 20 * Rs/Ro;
 ratio = constrain(ratio, 0, 30);
 Serial.print ( "CO :");
 Serial.println(LUT[ratio]);

}


Should help you forwards
rob

-- update --

- check - http://nootropicdesign.com/projectlab/2010/09/17/arduino-breathalyzer/

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

thermike

Hi everybody, I don't fully understand why Rs/Rl = (Vc-Vrl) / Vrl

robtillaart

Quote
Hi everybody, I don't fully understand why Rs/Rl = (Vc-Vrl) / Vrl


Hi Thermike,

Take figure 2 of the datasheet:

The resistance of the sensor Rs is the unknown value and need to be searched for.  note that Rs and Rl make a voltage divider which converts Vc into Vrl.

We know that the current through Rl equals the current through Rs:   

(1) Ampere(RL)  == Ampere(Rs) 

Ohms law states A = V/R:

So we can express the currents as:

(2) Ampere(RL) = Vrl/Rl
(3) Ampere(Rs) = (Vc-Vrl)/Rs
    // e.g. Vc = 5Volt and Vrl = 3Volt, the voltage over Rs = 5-3 = 2Volt

filling (2) and (3) into (1) gives:

(4) Vrl/Rl  == (Vc-Vrl)/Rs

Multiply with Rs on both sides gives:

(5)  Rs*Vrl/Rl == (Vc -Vrl)

Divide by Vrl on both sides gives:

(6) Rs/Rl  == (Vc -Vrl)/Vrl

QED,

Hopes this helpes.

Rob

@Cronus & Thermike
if you succeeded in making a working sketch, please post your code / schematics
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

thermike

Based on robtillaart's approach:

// GAS SENSOR MQ-2

// This sensor can detect smoke, methane, carbon dioxide and other gases


//VARIABLES
float Ro = 10000.0;    // this has to be tuned 10K Ohm
int sensorPin = 0;  // select the input pin for the sensor
int ledPin = 13;    // select the pin for the LED
int val = 0;        // variable to store the value coming from the sensor
float Vrl = 0.0;
float Rs = 0.0;
float ratio = 0.0;



// SETUP
void setup() {
pinMode(ledPin, OUTPUT); // declare the ledPin as an OUTPUT
Serial.begin(9600);      // initialize serial communication with computer
// analogReference(EXTERNAL);
}

// get CO ppm
float get_CO (float ratio){
  float ppm = 0.0;
  ppm = 37143 * pow (ratio, -3.178);
return ppm;
}

// LOOP
void loop() {
 
val = analogRead(sensorPin);     // read the value from the analog sensor
Serial.println(val);             // send it to the computer (as ASCII digits)
digitalWrite(ledPin, HIGH);      // turn the ledPin on
delay(100);                      // stop the program for some time
digitalWrite(ledPin, LOW);       // turn the ledPin off
delay(100);                      // stop the program for some time

Vrl = val * ( 5.00 / 1024.0  );      // V
Rs = 20000 * ( 5.00 - Vrl) / Vrl ;   // Ohm
ratio =  Rs/Ro;                     

Serial.print ( "Vrl / Rs / ratio:");
Serial.print (Vrl);
Serial.print(" ");
Serial.print (Rs);
Serial.print(" ");
Serial.println(ratio);
Serial.print ( "CO ppm :");
Serial.println(get_CO(ratio));


delay(10000);
}

With the following to mention and ask:
1. Ro has somehow to be figured out and I can't imagine how to make the tuning
2. Rl suggested as 20000ohms but has to be tuned as well
3. I preferred to make a correlation here instead of LUT. I made a table with x's and y's out of the graph and correlated the results

Rs/Ro   ppm
5   200
4   500
3,5   800
3   1000
2,5   2000
2,2   3000
1,9   5000
1,5   10000
then when you correlate you get y = 37143x-3,178 with a R² = 0,9948

What do you all think?


Go Up