ESP32 UNO - MQ3 Alcohol Sensor
Can a cheap gas module sense a breath of hand sanitizer? Hook an MQ3 alcohol sensor to the ESP32 Uno and it reports ethanol vapor within seconds. You get a yes/no alcohol detector from the DO pin, a 0–4095 level from the AO pin, and a small breathalyzer demo, all built on the ESP32 Uno form board with Arduino IDE code.
By the end, you can:
- Wire an MQ-3 module to a 3.3V board without frying its pins
- Detect alcohol vapor with digitalRead() on the DO output
- Measure ethanol concentration with analogRead() on the AO output
- Calibrate your own sensor and turn the numbers into a breath analyzer status

Components You Need
| 1 | × | ESP32 Uno-form Board | |
| 1 | × | USB Cable Type-A to Type-C (for USB-A PC) | |
| 1 | × | USB Cable Type-C to Type-C (for USB-C PC) | |
| 1 | × | MQ3 Alcohol Sensor | |
| 4 | × | Resistors for two voltage dividers (2 | |
| 1 | × | Jumper Wires |
Or you can buy the following kits:
| 1 | × | DIYables Sensor Kit (18 sensors/displays) |
Additionally, some of these links are for products from our own brand, DIYables .
Overview of MQ3 Alcohol Sensor
After this part, you know what the MQ3 senses, why it runs hot, and what each of its pins sends out.
The MQ3 belongs to the MOS (Metal Oxide Semiconductor) family of gas sensors. Its other name is Chemiresistor: the sensing layer changes its resistance when ethanol vapor reaches it. It is tuned for alcohol and picks up even a light trace of it.
The sensing element is a Tin Dioxide (SnO2) film on an Aluminum Oxide ceramic tube. A built-in heater keeps that film hot, because cold SnO2 does not react to alcohol. On top sits a stainless steel mesh, the anti-explosion network. It shields the hot parts and blocks dust, while gas still passes into the chamber.
Typical uses: breath analyzers, drunk driving detectors, alcohol alarms and air monitors that track ethanol levels.
Technical Specifications
| Item | Value |
|---|---|
| Supply voltage | 5V DC |
| Load resistance | 200 KΩ |
| Heater resistance | 33Ω ± 5% |
| Heater power | under 800mW |
| Sensing resistance | 1 MΩ to 8 MΩ |
| Detection range | 25 to 500 ppm |
| First preheat | 24 to 48 hours |
Good to know: ppm means parts per million. A reading of 500 ppm says that in every million gas molecules, 500 are ethanol and the remaining 999,500 are something else.
Pinout
Four pins sit on the module edge: two for power and two for the alcohol signal.
| Module Pin | Role |
|---|---|
| VCC | Supply for the heater and the comparator. Needs 5V |
| GND | Ground (0V) |
| DO | Digital signal. Goes LOW when alcohol passes the set level, stays HIGH in clean air. The blue trimmer sets that level |
| AO | Analog signal. Its voltage rises as the ethanol level rises |

Two LEDs help with checks. PWR-LED glows whenever the module gets power. DO-LED copies the DO pin, so it glows while alcohol is present and goes dark in clean air.
How It Works
Here is the chain from alcohol vapor to a number on your screen.
| Situation | What Happens in the SnO2 Film | Result |
|---|---|---|
| Clean air | Hot SnO2 holds oxygen on its surface. The oxygen grabs free electrons and forms a barrier | Very high resistance and almost no current |
| Alcohol present | Ethanol reacts with that surface oxygen. The barrier drops and electrons flow into the tin dioxide again | Resistance falls. More alcohol means lower resistance |
The module turns this resistance change into two outputs:
| Output | Behavior | Trimmer Effect |
|---|---|---|
| DO | LOW and DO-LED on when the ethanol level is above the trimmer setting. HIGH and DO-LED off when it is below | Sets the switching point |
| AO | Voltage follows the ethanol level. More vapor gives a higher voltage, less vapor a lower one | None |
Warming Up and Calibrating the MQ3
After this part, your sensor is hot, stable and has limits that match your own room.
Step 1 — Warm it up
How long the heater needs depends on the sensor's history:
- Brand new, or unused for over a month: keep it powered for 24 to 48 hours before you trust the values.
- Used in the last days: 5 to 10 minutes is enough. Expect high numbers at the start that slowly fall and settle.
Warm-up only needs power, no code. Feed the module from any 5V source; the 5V and GND header pins of the ESP32 Uno are fine. Then just wait.
Step 2 — Find your threshold values
The heater ages and the readings drift over long storage. Measure your own numbers before you build a breathalyzer:
- Clean-air baseline. Run the AO sketch away from any alcohol and note the values. With the voltage divider on this page, many sensors sit near 350 to 550 on the ESP32 Uno.
- Vapor test. Hold isopropyl alcohol or hand sanitizer close and squeeze out some vapor. Never let liquid touch the sensor. Note the peak values. Expect something between 1500 and 3700, based on how much vapor reaches the mesh.
- Choose three levels from your notes, for example:
- Sober: just above your clean-air number (e.g. under 480)
- Within legal limits: from the baseline up to a medium level (e.g. 480 to 1600)
- Above legal limits: over the medium level (e.g. 1600 and up)
※ NOTE THAT:
Every MQ3 sensor and every room gives different numbers. Use the values above only as a first guess, and replace them with what your own sensor shows.
Step 3 — Set the DO trigger point
The blue trimmer on the module decides when DO switches:
- Bring alcohol vapor close to the sensor.
- Turn the trimmer clockwise until DO-LED lights up.
- Turn it back counterclockwise until DO-LED just goes dark.
- The DO pin now switches at about this vapor level.
ESP32 Uno Pinout
Your code talks to GPIO numbers, while the board shows Uno labels like D2 and A0. Use this diagram to match the two before you plug in any jumper.

How to Connect
After this part, the MQ3 is powered from 5V and both of its outputs reach the ESP32 Uno at a safe 3.3V level.

This image is created using Fritzing. Click to enlarge image
※ NOTE THAT:
The wiring diagram may not show the correct wiring for the ESP32 Uno. The sensor outputs can reach 5V, but ESP32 Uno pins are 3.3V only. The picture shows DO and AO wired straight to the board. On the ESP32 Uno, put a 10 kΩ and 20 kΩ voltage divider on each output, as this page shows. We will update the diagram soon. Until then, follow the wiring table and the text on this page, not the picture.
| MQ3 Alcohol Sensor Pin | ESP32 Uno Pin |
|---|---|
| VCC | 5V |
| GND | GND |
| DO | D2 (GPIO26), through a 10 kΩ / 20 kΩ voltage divider |
| AO | A0 (GPIO2), through a 10 kΩ / 20 kΩ voltage divider |
You can use DO alone, AO alone, or both. With both wired, all three sketches below run without any change to the circuit.
WARNING
The MQ3 heater must run from 5V, so DO and AO can swing up to about 5V. A 5V signal can damage ESP32 Uno pins, because they are NOT 5V tolerant. Build one divider per signal: sensor pin to a 10 kΩ resistor, the far end of that resistor to the board pin (D2 or A0), and a 20 kΩ resistor from the board pin to GND. 5V then becomes about 3.3V at the pin. The wiring image does not show the resistors, so add them on a breadboard.
WARNING
A0 (GPIO2) is a boot strapping pin. The chip checks it at power-up, and it must not be pulled HIGH while you upload code. The 20 kΩ resistor to GND in the divider keeps it LOW, which is safe. If uploads fail, unplug the AO wire, upload, then plug it back in.
Good to know: A0 (GPIO2) is also an ADC2 pin. It reads fine in these sketches, but analogRead() on it stops working once you turn on WiFi.
ESP32 Uno Code - Alcohol Yes/No from the DO Pin
This sketch heats the sensor for 20 seconds and then prints a clear alcohol / no alcohol message from the DO pin, over and over.
Upload and Test
- First time with this board? Set it up with ESP32 Uno - Getting Started before you continue.
- Build the circuit by following the wiring table above, voltage dividers included.
- Plug in the USB Type-C cable between the ESP32 Uno and your computer.
- Select the board in Arduino IDE: pick ESP32 Dev Module and the COM port of the board (CH340).
- Paste the sketch into a new Arduino IDE window.
- Press Upload and wait for "Done uploading".
- Open the Serial Monitor at 9600 baud and wait for the warm-up line to pass.
- Bring vapor close: a cotton ball with rubbing alcohol or a drop of hand sanitizer on a tissue works well.
- Pro tip: watch DO-LED on the module while you test. If the LED and the Serial Monitor disagree, a divider wire is loose.
※ NOTE THAT:
Wrong results, like "detected" in clean air or no reaction near alcohol, mean the trigger point is off. Turn the blue trimmer clockwise for more sensitivity or counterclockwise for less, until the messages match what is really in the air.
ESP32 Uno Code - Alcohol Level from the AO Pin
This sketch prints the raw AO reading two times per second, on a 0–4095 scale.
Good to know: setup() calls analogSetAttenuation(ADC_11db). This lets the ESP32 Uno analog pin read the full span from 0V up to about 3.3V. With a narrow range, the numbers jump to 4095 far too early and the alcohol levels look wrong.
Upload and Test
- Paste the sketch into Arduino IDE, replacing the DO sketch.
- Press Upload.
- Open the Serial Monitor at 9600 baud and let the 20-second warm-up finish.
- Puff some vapor from hand sanitizer or rubbing alcohol toward the mesh.
- Pro tip: open Tools > Serial Plotter instead of the monitor. The rise and slow fall after each puff is much easier to read as a curve.
The DO and AO results give you everything you need to start an alarm, switch on a warning LED, or log readings for a breath analyzer.
ESP32 Uno Code - Three-Level Breathalyzer Demo
This sketch sorts each AO reading into one of three levels and prints the matching status every second.
The limits in the code (480 and 1600) already fit the 12-bit ADC and the divider, but they are only examples. Your own calibration numbers will work better.
Upload and Test
- Calibrate. Run the AO sketch and note the clean-air value and the peak with vapor.
- Edit the limits. Put your numbers into SOBER_THRESHOLD and DRUNK_THRESHOLD.
- Upload the sketch to the ESP32 Uno.
- Try it by waving a sanitizer bottle or an alcohol swab near the mesh.
- Read the status in the Serial Monitor at 9600 baud.
- Pro tip: fan fresh air over the sensor between tests. It takes 30 seconds or more to drop back to its clean-air number.
WARNING
This build is a learning project. It is not a legal breathalyzer, and you must never use it to judge if a person can drive.
Video Tutorial
See the ESP32 Uno build in action in the video below.
Code Explanation
After this part, you know which lines matter in the three sketches and which ones to change.
| Code Part | What It Does |
|---|---|
| #define DO_PIN 26 / #define AO_PIN 2 | Names the GPIOs for D2 and A0, so the rest of the code uses DO_PIN and AO_PIN |
| analogSetAttenuation(ADC_11db) | Opens the ADC input range to about 3.3V (AO and breathalyzer sketches only) |
| delay(20000) in setup() | Gives the heater 20 seconds before the first reading |
| digitalRead(DO_PIN) | Returns HIGH for clean air and LOW for alcohol |
| analogRead(AO_PIN) | Returns 0 to 4095. A higher number means more ethanol |
| SOBER_THRESHOLD / DRUNK_THRESHOLD | The two limits that split readings into three status messages |
The result: the DO sketch gives a simple yes/no, the AO sketch shows how much alcohol is there, and the breathalyzer sketch turns that number into words.
ESP32 Uno vs UNO R4 for This Project
This is what changes when you move the MQ3 project from the UNO R4 to the ESP32 Uno.
| Item | Arduino UNO R4 | ESP32 Uno |
|---|---|---|
| Logic voltage | 5V | 3.3V |
| MQ3 signal wiring | Direct to the pins | Through 10 kΩ / 20 kΩ voltage dividers |
| DO pin in code | 2 | 26 (D2) |
| AO pin in code | A0 | 2 (A0) |
| Default ADC range | 0 to 1023 (10-bit) | 0 to 4095 (12-bit) |
| Extra setup line | none | analogSetAttenuation(ADC_11db) |
| Breathalyzer limits | 120 and 400 | 480 and 1600 |
The header positions are the same, so the wiring image still fits. The big change is the two dividers, because the 5V module outputs would harm the 3.3V pins.
Go Wireless: Alcohol Level on Your Phone
After this part, you have a plan to see the MQ3 reading without a USB cable.
The ESP32 Uno has WiFi and Bluetooth built in. Send the AO number to a gauge or a live chart on your phone, and you can put the sensor at a party table or in a car and watch it from a distance. A DO-only build can also push a simple "alcohol detected" alert.
Good to know: A0 is an ADC2 pin, so analogRead() on it fails while WiFi is on. For a WiFi version, move the AO wire to A2 (GPIO35), A3 (GPIO34) or the extra hole GPIO32, and change AO_PIN in the code.
Function References
Troubleshooting
| Problem | Possible Cause | Solution |
|---|---|---|
| Board has no COM port in Arduino IDE | CH340 driver not installed, or a charge-only cable | Install the CH340 driver and swap to a USB cable that carries data |
| Upload stops at "Failed to connect" or "Waiting for download" | Board did not enter download mode | Hold the BOOT button while the upload starts, then let go |
| Board does not boot or upload with the sensor plugged in | A0 (GPIO2) is a boot strapping pin and the AO wire pulls it the wrong way | Unplug the AO wire while uploading, and check that the 20 kΩ resistor goes to GND |
| Both module LEDs stay dark | VCC or GND loose, or VCC on 3.3V | Move VCC to the 5V pin and push every jumper in firmly |
| AO numbers are high in clean air | Heater is still cold | Wait 5 to 10 minutes, or 24 to 48 hours for a new sensor |
| AO always reads 4095 | No divider on AO, or the attenuation line was removed | Add the 10 kΩ / 20 kΩ divider and keep analogSetAttenuation(ADC_11db) |
| AO always reads 0 | AO wire on the wrong header pin, or a divider resistor is open | Check that AO goes to A0 and measure the voltage at the pin |
| DO message never changes | Trimmer set fully one way | Redo the trimmer steps with vapor near the sensor |
| Serial Monitor shows strange symbols | Baud rate does not match | Set the Serial Monitor to 9600 baud |
FAQ
Can I run the MQ3 heater from the 3.3V header pin?
No. The heater is made for 5V. At 3.3V it never gets hot enough, so the readings stay low and jump around. Keep VCC on 5V and use the dividers to protect the signal pins.
What is the simplest way to drop the MQ3 AO voltage to 3.3V?
A two-resistor divider: 10 kΩ from the sensor pin to the board pin, and 20 kΩ from the board pin to GND. It scales 5V to about 3.3V. A logic level converter also works for DO, but a divider is the usual choice for AO.
Does the MQ3 sense only alcohol, or other gases too?
It is most sensitive to ethanol, but other vapors like benzine or some solvents can also raise the reading a little. That is why calibration in your own room matters.
Why are my ESP32 Uno numbers so much bigger than in older Arduino guides?
The ESP32 Uno ADC is 12-bit, so analogRead() goes up to 4095. The UNO R4 returns 0 to 1023 by default. The divider changes the scale a little more, so always use limits you measured on this board.
Why does the code call analogSetAttenuation(ADC_11db)?
The line widens the ESP32 Uno ADC window to roughly 0–3.3V, so the whole MQ3 swing lands somewhere in 0–4095. Leave it out and the window is narrow, so values pin at the top far too soon. The UNO R4 code has no such line, since only the ESP32 Uno core uses it. The divider keeps the pin at 3.3V or below, as it must be.
Is it a problem that A0 is a boot strapping pin?
Not with this circuit. GPIO2 must not be HIGH while you upload, and the 20 kΩ resistor to GND keeps it LOW. If uploads still fail, unplug the AO wire during the upload.
Can I use the AO reading together with WiFi on the ESP32 Uno?
Not on A0. A0 (GPIO2) and A1 (GPIO4) are ADC2 pins, and ADC2 cannot be read while WiFi is on. Move the AO wire to A2–A5 (GPIO35, 34, 36, 39) or GPIO32/33 and change AO_PIN in the code.
Can I use an Arduino Uno shield with an MQ3 on the ESP32 Uno?
The board has the Uno shape, so most shields fit. Check that the shield does not send 5V signals into the pins, because ESP32 Uno pins work at 3.3V.
How can I convert the AO reading into ppm or BAC?
You need the sensor's sensitivity curve from the datasheet, the load resistor value and a clean-air reference resistance. The math is possible, but cheap modules vary a lot, so the result is only a rough estimate. For learning, the three-level status is easier and more honest.
What if my project needs more pins than the Uno headers give?
The ESP32 Uno has a few extra holes near the power header: GPIO32 and GPIO33 (I/O, PWM, analog on ADC1, so they still read while WiFi is on) and GPIO15 (I/O, PWM, analog on ADC2). Add pin headers with a soldering iron, then put the plain GPIO number in your sketch. For a second MQ sensor's AO pin, or for a WiFi version of this project, GPIO32 or GPIO33 is the best pick. Two warnings: GPIO15 and GPIO0 (the IO0 pin at the unused Uno NC position) are boot strapping pins, and a wrong connection can stop the board from booting or uploading code, so use GPIO32/33 first. Also, never use the six holes under the digital header (SD0–SD3, CMD, CLK = GPIO6–GPIO11). They are wired to the flash chip, and using them crashes the board.