Saturday, November 8, 2014

65: Analog Devices

So, the RPi B+ has 14 more digital GPIO pins. Big deal.

From my perspective a few analog pins would have made a better "+" model. I have 3 Pi's and an Arduino Micro. Well, the Pi may have a nice OS but analog input is painful on the Pi and it is a chinch on the Arduino.

You can fake analog for devices like a photocell by programming a tight loop, e.g.:

# Python
import RPi.GPIO as GPIO, time, os      
GPIO.setmode(GPIO.BCM)
PHOTO_pin = 22 

def Ptime (pin):
        reading = 0
        GPIO.setup(pin, GPIO.OUT)
        GPIO.output(pin, GPIO.LOW)
        time.sleep(0.1)

        GPIO.setup(pin, GPIO.IN)
        while (GPIO.input(pin) == GPIO.LOW): # Eat the CPU!
                reading += 1
        return reading

 ## read by:
        print Ptime(PHOTO_pin)

Earlier, in Posts 50 and 54 I complained about the inherent inaccuracy of faking analog for an ultrasonic rangefinder (because of Linux scheduling other processes).  And I've noted that the DS18B20 temperature sensor (C language) code uses a lot of CPU cycles to achieve an analog output.

Supposedly, you only need only add am MCP3008 chip to the Pi and, voila, you can trade 4 GPIOs for 8 analog ports. Well, I haven't had much joy with that. I bought 2 chips from Adafruit (anyone besides me irritated by their exorbitant shipping fees?). I've downloaded 4 different sets of 3008 code and the first 3 didn't work for me.

Adafruit's wiring used BCM ports 18, 23, 24 and 25 -- all of which I was already using -- so I first tried the setup described at--

http://www.raspberrypi-spy.co.uk/2013/10/analogue-sensors-on-the-raspberry-pi-using-an-mcp3008/

--which used BCM 10, 9, 11 and 8 (ones I was not using). These are AKA as SP10 pins MOSI, MISO, SCLK AND CE0. This involves activating SPI and downloading stuff. I did this but (as I mentioned) it didn't work.

Finally, code that sort of works:
https://github.com/adafruit/Adafruit-Raspberry-Pi-Python-Code/blob/master/Adafruit_MCP3008/mcp3008.py

but my GPIO pins are:
SPICLK = 11
SPIMISO = 9
SPIMOSI = 10
SPICS = 8

MCP3008 CH0 photo sensor
 CH1 potentiometer
 CH2 - CH7 not connected

Trimmed down Python========

import RPi.GPIO as GPIO, time, os
GPIO.setmode(GPIO.BCM)

# read SPI data from MCP3008 chip, 8 possible adc's (0 thru 7)
def readadc(adcnum, clockpin, mosipin, misopin, cspin):
if ((adcnum > 7) or (adcnum < 0)):
return -1
GPIO.output(cspin, True)

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

commandout = adcnum
commandout |= 0x18  # start bit + single-ended bit
commandout <<= 3    # we only need to send 5 bits here
for i in range(5):
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
SPIMISO = 9
SPIMOSI = 10
SPICS = 8

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

print " #0  #1  #2  #3  #4  #5  #6  #7"
print "-----------------------------------------------------"
while True:
print "|",
for adcnum in xrange(0, 8):
ret = readadc(adcnum, SPICLK, SPIMOSI, SPIMISO, SPICS)
print ret,"\t",
print "|"
time.sleep(2)

=================(sorry, columns won't line up)==================

$ sudo python mcp.py 
 #0   #1   #2   #3   #4   #5   #6   #7
------------------------------------------------------------
 992  0 3 4 2 2 0 0      dark, rheostat closed
 991 0 12 14 14 15 18 31 
 990 0 7 7 4 3 1
 990 0 3 7 8 9 10 22 
...
 983 269 4 4 1 1 0 0      rheostat opening
 982 269 8 11 11 13 14 26 
...
 983 1023 2 1 0 0 0 1     rheostat  way open
 985 1023 13 15 16 17 19 33 
...
 509 663 17 16 12 10 8 13   flashlight on photocell
 445 663 0 5 6 9 9 21 
...

====================================

Note the extraneous readings on the non-connected ports.

After all of this trouble you'd hope that the MCP3008 would save a lot of CPU time getting analog readings but my half-assed tests don't show much reduction (on the photocell, only).

No comments:

Post a Comment