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:
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
- Temperature Sensor - ADC example with internal sensor
- Battery Voltage - Voltage divider example
- Light Sensor - Photoresistor ADC reading
- TI ADC Selection Guide - Professional ADC options
- Analog Devices University - Signal chain tutorials