¿Qué es un ADC? Convertidor analógico-digital con Arduino
¿Qué es un ADC y cómo funciona? Señal analógica y digital, resolución de 10 y 12 bits, analogReference, fórmula a voltios, ADC2 del ESP32 y reducción de ruido.
Un ADC (convertidor analógico-digital) es el circuito que transforma el voltaje que llega a un pin, y que puede variar de forma continua, en un número con el que el microcontrolador puede trabajar. Cada vez que ejecutas analogRead() en Arduino, este convertidor trabaja en segundo plano: el ADC de 10 bits del Arduino Uno convierte un voltaje entre 0 y 5 V en un número de 0 a 1023, mientras que los ADC de 12 bits del ESP32 y de la Raspberry Pi Pico convierten aproximadamente 0–3,3 V en un número de 0 a 4095. El ADC es la clave para leer cualquier componente con salida analógica: potenciómetros, LDR, sensores de humedad del suelo, joysticks y sensores de temperatura.
En esta guía aprenderás la diferencia entre señales analógicas y digitales, cómo un ADC convierte un voltaje en un número paso a paso y cómo la resolución y el voltaje de referencia afectan a tus mediciones. Veremos con números reales la fórmula para pasar una lectura a voltios, cómo cambiar el rango de medida con analogReference, la frecuencia de muestreo y formas prácticas de reducir el ruido. También trataremos el ADC del ESP32, que no es lineal en los extremos, el conflicto del ADC2 con el Wi-Fi y el ajuste de atenuación, el uso del ADC de la Raspberry Pi Pico con MicroPython y, para terminar, una breve introducción al DAC, que hace justo lo contrario.

