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()

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 = ");

Here is the code to determine BAC:

float R0= 0.28;
void setup() {

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);
    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

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.


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:

Sensitivity curve

It can be seen here

Sensitivity curve - three regions

that there are three regions that the curve can be broken into:

  1. The relationship is linearly proportional between 2.25 V and 3.25 V
  2. Between 3.25 V and 3.8 V there is a curve
  3. 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:

Straight line approximation

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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