MCP3002 example code for Raspberry Pi (ADC through SPI)

26 September, 2012

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

Raspberry Pi, TextStar LCD, and Python

4 July, 2012

I have my raspberry pi and have been trying to get it to talk to a serial LCD via the uart ports on the gpio header. This post aims to demonstrate simple comms with bash (the command line) and then with programmatically using python. You can download this code if it’s of any use.

The LCD

I purchased a serial LCD from Coolcomponents called the TextStar from Cat’s Whiskers Technologies (their product page). It’s a tiny display but incredibly easy to use. It even has four buttons on the sides to use as inputs to your project.

Read the rest of this entry »