Learn

Reading a Potentiometer on a Raspberry Pi 4B with an MCP3008 ADC

The Raspberry Pi has no analog input — read a real potentiometer's position using an MCP3008 ADC over SPI, with full wiring and Python code.

Note: the Potentiometer (MCP3008 ADC) is a Premium-tier component in the simulator — you’ll need a Premium or VIP plan to use it there.

Try this directly in the free Raspberry Pi 4B simulator — no hardware or signup required. New to the GPIO header? Start with the interactive pinout guide.

What you’ll need

  • Raspberry Pi 4B
  • MCP3008 ADC
  • 10kΩ Potentiometer

Step by step

  1. Drag Raspberry Pi 4B onto the Canvas.
  2. Drag the MCP3008 ADC onto the Canvas — a real DIP-16 chip, connects via drawn wires.
  3. Drag the 10kΩ Potentiometer onto the Canvas.
  4. Hover over every MCP3008 pin and note the exact labels shown (standard datasheet pins are CH0-CH7, VDD, VREF, AGND, CLK, DOUT, DIN, CS/SHDN, DGND — confirm against the actual on-screen labels).
  5. Wire the MCP3008 to the Pi's fixed SPI pins (physical/BOARD numbering):
MCP3008 pinPi pin
VDD3.3V
VREF3.3V
AGNDGND
DGNDGND
CLKPhysical pin 23 (SCLK)
DOUTPhysical pin 21 (MISO)
DINPhysical pin 19 (MOSI)
CS/SHDNPhysical pin 24 (CE0)
  1. Wire the Potentiometer: GND → GND. VCC → 3.3V. SIG → MCP3008's CH0 (or whichever channel — note which one you used).
import spidev
import asyncio
 
spi = spidev.SpiDev()
spi.open(0, 0)
spi.max_speed_hz = 1350000
 
def read_channel(channel):
adc = spi.xfer2([1, (8 + channel) << 4, 0])
return ((adc[1] & 3) << 8) + adc[2] # returns 0-1023
 
while True:
value = read_channel(0) # change to match whichever CH pin you wired
print(f"Potentiometer value: {value}")
await asyncio.sleep(0.5)
  1. Click Start. The Console prints "Potentiometer value: N" every half second. While it runs, drag the round knob on the potentiometer to change the value.

What “working correctly” looks like

  • With the knob at its default middle position, the value is about 512. This is the first thing to check.
  • Turning the knob fully counter-clockwise reads near 0, fully clockwise reads near 1023, with a smooth, proportional value in between.
  • The knob should physically stop at both ends of its travel.

If something’s wrong

  • The value is always 0 → check the chip's power first. VDD must reach a Pi power pin and DGND or AGND must reach a Pi GND pin. An unpowered MCP3008 returns zeros.
  • The value is still 0 with power wired → CS/SHDN must go to physical pin 24 (CE0) to match spi.open(0, 0), or to pin 26 (CE1) to match spi.open(0, 1). The simulator finds the chip by the chip-select pin.
  • The value does not follow the knob → your script reads one channel, and the potentiometer's SIG wire must go to that same channel. The example reads channel 0, so use CH0.
  • The value sticks at 1023 and the Console warns about the voltage → the potentiometer's VCC is on a higher voltage than the chip's VREF. Wire the potentiometer VCC to 3.3V, the same as VREF.
  • This chip reads single-ended values only, using the request [1, (8 + channel) << 4, 0]. Differential reads are not supported.