Model train controller with Nerves


Already long time I was thinking about trying Nerves, now finally I started using it, and I’d like to show my progress :slight_smile:
As I’ve got a model railroad in my garden which is controlled by normal rc transmitter, I thought I could do something more. If using a rpi in every loco, it would be possible to create a fully automated railway controlling system, maybe with RFID tags to identify a trains position on the track.

But of course that would be quite some work, so let’s start small:
I’ll build a simple remote control for a loco. I thought starting a wifi ap and a phoenix live view ond the rpi in the locomotive. Then it would be possible to connect to the loco with a mobile phone and control the speed through a web ui.

I just started yesterday, and now I’ve got a basic set up which lets me connect to the loco through ssh and controll the speed by setting a PWM signal directly in iex with GitHub - tokafish/pigpiox: An Elixir wrapper around pigpiod for the Raspberry PI

Let’s see where we’ll get from here… :smiley:

As I think “Elixir on Rails” might be slightly misleading as a projects name, I think I’ll call it RailDwarf


Hey, looks cool. Just in case you need some inspiration, there’s a something called CTC System that implements a model railway controller based on wifi.

Most of the documentation is in german, but there’s also a gitlab repo with most of the code.


Looks like a fun project Rainer - I’ll look forward to seeing your updates! You could prob turn it into a screencast series as you’ll have interesting visual elements (like in your video) to include :003:



Thanks for the link, didn’t know this yet, even if the one who does it seems to live about 45min away from me :smiley:

Nerves is really cool, and with the helpful examples on github I already got a first prototype with ui running :partying_face:

Weird thing now, the wifi just comes up on the first boot, after a restart nothing happens anymore until i burn the firmware again…

1 Like

Seems my wifi problem is somehow power input relatet and random, however works now most of the time…

Made some progress and a short video, already quite usable :slight_smile:


Any UI experts here? :wink:
Always a difficult thing for me, no idea what would be a good UI, so at the moment I’ll continue with my 3 buttons solution, slightly enhanced yesterday evening:

Good I didn’t throw my old phones, now i have some to use as remotes :slight_smile:

I think next thing to do is moving the loco state to a GenServer, atm I’m keeping it in the phoenix socket only.
After that I want to add soft acceleration and deceleration, and some LED lighting.

What would be a good solution to control high power LEDs? I think it would be too much current directly through a GPIO pin. One loco will have at least 6 red/white LED for front&back lights, and one white led for interior lighting…


Short train session at lunchtime, works great :smiley:


You can set up a rudimentary transistor control for the LEDs, here is what I used for my Nerves game at one point (EDIT: The left side GPIOs with the 330 Ω resistors are for some buttons in my game, you can ignore them here. But you get the idea, you can turn a more powerful energy source on and off using a transistor that you control with a GPIO pin.):

But obviously you’d need to find out the correct voltages/resistances/transistors to use in your system and I’m not good at electronics so maybe that circuit is doing something silly.

In the end I ended up buying AdaFruit NeoPixels for my project since they were easy to wire up and control (using Blinkchain). They could be controlled by a simpler/cheaper microcontroller too. The Jewels I got have very bright LEDs on 5V power supply.


Seems my wifi problem is somehow power input relatet and random, however works now most of the time…

Yep I know by direct experience that power supply, especially on the RPi 4, is critical. When voltage goes below 4.8V you get a lot of erratic behavior, and with poor quality power supply or even long cables it’s easy to hit this limit. Any peripheral absorbing additional current makes things worse of course.

My recommendation is to use a good quality power supply (best if 5.1v) and keep the cable short. Even better would be to power the Pi externally with a higher voltage source and a voltage regulator.


Still better than me :smiley:
But you confirm my initial thought “maybe something with transistors could do the trick”

But even to find the right components would be a challenge, so I think I’ll look for something already done, maybe ELV Bausatz LED-I2C-Steuertreiber, 16 Kanäle | Bausätze | ELV Elektronik


Yesterday I moved the control logic out of the page controller to a genserver and added smooth slow down. It’s now also possible to control the loco with 2 phones the same time as the state is not in the user socket anymore:


Finally we got some sun again, so I went outside for a lunchtime run :smiley:

If it is of interest, code can be found here:

Not sure what to do next, I’m already very happy with how it is now :slight_smile:


This is a really cool project, @Rainer ! Nerves is a lot of fun. I’ve been playing around a bit with it to make a telephone exchange for some old rotary dial phones. It’s a lot of fun to use Elixir to interact with physics things.


Slow progress, I added a settings button and modal, where the only setting yet is to reverse the direction of the loco (useful, because it is not possible to solder the esc to the motor with the correct polarity at the first try :roll_eyes: )

I tried to save the setting to /data/settings, but somehow this doesn’t work yet.


looking great!

one idea could be to add live updating speed in km/H (approximated from the pwm or something)…

in that vein you could also an accelerometer down the line to show live g forces (How to Interface MPU6050 (Accelerometer) with Raspberry pi using Python - MEVI HUB)

keep us posted - fun project.


AFAIK by default Nerves lives on a read-only filesystem? Possibly you have to change some settings to be able to store things on the memory card.

1 Like

Frequently-Asked Questions — nerves v1.7.12 :

By default the /data partition both read/writeable and is not overwritten when new firmware is pushed to the device. However, if you are using mix firmware.burn then the entire SD card is being overwritten each time so you won’t have any persistent data. -


I just added more information to the persistent data FAQ entry that’s linked above. Hopefully this helps.


Well, I’ve found the problem :roll_eyes:
My code for creating and reading the file was already working, just somehow I forgot a line of code for updating the file :joy:


Didn’t spend a lot of time implementing things, but I’ve bought a second rpi0 and put it into a second loco, a kit-built Darjeeling NDM-1 :slight_smile:
As I now have 2 locos with my remote fitted, I randomized the SSID and that’s it codewise.

Not sure what to do next. LED-lights would be nice, but also to control the locos from just one mobile.
And I’ve got a magnetig sensor which I could attach to an axis of my live-steam locomotive. The steam loco reacts to every slight change to the steepness of the track, so I’d need to check it’s speed through the sensor and then adjust the steam valve accordingly…