I connected a Raspberry Pi 3 with ArchLinux to a MCP3008 following the wiring explained in this tutorial.

When I run lsmod I see spi_bcm2835. My /boot/config.txt has the following line to enable spi: device_tree_param=spi=on.

When I run a python script to read the MCP3008 I get 4095 without change.

How can I make sure that the chip is communicating correctly?


The wiring I have followed is detailed below: mcp3008 wiring

My implementation real wiring


The script that I use to read the signals is

#!/usr/bin/env python2
# Bitbang'd SPI interface with an MCP3008 ADC device
# MCP3008 is 8-channel 10-bit analog to digital converter
#  Connections are:
#     CLK => 18
#     DOUT => 23 (chip's data out, RPi's MISO)
#     DIN => 24  (chip's data in, RPi's MOSI)
#     CS => 25

import RPi.GPIO as GPIO
import time
import sys

CLK = 18
MISO = 23
MOSI = 24
CS = 25

def setupSpiPins(clkPin, misoPin, mosiPin, csPin):
    ''' Set all pins as an output except MISO (Master Input, Slave Output)'''
    GPIO.setup(clkPin, GPIO.OUT)
    GPIO.setup(misoPin, GPIO.IN)
    GPIO.setup(mosiPin, GPIO.OUT)
    GPIO.setup(csPin, GPIO.OUT)

def readAdc(channel, clkPin, misoPin, mosiPin, csPin):
    if (channel < 0) or (channel > 7):
        print "Invalid ADC Channel number, must be between [0,7]"
        return -1

    # Datasheet says chip select must be pulled high between conversions
    GPIO.output(csPin, GPIO.HIGH)

    # Start the read with both clock and chip select low
    GPIO.output(csPin, GPIO.LOW)
    GPIO.output(clkPin, GPIO.HIGH)

    # read command is:
    # start bit = 1
    # single-ended comparison = 1 (vs. pseudo-differential)
    # channel num bit 2
    # channel num bit 1
    # channel num bit 0 (LSB)
    read_command = 0x18
    read_command |= channel

    sendBits(read_command, 5, clkPin, mosiPin)

    adcValue = recvBits(12, clkPin, misoPin)

    # Set chip select high to end the read
    GPIO.output(csPin, GPIO.HIGH)

    return adcValue

def sendBits(data, numBits, clkPin, mosiPin):
    ''' Sends 1 Byte or less of data'''

    data <<= (8 - numBits)
    for bit in range(numBits):
        # Set RPi's output bit high or low depending on highest bit of data field
        if data & 0x80:
            GPIO.output(mosiPin, GPIO.HIGH)
            GPIO.output(mosiPin, GPIO.LOW)

        # Advance data to the next bit
        data <<= 1

        # Pulse the clock pin HIGH then immediately low
        GPIO.output(clkPin, GPIO.HIGH)
        GPIO.output(clkPin, GPIO.LOW)

def recvBits(numBits, clkPin, misoPin):
    '''Receives arbitrary number of bits'''
    retVal = 0

    for bit in range(numBits):
        # Pulse clock pin
        GPIO.output(clkPin, GPIO.HIGH)
        GPIO.output(clkPin, GPIO.LOW)

        # Read 1 data bit in
        if GPIO.input(misoPin):
            retVal |= 0x1

        # Advance input to next bit
        retVal <<= 1

    # Divide by two to drop the NULL bit
    return (retVal/2)

if __name__ == '__main__':
        setupSpiPins(CLK, MISO, MOSI, CS)

        while True:
            val = readAdc(0, CLK, MISO, MOSI, CS)
            print "ADC Result: ", str(val)
    except KeyboardInterrupt:
  • The wiring and/or the script is wrong. If you show us both we may be able to help. – joan Mar 24 '16 at 7:12
  • @joan updated the question. Any clue on what could be wrong? – Stereo Mar 24 '16 at 16:16
  • We need to see your wiring and code. In this case I'd guess you haven't implemented the wiring diagram properly. So we need a clear photo or photos of your wiring. This assumes you have copied the code without modification. – joan Mar 24 '16 at 16:50
  • @joan updated with photo, I copy pasted the code. – Stereo Mar 24 '16 at 16:55

You have a breadboard with an interrupted power rail. There is a gap at position 30. You need to use some wires to jumper that gap so that the ADC is connected to power and ground.

| improve this answer | |
  • that was very helpful and I feel completely like a n00b, however now I am just getting 0 from the script. – Stereo Mar 24 '16 at 19:37
  • Try connecting the ADC input channel to ground and then 3V3. The reading should change. Another common problem is to have the ribbon cable twisted between the Pi and the cobbler, or inserted in the cobbler back to front. To check it's inserted properly use a meter to check that 3V3 on the breadboard is 3V3 and 5V is 5V. – joan Mar 24 '16 at 20:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.