¿Cuál es la diferencia entre una señal analógica y una digital?
Una señal analógica es una magnitud que puede tomar infinitos valores dentro de un rango y que cambia de forma continua en el tiempo. Cuando el voltaje del pin central de un potenciómetro pasa de 0 V a 5 V, recorre todos los valores intermedios, como 1,2 V, 1,21 V o 1,215 V; la onda sonora de un micrófono, el voltaje de un termistor que cambia con la temperatura o el voltaje de una pila que baja lentamente también son analógicos. Una señal digital, en cambio, solo conoce ciertos niveles. En el mundo de la lógica de Arduino son dos: LOW (0) y HIGH (1). En el Uno, una entrada digital considera LOW todo lo que está por debajo de unos 1,5 V y HIGH todo lo que supera 3,0 V; la zona intermedia está indefinida. Por eso digitalRead() no distingue entre 3,7 V y 4,2 V en una batería y en ambos casos devuelve HIGH. La ventaja de la señal digital es su inmunidad al ruido: 4,6 V y 5,0 V significan el mismo HIGH. Para medir, guardar o hacer cálculos con un valor analógico, primero tienes que convertirlo en un número, es decir, en un valor digital, y la pieza que se encarga de ello es el ADC.
¿Qué es un ADC y cómo funciona?
El trabajo de un ADC se resume en dos pasos. El primero es el muestreo: en el momento de la medición, el convertidor copia el voltaje de entrada en un pequeño condensador (circuito de muestreo y retención) y lo mantiene fijo hasta terminar la conversión; en el ATmega328P este condensador es de unos 14 pF. El segundo es la cuantización: el voltaje retenido se redondea al escalón más cercano de una escala que divide el voltaje de referencia en escalones iguales, y el número de ese escalón es el resultado. Los ADC del Arduino Uno, el ESP32 y la Pico son todos de aproximaciones sucesivas (SAR, Successive Approximation Register). Un ADC SAR funciona como un juego de adivinar números: primero prueba la mitad de la referencia, pone a 1 el bit más significativo si la entrada es mayor y lo deja a 0 si es menor; luego prueba la mitad del rango restante y repite lo mismo con cada bit. Así, un ADC de 10 bits encuentra el escalón correcto entre 1024 posibilidades con solo 10 comparaciones. Para simplificar, en la tabla ves cómo un ADC de 4 bits con referencia de 5 V mide una entrada de 3,2 V:
| Paso | Bit probado | Voltaje de comparación | ¿La entrada (3,2 V) es mayor? | Bits del resultado |
|---|---|---|---|---|
| 1 | Bit 3 (vale 8) | 8 / 16 × 5 = 2,500 V | Sí → 1 | 1000 |
| 2 | Bit 2 (vale 4) | 12 / 16 × 5 = 3,750 V | No → 0 | 1000 |
| 3 | Bit 1 (vale 2) | 10 / 16 × 5 = 3,125 V | Sí → 1 | 1010 |
| 4 | Bit 0 (vale 1) | 11 / 16 × 5 = 3,4375 V | No → 0 | 1010 |
| Resultado | Todos los bits probados | 1010 = 10 → 10 × 5 / 16 = 3,125 V | Error de 0,075 V (un escalón son 0,3125 V) | 1010 |
La diferencia de 0,075 V en el resultado es el error de cuantización, y ningún ADC puede evitarlo: si el voltaje real está entre dos escalones, el ADC solo puede indicar uno de ellos. El error se mantiene por debajo de un escalón (LSB), así que cuanto más pequeño es el escalón, más fina es la medición. Como el condensador de muestreo y retención tiene que cargarse en cada medición, también importa la resistencia de la fuente que alimenta el ADC: la hoja de datos del ATmega328P recomienda una impedancia de salida de unos 10 kΩ o menos; un divisor de voltaje con resistencias más altas no llega a cargar el condensador a tiempo y las lecturas se desvían. Además del tipo SAR de los microcontroladores, existen otros tipos de ADC. Los ADC sigma-delta son lentos pero muy precisos: el HX711 que se usa en las básculas ofrece 24 bits, y el módulo ADS1115, que se conecta por I2C, 16 bits. Los ADC flash usan un comparador distinto para cada escalón; son rapidísimos y se encuentran en los osciloscopios.
Resolución del ADC: ¿qué significan 10 bits y 12 bits?
La resolución indica en cuántos escalones divide el ADC su rango de medida. Un ADC de N bits produce 2^N escalones: 10 bits son 1024 escalones (0–1023), 12 bits son 4096 (0–4095) y 16 bits, 65.536. El voltaje de un escalón se llama LSB (bit menos significativo) y se calcula con LSB = Vref / 2^N. En el Arduino Uno son 5 V / 1024 = 4,88 mV, y en el ESP32 y la Pico, 3,3 V / 4096 = 0,81 mV. Es decir, el Uno no ve cambios menores de 4,88 mV; con un LM35, que entrega 10 mV/°C, eso supone un escalón de unos 0,5 °C. Pero resolución y precisión no son lo mismo. El ruido, la falta de linealidad y el error de referencia de un ADC hacen inútiles algunos de los bits que figuran en el papel. Esto se mide con el número efectivo de bits (ENOB): el ADC del RP2040 de la Raspberry Pi Pico entrega un resultado de 12 bits, pero según su hoja de datos el número efectivo de bits es 8,7. Comparemos los ADC de las tres placas:
| Característica | Arduino Uno R3 | ESP32 (WROOM-32) | Raspberry Pi Pico |
|---|---|---|---|
| Resolución del ADC | 10 bits (0–1023) | 12 bits (0–4095) | 12 bits (escalado a 0–65535 en MicroPython) |
| Entradas analógicas | 6 (A0–A5; A0–A7 en el Nano) | 18 canales: 8 en ADC1 y 10 en ADC2 | 3 pines (GP26–GP28) + VSYS/3 (GP29) + sensor de temperatura |
| Rango de medida por defecto | 0–5 V | Aprox. 0–3,1 V (atenuación de 11 dB) | 0–3,3 V (ADC_VREF) |
| Un escalón (LSB) | 4,88 mV | Aprox. 0,8 mV | 0,81 mV |
| Opciones de referencia | DEFAULT (5 V), INTERNAL (1,1 V), EXTERNAL (AREF) | Atenuación: 0; 2,5; 6 y 11 dB | Referencia externa en el pin ADC_VREF |
| Frecuencia de muestreo | Unas 10.000 lecturas/s | 20 kHz – 2 MHz en modo continuo (DMA) | 500.000 lecturas/s en hardware |
| Nota sobre precisión | Error absoluto de ±2 LSB | No lineal en los extremos, necesita calibración | ENOB de 8,7 bits, offset de unos 30 mV |
| Salida analógica (DAC) | No tiene (se usa PWM) | 2 canales de 8 bits (GPIO 25 y 26) | No tiene (se usa PWM) |
Fórmula para convertir el valor del ADC en voltios
El número que devuelve el ADC no significa nada por sí solo; para convertirlo en voltaje usas el voltaje de referencia y el número de escalones: Voltaje = valor del ADC × Vref / 2^N. En el Arduino Uno queda V = valor × 5,0 / 1024; si analogRead() devolvió 512, el voltaje del pin es 512 × 5 / 1024 = 2,50 V. En sentido inverso, averiguas a qué número corresponde un voltaje con valor = V × 1024 / Vref: 3,3 V se leen como unos 675 en el Uno. En muchos ejemplos verás que se divide entre 1023 en lugar de 1024. La hoja de datos del ATmega328P da la fórmula ADC = Vin × 1024 / Vref; el valor máximo, 1023, representa un escalón por debajo de Vref. Dividir entre 1023 hace que el valor máximo muestre exactamente 5,00 V, pero desplaza todos los valores cerca de un 0,1 %. Esa diferencia es menor que el propio error de ±2 LSB del ADC, así que ambas opciones sirven; lo importante es ser coherente en el proyecto. La gran fuente de error es el propio Vref: el pin de 5V de un Uno alimentado por USB suele estar entre 4,7 y 5,1 V, y escribir 5,0 en la fórmula provoca errores de hasta el 5 %. Por eso, en mediciones precisas, mide el pin de 5V con un multímetro y pon el valor real en el código. La única entrada analógica del ESP8266 (A0) también es de 10 bits; el chip mide 0–1 V, y el divisor integrado en placas como NodeMCU y Wemos D1 Mini amplía ese rango a unos 0–3,2 V.
| Placa y ajuste | Rango de lectura | Conversión a voltios | Ejemplo |
|---|---|---|---|
| Arduino Uno / Nano (DEFAULT, 5 V) | 0–1023 | V = valor × 5,0 / 1024 | 768 → 3,75 V |
| Uno, analogReference(INTERNAL) | 0–1023 | V = valor × 1,1 / 1024 | 512 → 0,55 V |
| ESP32 (11 dB) | 0–4095 | Calibrado: analogReadMilliVolts() / 1000; aproximado: valor × 3,3 / 4095 | 1650 mV → 1,65 V |
| Raspberry Pi Pico (read_u16) | 0–65535 | V = valor × 3,3 / 65535 | 32768 → 1,65 V |
| ESP8266 NodeMCU / Wemos D1 Mini (A0) | 0–1023 | V = valor × 3,2 / 1024 | 512 → 1,60 V |
Conexión del potenciómetro: Arduino, ESP32 y Pico
| Pin del potenciómetro | Arduino Uno | ESP32 | Raspberry Pi Pico |
|---|---|---|---|
| Pin exterior 1 | 5V | 3V3 | 3V3(OUT) (pin 36) |
| Pin central (señal) | A0 | GPIO 34 (ADC1_CH6) | GP26 / ADC0 (pin 31) |
| Pin exterior 2 | GND | GND | AGND (pin 33) o GND |
| Condensador antirruido opcional | 100 nF entre A0 y GND | 100 nF entre GPIO 34 y GND | 100 nF entre GP26 y AGND |
Paso a paso: tu primera lectura del ADC con Arduino
- Monta el circuito: conecta los pines exteriores de un potenciómetro de 10 kΩ a 5V y GND, y el pin central a A0.
- Mide el pin de 5V: mide con el multímetro el voltaje entre 5V y GND y escríbelo en la constante VREF del código (p. ej. 4.93).
- Sube el código: abre el sketch de abajo en el Arduino IDE, elige la placa y el puerto y súbelo.
- Abre el Monitor Serie: ponlo a 9600 baudios y observa cómo el valor del ADC cambia entre 0 y 1023 al girar la perilla (más detalles en la guía del Monitor Serie).
- Comprueba: mide con el multímetro entre A0 y GND y compáralo con el voltaje en pantalla; la diferencia debería quedarse en unos 10–20 mV.
1// Potansiyometreyi ADC ile okuma / Reading a potentiometer with the ADC
2// Kenar bacaklar 5V ve GND'ye, orta bacak A0'a / Outer legs to 5V and GND, wiper to A0
3const int POT_PIN = A0;
4const float VREF = 5.0; // 5V pininde ölçtüğün gerilim / voltage you measured on the 5V pin
5
6void setup() {
7 Serial.begin(9600);
8}
9
10void loop() {
11 int raw = analogRead(POT_PIN); // 0-1023 arası sayı / number between 0-1023
12 float volts = raw * VREF / 1024.0; // sayıyı volta çevir / convert the number to volts
13 int percent = map(raw, 0, 1023, 0, 100); // yüzdeye ölçekle / scale to percent
14
15 Serial.print(F("ADC: "));
16 Serial.print(raw);
17 Serial.print(F(" Gerilim / Voltage: "));
18 Serial.print(volts, 3);
19 Serial.print(F(" V Yuzde / Percent: "));
20 Serial.println(percent);
21 delay(200);
22}analogRead() completa una medición en unos 100 µs y devuelve un entero entre 0 y 1023. El código convierte primero ese número en voltios con la fórmula y luego en porcentaje con map(). Como map() usa aritmética entera, descarta la parte decimal; si necesitas un resultado con decimales, haz tú el cálculo con float. Se trata de una medición ratiométrica: como el potenciómetro y el ADC se alimentan de los mismos 5 V, la posición de la perilla, es decir, el valor del ADC, no cambia aunque la alimentación baje a 4,9 V; solo cambia el voltaje calculado. Lo mismo ocurre con los sensores que se leen mediante un divisor, como las LDR y los NTC. En cambio, cuando mides el voltaje de una pila o un sensor con salida fija en mV como el LM35, el valor real de Vref influye directamente en el resultado.
Voltaje de referencia y analogReference
El voltaje de referencia (Vref) es el punto más alto de la escala del ADC: si el voltaje de entrada iguala o supera Vref, el resultado se queda clavado en el valor máximo (1023). Reducir Vref estrecha el rango de medida, pero hace más pequeño cada escalón, así que mides las señales pequeñas con más finura. En el Arduino Uno eliges la referencia con la función analogReference(). Con la opción INTERNAL, Vref pasa a ser 1,1 V y un escalón baja a 1,07 mV; puedes leer un LM35 (10 mV/°C) en pasos de unos 0,1 °C, aunque a cambio no podrás medir nada por encima de 1,1 V, es decir, de 110 °C. La propia referencia interna de 1,1 V puede variar entre 1,0 y 1,2 V de un chip a otro, por lo que en proyectos precisos conviene calibrarla una vez con un multímetro. Las primeras lecturas después de cambiar la referencia pueden ser inexactas, como indica la documentación de Arduino, así que es buena costumbre descartar unas cuantas tras el cambio. Además, la referencia afecta a la vez a todos los pines analógicos de la placa. Las opciones varían según la placa:
| Opción | Referencia | Placas | ¿Cuándo usarla? |
|---|---|---|---|
| DEFAULT | 5 V (3,3 V en placas de 3,3 V) | Uno, Nano, Mega, Leonardo | Sensores ratiométricos respecto a la alimentación, como potenciómetros, LDR o joysticks |
| INTERNAL | 1,1 V (ATmega328P); 2,56 V en el Leonardo | Uno, Nano, Leonardo (no existe en el Mega) | Sensores de bajo voltaje como el LM35 |
| INTERNAL1V1 / INTERNAL2V56 | 1,1 V / 2,56 V | Solo Mega | Señales pequeñas en el Mega |
| EXTERNAL | El voltaje del pin AREF (0–5 V) | Uno, Nano, Mega | Usar tu propia referencia de precisión (p. ej. 2,5 V o 4,096 V) |
| AR_INTERNAL | Unos 1,43 V (referencia interna del chip) | Uno R4 Minima y WiFi | Señales pequeñas en el Uno R4 |
Frecuencia de muestreo: ¿cuántas lecturas por segundo hace un ADC?
La frecuencia de muestreo es el número de mediciones que el ADC puede hacer en un segundo. En el Arduino Uno, el reloj del ADC se fija en 125 kHz dividiendo los 16 MHz entre 128, y una conversión dura 13 ciclos de reloj; por eso analogRead() tarda unos 100 µs y se pueden hacer como máximo unas 10.000 lecturas por segundo. Para magnitudes que cambian despacio, como la temperatura, la luz o el voltaje de una batería, es más que suficiente; muchas veces basta con 10 lecturas por segundo. Con señales rápidas entra en juego el teorema de Nyquist: para captar una señal sin perderla debes muestrear al menos al doble de su frecuencia más alta, y en la práctica se prefiere de 5 a 10 veces. Para ver el zumbido de red de 50 Hz necesitas al menos 100 lecturas/s, y para grabar voz de hasta 4 kHz, al menos 8.000 lecturas/s. Si necesitas medir más rápido en el Uno, puedes reducir el preescalador del ADC: con ADCSRA = (ADCSRA & 0xF8) | 0x04; en setup() el preescalador pasa a 16, el reloj del ADC sube a 1 MHz y analogRead() baja a unos 16 µs, a costa de perder algo de precisión. En el ESP32, las llamadas sueltas a analogRead() permiten decenas de miles de lecturas por segundo, y en el modo continuo con DMA (analogContinuous() en Arduino) se puede elegir una frecuencia entre 20 kHz y 2 MHz; este modo solo funciona con pines del ADC1. El ADC de la Raspberry Pi Pico usa su propio reloj de 48 MHz, termina cada conversión en 96 ciclos, es decir, en 2 µs, y alcanza 500.000 lecturas por segundo; un bucle en MicroPython no puede seguir ese ritmo, y para la velocidad máxima necesitas el SDK de C y DMA.
ADC del ESP32: falta de linealidad, conflicto entre ADC2 y Wi-Fi, y atenuación
Sobre el papel, el ADC de 12 bits del ESP32 mide con cuatro veces más finura que el del Uno, pero en la práctica hay que vigilar tres cosas. La primera es la falta de linealidad: cerca de 0 V, el ADC del ESP32 lee 0 hasta unos 100–150 mV, y en el extremo superior se satura en 4095 antes de que la entrada llegue a 3,3 V; la curva intermedia tampoco es una recta perfecta. La segunda es la variación de la referencia: por diseño, la referencia interna del ESP32 es de 1100 mV, pero según Espressif varía entre 1000 y 1200 mV de un chip a otro, lo que supone un error de aproximadamente ±9 % en lecturas sin calibrar. Por eso Espressif graba datos de calibración en los eFuse de los chips durante la fabricación. La función analogReadMilliVolts() de Arduino usa esos datos para convertir el valor bruto directamente en milivoltios calibrados y, en la mayoría de los casos, es mucho más precisa que calcular analogRead() × 3,3 / 4095. La tercera es la atenuación: el núcleo del ADC solo mide hasta aproximadamente 1 V, así que los voltajes más altos se reducen con un atenuador ajustable en la entrada. En Arduino el valor por defecto es 11 dB, que permite leer hasta unos 3,1 V, pero el rango preciso que Espressif recomienda para este ajuste es de 150 a 2450 mV. Con señales pequeñas, reducir la atenuación mejora tanto la precisión como la resolución:
| Atenuación | Constante de Arduino | Rango preciso | Uso |
|---|---|---|---|
| 0 dB | ADC_0db | 100–950 mV | Señales pequeñas, medición más fina |
| 2,5 dB | ADC_2_5db | 100–1250 mV | Salidas de sensores en torno a 1 V |
| 6 dB | ADC_6db | 150–1750 mV | Señales de nivel medio |
| 11 dB (por defecto) | ADC_11db | 150–2450 mV (la lectura llega hasta unos 3,1 V) | Potenciómetros y sensores de 0–3,3 V |
1// ESP32 ADC: ham değer ve kalibre milivolt / ESP32 ADC: raw value and calibrated millivolts
2// Potansiyometre: 3V3, GND ve orta bacak GPIO 34 / Pot: 3V3, GND and wiper to GPIO 34
3const int POT_PIN = 34; // ADC1_CH6, Wi-Fi açıkken de çalışır / ADC1_CH6, works with Wi-Fi on
4
5void setup() {
6 Serial.begin(115200);
7 analogReadResolution(12); // 0-4095 (varsayılan / default)
8 analogSetPinAttenuation(POT_PIN, ADC_11db); // yaklaşık 3,1 V'a kadar / up to about 3.1 V
9}
10
11void loop() {
12 uint32_t rawSum = 0;
13 uint32_t mvSum = 0;
14 for (int i = 0; i < 16; i++) { // 16 ölçümün ortalaması / average of 16 readings
15 rawSum += analogRead(POT_PIN); // ham ADC değeri / raw ADC value
16 mvSum += analogReadMilliVolts(POT_PIN); // eFuse kalibrasyonlu mV / eFuse-calibrated mV
17 }
18 float raw = rawSum / 16.0;
19 float naiveV = raw * 3.3 / 4095.0; // basit formül / naive formula
20 float calibratedV = mvSum / 16.0 / 1000.0; // kalibre edilmiş / calibrated
21
22 Serial.printf("Ham / Raw: %4.0f Formul / Formula: %.3f V Kalibre / Calibrated: %.3f V\n",
23 raw, naiveV, calibratedV);
24 delay(500);
25}El código muestra dos resultados uno al lado del otro: el valor bruto convertido con la fórmula simple y el valor calibrado por analogReadMilliVolts(). Al girar el potenciómetro hacia los extremos verás que la diferencia crece, y abajo del todo, donde la fórmula marca 0,000 V, el multímetro todavía mide unos 0,1 V. analogSetPinAttenuation() cambia la atenuación de un solo pin, mientras que analogSetAttenuation() la cambia para todos. El ESP32 tiene bastante más ruido que el Uno, sobre todo mientras el Wi-Fi transmite; la propia Espressif recomienda añadir un condensador de 100 nF en la entrada y promediar varias muestras, que es justo lo que hace el promedio de 16 lecturas del código. Los chips más nuevos, como el ESP32-S3 y el ESP32-C3, usan una calibración más avanzada por ajuste de curva, pero los números de pin y las reglas del ADC2 cambian según el modelo, así que consulta siempre el mapa de pines de tu placa (herramienta Pinout). Explicamos cómo montar un divisor para medir voltajes de más de 3,3 V en la guía del divisor de voltaje.
ADC en la Raspberry Pi Pico (MicroPython)
La Raspberry Pi Pico tiene tres entradas analógicas accesibles desde fuera: GP26 (ADC0), GP27 (ADC1) y GP28 (ADC2). GP29 (ADC3) mide en la propia placa un tercio del voltaje de alimentación VSYS, y el ADC4 está conectado al sensor de temperatura interno del chip. La función read_u16() de MicroPython escala el resultado de 12 bits al rango 0–65535 para que el mismo código funcione en distintas placas, pero la resolución real sigue siendo de 4096 escalones. El RP2040 no tiene un voltaje de referencia propio: usa como referencia su propia alimentación del ADC. En la Pico, esa alimentación (ADC_VREF, pin 35) se obtiene de la salida del regulador conmutado de 3,3 V (SMPS), filtrada con una resistencia de unos 200 Ω. La hoja de datos de la placa de Raspberry Pi enumera claramente tres consecuencias: la precisión de los 3,3 V es limitada, la alimentación tiene algo de ruido y la corriente que consume el ADC crea un offset de unos 30 mV. Las soluciones están en el mismo documento: poner GP23 en HIGH para que el regulador pase al modo PWM, con menos rizado; conectar a AGND un canal del ADC que no uses y restar su lectura como offset; y, para una precisión mucho mayor, conectar una referencia de 3,0 V como el LM4040 entre ADC_VREF y AGND (el rango de medida pasa entonces a 0–3,0 V). Además, se sabe que el ADC del RP2040 tiene pequeños saltos (errores DNL) en los valores 512, 1536, 2560 y 3584; promediar varias lecturas reduce su efecto. En la Pico W, GP23 está reservado para el chip inalámbrico y el modo del regulador se controla mediante WL_GPIO1, así que en una Pico W borra las líneas de GP23 del código siguiente.
1from machine import ADC, Pin
2import time
3
4pot = ADC(26) # GP26 = ADC0 (pin 31)
5chip_temp = ADC(4) # dahili sıcaklık sensörü / internal temperature sensor
6VREF = 3.3 # ADC_VREF; multimetreyle ölçüp düzelt / measure and correct with a multimeter
7
8# Yalnız Pico ve Pico 2 (W değil): SMPS PWM moduna, daha az gürültü / Plain Pico and Pico 2 only (not W): SMPS to PWM mode, less noise
9smps_mode = Pin(23, Pin.OUT)
10smps_mode.value(1)
11
12
13def read_average(adc, samples=16):
14 total = 0
15 for _ in range(samples):
16 total += adc.read_u16() # 0-65535 (12 bit ölçeklenmiş / 12-bit scaled)
17 return total / samples
18
19
20while True:
21 raw = read_average(pot)
22 volts = raw * VREF / 65535 # sayıyı volta çevir / convert the number to volts
23 t_volts = read_average(chip_temp) * VREF / 65535
24 temp_c = 27 - (t_volts - 0.706) / 0.001721 # RP2040 veri sayfası formülü / RP2040 datasheet formula
25 print("ADC: {:5d} {:.3f} V Yonga / Chip: {:.1f} C".format(int(raw), volts, temp_c))
26 time.sleep(0.5)Cómo reducir el ruido del ADC
Incluso al medir un voltaje fijo, es normal que el valor del ADC baile uno o dos escalones; contribuyen la cuantización, el rizado de la alimentación, las interferencias que captan los cables largos y los motores o transmisiones Wi-Fi cercanos. En el Uno, una oscilación de ±1–2 escalones se considera sana; mucho más que eso suele indicar un problema en el circuito. Puedes combatir el ruido tanto en el hardware como en el software:
- Añade un condensador: un condensador cerámico de 100 nF entre el pin analógico y GND filtra las interferencias rápidas y proporciona carga lista al condensador de muestreo con fuentes de alta resistencia.
- Usa cables cortos: si el cable del sensor es largo, trenza el de señal con el de GND; aleja los cables de motores y relés de las líneas analógicas.
- Haz bien la masa: que la corriente de retorno de cargas de alto consumo, como motores, relés o tiras LED, no pase por el cable GND del sensor; une las masas en un solo punto (masa en estrella).
- Usa una referencia limpia: la alimentación USB tiene ruido; en mediciones de voltaje absoluto, la referencia interna o un circuito integrado de referencia externo dan resultados más estables.
- Descarta la primera lectura al cambiar de canal: el multiplexor de la entrada del ADC puede arrastrar carga del canal anterior; al leer varios pines seguidos, desperdicia una lectura en cada pin.
- Promedia: el promedio de N lecturas reduce el ruido aleatorio aproximadamente √N veces; 16 lecturas lo dejan en una cuarta parte.
- Sobremuestreo (oversampling): si sumas 4^n lecturas y desplazas el resultado n bits a la derecha, ganas n bits extra de resolución; desplazar 2 bits la suma de 16 lecturas convierte los 10 bits del Uno en 12. Para que funcione, la señal debe tener al menos un escalón de ruido natural.
- Filtros de mediana y exponencial: el filtro de mediana elimina los picos repentinos causados por motores, y la media móvil exponencial (EMA) da una curva suave con muy poca memoria.
1// Ham, ortalama ve EMA filtreli ADC değerleri / Raw, averaged and EMA-filtered ADC values
2// Serial Plotter ile izle / Watch with the Serial Plotter
3const int SENSOR_PIN = A0;
4const float ALPHA = 0.1; // EMA katsayısı (0-1) / EMA coefficient (0-1)
5float ema = 0;
6
7void setup() {
8 Serial.begin(115200);
9 analogRead(SENSOR_PIN); // ilk okumayı at / discard the first reading
10 ema = analogRead(SENSOR_PIN); // filtreyi başlat / seed the filter
11}
12
13void loop() {
14 int raw = analogRead(SENSOR_PIN); // ham değer / raw value
15
16 long sum = 0;
17 for (int i = 0; i < 16; i++) { // 16 ölçüm topla / sum 16 readings
18 sum += analogRead(SENSOR_PIN);
19 }
20 float average = sum / 16.0; // ortalama (0-1023) / average (0-1023)
21
22 ema += ALPHA * (raw - ema); // üstel hareketli ortalama / exponential moving average
23
24 Serial.print(F("ham:"));
25 Serial.print(raw);
26 Serial.print(F(" ortalama:"));
27 Serial.print(average);
28 Serial.print(F(" ema:"));
29 Serial.println(ema);
30 delay(20);
31}Al subir el código y abrir el Serial Plotter del Arduino IDE verás tres líneas: el valor bruto tiembla, el promedio de 16 lecturas está claramente más tranquilo y la EMA es la curva más suave, aunque reacciona a los cambios con algo de retraso. El coeficiente ALPHA se elige entre 0 y 1: 0,1 significa que cada lectura nueva aporta un 10 % al resultado, de modo que influyen aproximadamente las últimas 10 lecturas; si lo aumentas, la respuesta es más rápida pero hay más ruido. El filtro adecuado depende de la señal: para una temperatura que cambia despacio va bien una EMA fuerte, y para un joystick que debe responder rápido, un promedio corto. Comparamos la media móvil, el filtro de mediana y la histéresis con ejemplos reales de sensores en la guía de filtrado de datos de sensores.
Breve introducción al DAC: de digital a analógico
Un DAC (convertidor digital-analógico) hace lo contrario que un ADC: recibe un número y produce un voltaje proporcional a él. Si escribes 0 en un DAC de 8 bits obtienes 0 V, con 255 un valor cercano al voltaje de alimentación y con 128 aproximadamente la mitad. Los DAC más sencillos se construyen con una escalera de resistencias llamada R-2R. Aclaremos aquí una confusión habitual: analogWrite() en el Arduino Uno no es un DAC, sino que genera PWM; el pin en realidad conmuta muy rápido entre 0 V y 5 V. Para el brillo de un LED o la velocidad de un motor es suficiente, pero si de verdad necesitas un voltaje estable, tienes que añadir un filtro paso bajo RC a la salida PWM; puedes calcular la constante de tiempo del filtro con la calculadora de constante de tiempo RC. En cuanto a las placas con DAC real: el ESP32 tiene dos DAC de 8 bits en GPIO 25 y GPIO 26, que se usan con dacWrite(pin, valor), mientras que el ESP32-S3 y el ESP32-C3 no tienen DAC. El Arduino Uno R4 tiene un DAC de 12 bits en el pin A0. Para el Uno R3, el Nano y la Pico, lo más fácil es el módulo MCP4725 de 12 bits conectado por I2C. Con un DAC puedes generar sonido, sacar ondas senoidales o triangulares e incluso conectar la salida del DAC a una entrada del ADC para probar el ADC con voltajes conocidos:
1// ESP32 DAC ile sinüs dalgası / Sine wave with the ESP32 DAC
2// Çıkış GPIO 25'te, osiloskopla izle / Output on GPIO 25, watch it with an oscilloscope
3const int DAC_PIN = 25; // DAC1 = GPIO 25 (DAC2 = GPIO 26)
4const int STEPS = 64; // bir periyottaki nokta sayısı / points per period
5uint8_t sineTable[STEPS];
6
7void setup() {
8 for (int i = 0; i < STEPS; i++) {
9 sineTable[i] = 128 + 127 * sin(2 * PI * i / STEPS); // 1-255 arası tablo / table between 1-255
10 }
11}
12
13void loop() {
14 for (int i = 0; i < STEPS; i++) {
15 dacWrite(DAC_PIN, sineTable[i]); // 0 → 0 V, 255 → yaklaşık 3,3 V / 0 → 0 V, 255 → about 3.3 V
16 delayMicroseconds(150); // yaklaşık 100 Hz / roughly 100 Hz
17 }
18}Ideas de proyectos con el ADC
- Voltímetro digital: mide de 0 a 25 V con un divisor de voltaje y muestra el resultado en una LCD; los pasos están en la guía para hacer un voltímetro con Arduino.
- Luz nocturna automática: lee el voltaje de una LDR y enciende los LED cuando oscurezca.
- Maceta inteligente: usa la salida analógica de un sensor de humedad del suelo para activar una bomba cuando la tierra se seque.
- Robot controlado con joystick: los dos ejes de un joystick son dos entradas analógicas independientes; convierte sus valores en velocidad y dirección de los motores.
- Medidor de corriente: lee el voltaje proporcional a la corriente de un ACS712 para saber cuánta corriente consume un aparato.
- Medidor de nivel de sonido: muestrea rápido la salida analógica de un sensor de sonido KY-038 y enciende una barra de LED según el valor de pico.
- Indicador de batería: mide el voltaje en un proyecto con pilas y muestra en una pantalla la carga restante en porcentaje.
Errores frecuentes y cómo solucionarlos
| Síntoma | Causa probable | Solución |
|---|---|---|
| El valor cambia al azar sin nada conectado | El pin está flotando | Conecta el sensor; no leas pines sin usar o llévalos a GND |
| El valor se queda en 1023 (4095 en el ESP32) | La entrada supera la referencia o está seleccionada INTERNAL | Ajusta la referencia o la atenuación y reduce los voltajes altos con un divisor |
| En el ESP32, analogRead() devuelve 0 al activar el Wi-Fi | El sensor está en un pin del ADC2 | Usa los pines del ADC1, GPIO 32–39 |
| El ESP32 marca 0 con voltajes bajos y 4095 con altos | El ADC no es lineal en los extremos | Usa analogReadMilliVolts() y mantén la señal entre 150 y 2450 mV |
| El voltaje calculado difiere un 3–5 % del multímetro | Vref no es 5,00 V (alimentación USB) | Mide el pin de 5V y ponlo en VREF, o añade un factor de calibración |
| Al leer dos pines seguidos, los valores se influyen | Multiplexor y resistencia de fuente alta | Descarta la primera lectura tras cambiar de canal, mantén la fuente por debajo de 10 kΩ, añade 100 nF |
| Los valores saltan cuando funciona un motor o un relé | Ruido en la línea GND compartida, la alimentación cae | Da a las cargas su propio retorno a GND, usa condensadores y un filtro de mediana |
| Las lecturas fallan tras aplicar voltaje a AREF | Se usó AREF sin llamar a analogReference(EXTERNAL) | Selecciona primero EXTERNAL o conecta AREF a través de una resistencia de 5 kΩ |
| Tras elegir INTERNAL, el potenciómetro llega a 1023 a mitad de recorrido | La referencia de 1,1 V afecta a todos los pines analógicos | Vuelve a DEFAULT antes de leer sensores ratiométricos y descarta algunas lecturas |
| En la Pico, la lectura es mayor que 0 incluso con la entrada en GND | Offset del ADC y ruido en ADC_VREF | Conecta un canal a AGND, mide el offset y réstalo; pon GP23 en HIGH |
El ADC es el puente entre el mundo físico y tu código: cuando conoces su resolución, su voltaje de referencia y su frecuencia de muestreo, sabes también qué representa cada número que ves en pantalla y hasta qué punto puedes fiarte de él. En el Uno mide bien la referencia, en el ESP32 usa los pines del ADC1 y analogReadMilliVolts(), en la Pico ten en cuenta el offset y el ruido, y después suaviza el resultado con promedios y filtros. En la app de BlueGrays encontrarás proyectos basados en lecturas analógicas, como medir la intensidad de luz con una LDR, un voltímetro digital con LCD, medir la temperatura con un NTC y controlar un servo y el brillo de un LED con un potenciómetro, con esquemas y código paso a paso.
Preguntas frecuentes
¿Qué es un ADC y para qué sirve?
Un ADC (convertidor analógico-digital) es el circuito que convierte el voltaje de un pin en un número que el microcontrolador puede procesar. Sirve para leer componentes con salida analógica, como potenciómetros, LDR y sensores de temperatura y humedad. En Arduino, la instrucción analogRead() pone en marcha este convertidor.
¿Qué diferencia hay entre una señal analógica y una digital?
Una señal analógica puede tomar cualquier valor dentro de un rango y cambia de forma continua, mientras que una señal digital solo tiene ciertos niveles, LOW y HIGH en Arduino. digitalRead() solo te dice si un pin está a 0 o a 1; analogRead(), en cambio, te da con un número cuánto voltaje hay.
¿Por qué analogRead de Arduino da valores de 0 a 1023?
El ADC del Arduino Uno es de 10 bits y produce 2^10 = 1024 escalones distintos, numerados del 0 al 1023. El 0 representa 0 V, y el 1023, un escalón por debajo del voltaje de referencia (normalmente 5 V). Los ADC de 12 bits del ESP32 y la Pico dan valores de 0 a 4095.
¿Cómo se convierte el valor del ADC a voltaje?
Usa la fórmula voltaje = valor del ADC × voltaje de referencia / número de escalones. En el Arduino Uno es V = valor × 5,0 / 1024; en el ESP32, analogReadMilliVolts() da directamente milivoltios calibrados. En la Pico, para el valor de read_u16() de MicroPython se usa V = valor × 3,3 / 65535.
¿Funcionan los pines ADC2 del ESP32 con Wi-Fi?
No. En el ESP32, el controlador de Wi-Fi también usa la unidad ADC2, así que con el Wi-Fi activo no se puede leer de los pines del ADC2 (GPIO 0, 2, 4, 12–15, 25–27). En proyectos con Wi-Fi, conecta los sensores analógicos a los pines del ADC1 (GPIO 32–39).
¿Qué es un DAC y en qué se diferencia de un ADC?
Un DAC (convertidor digital-analógico) hace lo contrario que un ADC: convierte un número en voltaje. El ADC se usa para medir el voltaje que llega de un sensor, y el DAC para generar un voltaje, como sonido o una señal. El Arduino Uno no tiene DAC y analogWrite() genera PWM; el ESP32 tiene dos DAC de 8 bits en GPIO 25 y 26, y el Uno R4 un DAC de 12 bits en A0.
Proyectos para hacer después de leer esto
Ver todos los proyectos
Medir la intensidad de luz con LDR
¿Quieres ver en números cuánta luz hay en tu habitación? El LDR, una pequeña pieza sensible a la luz, mide la luz ambiente y el Arduino escribe el valor en la pantalla del ordenador cada medio segundo

