Skip to content

ADC Basics

Analog-to-Digital Converters (ADC) let microcontrollers read real-world analog signals like temperature, light, and battery voltage.


Why ADC?

The real world is analog - temperatures, distances, light levels vary continuously. But microcontrollers only understand digital values (0 and 1).

ADC bridges this gap by sampling analog voltage and quantizing it to a digital number.


Key Concepts

Sampling

Taking measurements at discrete time intervals.

Sample Rate: How often we measure (samples per second, Hz) - Higher rate = more detail, more data - Nyquist theorem: Sample at least 2x the highest frequency in signal

Quantization

Converting continuous voltage to discrete levels.

Resolution: Number of bits determines precision - 12-bit ADC (Pico) = 4096 levels (0-4095) - 16-bit ADC = 65536 levels

Reference Voltage

The maximum voltage the ADC can measure. - Pico: 3.3V reference - 12-bit: Each step = 3.3V / 4096 = 0.8 mV


Pico ADC Channels

Channel GPIO Use
ADC0 GP26 External analog input
ADC1 GP27 External analog input
ADC2 GP28 External analog input
ADC3 - Internal: VSYS/3
ADC4 - Internal: Temperature sensor
Warning

Only GP26, GP27, GP28 can be used for ADC. Other pins are digital only!


MicroPython ADC

Basic Reading

from machine import ADC, Pin

# Create ADC on GP26
adc = ADC(Pin(26))

# Read raw value (0-65535 in MicroPython)
raw = adc.read_u16()

# Convert to voltage
voltage = raw * 3.3 / 65535
print(f"Voltage: {voltage:.3f}V")

Internal Temperature

# Built-in temperature sensor
temp_sensor = ADC(4)

raw = temp_sensor.read_u16()
voltage = raw * 3.3 / 65535
temp_c = 27 - (voltage - 0.706) / 0.001721
print(f"Temperature: {temp_c:.1f}°C")

Common Issues

Noise

ADC readings fluctuate even with constant input.

Solutions: - Average multiple readings - Add capacitor to smooth input - Use filtering (moving average, low-pass)

def read_averaged(adc, samples=10):
    total = 0
    for _ in range(samples):
        total += adc.read_u16()
    return total // samples

Input Impedance

ADC inputs have limited input impedance (~100kΩ). High-impedance sources need buffering.

Voltage Dividers

For voltages >3.3V, use a resistor divider:

Vin ──┬── R1 ──┬── GND
      │        │
      └── R2 ──┴── ADC (Vout)

Vout = Vin × R2 / (R1 + R2)

Example: Measure 0-12V battery - R1 = 30kΩ, R2 = 10kΩ - 12V × 10k/(30k+10k) = 3V (safe for ADC)


Precision vs Accuracy

Term Meaning
Precision How repeatable are readings? (low noise)
Accuracy How close to true value? (calibrated)

A sensor can be precise but inaccurate (consistent wrong readings) or accurate but imprecise (scattered around true value).


Professional Context: Industrial & Automotive ADCs

The Pico's built-in 12-bit ADC is adequate for learning, but professional systems use significantly more sophisticated analog acquisition. Here's how they compare:

ADC Comparison

Feature Pico ADC Industrial DAQ Automotive ECU Medical/Scientific
Resolution 12-bit (4096 levels) 16-24 bit 10-12 bit 24-32 bit
Accuracy ±2-3 LSB typical ±0.1 LSB ±1 LSB ±0.001%
Sample rate 500 ksps shared 1-100 Msps 1 Msps/channel 10 ksps (high res)
Channels 3 external + 2 internal 8-64 simultaneous 16-32 multiplexed 1-8 differential
Input type Single-ended Differential Differential Instrumentation amp
Noise ~2-3 LSB <1 LSB RMS <1 LSB µV level
Input protection None (max 3.3V!) ±30V with clamps ±40V automotive Isolated to kV
Calibration None Factory + self-cal Factory per unit NIST traceable
Price Included (~$0.10) $50-5000 $5-50/channel $100-10000+

