This year was the first year I had Christmas “at home” for a long time – probably over 10 years – without having to go to one set of parents or the other for the holidays. As a result, this was the first year we have had a proper tree, decorations and friends around for Christmas day since I got back into hardware.
Clearly this combination meant I was going to have to do something that used arduino and interacted with something online. Inspired by the Tweetmas Tree made by Alpha One labs a couple of years ago I wanted to do something similar – especially given twitter is my social network of choice, had hundreds of LEDs laying around as well as some spare arduinos and a Raspberry Pi.
As with many things that are going to be situated in the family room there needs to be some discussion about “acceptable technology use”. To that end everything had to be tidy, no power supplies, no bare wires (due to little fingers on Christmas Day), the decorations had to be “tasteful” and once emplaced I had to be able to remotely administer it if needed (as other things would be around the tree – like presents).
I opted for some internally lit baubles that would have graphical icons on them representing different things (presents, Santa, family, love etc) which would activated via twitter keywords. An arduino or two would control the individual baubles by PWMing LEDs (to create a fade in, fade out effect rather than a harsh blink) and they in turn could be controlled via a Raspberry Pi over USB Serial to pass messages.
All designs have constraints leading to compromises – I had plenty of power to the tree (for the normal lights) but not much network connectivity due to where it was in the room. As such rather than running networked Arduinos (would have to run CAT5 = unsightly) or creating a mesh network or something with XBees (more fragile, more “moving” code parts) I opted for a more simple solution – use a Raspberry Pi for essentially networking and processing tweets and then use serially connected Arduinos for the light control. Each piece plays to its respective strengths and given how tiny they all are, they could be packaged under the tree very tidily with the RPi using WiFi for network connectivity.
In the design I wanted to get a sense of tweet volume so each bauble has a decay period. Thus one tweet wouldn’t individually light a bauble for very long but they would add up cumulatively so as you get closer to Christmas Day the baubles would stay lit for longer and longer periods as the tweet volume increased and then gradually die off again as we left Christmas towards New Year.
Getting hold of plain old baubles was a royal pain; I couldn’t source them anywhere in Australia so had to turn to Ali Express to see what could be had. Thankfully a very helpful supplier in China came to the rescue once she found out what I was doing – which meant I didn’t need to buy a thousand baubles!
Once I had them, the problem with the baubles was that they were totally clear acrylic – they are so well made in fact that they look just like hard soap bubbles – which meant that any electronics inside would be totally visible and you would just get spotlights from the LED. Time for some experimentation.
After trying different ways of sanding, spraying and etching to diffuse the light, we arrived at the following method to create a nice looking bauble (big thanks to my ever suffering wife for her contribution to this):
Using an eggbot, the design was drawn on the bauble. This had its own challenge as the hook on the bauble meant you had to test the design to not include a path where the bauble would rotate and hit the pen on the hook during travel. This was as simple as just running the eggbot with no pen and running it at a higher drawing speed to test.
Once the design was drawn on the surface I then used an engraving tool to etch the design on the internal, concave face of the bauble. This allowed the light to catch an edge and diffract, highlighting the design in the diffused bauble more strongly. Doing this by hand gave me a good excuse to get an engraving head for my EggBot for next Christmas.
Next up we sanded the outside face of the bauble with varying grades of sandpaper / wet and dry. Starting from about 200 through to 800 grit. The rough starting point removed the original design, leaving the etch and really scratched up the surface of the bauble. The finer grades smoothed out the scratch marks and left a surface that nicely diffused and made the whole bauble illuminate when hit by light.
A tiny notch (3mm) was put in the bauble edges near the eyelet in order to allow the LEDs wires to pass in. This was purposefully kept a very tight fit as it helped with keeping the LEDs in place. A knot in the wire on the internal side and then passing the wire through the eyelet (before attaching a ribbon for hanging) provided some strain relief as well as holding the LEDs in a nice spot for light.
Finally, the internally etched design was inked using a Sharpie to make the design stand out when lit internally.
I had a large number of super bright white LEDs left over from another project so I decided to use those. Warm white LEDs would have looked a little nicer as plain white LEDs are quite cold but they do look icy and contrast nicely to the warm white lights we had on the rest of the tree.
The LEDs were run off a pair of 9V supplies that were lying around – one for each of the arduinos. The arduinos would be run from the 5V USB supply so we only needed to worry about powering the LEDs.
Two LEDs were more than enough to light the baubles however being water clear they were too focussed. Out with the sandpaper again and after a minute or so each you have nicely diffused LEDs.
I had some concerns that at full tilt the LEDs would be drawing too much current through the arduino as there were 4 baubles attached to each one, and I wanted to use 9V in order to be able to power two LEDs in series (5V will only power one due to the voltage drop). Using a simple NPN transistor switching circuit was a simple solution for this. Now there were a few too many bits per bauble to simply wire together, I’d need to make a shield.
The shield is dead simple. A screw terminal for each bauble for easy connection and removal, through a transistor and connected to the 9V power supply which was set up as an alternative input and rail on the shield. Each bauble’s transistor is switched off an arduino PWM IO pin.
With the shield done and tested the code to control the lights was done next. The arduino would receive a message over the serial connection using a simple protocol:
<Channel Number> <msecs>\n
To turn a light on, all that was needed was to send a channel number and the time to turn it on for. If the light is off it will fade it up and then stay lit for more or less the number of milliseconds sent through. If the light is already on then the time will simply be added to the number currently left for that light to display – this is how multiple tweets in a short period can “stack” and keep a light illuminated.
The code is a bit long for here but you can see it in the gist.
The code was designed to run in parallel using a state machine so the state of each light was maintained and managed in the loop so no instruction would block the others if it was fading or checking the serial connection for incoming messages. This is a technique I use a lot and is similar to coding the animation of multiple sprites with different forces being applied to them so I can use the same concepts when designing a physical interaction.
An additional concern was that I wanted each of the Arduinos to not have any config code as I didn’t want to have to reflash them at any point. As such each arduino was given a “LIGHTNODE” value (0 or 1 in this case as there were only 2) and some code to identify itself (sending “n\n” over the serial connection). This meant that if an arduino reset for any reason and came up on a different serial device, the Raspberry Pi would still understand which one it was talking to. With a bit more time I should have probably put that in the EEPROM of the arduino itself (and having come across this multiple times before, I’m convinced arduino makers should burn UUIDs into each device to solve this).
At this stage we’ve now got baubles that can be lit via serial commands from a PC based on any input we decide to throw at it. Time to give it one.
Twitter stream processing
Twitter processing in Python is trivially simple to do using Tweepy. The hardest part is really getting all your OAuth creds set up properly. The easiest way to do this is to go to dev.twitter.com and set up developer access. From there create an application and on the application details page you’ll have the crucial pieces – Consumer Secret, Consumer Key, Access Token and Access Token Key.
Again, for space I won’t repeat the code but the script can be found in the gist.
Once authenticated the code is really just watching the twitter streming API for a bunch of keywords defined in the config.py file. When one is found it gets pushed into the callback listener class for processing which determines which keyword fired and which bauble should be lit. This results in a serial command to the relevant arduino and channel to do it.
As part of the stream class you have to implement handlers for error and timeout. In this case we don’t really care about them, we’ll just log them to StdErr so they can be viewed if needed but I don’t want the application dying as a result.
The only exception to this is a rate limited message from twitter – which essentially tells you you’re hitting the API too hard. At this point I just sleep the script for 5 seconds to slow things up a bit. If you get to this point the baubles will probably all be lit anyway so you’re not missing much.
All of this is run from a virtualenv on the Raspberry Pi which is the usual way most people work with python in order to manage varying dependencies (which in this case is Tweepy and PySerial). The script is then run in a screened terminal instance so it can be detached and still run. I could have used supervisord to have it fully daemonized but it wasn’t really worth it given this was all that was running on the RPi and it was trivial to restart via a quick SSH command if it was necessary (it wasn’t).
Gotchas, lessons and changes
The biggest issue that came out of this project was the instability of the Raspberry Pi seemingly due to power supply issues. I had the arduinos running off a laptop doing the processing for about a week without any restarts or issues at all. The Raspberry Pi had a string of issues however. This may be my Pi in particular but reading reports of general power supply issues makes me think it is not. Even running everything through a powered USB hub for the arduinos and WiFi adapter didn’t help particularly.
In the end I removed the WiFi adapter and the stability improved markedly. To get network connectivity I resorted to using PowerLine Ethernet which worked extremely well.
There were still stability issues when there was a lot of network activity and messages going to the serial connections at the same time which never seemed to resolve fully with different power adapters.
I understand why the RPi team chose to use 5V power adapters over MicroUSB given the ubiquity of mobile phone chargers, however the variability in output voltage stability across adapters is immense. I used everything from iPod adapters (apparently capable of 2A) to Galaxy phone charger (only capable of 0.7A but extremely stable voltage under load) to sony and Asus chargers (0.8A and 1.2A respectively but terrible stability under load with wild swings). Even different USB cables could provide a difference by up to 0.2V on the same charger. In the end I settled for the Samsung charger at 0.7A with a powered USB hub to smooth out the drops but it still resulted in an occasional crash.
Phone chargers, whilst ubiquitous, are designed to trickle charge a battery, not to power a device (if you’ve ever tried to USE your phone when it’s nearly empty and it’s on charge you’ll have seen this first hand) so the vagaries you wouldn’t notice on a charger are very noticeable on a Pi doing some processing.
Given this and the crashing I experienced as a result, were I doing this again I’d probably use a more “serious” 5V power supply designed for truly powering a device and then run it in via the Vin pins or make up a micro USB connector.
As an aside, overclocking did seem to help with this – I’m not sure why but it almost doubled the time between failures.
Twitter rate limiting
Initially I designed the twitter code to run in threads, one for each bauble, tracking keywords independently. It was a nice bit of code that worked well until I scaled it out to the eight baubles and started getting HTTP 420s back from twitter. This was because I was running too many authenticated streams at once. This was annoying as it meant I ran all my keywords in one stream instead (one connection but 8x the work) and had to do processing on the RPi side to pull the tweets apart and route to the appropriate bauble. Unfortunately there’s nothing you can do with twitter’s rate limiting policy but a couple of dummy accounts could have probably solved that.
I am quite pleased with the finished result. The effect was “tasteful” enough to pass the family and friend test, I got to actually build something that was in use the entire Christmas period and whilst I probably overstressed the problems I had with power for the RPi it didn’t affect things short of a quick power cycle once every several hours (and with more time I could have resolved properly).
The code, the shield design and the baubles are all reusable so I can use this again next year with little effort (or extend it) and it’s all available in GitHub (if anyone wants the shield design let me know and I’ll post one) free for anyone to use.
Many in the arduino / maker community are exposed to this sort of thing a lot and connecting lights to twitter is pretty easy so the effort to reward ratio of a project like this is very high (and allows you to concentrate on the design of the outward expression of the visualisation). Other than my wife and child, none of the other twenty friends around on Christmas Day get exposed to this type of display so the novelty value was really good and there was heaps of interest as a result.
In the words of a friend of ours, “It makes me feel as though there are people all over the world celebrating with their family and friends just like we are, and you’ve brought them all into the room with us” – and if that’s not what doing this sort of technology is all about then I don’t know what is.