Voltímetro digital con pantalla LCD
Descubre cuánto voltaje da una pila o un adaptador con un medidor hecho por ti. Un divisor de dos resistencias baja la tensión alta a un nivel que la placa puede leer, y el Arduino calcula el valor re

Lectura de la intensidad luminosa con el módulo LDR del ESP32
Visualización en tiempo real en el monitor serie del valor bruto del ADC del módulo LDR y del porcentaje relativo de luz calculado a partir de referencias de oscuridad y claridad. Este porcentaje no es una medición en lux. Explica el funcionamiento de la calibración del módulo. Es recomendable realizarlo antes del Proyecto 10, ya que se utiliza para determinar el valor umbral.

Brillo de LED con Potenciómetro en ESP32 (Analógico → PWM)
En este proyecto controlamos el brillo de un LED de forma analógica mediante un potenciómetro. El pin ADC del ESP32 lee la tensión de 0-3,3 V procedente del potenciómetro y este valor se convierte en una señal PWM (modulación por ancho de pulso) que se envía al LED. Al girar el potenciómetro, el LED se enciende y se apaga gradualmente. Con Arduino Core 3.0+ se usa directamente analogWrite(); en el ESP32-S2/S3, la resolución del ADC es de 12 bits.

Medición de temperatura con NTC y pantalla LCD 2x16
Mide la temperatura del ambiente con un sensor que parece una pequeña cuenta. Esta pieza, llamada NTC, deja pasar la electricidad con más facilidad cuanto más se calienta; el Arduino lee ese cambio, l

