Confused about ADC and MQ4 Gas Sensor

All ESP32 boards running MicroPython.
Target audience: MicroPython users with an ESP32 board.
Post Reply
merdenoms
Posts: 2
Joined: Mon Nov 20, 2017 12:14 am

Confused about ADC and MQ4 Gas Sensor

Post by merdenoms » Mon Nov 20, 2017 12:36 am

I thought I'd start learning MicroPython and I flashed it to a ESP32 dev board I had. https://www.tindie.com/products/ddebeer ... ith-ftdi-/

I recently bought a MQ4 gas sensor. Here is the exact one if this is useful: https://www.amazon.com/Phantom-YoYo-Ard ... B00AFQB69I

I was having trouble getting it running so I used some Arduino code.

void setup()
{
Serial.begin(9600);
}

void loop()
{
float sensorVoltage;
float sensorValue;

sensorValue = analogRead(A0);
sensorVoltage = sensorValue/1024*5.0;

Serial.print("sensor voltage = ");
Serial.print(sensorVoltage);
Serial.println(" V");
delay(1000);
}

This got it running properly but only after I switched the sensor from 3.3V to 5V

I tried translating the above Arduino code to MicroPython. I couldn't find any MQ sensor examples for the ESP32 and MicroPython so I looked up ADC examples in the MicroPython Docs and tried using that.

import utime
import machine
adc = machine.ADC(machine.Pin(32))
while True:
sensor = adc.read()
answer = (sensor/1024*5.0)
print(answer)
utime.sleep_ms(1000)

This displays data from the sensor and changes just like the Arduino code when I use gas from a BIC lighter.

But my question is about the pins. If I connect the OUT pin of the MQ4 sensor to the ESP32 pin specified in the code(32), nothing happens. If I connect the sensor pin to a different ESP Analog pin such as 33, it works. Why does this happen?
Why do I need to specify a different Analog pin rather than the actual one I am using in my code?
Is my code just bad? (probably)

I also noticed the readings seem to be much slower than when I use Arduino. Is there a reason for this?
I'd try another ESP32 board/module but I'm waiting on some others to arrive in the mail.

Here is some more code that blinks the LED when gas is detected:

import utime
import machine
pin21 = machine.Pin(21, machine.Pin.OUT)
adc = machine.ADC(machine.Pin(32))
while True:
sensor = adc.read()
answer = (sensor/1024*5.0)
if answer > 14:
pin21.value(1)
utime.sleep_ms(1000)
pin21.value(0)
utime.sleep_ms(100)
print(answer)
utime.sleep_ms(400)

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: Confused about ADC and MQ4 Gas Sensor

Post by pythoncoder » Wed Nov 22, 2017 7:52 am

I can't replicate this. I created two ADC instances:

Code: Select all

adc = machine.ADC(machine.Pin(32))
adc1 = machine.ADC(machine.Pin(33))
Each correctly read a voltage applied to its own pin and did not respond to a voltage applied to the other one. Is it possible that your board has incorrect pin markings?

This is on an Espressif ESP32-DEVKITC with ESP-WROOM-32 running the official firmware. As for performance the following quick test yielded a read time of 206μs.

Code: Select all

def foo():
    start = utime.ticks_us()
    a = adc.read()
    print(utime.ticks_diff(utime.ticks_us(), start), a)
Note that the ADCs' full scale output occurs at 1.0V. I haven't checked the hardware datasheet but it may be inadvisable to exceed this voltage. Also the ADCs on ESP32 and ESP8266 are not particularly accurate.
Peter Hinch
Index to my micropython libraries.

merdenoms
Posts: 2
Joined: Mon Nov 20, 2017 12:14 am

Re: Confused about ADC and MQ4 Gas Sensor

Post by merdenoms » Thu Nov 23, 2017 7:01 am

I thought it may be incorrect markings but the pin works fine when selected in the Arduino IDE. I'm not sure why MicroPython does that with this particular board. Anyways, after working around that, my code seems to run well now. I do notice that ADC is not very accurate. BBCode for my account is turned off so the syntax won't look correct but I'll post my code here in case any beginners need it in the future. This makes a simple gas detector alarm.

import utime
from machine import Pin, ADC, PWM
pin12 = Pin(12, Pin.OUT) # LED
pin14 = Pin(14, Pin.OUT) # Passive Buzzer
adc = ADC(Pin(32))
while True:
sensor = adc.read()
a = 5.0 / 1023.0 * sensor
if a > 10:
pin14.value(1)
for _ in range(6):
pin12.value(1)
utime.sleep_ms(500)
pin12.value(0)
utime.sleep_ms(100)
pin14.value(0)

Post Reply