Originally published in March 2014.
The clock in operation, during construction.
I've always, for some unknown reason, been fascinated by LED matrix signs. The science behind them is well known, as is how to drive them electronically. A lot of them are how to do more with less - by using the least number of electrical connections to a grid.
So something inspired me to make a large one of them, shown in the video above.
When I was planning this device, I was asking a few friends about it. And their first question was "why?". It's a very valid question. When they first asked why, I should have responded with "you're right, this is a silly idea." But I did not, and at some point I was far enough along that I just had to finish the device.
This clock has turned out to be a very expensive exercise, for, to be honest, not a whole lot of gain.
I've got a seperate page that documents the first three versions of the clock. The first three were built in 2009/2010.
My employer at the time had a routine. We had a collection of 15 developers in the company. At 4PM on a Friday, it was beer-o-clock time, and we'd shut down, reboot into Windows, and play violent first person shooter games with each other. It was great teambuilding, and great fun to play with this group of people.
Someone came up with the idea of having a countdown clock on the wall to show us how long until 4PM on Friday. That gave me the seed of the idea that became the first three clocks. Basically, it was designed to count down to 4PM on Fridays - that was it's sole purpose.
The employer who this was built for had some interesting times (and that is a novel in itself) and no longer exists, so as of September 2011, the clocks were not in use and instead shelved at home.
So given that I didn't have an employer who had beer-o-clock anymore, why would I build another one? Let's shelve that for the moment until I can figure that out myself.
About 12 months ago I learned about the WS2812 series of RGB LEDs. Individually addressable, once set they stay the colour they've been set to. And they're high brightness (with a power draw to match). Having individually addressable LEDs cuts down on the wiring required to build larger displays, and despite the specific timing requirements of these devices, is easier to build a controller for.
So, it's quite easy (although not cheap) to get strips of WS2812 LEDs from China. My initial plan was to buy 4M lots of 60LED/metre strips, trim them down to just over 2 metres (to make 128 LEDS across) and then position them vertically to get a square dot pitch. So, I ordered some rather expensive WS2812B based LED strips from Aliexpress. I chose some coated with a waterproof silicon as they had a nice finish.
5 weeks later, my LED strips arive. But on closer inspection, I realise that the 4 metre strips are actually 50cm strips that they've soldered together. As a single strip, they work and look great. However, when you place several strips in parallel, the LEDs don't line up - the manufacturer hasn't taken great care to ensure the 50cm segments line up properly. And why would they? They're not intended for this purpose.
So, the obvious thing to do is desolder then and realign a bit closer. However, I ordered waterproof ones that had a silicon coating that was really stuck to the LEDs and part of the strips. Whilst it was possible to remove, it was really labour intensive.
So I went back to the seller on Aliexpress. And I asked if he could supply just 50cm segments of the strips. He said he could, so I ordered a batch of those - enough to do what I wanted. These shipped a few weeks later, and were what I needed, except that they had meticulously soldered plugs onto each end of each 50cm strip, which I then had to de-solder.
So the next step was to find something to attach it to. The pixels were 16mm apart, so, doing the maths, it works out that you need about 2100mm of space to put 128 LEDs in a row. You also need about 130mm of height to place 8 rows of them. So each strip is 10mm wide, with a 6mm gap between each one to get the dot pitch right.
The cheapest possible solution was a 2400mm long, 140mm wide, 20mm thick pine board from the local Bunnings - about $9. Add some blackboard paint to make it black to start with, to provide a better contrast, and we're set. The LEDs take up 2100mm of the board, leaving 300mm for the control electronics. As it turned out, that's only just enough really, and I didn't account for having the power supply on the main board.
The rest of the parts used are as follows:
To affix the LEDs to the board, I needed to make sure they lined up so the display looked correct. The LED strips came with an adhesive backing, but the paper on the backing caused the strips to warp and bend and not sit flat. So, rather than risk that in the final product, I removed the adhesive backing. In the end, I used PVA glue to stick down all the strips. I used a paper template to get the vertical alignment correct, and compared the first LED position to get the horizontal alignment. The PVA glue allowed me to stick them down and then make minor adjustments to the position to get them aligned, before weighing them down with some books for 24 hours to let it set in position. In the end, it was done in 5 batches starting from the right end - the first set was 8 strips of 8 LEDs, then followed by four sets of 8 strips of 30 LEDs to get the total number of LEDs.
Once the LEDs were fixed down, it was time to solder them together. After some more head scratching, I ended up using male PCB headers (like Arduino shield connectors) as they're nice and thick and should have a reasonable current carrying capacity. Soldering them on was somewhat tedious, although less tedious than soldering 512 LEDs on Clock 2 and Clock 3. The only issue I ran into is because of the desoldering of the wires that came attached to the strips, in two places the strip itself disintegrated and lost electrical connection. For those two, I had to add a bypass wire to repair the circuit. In both cases it was just the signal wire, which meant I could patch it with just a small wire, as it didn't have to carry any significant current.
Soldering the strips together with headers.
Repairing the strip interconnects.
All of the control electronics.
The teensyduino and power interconnects.
So this time, I wanted to put a lot more smarts on the board, but make it much easier to work with than the previous clocks. So, the TeensyDuino has a very simple sketch that just takes a frame of data over USB and writes it to the display. And that's all that does. The smarts are on the Raspberry Pi.
I'm most familiar and comfortable with Python and most recently the Tornado asynchronous web framework. From that, I figured I could have a web interface, and have it generate frames in the background and sent them to the display. The web interface is for configuring the sequence that is displayed, changing settings, and also, using the magic of websockets (via socket.io) actually see what's on the display in your web browser.
In the software, you define a sequence (a list of things to show) made up of modes (that render something to the display). The core mode is the text mode, that handles rendering a text string to the display, and then moving it along the display. It was envisioned that other modes extend this to supply different text - for example, fetching weather data from the internet, and displaying that.
Internally, the software renders a frame periodically, and then writes it to the display, and also feeds it to any connected web browsers. It sends the frame to the Teensy via USB (which appears as a serial connection to the computer). The hardware is hidden behind a software abstraction, which means you can write to null hardware - great for developing on a laptop that isn't connected to the display. Also, my original intention was to have a minor display attached to the Raspberry Pi, and have it able to share the other display data. In the end, I didn't bother implementing this, although it's just a matter of writing the adapter to write to the hardware.
I developed most of it on my Laptop, which is somewhat faster than a Raspberry Pi. So when I put it on the Raspberry Pi, I was suddenly only rendering 2 frames per second. A little bit of digging showed that there were several slow parts. The first one was the algorithm in Python to convert from raw RGB format to the Teensy internal DMA format. Even though it was only rearranging 3072 bytes, on the Pi, it was taking 250ms. So I recoded that part in C, and got the Python code to use that instead. That reduced that time to about a millisecond.
The other slow part was writing the data to the display. That took about 22ms, and as it is a a synchronous call, it blocked. The CPU didn't have to do anything, just wait. I moved that onto a hastily hacked thread queue worker (as again, it's IO wait, nothing CPU bound, so the Python GIL won't affect this). This alowed the Pi to do about 15 frames per second.
In future, I plan to rewrite just the rendering parts in C. This would free up a lot of CPU time on the Pi, allowing the web interface not to interfere with the rendering. When I get time. An alternate solution would be to get the Teensy to actually do the rendering, as it's quite powerful on it's own - but that would make it harder to update the code.
With such a large item, the next question is how to mount it. It doesn't weight a huge amount, although it adds up - I would estimate about 5-10kg. Initially, I was going to drill holes in the wall and install hooks, and mount it on that. A few things stopped me; the first being I didn't have somewhere to mount the power supply, and I wanted it to be off the ground - given my home grown not-completely-legit mains wiring of the supply. The second was avoiding drilling holes in the wall if I can.
After quite a bit of headscratching, I came up with a solution that needed two upright legs mounted at each end. It could then be placed up against a wall, and with some double sided tape on the back affixing it to the wall, it would stay in place. And this was cheap too - the vertical boards (1800mm x 140mm x 20mm pine) were $7 each, and a few brackets to hold it all together. Additionally, by adding a board in the middle to provide strength, plus some hooks, I had some cable management as well.
The power supply is mounted on one of the legs - high up - and I made a cover for the mains wiring part of it. Also, what you can't see under the cover is a clip to ensure that the cord can't be pulled out, which would expose the live wires.
Final installation location.
So, overall, this project is not very useful. But it's very bright, and is interesting to look at. And people who come to visit the house are always fascinated by it and how it works. Or, scared by it a little bit, given that all the wiring is exposed. I like the look, but it does intimidate a few people.