The Raspberry Pi has a serial peripheral interface (SPI) which can be used to communicate with microcontrollers, display drivers or in our case digital/analog converters (DACs). By default the Raspberry Pi can’t read analog signals, it only can read digital ones. Depending on the model, there a multiple SPI’s available. In this Tutorial we will focus on a Raspberry Pi 2 Model B.
The MCP3008 is a DAC which can read up to 8 individual analog signals (CH0 – CH7) and converts it into digital data which can be read by the Raspberry Pi over it’s SPI interface. In this tutorial we will use 8 potentiometers which we want to read out.

Now there is one more thing to keep in mind: the GPIOs of the Raspberry Pi are all working with 3.3V. A higher voltage could damage them. The MCP3008 can be used with 5V and also with 3.3V but for our case we will use 3.3V to power it.
It can be connected directly to one of the 3.3V GPIOs of the Raspberry. If you only have a 5V powersource left or only the 5V GPIOs are free to use, you will need an additional level shifter (e.g. Adafruit TXB0104)

The SPI is disabled by default. To enable it on our Raspberry we need to edit the config.txt from terminal:
sudo nano /boot/config.txt
check if entry already exists, if not, add it at the end of the file
dtparam=spi=on
This will activate SPI0 with CE0 and CE1.

For more information please check out the documentation from Raspberry: https://www.raspberrypi.org/documentation/hardware/raspberrypi/spi/README.md
Circuit Setup without Level Shifter:
Raspberry Pi | MCP3008 | Potentiometer |
---|---|---|
Pin 1 (3.3V) | Pin 16 (VDD) | Pin 1 |
Pin 1 (3.3V) | Pin 15 (VREF) | Pin 1 |
Pin 6 (GND) | Pin 14 (AGND) | Pin 3 |
Pin 23 (SCLK) | Pin 13 (CLK) | |
Pin 21 (MISO) | Pin 12 (DOUT) | |
Pin 19 (MOSI) | Pin 11 (DIN) | |
Pin 24 (CE0) | Pin 10 (CS/SHDN) | |
Pin 6 (GND) | Pin 9 (DGND) | Pin 3 |
Pin 1-8 (CH 0-7) | Pin 2 |
Circuit Setup with Level Shifter:
Raspberry Pi | Adafruit TXB0104 | MCP3008 | Potentiometer |
---|---|---|---|
Pin 2 (5V) | HV | LV | Pin 16 (VDD) | Pin 1 |
Pin 2 (5V) | HV | LV | Pin 15 (VREF) | Pin 1 |
Pin 6 (GND) | GND | Pin 14 (AGND) | Pin 3 |
Pin 23 (SCLK) | Pin 13 (CLK) | ||
Pin 21 (MISO) | Pin 12 (DOUT) | ||
Pin 19 (MOSI) | Pin 11 (DIN) | ||
Pin 24 (CE0) | Pin 10 (CS/SHDN) | ||
Pin 6 (GND) | GND | Pin 9 (DGND) | Pin 3 |
Pin 1-8 (CH 0-7) | Pin 2 |

if everything is connected correctly, install spidev on your Raspberry:
pip3 install spidev
then we create our script to read out and print the analog values:
sudo nano read_analog.py
import spidev
import time
class MCP3008:
def __init__(self, chip_select):
self.spi = spidev.SpiDev()
self.spi.open(0, chip_select)
self.spi.max_speed_hz = 1000000
def analogInput(self, channel):
adc = self.spi.xfer2([1, (8 + channel) << 4, 0])
data = ((adc[1] & 3) << 8) + adc[2]
return data
mcp = MCP3008(0)
# analog inputs
amount = 8
while True:
for i in range(amount):
print("CH", str(i)+":", mcp.analogInput(i))
print("===========")
time.sleep(0.5)
press Ctrl + X and y to save the script. Now you can run it:
python3 read_analog.py

That’s it!