MCP3008 gives 0 or 1023 only: how do I prove SPI works on a Pi 3B+?
Weekend project gone sideways. Pi 3B+, an MCP3008 on a breadboard, reading a 4-20 mA pressure transmitter on my rainwater tank through a 150 ohm resistor (so 0.6 to 3.0 V). The plan is to send tank_bar to Hermetry every minute.
SPI is enabled in raspi-config, /dev/spidev0.0 and /dev/spidev0.1 both exist. But channel 0 reads 0 forever, and when I touch the wire it jumps to 1023 and back. Channel 1 (nothing connected) reads the same. My code:
spi = spidev.SpiDev()
spi.open(0, 1)
spi.max_speed_hz = 1350000
r = spi.xfer2([1, (8 + 0) << 4, 0])
val = ((r[1] & 3) << 8) + r[2]
How do I tell whether SPI itself is working, before I start blaming the chip? I’ve already swapped the MCP3008 once.
following, I have an MCP3008 in a drawer I never got working either
Is VREF tied to 3.3 V? If VREF floats you get exactly that 0 / 1023 behaviour.
VREF and VDD both on 3.3 V, AGND and DGND on ground. Checked twice.
Test SPI on its own first with a loopback, no chip. Pull the MCP3008 out, put a jumper from MOSI (GPIO10, pin 19) to MISO (GPIO9, pin 21) and run:
wget https://raw.githubusercontent.com/raspberrypi/linux/rpi-6.6.y/tools/spi/spidev_test.c
gcc -o spidev_test spidev_test.c
./spidev_test -D /dev/spidev0.0 -v -p "HELLO"
If RX shows the same bytes as TX, the Pi side is fine. If RX is all 00 or FF, SPI isn’t really running.
My bet though is in your code: spi.open(0, 1) uses chip select CE1, which is GPIO7 on pin 26. Most MCP3008 tutorials wire CS to CE0, GPIO8 on pin 24. If your CS goes to pin 24, the chip is never selected, its output floats, and you get 0 with the odd 1023 when you touch it. Either move the wire to pin 26 or change the code to spi.open(0, 0). I’ve done this exact mixup on a bench at work.
Your channel 1 reading the same is the giveaway: an unselected chip gives the same junk on every channel.
The loopback test is worth keeping in your notes. Saved me twice.
Once it reads, put a 100 nF cap on the input next to the chip. 4-20 mA loops pick up a lot of noise on a breadboard.
And for the scaling you can send the raw mA and let a Scale block in Hermetry’s root flow turn 4-20 into 0-10 bar, then you can fix the range later without touching the Pi.
CE0 vs CE1, of course. CS was on pin 24 and the code said 1. Changed it to spi.open(0, 0) and channel 0 now reads 412 with the tank half full, channel 1 floats like it should. Loopback test passed too, so I’ll keep that one. Sending mA now and scaling in the flow as twilson said.
- You must be logged in to reply to this topic.
Join the conversation
Sign in to ask and answer, like helpful posts and mark the reply that solved your problem. Every contribution earns points and levels.

