With 2012 posing to be the ‘year of the hack’ the Head Labs kids thought they should roll up their flannel trousers, dare to eat a peach and get stuck into an Arduino project. For those not yet in the know, an Arduino is an inexpensive open-source micro-controller designed for the DIY enthusiast and the amateur electrician/programmer geek. It’s basically used to create interactive objects or environments through a growing menagerie of add-on sensors, motors and shields. Its limited capacity is perfect for analysing input, processing data and delivering output. Simple.

I set the task of designing an Arduino powered voting machine that we could use at our bi-monthly Head Presentation evenings. Why tick a box on a boring old piece of paper when you can build an interactive electronic web-enabled vote counter? Rob M and I split the majority of the build between us, me on the software and him on the hardware with an awesome design by Andy B

How does it work?

The mechanism relies on a voter dropping a marble into a cut-out of the person he wants to vote for.

Choose a candidate

There are 3 individual tracks of a children’s marble run toy, each with its own light sensor wired into an Arduino Uno via a bit of Sugru and a cocktail straw. We programmed the Arduino to check every half a second for a change in the light sensor’s value. When a marble passes overtop, the value changes, the Arduino is informed of a change for that analogue input connection and a vote is counted for that candidate. These tracks are hidden from the voters’ view. Mostly to keep prying eyes from seeing how someone has voted but also to keep the light intensity of the environment consistent through a single LED light placed above each sensor.

A track sensor

Once the marble has passed the sensor it’s fed into a common funnel and continues it’s journey to the bottom of the run. Nice bit of distraction.

Voteomatic run

We also added 3 LED lights to the breadboard as a bit of a debugger to light up when a sensor has been tripped. This came in handy when testing the set-up before the Arduino was programmed to serve data to Mairead’s web page, more on that later. The layout is pretty simple and for someone who knows what they’re doing (not Rob) it would probably take 5 minutes to wire up the breadboard.

schematic

That’s the physical part. How are the votes tallied and a winner determined?

We went through several iterations of the web client to retrieve data from the Arduino. We had originally assumed we could build a web application and then turn the Arduino chip into a web client using the ethernet shield. My intention was to make a GET request to the web application every time a vote was cast. The Arduino web client turned out to be extremely unstable. We couldn't guarantee a connection to our webserver everytime. Alex K set up Netcat to create a lightweight TCP server to test basic functionality and then set up Tcpdump on the server to watch for the incoming connections. Some times the Arduino would connect, other times it wouldn't. We think it was a problem with the ethernet shield initialisation as the longer we waited the higher the chance of a connection request to the server.

We reasoned if we can't make multiple connections maybe we should try a websocket instead, that way we only need to make one successful connection. As socket messages would be minimal, the data that we were sending would be less complex. We found an Arduino websocket library and set up a Node websocket server to receive the messages. This seemed to be suffering from the same issue as the web client. The TCP packets were being sent but for some reason they were failing intermittently and we still couldn't get a stable replication of the inputs going into the Arduino as output rendered to the web application. 

After repeatedly banging our heads against the wall we accepted failure and moved on. Rob learnt the Arduino had received an upgrade to 1.0 and we upgraded our Arduino IDE and libraries. We then switched to using the Arduino webserver library to serve the captured data instead. We don't know why yet but this turned out to be far more stable as a solution. The webserver takes at least 20 seconds to initialise but once it is running any client can connect to it indefinitely. So then we had to re-engineer our existing web application so it could consume data from the Arduino web server. 

Our web application is built in Node.js so that I could utilise the GET method of the HTTP module to make a request to the Arduino. I used the Connect library to serve a static homepage, with a link to the page which displays the winning candidate. I mapped a route in connect to the '/winner' URL and wrote some middleware to make the GET request to the Arduino web server, which returns the number of the winning candidate as an HTTP response. Using the returned content I dynamically create a page of HTML on the fly in the Connect server. I'd initally planned to make the whole site in Express but it didn't want to play nicely with my Node v0.06 and in the end I had to resort to creating the dynamic content hardcoded into Connect. It's pretty rough and ready but I was running out of time and it did the job.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

var connect = require('connect'),
               http = require('http'),
              url = require('url')
        
function routes(app) {
  app.get('/winner', function (req, res, next) {

        var winner = ''; 
        var html = '';

        http.request(url.parse('http://192.168.0.177:80'), function (response) {
        console.log(response)  
        console.log("made request")
        response.setEncoding('ascii')
        response.on('data', function (chunk) {
                      winner += chunk.toString();
                    console.log(chunk)
         }).on('end', function () {....}



vote-o-matic web page

When I tried to chunk the body from the Arduino response I got an undefined variable even though the response object was being returned fully formed. I'd orginally spoofed a fake Arduino response using another Node server to use in development as a stub to the functionality and this page was getting parsed as normal. It took a long while to work out if we explicitly set a content length in the HTTP response from the Arduino then the Node application could chunk the data. I'm making an educated guess that this is because Node needs to know the content length before it can terminate the request and call the end method I'm using to read out the response. 

The last stumbling block was really trying to match the value being sent from the Arduino server with what the Node js application was expecting in the Javascript. We think Arduino sends ascii encoded text as a default so we made sure we set that in our HTTP request method for the response type. I spent a long time scratching my head over this one until Dave H and I managed to parse the string out using some regex in a simple Ruby client making a similar GET request. It turned out the Arduino webserver was spitting out a string with a carriage return as well as a line feed but that was virtually impossible to detect in anything like firebug or chrome dev tools.  We later discovered this syntax is as defined in the HTTP specification.

1
2
3
4

//if statement testing value of winning candidate
  if(winner === "1\r\n"){
    html += "......"

 

Stuff we learned

Apart from solving the stumbling blocks around the webserver library, sketch writing, board wiring and output string parsing; Rob also mentions, "If I continued using a changing light value as the trigger I think i would switch to lasers instead of fairy lights. My old Christmas tree hardware cast a low intensity and was probably 80% effective. I might also consider ditching the whole light thing and using FSRs (Force Sensitive Resistors) built into the track to register when a marble has passed overtop."

It also became apparent that there is a comprehensive knowledge base and support community for the Arduino. From shopping sites, schematics, sketch examples, tutorials, videos and full project examples to build yourself, there's no shortage of inspiration and assistance to get your own Arduino project under way.

So what's up next? Hopefully more hacking experiments around the office, maybe something with a Microsoft Kinect in reception, or a haptic navigation system or my dream project - an automatic door opener for the Head bike storage room. Stay tuned.