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)

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.

Raspberry Pi 2 SPI | https://pinout.xyz/pinout/spi

For more information please check out the documentation from Raspberry: https://www.raspberrypi.org/documentation/hardware/raspberrypi/spi/README.md

https://pinout.xyz/pinout/spi

Circuit Setup without Level Shifter:

Raspberry PiMCP3008Potentiometer
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 PiAdafruit TXB0104MCP3008Potentiometer
Pin 2 (5V) HV | LVPin 16 (VDD)Pin 1
Pin 2 (5V) HV | LVPin 15 (VREF)Pin 1
Pin 6 (GND)GNDPin 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)GNDPin 9 (DGND)Pin 3
Pin 1-8 (CH 0-7)Pin 2
setup

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!