Giant ShiftBrite Election Meter

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:

Election Meter

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:

Election Meter

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.

Election Meter

Next, I connected to the USB-RS232 converter at 9600bps on COM4 using PuTTY:

Election Meter

And held the reset button on the ACODE carrier board until the serial configuration terminal appeared:

Election Meter

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":

Election Meter

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":

Election Meter

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":

Election Meter

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:

Election Meter

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.

Election Meter

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.

Election Meter

Election Meter

Election Meter

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):

class CNN(object):
  def __init__(self):
    self.url = ""

  def get(self):
    """return the electoral balance
        (dpopular, delectoral), (rpopular, relectoral)
    u = urllib2.urlopen(self.url)
    for line in u.readlines():
      res ='var CNN_NData=(.*?);', line)
      if res is not None:
        data =
        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)

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

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



Delay 250

If Winner = "D" Then
    For n = 0 To Num_ShiftBrites
        CurrentRGB(n,2) = BlinkVal
Elseif Winner = "R" Then
    For n = 0 To Num_ShiftBrites
        CurrentRGB(n,0) = BlinkVal

BlinkVal = 1023 * (BlinkVal = 0)

Csgdec 0,Results(3)
Csgdec 1,Results(1)



    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
        Results(j) = Val(tempStr)

        Incr i
        Incr i
    Incr i
    Winner = Chr(RecvString_A(i))


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


        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
    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
        CurrentRGB(n,2) = 0

    CurrentRGB(n,0) = 1023 - CurrentRGB(n,2)


End Sub

Finally, I fastened everything to a board. Looks pretty good!

Election Meter

Election Meter

Election Meter

Submitted by Garrett on Tue, 11/04/2008 - 14:06.

Too bad the election didn't

Too bad the election didn't turn out as great as your project.

Wow, this is a neat idea. It

Wow, this is a neat idea. It looks like a nice build. I am amazed at how clean your work area is too, way better than mine. =)