#!/usr/bin/env python # # 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 = 11 MISO = 9 MOSI = 10 CS0 = 8 CS1 = 7 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) else: 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__': try: GPIO.setmode(GPIO.BCM) setupSpiPins(CLK, MISO, MOSI, CS) while True: val = readAdc(0, CLK, MISO, MOSI, CS) print "ADC Result: ", str(val) time.sleep(5) except KeyboardInterrupt: GPIO.cleanup() sys.exit(0)