August 17, 2016 · python raspberrypi linux

RPi model railway controller

I have this tiny n-scale model railway layout partially finished, designed to
sit in a coffee table. It's difficult to use a normal controller in this case,
so a different solution is needed - a controller I can use over wifi from my

top view of trainset



  • Raspberry Pi
  • usb wifi card (unless you have the Pi 3 or ethernet)
  • micro SD card
  • 5V battery to power the Pi (the type designed for charging phones via micro usb)
  • Motor driver (reversible, works well for pwm control)
  • 4+ MOSFET drivers
  • jumper wires
  • strip headers
  • 12-14V power supply for powering the trains (battery or wall transformer)


  • Raspberry Pi compatible OS image
  • python3
  • pip3
  • RPi.GPIO (pip)
  • tornado (pip)
  • tmux/screen


  • soldering iron
  • multimeter
  • wirecutter, pliers, etc...



First, the wires for everything on the railway itself needed to be connected. My
board is slightly raised by wooden strips, giving enough space to route the
wires underneath the board, and into a f-m strip header to act as a socket.

the setup as described
wiring underneath the board

This makes it easy to connect/disconnect the rest of the wiring using another
strip header:

the setup as described
m-m strip header used as a plug

Neat and portable!

the setup as described
view of the socket connected

That's the railway board done, now for the electronics. The wires for the
turnouts are connected to the MOSFET drivers, since they require a short pulse
of electricity to trigger (about half a second). Note that two drivers are
needed for each turnout, one for each direction.

A reversible motor driver is used for powering the train itself. Just connect
the two track wires to its output.

photo of drivers
the motor driver on left, MOSFET drivers on right

The Raspberry Pi is wired to the motor driver and MOSFET drivers via any GPIO
pins using the jumper wires. Don't worry about hardware PWM - the RPi.GPIO
library only supports software PWM, which is good enough to drive the train.

the setup as described
electronics setup with Pi connected

I used a dedicated power supply for the Pi (5V battery), and a 14V supply
(wall transformer) for powering the trains and turnouts.

the setup as described
all connected and ready to go

The Software

I installed Archlinux ARM on the Raspberry Pi, but
any compatible OS would do. Just have to set it up and install python and pip
(and other essential programs like tmux, cron, etc...).

Pip was used to install the RPi.GPIO python library, and later, tornado for
the server.

Now comes the tricky part - working out which pins are connected to what. It
took a bit of fiddling around to work out functions for triggering the correct
pins for controlling the turnouts and train speed.

Since the aim was to be able to control it wirelessly, I decided to set up a
tornado server with python, with an API that allowed securely controlling the
functions over the internet, along with sanity checks server-side to avoid
damage to components from the turnouts being spammed, etc.

The server I built is opensourced and available on GitHub as swalladge/trains.
If you want to use it, you'll likely need to make some modifications to work
with your setup.

To control it, I made a web client (also opensourced - swalladge/trains-client).
It's a static webapp that uses ajax to connect to the api server, so it doesn't
matter where it's hosted. There's currently a copy of the webapp hosted

Note that the server and client, while simple and configurable, aren't very
scalable as they stand - adding any more than a couple of extra turnouts would
require a lot of refactoring for example.
Pull requests with improvements are always welcome!

the setup as described
action shot during testing

With the server installed on the RPi and the webapp hosted on my server for
quick access, the final step was to add a cronjob to start a tmux session
running the server on boot. Now getting the trains running is as simple as
plugging in the RPi and the train power supply, and waiting a minute for it to
boot up.

Final Notes

To DCC users: the setup described here wouldn't be suitable, as they
usually use proprietary protocols and require specialized controllers. They
often have wireless options anyway...

Next steps will be adding scenery, buildings, and maybe even RPI controlled lighting!