My wife and I moved to Washington, DC, for many reasons, but one major reason was access to public transportation. The Metro system is one of the best in the US, and we deliberately chose an apartment within walking distance of the Red line. A few months before we moved, we took a brief trip down to DC for the Marine Corp Marathon and some apartment hunting, which gave us plenty of time to learn and appreciate the metro. When we got back, I wanted to start one last project before the move: I was inspired to bring the metro design and feeling into our space while also providing useful information about our primary transportation source, and I hoped to learn some new skills along the way.
The design of the metro stations is characterized by their clean, geometric lines and use of modern materials such as concrete, steel, and glass. The stations were designed to be bright, spacious, and easy to navigate, with clear signage and wayfinding systems.
I focused on the signage for this project. Knowing that we’d be close to the Metro, I could already envision a key need, or Job to be Done (JTBD): When do I need to leave my apartment to catch the metro? I approached the project with three key priorities:
- Create something that was reminiscent of the modern Metro aesthetic and something that looked finished enough that I could display it in our apartment
- Learn some new hardware and software skills
- Create something that solved my problem
Given those priorities, I settled on the following minimum viable product (MVP):
- I wanted to create an LED sign similar to the incoming train signs in each Metro station that would show how long it would take the next train to arrive
- I was comfortable requiring the user to compute when they’d need to leave the apartment based on travel time (although that did give me an idea for a future iteration!)
- I wanted to program the sign with a small but powerful processor so I could work in a more forgiving language and at my own skill level. I’m most familiar with the Raspberry Pi but was open to whatever the best fit was for the problem space.
- I wanted this sign to mimic the Metro signs in both form and function: the data should be as accurate as possible for the trains, but it had to be displayed in a way that would evoke Metro signage for any viewer.
Technical Experience (e.g. can you make this too?)
For context, I have a minor bachelor’s degree in Computer Science, which gave me a general overview of languages, data structures, and tools. Since I graduated in 2016, I’ve worked on a few different projects as a hobbyist to gain more experience in web dev (exhibit A), hardware (a few Raspberry Pi projects), and programming (exclusively Python). My Product Management work heavily involves API use, data analysis, and artificial intelligence, but I’m not directly writing any of the code, so this was a nice change!
I would consider myself beginner-to-intermediate level overall; I don’t write code every day, I send terminal commands infrequently enough that I have to look some up each time, and while Python is basically like writing English, that doesn’t stop me from making dozens of formatting errors as I re-familiarize myself at the beginning of a new project. All that said, I will assure you that you can build this too if you are willing to use one tool: Google. 99% of what you need to know for this project has already been done in some way, shape, or form, but not all the information is in one place; one thing I love about the tech hobbyist community is a willingness to share your experience freely and save other people the time and effort of endless troubleshooting. For the few things I did have to figure out through trial and error, I’ll try to note them as we go so that I can help you avoid the same issues if you give this a shot!
P.S. I’ve tried out switching from Google to ChatGPT for programming questions during this project, which worked pretty well for the basics. Just make sure you know enough to know when it’s wrong!
So now that I had my priorities and my MVP scope, I started scouting for hardware. I was most unfamiliar with LED signs, so I started there. While you can buy plenty of cheap signs on eBay, many of those seemed pre-programmed, and I was looking for something more open-ended so I could also learn how to program the sign myself. I ended up at Adafruit; I’ve bought boards, sensors, and all sorts of things from them for previous projects, so I knew their quality was good, and I knew their focus on learning would be helpful for my intermediate experience level.
I started at the LED panels and quickly noticed there are some obvious options when looking to create this type of project; I ended up going with a Matrix Portal for a couple of reasons:
- It integrated directly into the LED panel so I didn’t have to spend too much time in integration hell
- It supported CircuitPython, so I could work in my most comfortable programming language
- It had onboard wifi support via the ESP32 processor
- It had plug-and-play support for STEMMA QT sensors, which gave me the option to add sensors down the line (future iteration!)
I originally debated how many panels I should get; to really mimic the Metro look, I would need at least three rows of text, one for the sign headers and two for trains (one in each direction). After eyeballing how the metro font would look on a 64×32 panel (Helvetica Neue, although I ended up using something else), I was in between 2 panels or 4 panels chained together. I settled on just 2 panels for a few reasons:
- Power: while the majority of the pixels on the panel would be dark most of the time, I saw the max power draw for just one panel was around 4 amps, which meant I could comfortably support 2 panels on a 10A power supply. I also decided to sacrifice the sign headers and shift to supporting two lines of text, which gave me roughly 16 pixels per line to work with.
- One thing to note if you’re going to chain these displays together is that you’ll need to adapt the board power pins into a 5V power supply output; there’s a cheap adapter that fits the bill, plus it doesn’t require any soldering if that makes your life easier!
- Pitch: The pitch of a panel is how far apart the individual LEDs are spaced. While you can find a bunch of optimal range calculators online for what pitch to use at what distance, I ended up mostly winging this. I bought one panel at a time so I could look at the pitch in person and make my final decision, figuring I could always use the original panel for a different project if I didn’t think it would work. The pitch also definitely was a factor in the final reason:
- Price: these panels aren’t cheap! While I didn’t set a strict budget for this project, I was hoping to keep the electronics around $100. Doubling the panels would play a significant part in going over budget, and I figured I could always buy 2 more panels if I really needed the extra real estate.
With most of the major decisions made, my parts list for the MVP came to the following:
- Adafruit Matrix Portal – CircuitPython Powered Internet Display (adafruit)
- 5V 10A switching power supply (adafruit)
- Female DC Power adapter – 2.1mm jack to screw terminal block (adafruit)
- 64×32 RGB LED Matrix – 4mm pitch (adafruit) x 2
Price total: $136.80
I also added a few additional parts to my order, partially to spend enough to get some free stuff but also because who doesn’t think of the next iteration while they’re still planning their MVP? When comparing processors to power the sign, one big plus of the M4 I went with was the plug-and-play sensor support. I bought my wife a digital picture frame from Aura as an anniversary gift, and one delightful feature each frame has is a light sensor to automatically turn the frame off at night and on in the morning. I thought a cheap light sensor could achieve the same effect, plus it felt cooler than hardcoding on and off times! I used the following STEMMA parts:
- STEMMA QT / Qwiic JST SH 4-pin Cable – 100mm Long (adafruit)
- Adafruit APDS9960 Proximity, Light, RGB, and Gesture Sensor – STEMMA QT / Qwiic (adafruit)
Price total: $8.45
P.S. ChatGPT is also quite helpful for answering questions from unstructured data; I copied most of my order receipts into my conversation and asked ChatGPT to tally up the total costs here.
One final caveat: I’ve tried to honestly represent my experience level, and that means that the way I’ve built this project is simply how I personally figured it out. I did a fair bit of research before purchasing anything but clearly, I had to make some tradeoffs and work within the components available to me at the time. I have no doubt there are better, simpler, or cheaper ways to accomplish the same (or better) outcome–if you know, please share!
With my components in hand and still a few months until the move, I started getting my hardware set up and coding the MVP. As a reader’s note, I’ve actually surpassed the MVP requirements currently, but have been lagging in my build log, so I’m hoping to catch you up as soon as I can!