MQ-3 Alcohol Gas Sensor

Hi,i was wondering how to convert the MQ-3 analog voltage output measured to ppm value?your reply would be a great help :slight_smile:

This page has some basic explanation,

The MQ gas sensors are electro-chemical. If “something” is detected the resistance is lowered for a “certain” amount. You can measure the ppm after calibration, but it will never be accurate.

Hi there, I am currently using a MQ-3 Alcohol Sensor to build a breathalyzer…the problem i am facing is the conversion of units from mg/L to ppm…
In the MQ-3 Data sheet it states that 0.4mg/L is equivalent to 220ppm…however when i checked with google…1mg/l is equivalent to 1ppm…therefore i am very confuse with this conversion unit…please give your opinion and advice on this matter…=)

MQ-3 Data Sheet.pdf (55 KB)

thanks helps..but i would like to know more bout the conversion unit from mg/L to ppm..what i found in google is 1mg/L = 1ppm whereas in the MQ-3 Data sheet they stated there 0.4mg/L=220ppm..i am confuse with this stuff

I think that's in air vs in liquid solution

mg/l is not a dimensionless ratio. However if we are talking water as the solvent then it is basically the same
as mg/kg which is ppm. If we are talking air as the solvent, then air is 1.2g/l, so the conversion factor is
833ppm (by mass) and 525ppm (by molarity).

The google value matches the parts-per-million by molarity in air closely enough.

[ btw: molar mass of ethanol = 46g, of air ~= 29g ]

1mg/l is equivalent to 1ppm..

that is true only for water or other substances where 1 ml weights 1mg

For everything else you have to know its specific weight (mg/mL), because the conversion of mg/l to ppm depends on the substance - it isn't like going from ºF to ºC.

In your case, go with what the datasheets specifies: 0.4mg/L = 220ppm

okay..i get what you guys are trying to tell me..thanks a lot for the replies :slight_smile:

Sorry, I don't know.
The datasheet is about "Alcohol concentration in air", pehaps it has to do with weight, volume, mass. Something in that direction.


i'm using mq3 sensor, i have a problem with the response sometimes the response is 0.00 some times for the same mixture of alcohol the response is differente eg 36.33 and 200.56. I want to know the problem and what is the best load resistance for alcohol detection.

There is no ‘best’ load resistor. It depends on your sensor.

Did you do the preheat time ?

If the value is too low, use a higher value for the load resistor.

How is it powered ? With usb ? That is not reliable.

You could upload your sketch between [code][/code] tags.

Thanks for reply, the sensor is preheated by usb

here the code :

#include "arduino.h"
#include <LiquidCrystal.h>
#include <sstream>
#include <string>
#include <iostream>

using namespace std;

