San Francisco’s Muni trains are not well known for their ability to be on time. Recent sfmta data shows a ~60% on-time rate (where “on-time” includes arriving anywhere between 1 minute before to 4 minutes after the intended time). Fortunately, they provide real-time arrival estimates with the Next Bus service. While the QuickMuni app does a great job of displaying this on my phone, I wanted to build a more “ambient” display, to help me decide when to leave in the morning.
My first attempt at a muni display was an Arduino with 3 big LEDs, laid out as a stoplight. A python script parsed train arrival times, and sent them to the arduino, which then lit the corresponding lights: Green for >10 minutes, Yellow for 7-10, Red for 6-7. (These times were chosen based on how long it took for me to walk to the train).
The most obvious drawback here was the need for a computer to run the python script. I was eventually able to get the script running on a wireless access point with DD-WRT, but the package was still rather awkward.
Around this time, Quick Muni came out, so I had a quick phone-based way to check trains, and I lost interest for a while.
Some time later, I bought a Particle Photon (formerly known as the Spark Core). Small, and wifi-enabled, it was perfect for a tiny train display.
Instead of a stoplight, I found a small servo, and got the Photon using it very quickly thanks to their builtin
Servo library. Original Proof-of-concept pushed the train times to the device through the Particle Cloud api, but I wanted the device to be a bit more self-sufficient.
To that end, I put together a web server with some configuration that maps the Particle device name (which the device can fetch from the Particle cloud api) to a set of nextbus query parameters. The device requests
/times/scrapple_ferret (for instance), and the server returns the number of minutes until the next estimated arrival at the stop at which
scrapple_ferret is configured.
The servo, however, makes a slight noise when it moves, and I found that having it run all night was not ideal. I added a button to activate the device for ~30m, and a pair of LED headlights that turn on when the device activates, and gradually dim as the device turns off.
All that remained was to paint up a display face, vaguely resembling the from of an SF Muni train, and hang it on the wall!
The code for this project is available from github.com/muncus/muni-display.