Saturday, March 17, 2012

Ambient bus arrival monitor from hacked Linksys WRT54GL

London's Transport for London has a wonderful service called Countdown that can give live bus arrival times. For example, here's a page showing live buses passing No. 10 Downing St.

Underlying this is a simple JSON API that, while not public, seems to be usable by the average programmer as long as I'm not abusive. So with its details deciphered (hardly hard since the web site uses the API) I set about building an ambient bus monitor into a model London bus. The idea is that I can glance at the bus and see the times of up to the next two buses that I'm likely to want to catch and know when to leave the house.

Here's a picture of the completed unit:

To make that work I needed a computer of some kind and I'd originally planned on using a eRaspberry Pi. But with the delay in being able to buy one I switched to another host: a hacked Linksys WRT54GL. It's possible to reflash the Linksys with a custom Linux installation that lets me control the box completely (and still use it as a wireless router). There are various project, but I used OpenWRT.

With OpenWRT it's possible to SSH into the box and treat it as any Linux server (albeit a rather slow one). But there's plenty of power to grab bus times and update an LED display connected to the WRT54GL's serial port. Yes, there's a serial port inside the WRT54GL that uses TTL levels and can be easily accessed by soldering on three wires.

First you remove the cover of the router. It's easy because it simply pulls apart, but first you have to cut through a sticker warning you that your warranty is about to end.

The front part pulls away easily to reveal the circuit board:

And the back is just as easy to remove leaving you with the circuit board itself (you must remove the two antennas at the back):

The two serial ports are conveniently easy to access at the edge of the board:

The LED module I'm using is from SparkFun and accepts TTL levels and needs a 3.3V power supply.

Happily the WRT54GL's serial port is TTL and has Vcc and GND, so three wires supply all that's needed:

(Yes, those wires are rather large because I'm using up surplus wire from my homemade matrix display made from hacked Christmas lights).

A quick test with the multimeter showed that I was getting about the right voltage:

Next I used a standard three pin 'headphone' socket and drilled a hole in the front of the Linksys for it:

And put it all back together it makes a neat little unit that's got a serial port on the front:

To wire up the display I took an old sound card cable that came with a PC and cut one end off and soldered the wires to the display. The plug end goes into the Linksys. Here is it showing a number for the first time:

With the hardware half done (no bus yet for the display) it was time for software. The code for the project (written in Lua, which is installed by default as part of OpenWRT) is here.

It relies on STTY so install it with apt-get install coreutils-stty so that it can set the serial port up correctly. On my box that second serial port is /dev/ttyS1.

The program has three parameters: a comma separated list of bus routes, a bus stop number and a 'walking time'. For example, it's possible to do:
lua ambibus.lua 3,12 50906 2
Which means get the times for buses 3 and 12 arriving at stop 50906 (close to No. 10 Downing St.) and allow me two minutes to walk there. The program will find the buses, adjust the times by 2 minutes to allow you to arrive and once a minute update the display with the times of the next two buses.

Next up is a nice case for the display. What better than a London bus. I chose a Plaxton Pointer as it was the right size for LED display to show through the side windows.

If you collect model buses you may want to avert your eyes as I decapitate the bus, gut it, cut out some seats and then put it back together again.

I prised the top off using a screwdriver to reveal the plastic window piece:

Then I removed the windows themselves to reveal the seats:

And then removed the seats to get access to the 'engine' at the back which I removed to make a space for the cable to pass out of the bus.

Then I wired in the display with a small hole cut in the back seats to allow the cable to pass through:

The display was glued in (upside down because of the available clearance: a problem which is fixed in the code) and a few seats cut out to make space.

Then put it all back together and power on the display for a quick test:

And here it is running. The display is capable of showing two buses, but here there was only one bus coming in four minutes:


Anonymous said...

Great! The model bus adds a nice touch. I've been contemplating doing something similar using the Helsinki transport system, but the electronics component is what scares me off.

Luke Closs said...

This is so awesome! Thank you not only for describing the project but also for the detailed instructions to re-purpose this hack! I can think of many ideas that I'd like to apply this to!

Thank you for taking the time to write this up!

Vijay Raj said...


I am interested in electronics hacking, but a n00b. How did you know that those were the serial ports on the router? Also, any advice on getting more knowledge to help in these?

Bijan said...

This was absolutely fascinating for me. I've been reading Charles Petzold's book Code and taking a course on circuits and this is the first time I've actually gotten to see a modern practical usage behind some of the concepts presented in a digestible way.

Thanks for the post. It's inspiring work.

ngupta said...

I think in the following photo you are showing a wrong connection to pin hole number 7. It should be pin hole number 3.

ngupta said...

I think in the following picture, you are showing a wrong connection to pin hole number 7. It should be pin number 3.

John Graham-Cumming said...

@ngupta. You are correct that it should be pin 3 and pin 7. I must have taken that photograph before I realized that I'd screwed it up.

Anonymous said...

Vijay Raj > I am interested in electronics hacking, but a n00b. How did you know that those were the serial ports on the router?

You should probably ask in the OpenWRT forum:

LeuMund said...

Great idea! I built a Busstop Lamp, which is indicating with green light the right time to leave the appartment to catch the bus. My lamp is based on Arduino Ethernet which is fine to collect json information from the internet. Here is my <a href=" article in german</a>. I think i should do a english version too.

Making an old USB printer support Apple AirPrint using a Raspberry Pi

There are longer tutorials on how to connect a USB printer to a Raspberry Pi and make it accessible via AirPrint but here's the minimal ...