float concentration(float x) {
  const float A[] = { 
    2.71494E+02, -3.10999E+02, 6.85051E+02, -3.47587E+02, 7.47499E+01            }; 
  float result;
  float B[4];
  B[0] = x*x;
  B[1] = B[0]*x;  
  B[2] = B[1]*x;
  B[3] = B[2]*x;

  result = A[0]*x+A[1]*B[0]+A[2]*B[1]+A[3]*B[2]+A[4]*B[3];
  return result;

char messages[5][16] = {
  "Heating sensor", "64 seconds", "Autozero", "Ready!", "ppm"};

int L;
float x;
float x0[5];
float x_initial;

LiquidCrystal lcd(12, 11,5, 4, 3, 2); // Wiring microcontroller - LCD:

const int pushbutton = 8; // Pushbutton (normally open). Stops initial heating time when it is pressed. .
const int analogPin = A0; // Reads sensor voltage as a float int the interval (0-1) corresponding to (0 - 3.3V).
float sensor_value_AnalogIn = 7; // Analog output to a multimeter or datalogger (1V = 1000 ppm).

void text_screen( char messages[],  int colum, int row) {
  lcd.setCursor( colum, row);

void setup() {
  text_screen(messages[0], 0, 0);
  text_screen(messages[1], 0, 1);

  for (int j = 0; j<4; j++)
    lcd.clear();  // Heating sensor 4x16 = 64 seconds
    text_screen(messages[0], 0, 0);

    for (int i = 0; i<16; i++){  
      if (pushbutton == 1){   // Pressing pushbutton stops initial heating and enters in measuring mode.

      lcd.setCursor(i, 1);

  text_screen(messages[2], 0, 0);

  float sensor_value_AnalogIn = 7; // Analog output to a multimeter or datalogger (1V = 1000 ppm).
  for (int i=0; i<5; i++)
   x0[i]= analogRead(analogPin);

  x_initial = (x0[0]+x0[1]+x0[2]+x0[3]+x0[4])/5.0; // Autozero. Average of 5 initial measures.

  text_screen(messages[3], 0, 0);


void loop()  {
  x = analogRead(analogPin);
  x = (x-x_initial)*3.3; // Calculate real voltage. 
  float sensor_value_AnalogIn = x/1000;  

    x = 0;

  x = concentration(x);


  //Float to string conversion.

char buffer[10];      

  dtostrf(x, 10, 3, buffer);


  for (int i=0; i<strlen(buffer); i+=1)
 text_screen(messages[4], 10, 0); 


It is hard to tell if there is a problem with the sketch.

Could you make a minimal sketch, that only writes the analog value to the serial monitor. That way you can check if the value is stable.

The heater of the sensor requires some current. Also the backlight of the LCD requires some current. That combined might be too much for the usb power. Could you try a power supply ?

I have some comments on you sketch:
You don’t need all those includes, perhaps only .
The variable “analogPin” does not indicate what it is, a better name would be “pinSensor”, or “MQ3pin” or something like that.
The function dtostrf() has a width of 10, but that is the minimum field size. And a zero terminator will be added. The buffer size is 10, but 16 or 20 would be better.
When you compare or substract something to a float, it is better to use floating point number, like “x / 1000.0” and “if (x < 0.0)”.

ok thanks for advices.
for the power supply which one it's suitable for Mq3 ???

I think (I'm not sure) that the heater is about 150mA at 5V.

That is too much for the Arduino 5V output pin.
You could try a power supply of 7V or 7.5V, and use the 5V output pin of the Arduino board.
You have to check if the voltage regulator gets too hot. If you can't keep your finger on it, it is too hot.
In that case you need a seperate power supply or a seperate voltage regulator (LM7805 or LM317 or DC-DC converter).

A DC-DC converter is a module that uses a coil to convert the voltages. They are 95% effective, so they don't get hot. They cost only a few dollars/euros.

Ok, thanks for reply.

In order to use my MQ-3 on line to have a concentration of alcohol in the air, i use a 500 ohms load resistance and after calibration between 1% - to 6 % than correction of the response ( because the Mq3 response is not linear with voltage output) i remark that the response is not the same for the same concentration when i restart my arduino.
this is a problem for percentage convertion.

why this difference ?

Do you have a multimeter ?
The voltages must be good, for a good analogRead().
Using the usb to power the Arduino and the MQ-3 would give bad result.

Do you use a breadboard ? Those have sometimes bad contacts.

You should allow the MQ-3 to heat up for a few minutes (2 ... 5minutes) to compare the results.

The load resistor of 500 ohm seems very low. I don't have a MQ-3 myself to test, but I read that a value of 10k is normal. Does it have to be that low to measure the concentration ?

Are you talking about ethanol ?

That is combustable between 3% and 19% ethanol in air.
When you measure 6% with a sensor that has a heater, it is not safe.

I don't know about the sketch. There are a few issues with it. Please use a minimal sketch to test the sensor. What are the raw values of analogRead(). They should normally be around 50 ... 200 with clean air.


i use a multimetre and breadboard. for the bad contact it's true.
the voltage was between 0.65 v and 1.3 v for resp. 2.5% and 5% of alcohol.
i use the mq3 to calculate the ethanol in an on line mesure.
For the safety no problem the circulation of the air make the sensor secure.
i will try the 10K load resistance.

The voltages of 0.65V and 1.3V are okay. So perhaps the load resistor is good for that concentration.

There are many breadboard problems on the forum. Perhaps the 150mA is a problem if that is going through the breadboard contacts.


whats the best way to reinitialize to zero the sensor (authozero) ?