PyRaspBeta

Analog inputs and ADCs

A digital input answers yes or no: is the pin high or low? Many of the most useful sensors answer with a value instead — a potentiometer gives a voltage that depends on the knob's angle, an LDR one that depends on the light, a soil probe one that depends on moisture. The Pi has no pin that can measure a voltage, so every such sensor needs an analog-to-digital converter (ADC) between it and the Pi.

Why an ADC is needed

The 40-pin header is digital only: a GPIO reads high or low, with nothing in between. An ADC measures a voltage and reports a number, and it talks to the Pi over a digital bus — usually SPI or I²C. Two chips cover almost every case: the MCP3008 (cheap, 10-bit, eight channels, SPI) and the ADS1115 (precise, 16-bit, four channels, I²C).

MCP3008 — 10 bits, 8 channels, SPI

The classic Raspberry Pi ADC. It has eight single-ended inputs, converts one at a time, and returns a number from 0 to 1023 — 10 bits — proportional to the input voltage relative to its reference:

code = 1024 × Vin ÷ VREF

Wire VREF to 3V3 and the range is 0–3.3 V, with each step worth 3.3 V ÷ 1024 ≈ 3.2 mV. Power VDD from 3V3 as well: at 5 V the chip's data output swings to 5 V, which a GPIO must not see. It costs $4.

PinWhat it isType
CH0Analog input 0 (pin 1)io
CH1Analog input 1 (pin 2)io
CH2Analog input 2 (pin 3)io
CH3Analog input 3 (pin 4)io
CH4Analog input 4 (pin 5)io
CH5Analog input 5 (pin 6)io
CH6Analog input 6 (pin 7)io
CH7Analog input 7 (pin 8)io
DGNDDigital ground (pin 9)ground
CSChip select, active low (pin 10)io
DINSerial data in, from MOSI (pin 11)io
DOUTSerial data out, to MISO (pin 12)io
CLKSerial clock, from SCLK (pin 13)io
AGNDAnalog ground (pin 14)ground
VREFReference voltage (pin 15)io
VDDSupply 2.7–5.5 V (pin 16)power

A potentiometer read through channel 0:

from wiring import *

pi = Pi()
adc = MCP3008()
pot = Potentiometer()

pi.V3_3 >> adc.VDD >> adc.VREF
pi.GND >> adc.AGND >> adc.DGND
pi.SCLK >> adc.CLK
pi.MOSI >> adc.DIN
pi.MISO >> adc.DOUT
pi.CE0 >> adc.CS

pi.V3_3 >> pot.pin1
pot.pin3 >> pi.GND
pot.wiper >> adc.CH0
from gpiozero import MCP3008
from time import sleep

knob = MCP3008(channel=0)

while True:
    print(f"{knob.value:.3f}  ({knob.voltage:.2f} V)")
    sleep(0.5)

gpiozero.MCP3008 gives you value (0.0–1.0), voltage (0–3.3 V) and raw_value (0–1023). The MCP3008 page has the full pinout, and the potentiometer page explains the three terminals.

ADS1115 — 16 bits, 4 channels, I²C

The ADS1115 is the precise option: four inputs, 16-bit conversions, an internal reference and a programmable gain that picks the full-scale range (±4.096 V down to ±0.256 V), at 8–860 samples per second. It costs $6 and needs only the I²C pins:

  • VDD and GND from the Pi.
  • SDA and SCL to GPIO2 and GPIO3, alongside any other I²C devices — its part page has the pull-ups covered.
  • ADDR picks the address: GND = 0x48, VDD = 0x49, SDA = 0x4A, SCL = 0x4B, so four can share one bus.

Its registers are 16-bit and big-endian: write a pointer byte, then read two bytes — which smbus2 can drive directly, or use the vendored Adafruit ADS1x15 driver.

Reading real sensors

  • Potentiometer — ends to 3V3 and GND, wiper to the ADC. The wiper voltage is the knob's position across the full range.
  • LDR — an LDR needs a partner: put the LDR from 3V3 to the ADC input and a 10 kΩ resistor from the input to GND. More light lowers the LDR's resistance and raises the voltage. The light sensor module is exactly this, pre-wired to an MCP3008.
  • Soil moisture — the capacitive probe outputs a voltage that falls as the soil gets wetter. It drifts part to part, so calibrate: note the reading in dry air and in a glass of water, then scale between them. The soil module includes the ADC.

10 bits or 16?

  • MCP3008: 1024 steps over the reference, 3.2 mV at 3V3. Plenty for a knob, an LDR or a soil probe — which are not that precise themselves — and its eight channels are handy.
  • ADS1115: 32768 steps, about 125 µV at its 4.096 V range, but the noise floor is around a step, so treat the lowest bits as noise. Worth it for small signals (a thermocouple, a strain gauge), not for a doorbell light sensor.
  • The reference matters more than the bits. On the MCP3008 the counts mean nothing if VREF is not the voltage you assumed; tie it to the same 3V3 the sensor uses, and keep inputs between 0 V and VREF.

Going deeper

  • The MCP3008 is modelled at bit level. After CS goes low it waits for a start bit, a single-ended/differential bit and three channel bits; it samples, then shifts out a null bit, the 10-bit result MSB first, and the same bits LSB first, as the datasheet describes. VREF at or below 0.25 V reads 0. The simulated chip answers in SPI mode 0; another mode rotates the reply and warns. Missing MISO wiring or an unwired CS reads zeros.
  • The ADS1115's model implements the register map: conversion (0), config (1) and threshold registers; 16-bit big-endian; single-shot mode sets the OS bit and takes 1/sample-rate of simulated time, clearing OS when done; the PGA picks the range. Noise is roughly one LSB, as the datasheet says.
  • gpiozero's MCP3008 uses spidev in the simulator (port 0, device 0 — CE0) and falls back to bit-banging four GPIOs on real hardware if spidev is missing. channel, differential and the normalized reading all work as documented.
  • Unused inputs should be grounded; a channel with nothing wired to it has no defined voltage, and its readings wander.
  • Divider maths for an LDR (LDR on top, 10 kΩ below): Vout = 3.3 V × 10 kΩ ÷ (LDR resistance + 10 kΩ). At 10 lux the GL5528 sits around 10–20 kΩ, so the reading lands near mid-scale; swap the resistor if your light range sits at one end.
  • Never power the MCP3008 at 5 V. VREF may be 3.3 V while VDD is 5 V — the reference only sets the conversion range — but the digital output levels follow VDD, so at 5 V the chip puts 5 V on MISO.
  • Datasheets: MCP3004/3008 (Microchip) and ADS111x (TI); gpiozero's SPI device docs cover MCP3008 and friends.