Why Resolution Matters

12-bit ADC (Pico) measuring 0-3.3V:
    Step size = 3.3V / 4096 = 0.8 mV
    Can distinguish: 0.000V, 0.001V, 0.002V, ...

    For battery voltage (7-8.4V via divider to 2.3-2.8V):
    Each step = 0.8mV × 3 = 2.4mV actual
    Can detect ~0.3% battery change

16-bit ADC measuring same:
    Step size = 3.3V / 65536 = 50 µV
    16× finer resolution

24-bit ADC:
    Step size = 3.3V / 16,777,216 = 0.2 µV
    Measures µV-level signals directly

Differential vs Single-Ended

Your Pico (single-ended):
    Signal ────┤ADC├──── measures voltage relative to GND

    Problem: Any noise on GND appears in reading

Industrial (differential):
    Signal+ ───┤     ├
               │ ADC │──── measures DIFFERENCE (rejects common noise)
    Signal- ───┤     ├

    50/60 Hz hum, motor noise → rejected by 60-120 dB

Automotive Sensor Interfaces

Professional ECUs don't just read ADC values:

Sensor Type Robot Approach Automotive Approach
Temperature (NTC) Read ADC, lookup table Ratiometric, fault detection, range check
Pressure Read ADC SENT protocol (digital), diagnostics
Position Potentiometer + ADC Redundant sensors, plausibility check
Current Shunt + ADC Hall sensor, galvanic isolation

Ratiometric Measurement:

Robot: Vout = ADC × 3.3V / 4096
       If 3.3V rail drops to 3.2V → wrong reading!

Automotive: Vout/Vref measured
            Same reference for sensor and ADC
            Power supply variations cancel out

Sample-and-Hold / Simultaneous Sampling

Robot (multiplexed ADC):
    Time 0: Read Ch0
    Time 1: Read Ch1
    Time 2: Read Ch2
    → Channels sampled at DIFFERENT times!

Motor control (simultaneous):
    Time 0: Read all 3 phase currents SIMULTANEOUSLY
    → Required for accurate FOC calculations

For your robot, multiplexing is fine (sensors change slowly). For 20 kHz motor control, simultaneous sampling is essential.

What the Industry Uses

Manufacturer Product Application
Texas Instruments ADS1256 24-bit precision measurement
Analog Devices AD7768 24-bit simultaneous sampling
Microchip MCP3008 10-bit low-cost SPI ADC
NXP S32K3xx Automotive MCU with 12-bit ADC
National Instruments DAQ Lab data acquisition

Hardware Limits Principle

What Software Can and Cannot Fix

Software CAN improve: - Noise → averaging (reduces by √N for N samples) - Offset error → calibration with known reference - Non-linearity (mild) → lookup table correction - Slow signals → oversampling + decimation (adds ~1 bit per 4× oversampling)

Software CANNOT fix: - 12-bit resolution limit → need external ADC for 16+ bits - Missing bits (DNL errors) → hardware defect - Input voltage >3.3V → will damage Pico! - Common-mode noise → need differential ADC - Aliasing (signal > Nyquist) → need analog anti-alias filter - Absolute accuracy → need calibrated reference

The lesson: Averaging 16 samples improves noise by 4×, effectively adding ~2 bits of resolution. But you cannot average your way from 12-bit to 24-bit precision—the quantization noise floor is fixed by hardware.

Real Example: Temperature Measurement

Requirement Pico ADC Solution Needed
±1°C accuracy ✓ Works Built-in sensor OK
±0.1°C accuracy ✗ Noise too high External precision ADC + averaging
±0.01°C accuracy ✗ Not possible 24-bit ADC + precision reference + calibration
Medical grade ✗ Not certified Certified measurement system

Your robot needs ±5% battery reading and ±2°C temperature. The Pico ADC is more than adequate. A medical thermometer needs ±0.1°C—that requires different hardware.


Further Reading