Funcionamiento del servomotor con potenciómetro
A medida que giras el mando del potenciómetro, el brazo del servomotor gira con él: un extremo del mando equivale a cero grados y el otro a media vuelta. El Arduino lee sin parar la posición del mando

Control Led con Joystick
Empuja hasta el fondo la palanquita del joystick en cualquier dirección y se enciende el LED de esa dirección: hay cuatro colores distintos para derecha, izquierda, arriba y abajo. Cuando sueltas la p

Lámpara con mezclador de colores ESP32 (3 potenciómetros + LED RGB + OLED)
¡Una lámpara mezcladora de colores inteligente que combina el color que quieras girando tres potenciómetros con el ESP32! A medida que giras los potenciómetros de rojo, verde y azul, el LED RGB de cátodo común cambia de color al instante. En la pantalla OLED SSD1306 se muestran en tiempo real los valores de cada color en un rango de 0 a 255, barras de relleno visuales y el código de color HEX para la web (como #FF8040). Un miniestudio de color profesional: enseña la teoría del color RGB, la lect
Más artículos
App BlueGrays
Monta este circuito paso a paso en tu teléfono
Esquema, código y lista de piezas en una sola pantalla. Más de 200 proyectos de Arduino, ESP32 y Pico listos para montar.
Escanea con tu teléfono
Apunta la cámara al código y se abrirá la tienda de apps de tu teléfono.
o ábrela en la tienda

