An example of motorizing a LEGO® train switch (turnout), and controlling it from Mindstorms
A goal of mine is to – someday – create a more or less automated running LEGO® railroad layout. One of the steps towards that is to operate the switches by motors, and then control the motors by programming on the EV3.
Inspired by a video (which I can’t find again and credit properly), I simplified, and made the shown design.
Two 16 long studded technic bricks keeps the motor in place, and is attached to the switch with normal bricks. This can be done in many ways, and probably also more compact and sturdier than this design.
A 5 long liftarm is attached to the motor, and 2 x thin 4 long liftarms are connecting to the switch. The thin liftarms has an axle hole at the ends, which can hold the tap of the lever.


This was the easy part. The programming is also not difficult – it is basically just turning a motor a certain number of degrees. The tuning of the degrees needed as well as the speed takes some time, but I found an angle of 43 and speed of 50 works well. See my code at the end of this post.
Videos of other builds using Mindstorms to control the switches:
My code example used in the video:
#!/usr/bin/env python3
from ev3dev.ev3 import *
from time import *
# Connect motors and sensors
ts = TouchSensor("in1")
lm = LargeMotor("outA")
# Variables for tuning the switch.
# Make sure that the polarity of the motor is right.
# Test it before attaching the motor to the switch.
degrees = -43
speed = 50
# Make sure that the switch is manually put to "straight" position
# before running the program. Below resets the angle counter
# of the motor to zero.
lm.position = 0
def main():
# direction of the switch: 0 = straight, 1 = turn/diverting
switch_state = 0
while True: # Loop forever - press back button on EV3 to stop.
if ts.value() >= 1: # If touchsensor pressed.
if switch_state == 0:
lm.run_to_abs_pos(position_sp=degrees, speed_sp=speed, stop_action="brake")
Sound.speak("Turn")
sleep(3)
switch_state = 1
elif switch_state == 1:
lm.run_to_abs_pos(position_sp=0, speed_sp=speed, stop_action="brake")
Sound.speak("Straight")
sleep(3)
switch_state = 0
if __name__ == '__main__':
main()