An Arduino library for controlling LEGO Powered Up trains with automated layouts, sensor-based automation, and intelligent routing.
- Multi-train management - Control multiple LEGO Powered Up trains simultaneously
- Sensor integration - Support for light sensors and reed switch sensors
- Track switch control - Automated control of track switches via relays
- Position tracking - Advanced position tracking with collision avoidance
- Action sequencing - Complex automated behaviors with sequential actions
- Arduino ESP32 or compatible microcontroller
- One or more LEGO Powered Up train hubs
- Optional: Reed switch sensors for position detection
- Optional: Relay modules for track switch control
- Open Arduino IDE
- Go to Sketch > Include Library > Manage Libraries
- Search for "LEGO Train Controller"
- Click "Install"
- Download the library as a ZIP file from GitHub
- In Arduino IDE: Sketch > Include Library > Add .ZIP Library
- Select the downloaded ZIP file
This library requires:
#include <LegoTrainController.h>
// Create controller instance
LegoTrainController trainController;
void setup() {
  Serial.begin(115200);
  
  // Initialize the library
  trainController.begin();
  
  // Create sensor locations
  SensorLocation westStation("WEST_STATION", 1);
  SensorLocation eastStation("EAST_STATION", 2);
  SensorLocation bridgeEntrance("BRIDGE_ENTRANCE", 3);
  
  // Add a train with starting position
  size_t trainIndex = trainController.addTrain("MyTrain", PoweredUpHubPort::B, westStation);
  
  // Add sensors using locations
  trainController.addReedSwitchSensor(D9, westStation);
  trainController.addReedSwitchSensor(D10, eastStation);
  trainController.addReedSwitchSensor(D11, bridgeEntrance);
  
  // Start the train
  trainController.setTrainSpeed(trainIndex, 30);
}
void loop() {
  trainController.update();
}The library includes several examples:
- BasicTrainControl - Simple train control with manual commands
- MultiTrainSystem - Advanced multi-train automation with sensors and switches
Initialize the train controller system. Call this in setup().
bool success = trainController.begin();Main update loop. Call this in loop().
trainController.update();Add a train to the system.
// Create a starting location
SensorLocation depot("DEPOT", 1);
size_t trainIndex = trainController.addTrain("MyTrain", PoweredUpHubPort::B, depot);Set train speed (-100 to 100, negative for reverse).
trainController.setTrainSpeed(0, 50); // 50% forward
trainController.setTrainSpeed(0, -30); // 30% reverseStop a specific train.
trainController.stopTrain(0);Add a reed switch sensor at a track position.
// Create sensor location
SensorLocation station("MAIN_STATION", 10);
trainController.addReedSwitchSensor(D9, station);Add a light sensor with detection threshold.
// Create sensor locations for tunnels and bridges
SensorLocation westTunnel("WEST_TUNNEL", 15);
SensorLocation tunnelEntry("TUNNEL_ENTRY", 20);
trainController.addLightSensor(A0, 50, westTunnel);
trainController.addLightSensor(A1, 30, tunnelEntry);Define track topology for position tracking.
// Create custom locations for track layout
SensorLocation westStation("WEST_STATION", 1);
SensorLocation eastStation("EAST_STATION", 2);
SensorLocation westTunnel("WEST_TUNNEL", 3);
trainController.addTrackSegment(
  westStation,
  eastStation,
  westTunnel,
  0 // train index
);Make train stop when reaching a sensor location.
// Create station location
SensorLocation mainStation("MAIN_STATION", 5);
trainController.addStopAction(mainStation, 0, 0);Execute a sequence of actions at a sensor location.
// Create turnaround location
SensorLocation turnaround("TURNAROUND_POINT", 25);
std::vector<ActionConfig> actions;
actions.push_back(ActionConfig(TrainActionType::STOP));
actions.push_back(ActionConfig(TrainActionType::REVERSE));
trainController.addSequentialAction(turnaround, 0, actions);Create custom sensor locations for flexible track layouts:
// Create locations with descriptive names and unique IDs
SensorLocation bridgeEntry("BRIDGE_ENTRANCE", 100);
SensorLocation tunnelExit("TUNNEL_EXIT", 101);
SensorLocation maintenanceBay("MAINTENANCE_BAY", 200);
// Use them with sensors
trainController.addReedSwitchSensor(D8, bridgeEntry);
trainController.addLightSensor(A2, 40, tunnelExit);
// Use them in track layout
trainController.addTrackSegment(bridgeEntry, tunnelExit, maintenanceBay, 0);The library supports multiple trains with collision avoidance:
// Create starting positions for each train
SensorLocation westStation("WEST_STATION", 10);
SensorLocation eastStation("EAST_STATION", 20);
SensorLocation depot("MAINTENANCE_DEPOT", 200);
size_t train1 = trainController.addTrain("Train1", PoweredUpHubPort::B, westStation);
size_t train2 = trainController.addTrain("Train2", PoweredUpHubPort::B, eastStation);
size_t train3 = trainController.addTrain("Train3", PoweredUpHubPort::B, depot);Control track switches with relay modules:
int switchId = trainController.addSwitch(D5, SwitchPositions::STRAIGHT);
trainController.operateSwitch(switchId, SwitchPositions::DIVERGED);Advanced position tracking with automatic direction detection:
int position = trainController.getTrainPosition(0);
bool connected = trainController.isTrainConnected(0);Enable debug output to troubleshoot issues:
trainController.enableDebug(true);
trainController.printStatus();Contributions are welcome, especially if you can port this over to new platforms.
This project is licensed under the MIT License (see the LICENSE file for details).
- Legoino Library for LEGO Powered Up communication
- NimBLE-Arduino for Bluetooth Low Energy support