I tried to build project to detect alcohol with Arduino Uno and an MQ-3 Alcohol sensor.
I already have the R0
value, but I faced problem here: I don't know how to convert it to PPM or BAC. I already tried some code from tutorial for convert it to BAC but when I gave the sensor alcohol the code gives me a value of 0.00
, and I don't know why.
Here is the code to find R0
value:
void setup()
{
Serial.begin(9600);
}
void loop()
{
float sensor_volt;
float RS; // Get the value of RS via in a clear air
float R0; // Get the value of R0 via in Alcohol
float sensorValue;
for(int i = 0 ; i < 100 ; i++)
{
sensorValue = sensorValue + analogRead(A0);
}
sensorValue = sensorValue/100.0; //get average of reading
sensor_volt = sensorValue/1024*5.0;
RS = (5.0-sensor_volt)/sensor_volt; //
R0 = RS/60.0; // 60 is found using interpolation
Serial.print("R0 = ");
Serial.println(R0);
delay(1000);
}
Here is the code to determine BAC
:
float R0= 0.28;
void setup() {
Serial.begin(9600);
}
void loop() {
float sensor_volt;
float RS_gas; // Get value of RS in a GAS
float ratio; // Get ratio RS_GAS/RS_air
float BAC;
int sensorValue = analogRead(A0);
sensor_volt=(float)sensorValue/1024*5.0;
RS_gas = (5.0-sensor_volt)/sensor_volt; // omit *RL
/*-Replace the name "R0" with the value of R0 in the demo of First Test -*/
ratio = RS_gas/R0; // ratio = RS/R0
float a = pow(ratio, 2);
float b = ratio/10;
BAC = (0.1896*a) - (8.6178*b) + 1.0792 ; //BAC in mg/L
Serial.print("BAC = ");
Serial.println(BAC*0.0001); //convert to g/dL
Serial.print("\n\n");
delay(1000);
}
I would to know what's wrong with the code, and if you know how to convert the R0
values to PPM, please tell me.
-
figure 5 in the datasheet shows the relation between the output voltage and PPM value .... cdn.sparkfun.com/datasheets/Sensors/Biometric/… ........... you have to use a lookup table to convert the valuejsotola– jsotola2018年07月18日 07:16:15 +00:00Commented Jul 18, 2018 at 7:16
1 Answer 1
A series of if()
statements and some simple division should be able to provide you with your PPM results.
From the datasheet, Alcohol Gas Sensor(Model:MQ-3), figure 5 shows the sensitivity curve:
It can be seen here
Sensitivity curve - three regions
that there are three regions that the curve can be broken into:
- The relationship is linearly proportional between 2.25 V and 3.25 V
- Between 3.25 V and 3.8 V there is a curve
- The relationship is linearly proportional between 3.8 V to 4.25 V
The slope of the straight line regions described in points 1 and 3 can be represented by the use of a constant and the PPM value by a simple division of the voltage by the constant.
The curve from the second part could be:
- approximated by a straight line (thus, once again, using a constant), for simplicity, or;
- more accurately, using a lookup table.
Using a straight line approximation for the curve (shown in lurid green), the graph becomes:
To determine the constant for the three lines simply take two points on each line and use:
(y2 - y1) / (x2 - x1)
So for region one, assuming (by approximation, 3 V corresponds to 100 ppm and 2.5 V corresponds to 85 ppm (my eye sight may be slightly off here), the slope is
(3 - 2.5)/(100-80) = 0.5/20 = 0.025
You can calculate the constants for regions two and three in a similar manner (if using a straight line approximation for region two).
Therefore the code would be alomg the lines of
const double kRegionOne = 0.025; // region one constant
const double kRegionTwo = ???; // region two constant
const double kRegionThree = ???; // region three constant
int ppm; // ppm result
/*
* your code here
* ...
*/
if ((sensor_volt < 3.25) && (sensor_volt >= 2.25)) {
ppm = sensor_volt/kRegionOne; // we are in region 1
} else if ((sensor_volt < 3.8) && (sensor_volt >= 3.25)) {
ppm = sensor_volt/kRegionTwo; // we are in region 2
} else if (sensor_volt >= 3.8) {
ppm = sensor_volt/kRegionThree; // we are in region 3
}
If you wish to be more accurate then use a lookup table for region two, as jsotola states in their comment.