Giant ShiftBrite Election Meter
I built a giant red/blue bar graph to display the electoral vote at my house tonight. It uses 32 ShiftBrite RGB LED modules, two CSG-4M LED numerical displays, a Cubloc CB405 with Quick Start 1000 board, and an ACODE-300B Bluetooth module. I used Eric's code from Hackaday last night to scrape CNN's election results. The code runs on a small 400MHz Linux server I always have running for file storage and random scripting.
Here's how I did it:
I started with the above parts already listed. In addition, there's a carrier board for setting up the ACODE Bluetooth module, an LM1086 3.3 volt regulator for powering the ACODE module later, and a cheap (~$5) Bluetooth USB dongle from DealExtreme.
First, I wanted to make sure the Bluetooth dongle would work from Linux. I've had really good results with these before, Linux seems to pick up all the common chipsets immediately. I plugged it into the old Linux server running in the lab at my house, and checked the results with dmesg:
Lookin' good! Next, let's try to get the Linux computer talking to the ACODE module over Bluetooth. First, I plugged the ACODE module into a USB-RS232 converter and power.
Next, I connected to the USB-RS232 converter at 9600bps on COM4 using PuTTY:
And held the reset button on the ACODE carrier board until the serial configuration terminal appeared:
You can select menu items by typing the letter and pressing Enter. I changed the name to "Election", left authentication off, changed the connection mode to "MODE2" which automatically reconnects to the last connected device. I also disabled the status message since I didn't want to have non-data text coming into the Cubloc serial port. I made sure the role was "SLAVE" since I planned to use the Linux server as the master device. I turned the power to the ACODE on and off, and it's ready to go!
Back in my SSH session to the Linux server, I scanned for the ACODE module with "hcitool scan":
There it is! I also copied the device address since it's required later.
Next, I made sure the Bluetooth serial port service was available with "sdptool search SP":
And everything still looks good. I noted that my RFCOMM service was on Channel 1, this is generally true for a single function device like the ACODE-300, but it may be different on other Bluetooth devices.
To map the remote Bluetooth serial port to a local serial port, I used "rfcomm bind 0 00:06:6E:11:B7:36":
I tested the connection by echoing some text to /dev/rfcomm0, and it appeared in my local serial connection to COM4, from the ACODE-300 Bluetooth serial port.
So I wouldn't have to issue the rfcomm command manually again, I added the following configuration in /etc/bluetooth/rfcomm.conf:
So I've definitely got a wireless link going! I can treate /dev/rfcomm0 as a normal serial port. This will make it easy to communicate from Python later.
First, I've got to get some hardware together. I used the CB405 and Quick Start 1000 board, and added the ACODE-300 module to the breadboard area. The ACODE module needs 3.3 volts, so I used an LM1086 regulator. It's not picky about logic levels, so I was able to run those directly into the TTL serial ports for Channel 1 on the CB405. I also added a 10K pullup resistor on the ACODE Reset line, and a 100 ohm resistor and LED for the status indicator. This will blink at first, but will stay on when a connection is active.
Next, I added connections for a ShiftBrite chain, hooked up the CSG-4M displays, and used some old code to test the ShiftBrites and displays. I lined up 32 ShiftBrites on a piece of 3/4x3/4 hardwood, fastened with zip ties, and chained with the 3.5" cables from my store.
Before writing the Cubloc code, I wanted to get Eric's CNN scraper sending data to the serial port. Here's what I ended up using:
import urllib2 import re import serial class ElectionWon(Exception): pass class CNN(object): def __init__(self): self.url = "http://www.cnn.com/ELECTION/2008/results/president/" def get(self): """return the electoral balance (dpopular, delectoral), (rpopular, relectoral) """ u = urllib2.urlopen(self.url) for line in u.readlines(): res = re.search(r'var CNN_NData=(.*?);', line) if res is not None: data = res.group(1) data = data.replace("true", "True") data = data.replace("false", "False") data = eval(data) demp = None deme = None repp = None repe = None w = "N" for candidate in data['P']['candidates']: if candidate['party'] == 'D': demp = candidate['votes'] deme = candidate['evotes'] if candidate['winner']: w = 'D' elif candidate['party'] == 'R': repp = candidate['votes'] repe = candidate['evotes'] if candidate['winner']: w = 'R' return demp,deme,repp,repe,w if __name__=='__main__': cnn = CNN() s=str(cnn.get()) + "\n" ser = serial.Serial('/dev/rfcomm0', 9600, timeout=1) ser.write(s) ser.close()
Next, I needed to process the data coming from the Bluetooth connection. I used the Cubloc's serial routines to iterate through the received string and extract the numbers and winner data. Then, I calculated the position of the bar graph and sent the color commands out to the ShiftBrite array.
Const Device = CB405 Ramclear Opencom 1,9600,3,32,32 On Recv1 Gosub GetSerial Set Until 1,32,10 Set I2c 45,44 #define CI 2 #define EI 3 #define LI 4 #define DI 5 Low CI Low LI Low DI Low EI #define Num_ShiftBrites 32 Dim CurrentRGB(Num_ShiftBrites,3) As Integer Dim RecvString As String * 64 Dim Results(4) As Integer Dim Winner As String * 1 Dim ElectoralPercentage As Long Dim i As Byte Dim j As Byte Dim k As Integer Dim n As Integer Dim tempStr As String * 12 Dim BlinkVal As Integer DrawShiftBrites Do Delay 250 If Winner = "D" Then For n = 0 To Num_ShiftBrites CurrentRGB(n,2) = BlinkVal Next Elseif Winner = "R" Then For n = 0 To Num_ShiftBrites CurrentRGB(n,0) = BlinkVal Next Else CalcBarGraph Endif BlinkVal = 1023 * (BlinkVal = 0) DrawShiftBrites Csgdec 0,Results(3) Csgdec 1,Results(1) Loop GetSerial: RecvString = Getstr2(1,32,10) Bclr 1,2 i = 1 For j = 0 To 3 tempStr = "" Do While RecvString_A(i) <> 44 tempStr = tempStr + Chr(RecvString_A(i)) Incr i Loop Results(j) = Val(tempStr) Incr i Incr i Next Incr i Winner = Chr(RecvString_A(i)) Return End Sub DrawShiftBrites() For k = 1 To Num_ShiftBrites Shiftout CI,DI,1,0b010001101111,12 Shiftout CI,DI,1,0b0001111111,10 Shiftout CI,DI,1,0b0001111111,10 Next High LI Low LI For k = Num_ShiftBrites To 1 Step -1 Shiftout CI,DI,1,CurrentRGB(k-1,2),12 Shiftout CI,DI,1,CurrentRGB(k-1,0),10 Shiftout CI,DI,1,CurrentRGB(k-1,1),10 Next High LI Low LI End Sub Sub CalcBarGraph() ElectoralPercentage = (1024*Results(1)/(Results(1)+Results(3)))*Num_ShiftBrites If Results(1) = 0 And Results(3) = 0 Then ElectoralPercentage = 1024*32/2 For n = 0 To Num_ShiftBrites If (ElectoralPercentage >= (n*1024) And ElectoralPercentage < (n*1024+1023)) Then CurrentRGB(n,2) = ElectoralPercentage - (n*1024) Elseif ElectoralPercentage > (n*1024) Then CurrentRGB(n,2) = 1023 Else CurrentRGB(n,2) = 0 Endif CurrentRGB(n,0) = 1023 - CurrentRGB(n,2) Next End Sub
Finally, I fastened everything to a board. Looks pretty good!
Submitted by Garrett on Tue, 11/04/2008 - 14:06.