Reading Analog Sensors with an MCP3008 ADC
The Raspberry Pi has no built-in ADC at all — here's the small external chip that gives it one, and how to read it over SPI.
You'll need: an MCP3008 (an 8-channel, 10-bit ADC chip), a potentiometer or LDR-divider from Lesson cb-12, jumper wires, a breadboard, and your Pi.
Lesson 29 covered ADCs, and the Arduino Uno has one built in, ready to use with a single analogRead() call. The Raspberry Pi's GPIO pins are purely digital — there's no equivalent built-in ADC at all. To read any analog voltage on a Pi, you need an external ADC chip like the MCP3008, connected over the SPI protocol from Lesson 34.
Wire the MCP3008 to the Pi's SPI pins (covered fully in Lesson rpi-14), connect your analog source (a potentiometer's wiper, or an LDR divider's junction) to one of the MCP3008's 8 analog input channels, and read it in Python using the spidev library:
import spidev
spi = spidev.SpiDev()
spi.open(0, 0)
spi.max_speed_hz = 1350000
def read_channel(channel):
cmd = [1, (8 + channel) << 4, 0]
reply = spi.xfer2(cmd)
value = ((reply[1] & 3) << 8) + reply[2]
return value
print(read_channel(0)) # 0-1023, same range as Arduino's analogRead()The MCP3008 communicates over SPI using a specific 3-byte command format, which is what the slightly cryptic cmd list encodes — you don't need to fully understand SPI's byte-level protocol to use this function, just to know that read_channel(0) through read_channel(7) reads each of the chip's 8 input channels, returning the same familiar 0–1023 range as the Uno's analogRead().