esp32-adc

Cómo usar las entradas analógicas ADC en un ESP32

Todos los modelos de ESP32 tienen disponibles dos ADC (analog-to-digital converter) SAR (Successive Approximation Register) de 12 bits, denominados ADC1 y ADC2.

Con una resolución de 12bits, una resolución de 3.3 voltios / 4096 unidades, es equivalente a 0.8 mV por paso. Además, podemos configurar mediante programación la resolución del ADC y el rango del canal.

La tensión máxima admisible es 3V3. Aunque muchos GPIO del ESP32 son tolerantes a 5V, el ADC no lo es. Así que no metáis más de 3.6V en un pin que uséis como entrada analógica, o dañaréis el ADC.

La cantidad de pines dependerá del modelo de ESP32 que estemos usando. Por ejemplo, en el ESP32 tiene 18 pines, organizados así,

  • ADC1 conectado a 8 GPIOs (32-39)
  • ADC2 conectado a 10 GPIOs (0, 2, 4, 12-15 y 25-27)

Mientras que un ESP32-S3 tiene 20 pines analógicos, organizados en,

  • ADC1 conectado a 10 GPIO (1-10)
  • ADC2 conectado a 10 GPIO (11-20)

Además, dependiendo de tu placa de desarrollo, es posible que no todos los estén disponibles en tu placa. Ante la duda, consulta la documentación de tu modelo completo. leer más ⯈

Por otro lado, muy importante, el ADC2 es usado por el módulo de Wi-Fi, por lo que no podremos usar los pines del ADC2 pines cuando el Wi-Fi está habilitado. Si su proyecto requiere Wi-Fi, utiliza únicamente los pines del ADC1.

Cómo leer la entrada analógica del ESP32

Bajo el entorno de Arduino, la lectura de una entrada analógica en el ESP32 es exactamente igual a como lo haríamos en un Arduino “convencional”.

Simplemente tenemos que usar la función analogRead(GPIO). Que acepta como único argumento el único de pin al que está conectado el sensor.

Por ejemplo así leeríamos el valor analógico del pin A0 y lo mostraríamos en por puerto serie,

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

void loop() 
{
  int sensorValue = analogRead(A0);
  Serial.println(sensorValue);
  delay(100);
}

Por lo demás, el funcionamiento es similar alas entradas analógicas en Arduino. Podemos leer tensiones y resistencias o potenciómetros.

Más funciones útiles

Además de la funcionalidad normal que encontraríamos en un Arduino “normal”, el ESP32 ofrece estas funciones adicionales,

// Establece los bits de muestra y la resolución.
// Puede ser un valor entre 9 (0 – 511) a 12 bits (0 – 4095).
// Resolución predeterminada: 12 bits.
analogReadResolution(resolución);

// Establece los bits de muestra y la resolución.
// Puede ser un valor entre 9 (0 – 511) y 12 bits (0 – 4095).
// Resolución predeterminada: 12 bits.
analogSetWidth(ancho);

// Establece el número de ciclos por muestra.
// Valor predeterminado: 8. Rango: 1 a 255.
analogSetCycles(ciclos);

// Establece el número de muestras en el rango.
// Tiene un efecto de aumentar la sensibilidad.
// Valor predeterminado: 1 muestra.
analogSetSamples(muestras);

// Establece el divisor para el reloj del ADC.
// Valor predeterminado: 1. Rango: 1 a 255.
analogSetClockDiv(attenuation);

// Establece la atenuación de entrada para todos los pines ADC.
// Valor predeterminado: ADC\_11db.
// Valores aceptados:
// - ADC\_0db: sin atenuación
// - ADC\_2\_5db: atenuación extendidamV.
// - ADC\_6db: atenuación extendida
// - ADC\_11db: atenuación extendida
analogSetAttenuation(atenuación);

// Establece la atenuación de entrada para el pin especificado.
// Valor predeterminado: ADC\_11db.
// Valores de atenuación iguales a la función anterior.
analogSetPinAttenuation(pin, atenuación);

// Asocia un pin al ADC (también despeja cualquier otro modo analógico que pueda estar activo).
// Devuelve un resultado VERDADERO o FALSO.
adcAttachPin(pin);

