Train Departures Board at Nottingham Hackspace
This is a project that ended up coming together really nicely. Nottingham Hackspace has had a railway departure board hanging off an RSJ for the past 10+ years. Unfortunately it's never done anything! I decided that we should change that and removed one of the LED boards to figure out how it was being driven.
Each side of the departure board consists of 4480 LEDs, split across two chains which are driven in parallel. The ASCII diagram below shows how these are configured.
+------------------+------------------+------------------+
| A2 | A1 | A0 | <--- Input
+------------------+------------------+------------------+
| A5 | A4 | A3 |
+------------------+------------------+------------------+
| B2 | B1 | B0 | <--- Input
+------------------+------------------+------------------+
|//////////////////| B3 |//////////////////|
+------------------+------------------+------------------+
Each chain has the following data lines:
Clock
Data In
BCD A
,BCD B
,BCD C
andBCD D
Strobe
- A pin which we'll refer to as the
mystery pin
The BCD lines are fed into a BCD decoder (CD4028BCN). The decimal
outputs go off to a UDN2981A octal source driver, which switches 8
MOSFETs (IRF540) - even though this display only has 7 rows. The idea is
to write out 384 pixels, pulsing the clock for each one, then update the
BCD lines, then strobe - doing that quickly enough will draw the buffer.
I got quite confused though. I had incorrectly assumed that all of the
data lines were using 5V logic levels. I could tell that the
mystery pin
was high because I'd logged this with my logic
analyzer, but it was actually slightly higher than high - about 7-8v.
This is the power rail for the UDN2981A, and is roughly the voltage that
gets used to drive the MOSFETs - once I realised this I was flying.
I decided to design a small circuit board in KiCAD to act as a
breakout for the IDC headers, and to provide a stable voltage for the
mystery pin
. I think it turned out quite nice :)
Embarrassingly, in this photo, the LM317 voltage regulator was installed backwards, leading me to one night of confusion. But then I was off, writing Arduino code. I decided to use an Arduino Uni R4 (WiFi) for this project - they are super fast and the 5v voltage levels worked out ideally for the CMOS logic in the display. The main purpose of the display is to show Discord messages in real-time (the Discord bot I wrote earlier pushes these to MQTT), but I also wanted to display live train departures from Nottingham Railway station every 5 minutes or so. Fortunately, National Rail provide free access to their API, as long as you agree to their terms. A small script getting called by cron every minute does the job nicely, and pushes a condensed departure board to MQTT.
#!/bin/bash
API_KEY="You can't have this"
CRS="NOT"
URL="https://api1.raildata.org.uk/1010-live-departure-board-dep/LDBWS/api/20220120/GetDepBoardWithDetails/${CRS}?numRows=3"
departures=$(curl -s -H "x-apikey: ${API_KEY}" "${URL}" | \
$HOME/jq -r 'try .trainServices[] | { destination: .destination[0].locationName, std: .std, platform: (.platform // "-"), etd: .etd }' | \
$HOME/jq -sc)
mosquitto_pub -t "nh/tdb/${CRS}" -m "${departures}"
At this point, I had something working, but it was a tad flickery and required some optimisation. I did a few things:
- Split an inner loop into two parts - one doing columns 0 to 191, and the other doing 192 to 353. This removed a condition and (non-power of 2 modulo) and increased the speed dramatically.
- Replaced a
delayMicroseconds(1)
with three no-ops, which seems to be enough time for the clock and latch pulses. - Removed calls to Adafruits GFX
getPixel
function, which wasted some cycles on determining rotation, and some out of bounds checks, and addressed the buffer directly.
The display now runs at about more than 250 frames per second and my
phone's "Slow Mo" mode is not able to see the rows being drawn. It does
still blank briefly every 1.5 seconds for the mqtt.loop()
call (I'm using PubSubClient).
So, here are the results.
I also made a demo video and posted to YouTube, but this was taken before the optimisations had been made.
Related posts:
Wanting to leave a comment?
Comments and feedback are welcome by email (aaron@nospam-aaronsplace.co.uk).