It works. Well, it works inasmuch as the locomotive stays on the track. The crash in the video may be caused the servo being out of trim, or it could be caused by the poor track fit. The video quality is horrendous.

To do:

  • Add servo trim from the remote and save to the uBit's "file system" (flash)
  • I guess I could change the radio settings so it doesn't use the default frequency and group

Build:

  1. Connect the servo to ground and 3v pads, and the data pin to pad 0
  2. Connect the reed switch to the 3v pad and pad 1
  3. Flash the Micro:Bit(s). The main controller works the same whether or not another Micro:Bit is being used. It uses a little more power since it's using the radio, though.
  4. Everything else is MacGyvering. I used a paper clip for the servo rod and cardboard and hot glue for the structure.

MicroPython code:

from microbit import *
import radio
pin0.set_analog_period(20)
straight = 110
turn = 75
# how long (in ms) to wait after the last train car passes over before automatically switching
switchAfter = 2000
trainPassing = False
switchState = straight
lastDetect = 0
pin0.write_analog(switchState)
radioSwitch = False
radio.on()
while True:
    if pin1.read_digital():
        trainPassing = True
        lastDetect = running_time()
    if radio.receive() == 'go':
        radioSwitch = True
    if (trainPassing and not pin1.read_digital() and (running_time() - lastDetect) >= switchAfter) or (radioSwitch and not trainPassing):
        radioSwitch = False
        trainPassing = False
        if switchState == straight:
            radio.send('turn')
            switchState = turn
        else:
            radio.send('straight')
            switchState = straight
        pin0.write_analog(switchState)

Optional remote control code for second Micro:Bit:

from microbit import *
import radio
radio.on()
while True:
    queue = radio.receive()
    if queue == 'straight':
        display.show(Image.ARROW_N)
    elif queue == 'turn':
        display.show(Image.ARROW_E)
    if button_a.was_pressed() or button_b.was_pressed():
        radio.send('go')
    sleep(50)