// Inicia una conversión ADC en el bus del pin asociado.
// Verifica si la conversión en el bus ADC del pin está en curso actualmente.
// Devuelve VERDADERO o FALSO.
// Obtiene el resultado de la conversión: devuelve un entero de 16 bits.
adcStart(pin);
adcBusy(pin);
adcEnd(pin);

Valores de atenuación del ADC

Para realizar la medición. el ESP32 compara la tensión que queremos medir con un valor de referencia Vref que, por diseño, es 1.1V.

Para permitir medir un rango de tensiones superiores, el ESP32 emplea un circuito de atenuación de ganancia variable. A -11dB, que es el valor por defecto para poder medir hasta 3V3.

El comportamiento del ADC del ESP32 en sus distintas variantes, nunca ha sido uno de sus puntos más fuertes. Ver más abajo ‘Precisión del ADC’. Por lo tanto el fabricante recomienda unos valores “óptimos” para las tensiones que podemos medir con el ADC.

Valores de atenuación ESP32

AtenuaciónRango tensión preferido
ADC_ATTEN_DB_0100 mV ~ 950 mV
ADC_ATTEN_DB_2_5100 mV ~ 1250 mV
ADC_ATTEN_DB_6150 mV ~ 1750 mV
ADC_ATTEN_DB_11150 mV ~ 2450 mV

Valores de atenuación ESP32-S3

AtenuaciónRango tensión preferido
ADC_ATTEN_DB_0100 mV ~ 950 mV
ADC_ATTEN_DB_2_5100 mV ~ 1250 mV
ADC_ATTEN_DB_6150 mV ~ 1750 mV
ADC_ATTEN_DB_11150 mV ~ 2450 mV

Precisión del ADC en el ESP32

Mucho se ha hablado, y no para bien, de la precisión del ADC del ESP32. Lo cierto es que, tradicionalmente, no es de los puntos más fuertes del ESP32.

Sin embargo, muchas de las cosas que se han dicho no están vigentes a día de hoy, y se aplican únicamente el ESP32 “normal” (no al S2, S3… etc).

El problema del ESP32 es que, como hemos dicho antes, el ESP32 compara con un valor Vref interno 1.1V. Sin embargo, las placas salen con distintas variaciones que hacen que ese 1.1V sea realmente 1.0 a 1.2V.

Por otro lado a -11dB, el valor de atenuación por defecto para poder medir hasta 3V3, el circuito de atenuación mete un comportamiento fuertemente no lineal.

Es decir, que la respuesta que tenemos es algo así. Bastante churro cuando operamos en -11dB.

esp32-adc-response

Es posible calibrar el ESP32 para mejorar el comportamiento del ADC. Aquí tenéis un buen repositorio donde cuentan como calibrarlo de forma sencilla GitHub - e-tinkers/esp32-adc-calibrate.

Sin embargo, lo que normalmente no se dice es que a partir de 2019, los ESP32 salen precalibrados de fábrica y el código se cambió para añadir una corrección por software. Por lo que el comportamiento es bastante mejor.

Por otro lado, en el caso del ESP32-S3 la cosa es diferente. Este modelo incluye un chip de calibrado por hardware interno, por lo que la respuesta del ESP32-S3 es algo así.

esp32-s3-adc-response

Que es mucho mejor que la que teníamos en el ESP32 (sin versión) antiguo.

Por último, incluso en el modelo antiguo, hay que relativizar la importancia de la falta de precisión del ESP32, en función de la que realmente necesites en tu proyecto.

Es decir, si quieres el ADC, por ejemplo, para leer un potenciómetro y cambiar la iluminación de un LED, o la velocidad de un motor, probablemente te sirve perfectamente incluso aunque no lo tengas calibrado.

Si necesitas una medida realmente precisa, probablemente no deberías usar “a pelo” el ADC de ningún procesador, ni del ESP32 ni de un Arduino “convencional”.

En ese caso, puedes o realizar una calibración del ADC, o usar un ADC de alta precisión como el AD1115 que vimos en esta entrada Entrada analógica de 16 bits con Arduino y ADC ADS1115



Referencias: