Using an MCP3008 ADC to Read Analog Sensors with Raspberry Pi
Connecting analog sensors to a Raspberry Pi can be challenging because the Pi’s GPIO pins are only digital. An inexpensive solution is the MCP3008, an 8‑channel 10‑bit analog‑to‑digital converter that plugs straight into the Pi’s SPI bus and requires no extra components.
In this guide we’ll walk through wiring an MCP3008 to a Raspberry Pi, hooking up a light‑dependent resistor (LDR) and a TMP36 temperature sensor, and reading the data with a simple Python script.
What You’ll Need
- Raspberry Pi (any model with a GPIO header)
- MCP3008 8‑channel ADC
- Light‑dependent resistor (LDR) – e.g. NORPS‑12
- TMP36 temperature sensor
- 10 kΩ resistor (for the LDR circuit)
Enable SPI on the Pi
The SPI interface is disabled by default. Follow the steps in Enabling The SPI Interface On The Raspberry Pi to activate SPI and install the spidev Python library.
Circuit Connections
The MCP3008 requires four GPIO pins on the Pi’s 40‑pin header. Connect the following pins (pin numbers refer to the header’s P1 numbering):
VDD 3.3V VREF 3.3V AGND GROUND CLK GPIO11 (P1‑23) DOUT GPIO9 (P1‑21) DIN GPIO10 (P1‑19) CS GPIO8 (P1‑24) DGND GROUND
Each of the CH0–CH7 pins on the MCP3008 becomes an analog input. In the example below we use CH0 for the LDR and CH1 for the TMP36; the remaining six channels are left free for future sensors.
Light‑Dependent Resistor (LDR)
The LDR’s resistance drops to about 10 kΩ under bright light and climbs to several megaohms in darkness. By forming a voltage divider with a 10 kΩ resistor, the MCP3008 reads a voltage that falls toward 0 V when illuminated and rises toward 3.3 V in the dark.
TMP36 Temperature Sensor
The TMP36 is a 3‑pin analog temperature sensor. Power it with 3.3 V and read its VOUT pin. The sensor outputs 0.750 V at 25 °C, with a linear slope of 10 mV per °C. Thus 0 °C yields 0.500 V and 100 °C yields 1.500 V.
Reading Data with Python
The MCP3008 outputs 10‑bit values ranging from 0 to 1023, mapping linearly to 0 V–3.3 V. For the TMP36, this corresponds to a temperature range of roughly –50 °C to +280 °C.
Below is a minimal example using the spidev library to read channels 0 and 1:
import spidev
import time
spi = spidev.SpiDev()
spi.open(0, 0) # bus 0, device 0
spi.max_speed_hz = 1350000
def read_channel(channel):
# MCP3008 protocol: start bit, single/diff, channel (3 bits), 5 dummy bits
adc = spi.xfer2([1, (8 + channel) & 0x0F << 4, 0])
data = ((adc[1] & 3) << 8) + adc[2]
return data
while True:
ldr_val = read_channel(0)
temp_val = read_channel(1)
temp_c = (temp_val * 3.3 / 1023) * 100 - 50 # Convert to °C
print(f'LDR: {ldr_val}, Temp: {temp_c:.2f}°C')
time.sleep(1)
Replace the channel numbers as needed for your sensor layout. The script continuously prints the raw ADC value for the LDR and the calculated temperature in degrees Celsius.
With this setup you can add additional analog sensors—such as photodiodes, pressure transducers, or humidity probes—by wiring them to the remaining CH2–CH7 pins and extending the Python code accordingly.
Happy hacking!
Manufacturing process
- Accurate Raspberry Pi Temperature Profiling with Python, SQLite, and LabVIEW
- Professional Raspberry Pi Temperature Monitoring with DS18B20
- TMP006 Infrared Temperature Sensor with Raspberry Pi: Python Library & Setup Guide
- Build a Remote Temperature Sensor with Raspberry Pi and Python – Step‑by‑Step Guide
- Accurate Temperature Monitoring in a Server Closet with Raspberry Pi
- Measure Analog Sensors on Raspberry Pi Without Native ADC
- Monitor Your Home Temperature with a Raspberry Pi Dashboard
- Build a Raspberry Pi Home Temperature Monitor with MCP9808, InfluxDB & Grafana
- Integrating the Acconeer A111 Pulsed Radar with a Raspberry Pi: A Practical Guide
- Arduino Tutorial: Master Temperature & Humidity with DHT11 & DHT22 Sensors