An Analog-to-Digital Converter (ADC) is a hardware circuit that samples a continuous, real-world voltage and translates it into a discrete binary integer that a microcontroller can process. In a physical circuit, the ADC changes an infinite range of analog potentials (like 1.45382V) into a finite set of digital steps (like the integer 1850), bridging continuous physical phenomena and discrete computational logic. Beginners commonly confuse ADC resolution (the number of discrete steps available) with sampling rate (how frequently those steps are measured), or they mistake an ADC for a simple comparator that only outputs a binary 1 or 0 based on a threshold.
Resolution, Reference Voltage, and the Quantization Table
To understand how an ADC works, think of it as a digital ruler. If you have a 12-inch ruler marked only in whole inches, you cannot measure 1.5 inches precisely; you must round to either 1 or 2. This rounding is called quantization. The ADC's bit-depth determines how many marks are on the ruler, while the reference voltage (V_ref) determines the total length of the ruler.
The smallest voltage change the ADC can detect is the Least Significant Bit (LSB), calculated as V_ref / (2^bit_depth). If your sensor outputs a voltage change smaller than the LSB, the microcontroller will not see it. Below is a spec-sheet-table comparing the internal ADCs of popular maker boards against dedicated external ADC ICs.
| Microcontroller / ADC IC | Bit Depth | Total Steps | Typical V_ref | Voltage per Step (LSB) |
|---|---|---|---|---|
| Arduino Uno (ATmega328P) | 10-bit | 1024 | 5.0V | 4.88 mV |
| ESP32 DevKit V1 (Internal) | 12-bit | 4096 | 3.3V | 0.80 mV |
| Raspberry Pi Pico (RP2040) | 12-bit | 4096 | 3.3V | 0.80 mV |
| Texas Instruments ADS1115 (External I2C) | 16-bit | 65536 | 4.096V (PGA) | 0.0625 mV |
| Microchip MCP3008 (External SPI) | 10-bit | 1024 | 3.3V | 3.22 mV |
V_ref is nominally 3.3V, but due to internal silicon variations and voltage drops, the actual full-scale voltage often sits closer to 3.1V or 3.2V. Always calibrate using the esp_adc_cal library if you need absolute voltage accuracy.
Worked Numeric Example: Reading a Thermistor on an ESP32
Let us walk through a concrete numeric example using the internal 12-bit ADC on an ESP32 DevKit V1 (specifically on GPIO 34, which is input-only and lacks an internal pull-up). We are measuring a 10kΩ NTC thermistor wired in a voltage divider with a 10kΩ fixed resistor, powered by the 3.3V rail.
Assume the ESP32's analogRead(34) function returns a raw integer of 1850. To find the actual voltage at the ADC pin, we use the standard quantization formula:
Calculation: V_in = (1850 / 4096) × 3.3V
Result: V_in = 1.488V
At 1.488V, the voltage divider is split almost perfectly in half, indicating the thermistor's resistance is currently very close to 10kΩ (which corresponds to roughly 25°C for a standard Beta 3950 NTC). From this voltage, your code uses the Steinhart-Hart equation to calculate the final temperature.
However, here is where real-world hardware deviates from textbook theory. The ESP32 internal ADC is notoriously non-linear. According to the Espressif ESP-IDF ADC documentation, the internal ADC exhibits significant non-linearity near 0V and near the 3.3V rail, and the attenuation settings (0dB, 2.5dB, 6dB, 11dB) shift the readable window. If your thermistor voltage pushes past 2.5V, the raw integer will saturate and flatten out, giving you completely inaccurate temperature readings at the extremes. For precision thermal monitoring, bypassing the internal ADC in favor of an external 16-bit IC is the standard professional fix.
Where You Meet This In Practice
Understanding how an ADC works is only half the battle; knowing which ADC architecture to deploy is where the engineering happens. Here is where you meet this in practice across different project tiers:
- Tier 1: Internal MCU ADCs (ATmega328P, ESP32, RP2040). You use these for crude, non-critical measurements. Examples include reading a manual potentiometer for a UI dial, checking a LiPo battery voltage via a high-resistance divider, or detecting simple light levels with an LDR. The RP2040 datasheet notes its internal ADC is excellent for general use but requires a clean 3.3V supply to avoid injecting digital noise into the analog readings.
- Tier 2: External I2C/SPI ADCs (ADS1115, MCP3008). You graduate to these when your sensor outputs microvolt or millivolt changes. Load cells (via HX711 or ADS1256), precision RTD temperature probes, and audio waveform sampling require 16-bit to 24-bit resolution. The Texas Instruments ADS1115 datasheet highlights its internal Programmable Gain Amplifier (PGA), which allows you to measure signals as small as ±256mV with an LSB of 7.8µV—something an ESP32 could never resolve internally.
- Tier 3: Sigma-Delta vs. Successive Approximation (SAR). Most maker boards use SAR ADCs, which are fast and power-efficient but limited to 12-16 bits. Sigma-Delta ADCs (found in high-end audio interfaces and 24-bit load cell amplifiers) trade speed for extreme resolution by oversampling and digitally filtering the signal.
Common ADC Pitfalls and Debugging Framework
When your analog readings are erratic, drifting, or completely stuck, the issue is rarely the microcontroller's silicon. It is almost always a circuit-level violation of the ADC's sample-and-hold requirements. Use this troubleshooting framework:
1. Source Impedance Mismatch (The "Ghosting" Effect)
Inside a SAR ADC is a tiny sample-and-hold capacitor (often 10pF to 14pF). When the ADC multiplexer switches to your pin, this capacitor must charge to the input voltage within a few microseconds. The ATmega328P requires a source impedance of less than 10kΩ. If you build a battery-monitoring voltage divider using 100kΩ and 100kΩ resistors to save power, the capacitor will not charge in time. The ADC will read a ghost voltage left over from the previously scanned pin. Fix: Keep divider resistances under 10kΩ, or add a 100nF ceramic capacitor at the ADC pin to act as a local charge reservoir.
2. Floating Analog Pins
If you run analogRead() on an unconnected GPIO, you will see random numbers jumping from 0 to 1023. This is not a broken ADC; it is a high-impedance input acting as an antenna, picking up 50/60Hz mains hum and RF noise from the room. Fix: Always tie unused analog pins to GND via a 10kΩ pull-down resistor in hardware, or configure them as digital outputs in software.
3. Noisy V_ref Rails
The ADC measures the ratio of the input voltage to the reference voltage. If your 3.3V regulator has 50mV of ripple from a nearby switching buck converter, your ADC readings will ripple by the exact same proportion, even if the sensor signal is perfectly clean. Fix: Place a 1µF tantalum and a 0.1µF ceramic capacitor directly across the V_ref and GND pins of external ADC ICs. For internal ADCs, ensure your microcontroller's analog ground (AGND) is properly bonded to digital ground (DGND) at a single star point.
analogRead() for critical decisions. Always implement a software oversampling routine: read the pin 16 times, discard the highest and lowest 2 values, and average the remaining 12. This mathematically filters out high-frequency transient noise without requiring extra hardware components.






