-
Notifications
You must be signed in to change notification settings - Fork 1
Railroad
Having a boy, who caught interest in a model railroad, my wife started looking for a ready-to-use layout of a model railroad and also found a used one for a decent price. To be able to transport it, all the electric connections were disconnected, so it was obvious that I had to invest some time into wiring it up again and making it work.

Looking at it, I realized that there were wires not only for driving the trains on the tracks, but also for the railroad switches. At that point my interest started to grow, and I wondered if it wouldn't be nice to have a full-custom electronics control unit for the operating these track-switches via a tablet.
So there was the idea of having vintage technology meeting the IOT age.
The past years I had invested some time in developing Atrium for exactly such use-cases. So Atrium provides all necessary infrastructure to bring live to some devices with support for remote-operation, data-recording, and everything else one would need for such a setup.
So I decided to design a PCB that can operate the railway switches using the Atrium firmware. As core controller I decided for an ESP32-C3, which has the nice USB interface that can be used for flashing, debugging, and as a console. For driving the railway-switches I added an I/O-expander with N-channel MOSFETs that can drive the amount of current for switching the railways.
Additionally, I included 2 channels for running WS2812b chains, which are multi-color LEDs on a daisy-chain wire, which could later be used to illuminate different parts of the model with different colors or even blinking stuff like the blue or red-blue toggling lights of a police car or something similar.
So the PCB for switching the railway tracks has following features:
- ESP32-C3 with WiFi
- I/O-expander with 16 low-side MOSFETS capable of driving 8 railway-switches
- 12V and 5V bucks for WS2812b supply
- high-side for WS2812b supply
- USB-C connector with ESD protection for flashing and debugging
- reset- and boot-mode-buttons
- status LEDs
- 2 supply connectors (barrel and screw-terminal) with reverse-polarity-protection
- UART interface (fallback for flashing/debugging)
This is a 2-layer board that I ordered fully assembled at JLCPCB. 3 pieces were around 160 Euro, including shipping, taxes, and customs.

As usual, basic hardware configuring Atrium for that board is straight forward and does not require compiling anything. Just connect to the board, set the ports for I2C and GPIOs for buttons etc. for the hardware configuration and configure WiFi etc. for integration into the home network.
But, to make it fully operational with a internet-of-things user interface, some necessary drivers are missing and additionally some application specific customization is required to make it convenient and easy to use. On Atrium, this can achieved with small Lua scripts as described below.
Remote operation is done using MQTT and an Android app running on either a smart-phone or tablet. For this I use IoT MQTT Panel, as it is possible to export the setup from one device and import it into another device. So it is easy to distribute the configuration to multiple devices.
As Atrium does not provide a track-switch device driver out of the box, the question is, if it makes sense to add one natively in C++, or if it is feasible to implement it in Lua. As the timing requirements of switching a track are pretty low, I wondered if Lua could be used for this and gave it a try.
Operating a track switch is done by turning on the related low-side MOSFET for a specific time. 250ms seems to be reasonable, as it makes sure the track switching has finished successfully and not having the MOSFET turned on for too long to cause any damage or unnecessary power-consumption.
Lua provides all necessary functions in Atrium to access and set a GPIO and perform timed actions using timers. Also functions for logging executed actions or parameters are included, which can make debugging a bit easier.
The track-switching driver is implemented with 2 simple functions as shown
below. One for turning on the MOSFET and starting a timer, the other one for
turning off the MOSFET once the switching phase is finished. The relevant
timer is also created by the track_switch function on demand if necessary
(i.e. when a certain track-switch is operated the first time).
function track_switch(tr)
log_info('track_switch '..tr)
local tid = tmr_getid(tr)
if tid == 0 then
tid = tmr_create(tr,250)
event_attach(tr..'`timeout','lua!run','track_switch_off("'..tr..'")')
end
gpio_set(tr,1)
tmr_start(tr)
end
function track_switch_off(tr)
log_info('track_switch_off '..tr)
gpio_set(tr,0)
end
In the same fashion, it is possible to drive the LED-strings (WS2812b type) that can be attached to the board to provide custom lighting in the little world of the model railroad layout. This needs some more mechanical work for integration, but the WS2812b strings make it also possible to have dynamic lighting such as the blinking lights on top of a police car, which is of course much more attractive than static lights that are just turned on.
ws2812b-rainbow-low.mp4
The interesting question here is, what kind of update rate can be achieved with Lua running on an ESP32-C3 when driving a serious number of WS2812b color LEDs. As can be seen in the clips the dynamic can be high enough so that the human eye doesn't recognize the changes as individual steps directly.
ws2812b-flashes.mp4
In these 2 demos 100 LEDs are getting updated at a 50ms interval rate. More LEDs or a lower update interval would be possible. So the performance is perfect for this task.
As this board has only 1 user button for some testing, all the provided functionality shall be operated via remote interfaces using MQTT.
Therefore, the Atrium firmware of the track switching PCB and a smartphone or tablet connect to an MQTT server to exchange information that can be used to display status data or trigger actions. Lua actions can be triggered directly, which makes it easy to associate above described actions with buttons in an MQTT app, as can be seen below.

Configuration in the IoT MQTT Panel app is pretty easy. See the screenshot below for an example. All you need to do is trigger the action called lua on the relevant device, and provide a Lua function with arguments as a parameter to execute:

In this example the argument to the function ("w1a") , tells the function to
operate track-switch number one into position A. Another button is there for
putting it in position B. Of course A and B can be replace by something more
meaningful like left and right or East and West.
But as always with making little models - they are never finished, and you can continue whenever you like and want to have fun.
So have fun modeling with Atrium and PCBs to bring those little world to the Internet-Of-Things.