La Guía Definitiva del ADC en ESP32: Lectura Analógica, Calibración y Trucos de Precisión
¡Hola equipo! Bienvenidos a una nueva clase maestra en Ingtelecto Pro. Hoy vamos a atacar uno de los temas más incomprendidos y criticados del ESP32: su Convertidor Analógico a Digital (ADC).
Si vienes del mundo Arduino UNO, estarás acostumbrado a que analogRead() sea perfecto y lineal. Pero cuando pasas al ESP32, te encuentras con lecturas ruidosas, valores que no llegan a cero y errores de medición. Muchos principiantes culpan a la placa, pero la realidad es que el ADC del ESP32 es una bestia compleja que necesita ser "domada".
En este artículo no solo vamos a leer un potenciómetro. Vamos a entender la arquitectura interna SAR, aprenderemos a usar la calibración de fábrica Vref oculta en el chip, y diseñaremos circuitos para leer voltajes superiores a 3.3V (como baterías de 12V). ¡Saca tu multímetro, que empezamos! ⚡📉
El Mito de la Precisión
Imagina que tienes una regla de medir de goma elástica. Si la estiras, las marcas se separan. Si la encoges, se juntan.
El ADC del ESP32 es un poco así: su referencia interna de voltaje (Vref) debería ser de 1100mV, pero en la realidad varía entre 1000mV y 1200mV de una placa a otra. Si no calibras tu código para TU placa específica, siempre tendrás un error del 5% al 10%. Hoy aprenderemos a corregir esa "goma elástica" por software.
- Fundamentos: Arquitectura SAR y Resolución
- El Mapa de Pines: ADC1 vs ADC2 (El conflicto WiFi)
- Atenuación: El concepto de los Decibelios (dB)
- El Problema de la No-Linealidad 📉
- La Solución Profesional: analogReadMilliVolts()
- Cómo medir voltajes mayores a 3.3V (Divisor de Tensión) 🔋
- Truco Avanzado: Multisampling para eliminar Ruido
- Conclusión
Fundamentos: Arquitectura SAR y Resolución
Antes de tirar código, hay que entender el hardware.
ADC SAR
Arquitectura Interna
A diferencia de otros métodos, el SAR funciona como una balanza: compara el voltaje de entrada con una serie de voltajes de referencia internos, bit por bit, hasta encontrar el valor más cercano. Es rápido, pero sensible al ruido eléctrico.
Resolución de 12 Bits
$$ 2^{12} = 4096 \text{ niveles} $$
Esto significa que dividimos el voltaje máximo (3.3V) en 4095 pasos.
Precisión teórica: $ \frac{3.3V}{4095} \approx 0.8 \text{ milivoltios por paso} $.
Es 4 veces más preciso que un Arduino UNO... en teoría.
El Mapa de Pines: ADC1 vs ADC2 (El conflicto WiFi)
Este es el error #1 que hace que los proyectos de IoT fallen. El ESP32 tiene dos unidades ADC, pero no son iguales.
ADC1 (El Seguro)
Consta de 8 canales. Está totalmente dedicado a tus sensores. Es el que debes usar siempre.
- GPIO 32 (ADC1_CH4)
- GPIO 33 (ADC1_CH5)
- GPIO 34 (ADC1_CH6) - Solo entrada
- GPIO 35 (ADC1_CH7) - Solo entrada
- GPIO 36 (VP) - Solo entrada
- GPIO 39 (VN) - Solo entrada
ADC2 (El Restringido)
Consta de 10 canales. El problema es que el controlador del WiFi y Bluetooth usa internamente este ADC para calibrar la radiofrecuencia.
Si usas las librerías [sintsaxis] WiFi.h [/sintaxis],
BluetoothSerial.h o ESP-NOW, el ADC2 deja de funcionar para tus sensores. Si intentas leer el GPIO 4 o el GPIO 2 mientras el WiFi está activo, obtendrás lecturas vacías o el código se bloqueará.Regla de Oro: Usa pines del 32 al 39 para sensores analógicos en proyectos IoT.
Atenuación: El concepto de los Decibelios (dB)
Aquí es donde la gente se confunde. El ADC interno del ESP32 en realidad solo puede medir voltajes entre 0V y 1.1V.
¿Cómo es que medimos 3.3V entonces? Porque el chip tiene unos atenuadores (divisores de voltaje) internos programables.
Podemos configurar la "Atenuación" para cambiar el rango de lectura:
| Atenuación | Rango de Voltaje Medible | Precisión |
|---|---|---|
ADC_0db | 0 mV a 950 mV (aprox 1V) | Alta |
ADC_2_5db | 0 mV a 1250 mV (aprox 1.25V) | Media |
ADC_6db | 0 mV a 1750 mV (aprox 1.75V) | Media |
ADC_11db (Default) | 0 mV a 3100 mV (aprox 3.3V)* | Baja (Ruidosa) |
Nota: Aunque decimos 3.3V, muchos chips ESP32 se saturan (llegan a 4095) alrededor de los 3.1V o 3.2V debido a la no-linealidad.
El Problema de la No-Linealidad 📉
El ADC del ESP32 no es una línea recta perfecta. Tiene una "curva en forma de S".
- Zona Muerta Inferior: Por debajo de 100mV (0.1V), el ESP32 probablemente leerá 0. No sirve para medir milivoltios muy bajos.
- Zona Lineal (Sweet Spot): Entre 0.2V y 2.5V el comportamiento es excelente.
- Zona de Saturación Superior: Por encima de 3.1V, el valor se dispara a 4095 y ya no distingue cambios.
¿Cómo lo solucionamos?
Si necesitas precisión absoluta, usa la función calibrada que veremos a continuación o usa un ADC externo como el ADS1115. Para el 90% de los proyectos, la calibración por software es suficiente.
La Solución Profesional: analogReadMilliVolts()
Olvídate de hacer la regla de tres manual: float voltaje = lectura * (3.3 / 4095.0). Eso es para principiantes y asume que tu regulador es perfecto (que nunca lo es).
El SDK de Espressif incluye una función que lee la calibración de fábrica quemada en los eFuses del chip (Vref) y te devuelve el valor corregido directamente en milivoltios.
// CÓDIGO PRO: Lectura Calibrada en mV
const int sensorPin = 34; // Pin ADC1
void setup() {
Serial.begin(115200);
// Configuración explícita de la atenuación
// 11db nos permite leer hasta ~3.1V
analogSetAttenuation(ADC_11db);
}
void loop() {
// 1. Lectura RAW (Cruda 0-4095)
int rawValue = analogRead(sensorPin);
// 2. Lectura CALIBRADA (Devuelve milivoltios reales)
// Esta función usa la corrección Vref interna del chip
uint32_t milivoltios = analogReadMilliVolts(sensorPin);
Serial.printf("Raw: %d \t Voltaje Real: %d mV \n", rawValue, milivoltios);
delay(500);
}Cómo medir voltajes mayores a 3.3V (Divisor de Tensión) 🔋
¿Quieres medir la batería de 12V de tu robot o un sensor industrial de 5V? No conectes directo o saldrá humo. Necesitas un Divisor de Voltaje resistivo.
Fórmula del Divisor de Voltaje
Donde $V_{in}$ es el voltaje alto (ej. 12V) y $V_{out}$ es lo que entra al ESP32 (Max 3.3V).
Ejemplo práctico para batería de 12V:
- R1 (Arriba): 27k$\Omega$
- R2 (Abajo, a Tierra): 4.7k$\Omega$
Cálculo:
$$ V_{out} = 12V \times \frac{4700}{27000 + 4700} = 12V \times 0.148 = 1.77V $$
¡Perfecto! 1.77V está en la zona más lineal del ADC del ESP32.
// CÓDIGO PARA LEER BATERÍA 12V
// Usando R1 = 27k y R2 = 4.7k
const int batPin = 34;
// Factor de división calculado: (R1 + R2) / R2
// (27000 + 4700) / 4700 = 6.74
const float factorDivision = 6.744;
void setup() {
Serial.begin(115200);
analogSetAttenuation(ADC_11db);
}
void loop() {
// Leemos el voltaje en el pin (0 a 3300mV aprox)
int mV_pin = analogReadMilliVolts(batPin);
// Calculamos el voltaje real de la batería
float voltajeBateria = (mV_pin * factorDivision) / 1000.0;
Serial.printf("Batería: %.2f V \n", voltajeBateria);
delay(1000);
}Truco Avanzado: Multisampling para eliminar Ruido
Incluso con la calibración, el valor puede saltar (ej: 1500, 1520, 1490). Para estabilizarlo, usamos una técnica de "Promedio Móvil".
// Función para leer el ADC promediando muestras
int leerPromedio(int pin, int muestras) {
unsigned long suma = 0;
for(int i=0; i < muestras; i++) {
suma += analogReadMilliVolts(pin);
delay(1); // Pequeña pausa vital
}
return suma / muestras;
}
void loop() {
// Tomamos 64 lecturas para tener un valor "roca sólida"
int voltajeEstable = leerPromedio(34, 64);
Serial.println(voltajeEstable);
delay(100);
}Conclusión
¡ADC Dominado! 🎓
Has pasado de leer valores aleatorios a tener un sistema de medición robusto.
Recuerda los 3 mandamientos del ADC en ESP32:
- Usarás ADC1 (GPIOs 32-39) si usas WiFi.
- Usarás analogReadMilliVolts() para obtener valores calibrados de fábrica.
- Usarás un Divisor de Voltaje para cualquier señal mayor a 3.3V.
Tu Próximo Reto:
Ahora que sabes medir voltaje, construye un Monitor de Batería WiFi. Usa un divisor de voltaje para leer una batería LiPo y envía el porcentaje de carga a tu celular vía Telegram o MQTT.
Deja una respuesta

Estos temas te pueden interesar