Introduction
Back in October 2022 disaster struck with the Industrial Board, the raspberry pi that was the controller for the board failed, it fried its' self meaning that the Industrial board was now no longer usable. The price, and availability, of a replacement Raspberry pi, coupled with feedback from many members meant that it was time to re-consider how the Industrial Board was to be controlled and a project to replace the raspberry pi with. a new control box was started in 2023.
Design Objectives
- To support eight (8) segments organised into four (4) tracks and eighteen (18) points.
- To be entirely powered from a standard ATX PC power supply.
- To be electrically compatible with the control system connector (5-way DIN) on the existing Industrial Board.
- To use the same control protocols (I2C) as the existing Industrial Board, no changed permitted.
- To allow the speed and direction of the trains to be independently controlled via physical switches and control knobs.
- To allow the position of the points to be independently controlled via physical switches.
- To provide visual feedback of the position of the points, the speed and direction of the trains on the tracks,
Hardware
The hardware designed for the new method of controlling the Industrial Board is in two parts, the wooden box and the electronics to read user inputs, drive the Industrial board and provide status feedback to the user.
The physical (wooden) box
The physical control box was made by a club member who does wood carving as a hobby and the design of the box is modeled on the physical control box of the 10-foot Main board, albeit a little taller. The basic design is to have a sloping front panel, hinged at the top, that would be used to both capture inputs from the user and provide status outputs. The board was designed to be large enough to hold a standard ATX PC power supply (the chosen power source) along with all the components needed to provide control commands to the Industrial Board via the I2C bus and due to power requirements, the box would need to include passive ventilation. The design of the box was started around mid 2023 and was completed by the end of July 2023 ready for the control electronics and PSU to be fitted.
The control electronics
The control electronics had to be compatible with the existing Industrial board, which was out of scope for any major changes upgrade, so had to rely on the same control method (I2C) and be driven from 12VDC. As part of this project one minor change to the Industrial Board was made, to separate out how the 12VDC was used to drive the decoder logic, CDU and track power. The decision was made to power the CDU and track power from the same 12VDC line and have a separate 12VDC line for the control logic, this proved to be a very wise decision as it allowed the power to the track controllers to be varied to provide a "boost" for old/heavier locomotives.
User inputs
One of the main objectives for the new control box was to provide a more physical way of controlling the train direction, speed and track points, as follows:
- SPST momentary on push switch - one for each point, when pressed the position of the point would be toggled.
- SPDT centre off toggle switch - one for each of the tracks, allowing a direction of forward, reverse or off to be selected for each track.
- Rotary control knob - one for each track to allow the speed to be changed from zero (min) to 100% (max).
User feedback
Another of the main objectives for the new control box was to provide physical feedback on the status of the trains and points on the board, as follows:
- bi-colour (red/green) LEDs - one for each point, show RED when the point is in the "branch" position and GREEN when the point is in the "main-line" position.
- 4 line 16 character LCD - each line of the LCD shows the speed and direction of each track.
Logic control
The previous control box was based around a Raspberry Pi, the decision made was to move away from a raspberry pi, due to boot times, and use an ESP32 micro-controller. The ESP32 was coupled with an I2C buffer driver (TCA4307) to help boost the signal to the Industrial Board and better protect the micro-controller from voltage spikes and current surges. In addition to help with diving the LEDs and the LCD an MAX7219 and PCF8574 were used, along with an MCP23017 and a ADS1115 used to read the input switches and speed control knobs.
Block diagram of Control Board sub-systems
Front Panel Outside view
Front Panel inside view
ESP32 Microcontroller
Switch Scanner and RTC
LED Matrix Driver
Switch wiring matrix
Control Box inside view (ATX power supply and track voltage booster)
Control Box rear view
This completed the hardware in the control box, the following section talks about the control software that runs on the ESP32.
Software
The original control software was written in python for the raspberry pi and used pygame to handle all the user interface elements. The ESP32 microcontroller chosen was able to run micropython which is compatible with cython so the decision was made to port the existing code and structure the new code as follows:-
- ads1x15.py - Ported from python3, this module handles the low level interactions with the ADS1115 ADC.
- controlbox.py - This is the main flow for the application and was updated to remove all reference to pygame, keyboard, and mouse control and replace with logic to read the switches and screen controllers, then based on logic drive the points and track speed controllers.
- displaykeypaddriver.py - Written to provide a layer of abstraction to read the key presses and write to the display
- ds3231.py - Ported from python3, this module handles the low level interactions with the DS3231 RTC
- i2c_lcd.py - Written to provide a layer of abstraction to write text strings to the LCD
- industrialboarddriver.py - The module that provides a level of abstraction to drive the Industrial Board
- lcd_api.py - Written to provide a layer of abstraction to write text strings to the LCD
- logging.py - Written to provide a method to record any events in the program (info, debug, warning, error) and write then to a text file in a standard format
- main.py - This is the bootloader, first called following power-up, that allows either the main program (controlbox.py) to be executed, or the code exit and drop back to REPL
- max7219.py - Ported from python3, this module handles the low level interactions with the MAX7219 Display driver.
- MCP23017.py - Ported from python3, this module handles the low level interactions with the MCP23017 I2C Expander.
- PCA9685.py - Ported from python3, this module handles the low level interactions with the PCA9685 I2C PWM controller.
User Interface
There is no graphical user interface to this control box, the interaction with the user happens through the switches and control knobs, with the user will change the state of in response to what the train is doing, the position of the points and the status shown on the LCD. The main program (controlbox.py) runs an infinite loop as follows:
- while (True):
- read the status of the switches
- read the status of the control knobs
- update the position of the points based on the state of the switches
- update the track speed and direction based on the state of the switches and control knobs
- update the point LEDs with the status of the points
- update the LCD with the direction and speed of track
- wait a short amount of time
In the current implementation the loop described above loops approximately 3 times a second.
Board control logic
The bulk of the logic to control the points and track direction/speed is contained within the "industrialboarddriver.py" file and is designed to provide a level of abstraction between the hardware that controls the board (ADS1115 ADC, MCP23017 I2C Expander, PCA9685 I2C PWM controller) and by its' nature is complex. the file exposes three classes:
- class channel(object): Provides primitives to allow the ADC channel to be linked to the track segments
- class PowerDriver(object): Provides the methods to allow the speed and direction of the tracks to be controlled.
- class PointDriver(object): Provides the methods to operate the points.
- class ProximitySensors(object): This class is obsolete and not use in the ESP32 implementation.
The exact function of the class above are complex and beyond the scope of this article, for more information on the function the source code should be reviewed, which is available upon request.