MCP3002 example code for Raspberry Pi (ADC through SPI)

I’ve been tinkering with my Raspberry Pi for quite a few weeks now. It’s a great little thing. Like many, though, I’ve been a little frustrated with the lack of analogue inputs into the Pi. I was for a while using a barebones arduino to service serial comms from the Pi but this had it’s own limitations. (One day I’ll post the code I used for that on this blog!). Adafruit industries have been doing a great job of promoting the use of the Pi to hobbyists and showing examples of hardware control. One of these was to control the SPI controlled 8 channel ADC chip known as the MCP3008 from Microchip. Find it here!

In my naivety I thought that the control would be exactly the same for its 2 channel sibling, the MCP3002. I was wrong! It’s still an SPI chip and when I started to delve into the datasheets it was relatively straight forward to modify the code. I thought I’d post that here so others could make use of it. You’ll notice I haven’t changed the meat of the code and all credit goes to Adafruit for their hard work on which I build!

The code:

#!/usr/bin/env python

# just some bitbang code for testing the 2 channels

import RPi.GPIO as GPIO, time, os

DEBUG = 1
GPIO.setmode(GPIO.BCM)

# read SPI data from MCP3002 chip, 2 possible adc's (0 thru 1)
def readadc(adcnum, clockpin, mosipin, misopin, cspin):
    if ((adcnum > 1) or (adcnum < 0)):
        return -1
	if (adcnum == 0):
            commandout = 0x6
        else:
            commandout = 0x7
	GPIO.output(cspin, True)

	GPIO.output(clockpin, False)  # start clock low
	GPIO.output(cspin, False)     # bring CS low

	#commandout = 0x6  #start bit and 1, 0 to select single ended ch0
	commandout <<= 5    # we only need to send 3 bits here
	for i in range(3):
		if (commandout & 0x80):
			GPIO.output(mosipin, True)
		else:
   			GPIO.output(mosipin, False)
                commandout <<= 1
                GPIO.output(clockpin, True)
                GPIO.output(clockpin, False)

	adcout = 0
	# read in one empty bit, one null bit and 10 ADC bits
	for i in range(12):
		GPIO.output(clockpin, True)
		GPIO.output(clockpin, False)
		adcout <<= 1
		if (GPIO.input(misopin)):
			adcout |= 0x1

	GPIO.output(cspin, True)

	adcout /= 2       # first bit is 'null' so drop it
	return adcout

# change these as desired
SPICLK = 11
SPIMOSI = 9
SPIMISO = 10
SPICS = 18

# set up the SPI interface pins
GPIO.setup(SPIMOSI, GPIO.OUT)
GPIO.setup(SPIMISO, GPIO.IN)
GPIO.setup(SPICLK, GPIO.OUT)
GPIO.setup(SPICS, GPIO.OUT)
adcnum = 0

# Note that bitbanging SPI is incredibly slow on the Pi as its not
# a RTOS - reading the ADC takes about 30 ms (~30 samples per second)
# which is awful for a microcontroller but better-than-nothing for Linux

while True:
    print "------------"
    for adcnum in range(2):
        ret = readadc(adcnum, SPICLK, SPIMOSI, SPIMISO, SPICS)
        print adcnum, ": ",ret
    print "------------"
Advertisements

8 Responses to MCP3002 example code for Raspberry Pi (ADC through SPI)

  1. Bosstiger says:

    Reblogged this on Gigable – Tech Blog.

  2. Duncan White says:

    Sorry to be thick, but how do you wire up the MCP3002 in
    order to use the above python code? In particular, the datasheet
    is very reticient about what Vss means – is that Ground?

    • dmt195 says:

      Yeah, sorry – not thick at all. It’s taken me a while to get all the facts together for this reply so perhaps not obvious! Vss normally relates to the negative supply, which in our case would be ground. In the code I define the following:
      SPICLK = 11 (CLK pin on MCP3002, pin 7)
      SPIMOSI = 9 (Master Out, Slave In, ie Din on MCP3002, pin 5)
      SPIMISO = 10 (Master In, Slave Out, ie Dout on MCP3002, pin 6)
      SPICS = 18 (Chip select, CS on MCP3002, pin 1)

      The values they are assigned relate to the GPIO pin values (not the pinout) of the Raspi, as per this kind of thing. ie GPIO9,10,11,18

      I hope this helps!

  3. Tony says:

    Hi I’m using the standard SPI pin so modified :

    SPICLK = 11
    SPIMOSI = 10
    SPIMISO = 9
    SPICS = 8

    But always read 0 even if the input is connected to 3.3v.

    If I use the C software I found here : http://www.skpang.co.uk/blog/archives/615 every thing is working.

    I need it in python. What could be wrong ?
    Thanks
    Tony

  4. Chris says:

    Have you looked at the PiFace at all? I ordered one a few weeks ago, not had time to play with it yet.

    http://pi.cs.man.ac.uk/interface.htm

    • dmt195 says:

      No I haven’t. I build a ‘shield’ for my pi which had an LCD, ADC, and relay on it. I was quite impressed but my programming and linux skills let me down. I couldn’t get my heating control programme to reliably boot. If I get the time I’d lime to write that up and provide plans and schematics. My build just used veroboard but I really wanted to knock something up in eagle and release it to the world. Too many other things to do though!

  5. Der Paul ist doch bei Akasol mitten in Darmstadt, es kann ja mal jemand bei ihm vorbeigehen, vielleicht weiu00df er noch garnichts von eurem Blog. Er Click https://twitter.com/moooker1

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: