entradas-analogicas-adc-micropython

How to Read Analog Inputs (ADC) in MicroPython

  • 5 min

In this tutorial, we will see how to use ADCs in MicroPython to perform an analog input for reading sensors and other devices.

Unlike digital inputs, which can only detect two states (HIGH or LOW), analog inputs allow us to measure continuous values, within a specific voltage range and with a certain resolution.

The measurement is performed by an ADC (Analog-to-Digital Converter), which transforms the analog voltage into a digital value that can be processed by the microcontroller.

We can use analog inputs to read sensors that operate via analog signals, such as potentiometers, temperature sensors, light sensors, pressure sensors (or any other magnitude that varies gradually).

Configuring Analog Inputs

In MicroPython, analog inputs are configured using the ADC class from the machine module (which we know well by now).

# Configure the analog pin (GPIO 34 on ESP32)
pot = ADC(Pin(34))
Copied!

Once the ADC instance is defined, we can use some of its methods. Some common ones are:

CommandDescription
adc.read()Reads the analog value on a scale of 0 to 4095 (ESP32) or 0 to 1023 (ESP8266)
adc.read_u16()Reads the analog value with 16-bit resolution (0 to 65535)
adc.atten(attenuation)Sets the attenuation to adjust the input voltage range
adc.width(width)Sets the reading resolution (only on ESP32)

We can use the atten(attenuation) function to adapt the analog input range. On the ESP32, the available values are:

  • ADC.ATTN_0DB: 0 to 1.1V.
  • ADC.ATTN_2_5DB: 0 to 1.5V.
  • ADC.ATTN_6DB: 0 to 2.0V.
  • ADC.ATTN_11DB: 0 to 3.3V.

MicroPython allows setting the ADC resolution via the width() method. On the ESP32, the available options are:

  • WIDTH_9BIT: Range from 0 to 511.
  • WIDTH_10BIT: Range from 0 to 1023.
  • WIDTH_11BIT: Range from 0 to 2047.
  • WIDTH_12BIT: Range from 0 to 4095.

All functions and values may not be available on all board models. Check the information specific to your particular board.

Practical Example

Let’s see it in a simple example. The following code shows how we could read an analog voltage value from a GPIO36 pin (corresponds to an ADC1 on the ESP32).

from machine import ADC, Pin

# ADC pin configuration
adc = ADC(Pin(36))  # GPIO36 or VP

adc.width(ADC.WIDTH_12BIT)  # Set resolution to 12 bits (default value)
adc.atten(ADC.ATTN_11DB)    # Set input range to 0-3.3V

# Read the analog value
value = adc.read()  # Read a value between 0 and 4095
print(f"Analog value read: {value}")
Copied!

Analog signals often have noise. Use hardware filters (like capacitors) or software filters (averaging readings) to reduce noise. We will see this in the sensor reading tutorial.

Converting Analog Values to Physical Magnitudes

In general, the digital value obtained from the ADC is not useful by itself. We don’t care at all about its value, in ADC units 😜.

What we need is to convert it into a physical magnitude (like voltage, temperature, light, etc). To do this, a conversion formula must be applied.

For example, suppose we want to convert the digital value obtained from the ADC into a real voltage. The conversion formula is as follows:

In a 12-bit ADC with a reference voltage of 3.3V, the formula would be:

In code, this would look like this:

from machine import ADC, Pin
from time import sleep

# Configure the analog pin (GPIO 34 on ESP32)
pot = ADC(Pin(34))

# Configure the reading range (0-4095 for a 12-bit ADC)
pot.atten(ADC.ATTN_11DB)  # Full range of 0 to 3.3V

while True:
    value = pot.read()  # Read the analog value
    voltage = (value * 3.3) / 4095  # Convert to voltage
    print(f"Voltage: {voltage:.2f} V")
    sleep(0.5)  # Wait 0.5 seconds
Copied!

Which would give this output (for example), which is what we need:

Voltage: 1.65 V
Voltage: 0.82 V
Voltage: 2.47 V
...
Copied!

To convert it to another magnitude, like temperature or light, you will need the sensor’s characteristic equation, which converts voltage values into the measured magnitude.

Practical Examples