En este tutorial vamos a ver cómo podemos usar los ADC en MicroPython para realizar una entrada analógica con la que leer sensores y otros dispositivos..
A diferencia de las entradas digitales, que solo pueden detectar dos estados (HIGH o LOW) las entradas analógicas nos permiten medir valores continuos, en un rango de tensiones y con una resolución determinados.
La medición se realiza mediante un ADC (Convertidor Analógico-Digital), que transforma la tensión analógica en un valor digital que puede ser procesado por el microcontrolador.
Podemos usar las entradas analógicas para leer sensores que operan mediante señales analógicas, como potenciómetros, sensores de temperatura, sensores de luz, de presión (o cualquier otra magnitud que varía de forma gradual).
Si quieres aprender más consulta,
Configuración de entradas analógicas
En MicroPython, las entradas analógicas se configuran utilizando la clase ADC
del módulo machine
(que a estas alturas que conocemos bien).
# Configurar el pin analógico (GPIO 34 en ESP32)
pot = ADC(Pin(34))
Una vez definida la instancia del ACD, podemos usar alguno de sus métodos. Algunos de los habituales son,
Comando | Descripción |
---|---|
adc.read() | Lee el valor analógico en una escala de 0 a 4095 (ESP32) o 0 a 1023 (ESP8266) |
adc.read_u16() | Lee el valor analógico con resolución de 16 bits (0 a 65535) |
adc.atten(attenuation) | Establece la atenuación para ajustar el rango de voltaje de entrada |
adc.width(width) | Establece la resolución de lectura (solo en ESP32) |
Podemos usar la función atten(attenuation)
para adaptar el rango de entrada analógica. En el ESP32 los valores disponibles son :
ADC.ATTN_0DB
: 0 a 1.1V.ADC.ATTN_2_5DB
: 0 a 1.5V.ADC.ATTN_6DB
: 0 a 2.0V.ADC.ATTN_11DB
: 0 a 3.3V.
MicroPython permite establecer la resolución del ADC mediante el método width()
. En el ESP32, las opciones disponibles son:
WIDTH_9BIT
: Rango de 0 a 511.WIDTH_10BIT
: Rango de 0 a 1023.WIDTH_11BIT
: Rango de 0 a 2047.WIDTH_12BIT
: Rango de 0 a 4095.
Todas las funciones y valores no estarán disponibles en todos los modelos de placas. Comprobar la información relativa a vuestra placa en particular
Ejemplo práctico
Vamos a verlo en un ejemplo sencillo. El siguiente código muestra como podríamos leer un valor analógico de tensión que tengamos en un pin GPIO36 (corresponde a un ADC1 en el ESP32).
from machine import ADC, Pin
# Configuración del pin ADC
adc = ADC(Pin(36)) # GPIO36 o VP
adc.width(ADC.WIDTH_12BIT) # Configurar resolución a 12 bits (valor por defecto)
adc.atten(ADC.ATTN_11DB) # Configurar rango de entrada a 0-3.3V
# Leer el valor analógico
valor = adc.read() # Leer un valor entre 0 y 4095
print(f"Valor analógico leído: {valor}")
Las señales analógicas suelen tener ruido. Usa filtros de hardware (como condensadores) o software (promedio de lecturas) para reducir el ruido. Veremos esto en el tutorial de lectura de sensores.
Conversión de valores analógicos a magnitudes físicas
En general, el valor digital obtenido del ADC no es útil por sí mismo. Nos da absolutamente igual su valor, en unidades del ADC 😜.
Lo que necesitamos convertirlo en una magnitud física (como tensión, temperatura, luz, etc). Para ello, es necesario aplicar una fórmula de conversión.
Por ejemplo, supongamos que queremos convertir el valor digital obtenido del ADC en un voltaje real. La fórmula de conversión es la siguiente:
En un ADC de 12 bits con un voltaje de referencia de 3.3V, la fórmula sería:
En código, esto quedaría así,
from machine import ADC, Pin
from time import sleep
# Configurar el pin analógico (GPIO 34 en ESP32)
pot = ADC(Pin(34))
# Configurar el rango de lectura (0-4095 para un ADC de 12 bits)
pot.atten(ADC.ATTN_11DB) # Rango completo de 0 a 3.3V
while True:
valor = pot.read() # Leer el valor analógico
voltaje = (valor * 3.3) / 4095 # Convertir a voltaje
print(f"Voltaje: {voltaje:.2f} V")
sleep(0.5) # Esperar 0.5 segundos
Que daría esta salida (por ejemplo), que es lo que necesitamos
Voltaje: 1.65 V
Voltaje: 0.82 V
Voltaje: 2.47 V
...
Para convertirlo a otra magnitud, como temperatura, o luz, necesitaréis la ecuación característica del sensor, que convierta valores de tensión en la magnitud medida
Ejemplos prácticos
Mapear valores
En algunos casos, es útil mapear el rango de entrada (0-4095) a un rango más significativo (por ejemplo, 0-100%):
def mapear(valor, in_min, in_max, out_min, out_max):
return (valor - in_min) * (out_max - out_min) // (in_max - in_min) + out_min
# Mapear valor analógico a porcentaje
porcentaje = mapear(valor, 0, 4095, 0, 100)
print(f"Porcentaje: {porcentaje}%")
Lectura de un potenciómetro
Un potenciómetro es un componente electrónico que varía su resistencia en función de la posición de un cursor. Al conectarlo a una entrada analógica, podemos medir su posición y convertirla en un valor digital.
- Conecta un extremo del potenciómetro a 3.3V (o 5V, dependiendo del microcontrolador).
- Conecta el otro extremo a GND.
- Conecta el cursor (pin central) a un pin analógico, como el GPIO 34 en el ESP32.
from machine import ADC, Pin
from time import sleep
# Configurar el pin analógico (GPIO 34 en ESP32)
pot = ADC(Pin(34))
# Configurar el rango de lectura (0-4095 para un ADC de 12 bits)
pot.atten(ADC.ATTN_11DB) # Rango completo de 0 a 3.3V
while True:
valor = pot.read() # Leer el valor analógico
print(f"Valor del potenciómetro: {valor}")
sleep(0.5) # Esperar 0.5 segundos
En este ejemplo, el valor leído variará según la posición del potenciómetro. Si giras el potenciómetro, verás que el valor cambia entre 0 y 4095.