Students make a conductor micro:bit that plays a tune phrase by phrase and sends a radio cue as each phrase starts; robots dance the move for each cue, so the dance keeps in time with the music.
Load these into Waypoints Prepare: choose Load URL and paste the copied address, or download the file and import it. In Prepare, the worksheet's Teacher edition shows the answers; the student copy hides them.
Predict and Run 8 min · Investigate 10 min · Modify 12 min · Make 15 min · Real robot 5 min (optional)
This is the performance strand: lesson 2's dance moves (functions) plus lesson 7's radio. Each phrase is a function that sends its cue, then plays its notes until done. Because the music waits, the next phrase (and its cue) only starts when the last one ends, so cues arrive in time with the tune. Dancers decide what each cue means in on radio received.
Lily's show is the key slip: in background starts the music and moves on at once, so all the cues are sent together. In the simulator, two micro:bits and two robots appear (radio); pressing A on one makes the other robot dance, because a micro:bit never hears its own messages. Students need sound on (or headphones, which are not always available: the moves still show the timing).
Notes are written as letters with - for a rest, at 120 beats per minute. With real hardware, one bare micro:bit can conduct a whole class of robots in one group. Untested on real hardware: whether the robot start block errors on a micro:bit that is not in a robot (if so, the conductor's copy leaves it out). MOVE Motor classes can dance with Kitronik blocks in the same functions.
Timing cues by playing each phrase until done. When moves happen at once, ask whether the music plays until done or in the background.
| What you will see | A question to ask | The fix |
|---|---|---|
| The robot does every move at once. | Is the music playing until done or in the background? | Use play … until done, so the next cue waits for the phrase to finish. |
| Nothing dances. | Which micro:bit did you press A on, and which robot are you watching? | Watch the other robot; check both use the same radio group. |
| A move runs on the wrong phrase. | Does each phrase send its own number, and does the dancer check that number? | Match the cue in each phrase to the branch in on radio received. |
One possible solution for each task. Other correct programs are fine.

function wiggle () {
robot.motorTank(50, -50, 300)
robot.motorTank(-50, 50, 300)
robot.motorStop()
}
function spin () {
robot.motorTank(50, -50, 1200)
robot.motorStop()
}
function shuffle () {
robot.motorTank(50, 50, 300)
robot.motorTank(-50, -50, 300)
robot.motorStop()
}
function phraseA () {
radio.sendNumber(1)
music.play(music.stringPlayable("C C G G A A G - ", 120), music.PlaybackMode.UntilDone)
}
function phraseB () {
radio.sendNumber(2)
music.play(music.stringPlayable("F F E E D D C - ", 120), music.PlaybackMode.UntilDone)
}
function phraseC () {
radio.sendNumber(3)
music.play(music.stringPlayable("G G F F E E D - ", 120), music.PlaybackMode.UntilDone)
}
input.onButtonPressed(Button.A, function () {
phraseA()
phraseB()
phraseC()
})
radio.onReceivedNumber(function (receivedNumber) {
if (receivedNumber == 1) {
wiggle()
wiggle()
} else if (receivedNumber == 2) {
spin()
} else if (receivedNumber == 3) {
shuffle()
shuffle()
}
})
robot.elecfreaksCuteBot.start()
radio.setGroup(1)

function wiggle () {
robot.motorTank(50, -50, 300)
robot.motorTank(-50, 50, 300)
robot.motorStop()
}
function spin () {
robot.motorTank(50, -50, 1200)
robot.motorStop()
}
function shuffle () {
robot.motorTank(50, 50, 300)
robot.motorTank(-50, -50, 300)
robot.motorStop()
}
function phraseA () {
radio.sendNumber(1)
music.play(music.stringPlayable("C C G G A A G - ", 120), music.PlaybackMode.UntilDone)
}
function phraseB () {
radio.sendNumber(2)
music.play(music.stringPlayable("F F E E D D C - ", 120), music.PlaybackMode.UntilDone)
}
function phraseC () {
radio.sendNumber(3)
music.play(music.stringPlayable("G G F F E E D - ", 120), music.PlaybackMode.UntilDone)
}
input.onButtonPressed(Button.A, function () {
phraseA()
phraseB()
phraseC()
})
radio.onReceivedNumber(function (receivedNumber) {
if (receivedNumber == 1) {
robot.setColor(0xff0000)
wiggle()
wiggle()
} else if (receivedNumber == 2) {
robot.setColor(0x00ff00)
spin()
} else if (receivedNumber == 3) {
robot.setColor(0x0000ff)
shuffle()
shuffle()
}
})
robot.elecfreaksCuteBot.start()
radio.setGroup(1)

function wiggle () {
robot.motorTank(50, -50, 300)
robot.motorTank(-50, 50, 300)
robot.motorStop()
}
function spin () {
robot.motorTank(50, -50, 1200)
robot.motorStop()
}
function zigzag () {
robot.motorTank(50, 20, 500)
robot.motorTank(20, 50, 500)
robot.motorStop()
}
function phraseA () {
radio.sendNumber(1)
music.play(music.stringPlayable("E D C D E E E - ", 120), music.PlaybackMode.UntilDone)
}
function phraseB () {
radio.sendNumber(2)
music.play(music.stringPlayable("D D D - E G G - ", 120), music.PlaybackMode.UntilDone)
}
function phraseC () {
radio.sendNumber(3)
music.play(music.stringPlayable("E D C D E E E E ", 120), music.PlaybackMode.UntilDone)
}
input.onButtonPressed(Button.AB, function () {
phraseA()
phraseB()
phraseC()
})
radio.onReceivedNumber(function (receivedNumber) {
if (receivedNumber == 1) {
wiggle()
wiggle()
} else if (receivedNumber == 2) {
zigzag()
} else if (receivedNumber == 3) {
spin()
}
})
robot.elecfreaksCuteBot.start()
radio.setGroup(1)
Stretch: Give each robot its own part: robots with a role variable (lead or backup) do different moves for the same cue.
Support: Give phraseC complete; students add the dancer's branch and the new move.
Why does each phrase play its music until done before the next phrase starts?
So the next cue is only sent when the music reaches the next phrase. The robots then move in time with the tune.
Next: the robot talks back, sending an alert to a base station. Real-world links: drone light shows, stage lighting cues, a conductor and an orchestra, synchronised swimming.