I have a LEGO City train set (60336):

60336 Box

The set includes a remote control as well as an app that can be used to control the train. Is it possible to automate the operation of LEGO City trains, ideally without needing to be tethered to a smart device to help reduce children getting distracted by a screen?

3 Answers 3


I've been exploring this recently, and I wanted to share my experiences in the hopes that they are useful to others. There are a few ways this can be accomplished. Some are possible out of the box, and others require extra hardware or 3rd-party software.

Typical Package Contents

Here's the electronics we typically get out of the box with a Powered Up train set:

  1. Powered Up City hub (28738). This includes two I/O ports (used for a motor and possibly lights). The City hub does not include an accelerometer, compass, or GPS, so there is limited feedback provided. It does include a programmable RGB LED and a button.

City Hub

  1. Train Motor (28740). This motor is one of only two Powered Up motors that do not include rotation and distance tracking, so there is no easy way to know how far the train has traveled, but we are able to adjust its relative speed.

Train motor

  1. Lights (22168) may be included as headlights for the train.


Programming using Powered Up App

The default experience in the Powered Up app provides a controller for the train, but we can also automate the train using a Scratch-like programming environment. This environment is powerful, but the hardware at our disposal is quite limited as a robotics platform. In particular, the included hardware has no useful sensors, which makes the environment unobservable.

If we start the train from a known location, we can run it at a set approximate speed for a certain amount of time, leaving it at a new approximate location. Unfortunately, these locations will change slightly over time, as we have no way of sensing exactly far we have traveled. This might be fine if you just want the train to move for a while then stop for a while, but if you want to stop at stations, things get trickier.

One solution is to induce the train to stop at a known location regularly, such as a siding. We can intentionally stall against the buffer on the siding to reset to a known position.

Adding Sensors

If we're willing to add some additional hardware, things can get much more advanced. One option is to add a color sensor to the bottom on the train:

Step 1

We can connect the sensor to the port not being used by the motor.

Step 2

Step 3

With this in place, we can modify our track by adding plates or tiles of different colors to indicate location on the track or particular actions to take. In this way, we can have the train reliably stop at stations or take other actions. Here's an example program that allows the train to wait when it sees red under the color sensor:

Program screenshot

This is similar in concept to the DUPLO trains in terms of input, but we can program the colors to change behaviors in any way we'd like.

We could also choose to add a different sensor, such as a distance sensor or a tilt sensor. Alternatively, we could replace the City hub with a larger hub and add multiple sensors, but this would likely require redesigning the train and would add significant cost.

Standalone Operation

One of the weaknesses of the City Hub currently is that it requires a tethered Bluetooth device, such as a phone, tablet or computer, in order to function. By flashing the custom Pybricks firmware to the hub, we can overcome this limitation and write programs directly to the device. This is especially useful for public displays or other use cases where Bluetooth connections may become problematic.

Here is an example Pybricks program that would allow a train to run for 10 seconds and then pause for 35 using the RGB LED on the hub to indicate its status:

Simple automated train that runs for 10 seconds then pauses for 35

Light transitions from red to orange to yellow as timer counts down

from pybricks.hubs import CityHub
from pybricks.pupdevices import DCMotor, Light
from pybricks.parameters import Button, Color, Direction, Port, Stop
from pybricks.robotics import DriveBase
from pybricks.tools import wait, StopWatch

hub = CityHub()
motor = DCMotor(Port.A)

while True:

I use a setup similar to the above to allow an automated train to run around my son's city without the need to have a screen nearby the whole time.


If you don't want to touch the original hardware, you can replace the smartphone with something else like an ESP32.


This would require some programming knowledge.


For the sake of completeness: it's possible to replace the 2-port "city" powered-up hub with the 6-port technic powered-up hub. That should offer more flexibility when programming.

This is doable since the technic powered-up hub is 4 studs high, so it will fit within the locomotive (leaving a gap of half a stud on the front and back). It will, however, protrude about one stud over the ceiling of the locomotive (without taking into account cables and connectors!), so this is not a very aesthetic approach.

CAD drawing of a locomotive with the bigger hub inside

It should be possible to enclose the hub (or at least make it flush with the locomotive's ceiling) by increasing the overall height of the locomotive.

It should also be possible to replace the train motor with a SPIKE medium angular motor (since the latter is slightly smaller than the former), but connecting such an assembly to the train underside (and make it pivot as the train motor does) is a bit too challenging.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.