-
-
Save ladyada/3151375 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python | |
# Written by Limor "Ladyada" Fried for Adafruit Industries, (c) 2015 | |
# This code is released into the public domain | |
import time | |
import os | |
import RPi.GPIO as GPIO | |
GPIO.setmode(GPIO.BCM) | |
DEBUG = 1 | |
# 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 >>= 1 # first bit is 'null' so drop it | |
return adcout | |
# change these as desired - they're the pins connected from the | |
# SPI port on the ADC to the Cobbler | |
SPICLK = 18 | |
SPIMISO = 23 | |
SPIMOSI = 24 | |
SPICS = 25 | |
# 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) | |
# 10k trim pot connected to adc #0 | |
potentiometer_adc = 0; | |
last_read = 0 # this keeps track of the last potentiometer value | |
tolerance = 5 # to keep from being jittery we'll only change | |
# volume when the pot has moved more than 5 'counts' | |
while True: | |
# we'll assume that the pot didn't move | |
trim_pot_changed = False | |
# read the analog pin | |
trim_pot = readadc(potentiometer_adc, SPICLK, SPIMOSI, SPIMISO, SPICS) | |
# how much has it changed since the last read? | |
pot_adjust = abs(trim_pot - last_read) | |
if DEBUG: | |
print "trim_pot:", trim_pot | |
print "pot_adjust:", pot_adjust | |
print "last_read", last_read | |
if ( pot_adjust > tolerance ): | |
trim_pot_changed = True | |
if DEBUG: | |
print "trim_pot_changed", trim_pot_changed | |
if ( trim_pot_changed ): | |
set_volume = trim_pot / 10.24 # convert 10bit adc0 (0-1024) trim pot read into 0-100 volume level | |
set_volume = round(set_volume) # round out decimal value | |
set_volume = int(set_volume) # cast volume as integer | |
print 'Volume = {volume}%' .format(volume = set_volume) | |
set_vol_cmd = 'sudo amixer cset numid=1 -- {volume}% > /dev/null' .format(volume = set_volume) | |
os.system(set_vol_cmd) # set volume | |
if DEBUG: | |
print "set_volume", set_volume | |
print "tri_pot_changed", set_volume | |
# save the potentiometer reading for the next loop | |
last_read = trim_pot | |
# hang out and do nothing for a half second | |
time.sleep(0.5) |
Hey guys!
take a look at my library that uses SpiDev to communicate with the chip.
Reviving this because I think the issue ChickenProp raised in 2012 still remains. Reading 12 bits in that loop is indeed 1 too many, and a right shift or, equivalently, division by 2 is misleading, as is the comment that this is a "null" bit. As someone learning about SPI, this mysterious shift confused me for 2 solid days. The empty bit is already on the bus after the command, as ChickenProp states, so you only need to read out 11 bits: 1 null and 10 valid ADC bits. Sure, you can read the additional bit and shift it out after, but what's the point?
You have to follow these instructions or else the account blocks the script.
"> If the tips above didn't help, visit https://www.google.com/accounts/DisplayUnlockCaptcha and follow the steps on the page."
Can you make the print
statements compatible with Python 2.7/3.x?
Has anyone ported the code to use the SPI interface?
Thank,
Ralf