7:Lesson:Robot PU Sensors (Observation)
Robot PU “senses” the world using a mix of:
- micro:bit built-in sensors (IMU, buttons, microphone)
- Robot PU add-on sensors (ultrasonic sonar) This lesson shows which sensor APIs you can use and how to build simple observation behaviors. Knowledge
https://makecode.microbit.org/types
https://makecode.microbit.org/javascript/types
https://arcade.makecode.com/types
https://microbit.org/get-started/features/sensors/
1. What sensors are available?
A. micro:bit motion (IMU)
The micro:bit has an accelerometer (and magnetometer depending on board/runtime). In MakeCode you can read motion using:
input.isGesture(Gesture.FreeFall)input.isGesture(Gesture.Shake)input.rotation(Rotation.Roll)/input.rotation(Rotation.Pitch)Robot PU internally uses FreeFall detection as part of its safety behavior (see the updateStates() logic in the extension). B. micro:bit buttonsinput.onButtonPressed(Button.A, ...)input.onButtonPressed(Button.B, ...)input.onButtonPressed(Button.AB, ...)Buttons are useful for manual control / testing. C. micro:bit microphone (sound level)input.soundLevel()returns 0–255 Robot PU uses sound level in some behaviors (for example, some dance/rest behaviors react to audio). D. Ultrasonic sonar (distance) Robot PU includes an HCSR04 ultrasonic sensor interface. In this extension, you can read it using:robotPu.sonarDistanceCm()Wiring note (default pins used by the extension): Trigger:P2Echo:P8
2. Example: show sonar distance on the LED display
basic.forever(function () {
const cm = robotPu.sonarDistanceCm()
basic.showNumber(Math.round(cm))
basic.pause(200)
})
3. Example: obstacle stop / backup (sonar)
This is a simple reactive behavior:
- If something is too close, stop and back up / turn
- Otherwise, keep walking forward
basic.forever(function () {
const cm = robotPu.sonarDistanceCm()
if (cm > 0 && cm < 20) {
// Too close: turn away
for (let i = 0; i < 200; i++) {
robotPu.walk(-2, 0)
}
for (let i = 0; i < 200; i++) {
robotPu.walk(2, 0.8)
}
} else {
// Clear: walk forward
robotPu.walk(2, 0)
}
})
Notes:
robotPu.walk(...) is an action that advances when you call it repeatedly.
Sonar readings can be noisy; consider averaging if you see jitter.
4. Example: fall / free-fall safety response (IMU)
The micro:bit can detect a free-fall gesture.
You can use this to stop movement and return to a safe pose:
basic.forever(function () {
if (input.isGesture(Gesture.FreeFall)) {
// Try to stop motion and recover pose
for (let i = 0; i < 200; i++) {
robotPu.stand()
}
} else {
robotPu.walk(2, 0)
}
})
5. Example: clap to jump (microphone)
basic.forever(function () {
const s = input.soundLevel()
if (s > 140) {
// One jump (call repeatedly until you see completion boundaries)
for (let i = 0; i < 200; i++) {
robotPu.jump()
}
}
})
6.Example: send the front distance array via radio (key/value pairs)
This example uses two micro:bits:
- Robot PU micro:bit = sender
- Gamepad micro:bit = receiver
The sender transmits 5 values using radio.sendValue(key, value).
A. Sender (Robot PU) code
radio.onReceivedString(function (receivedString) {
robotPu.runStringCommand(receivedString)
})
radio.onReceivedValue(function (name, value) {
robotPu.runKeyValueCommand(name, value)
})
let d: number[] = []
robotPu.setChannel(166)
basic.forever(function () {
d = robotPu.frontDistanceArray()
radio.sendValue("fd0", d[0])
radio.sendValue("fd1", d[1])
radio.sendValue("fd2", d[2])
radio.sendValue("fd3", d[3])
radio.sendValue("fd4", d[4])
radio.sendValue("broll", robotPu.bodyRoll())
radio.sendValue("bpitch", robotPu.bodyPitch())
basic.pause(100)
})
Notes:
robotPu.frontDistanceArray()returns 5 bins from left-to-right across the front view.- If you’re already using a specific radio group/channel elsewhere, keep them consistent on both devices.
B. Receiver (Gamepad) code
The receiver listens for the 5 keys and plots them as 5 columns on the 5×5 LED display.
radio.setGroup(166)
let d: number[] = [0, 0, 0, 0, 0]
let minD = 0
function clampInt(x: number, lo: number, hi: number): number {
if (x < lo) return lo
if (x > hi) return hi
return x
}
function updateMinDistance(): void {
minD = d[0]
for (let i = 1; i < 5; i++) {
if (d[i] < minD) minD = d[i]
}
}
ffunction drawDistances () {
basic.clearScreen()
for (let x2 = 0; x2 <= 4; x2++) {
h = Math.map(d[x2], 2, 50, 5, 0)
for (let y2 = 4; y2 >= h; y2--) {
led.plot(x2, y2)
}
}
}
radio.onReceivedValue(function (name: string, value: number) {
if (name == "fd0") d[0] = value
else if (name == "fd1") d[1] = value
else if (name == "fd2") d[2] = value
else if (name == "fd3") d[3] = value
else if (name == "fd4") d[4] = value
})
basic.forever(function () {
const distance = clampInt(minD, 0, 100)
// Closer = Higher Frequency
let pitch = Math.map(distance, 2, 100, 2000, 200);
// Closer = Faster Beeps
let pulseDelay = Math.map(distance, 2, 100, 100, 800);
// Play the ping
music.playTone(pitch, 50);
// Wait before the next pulse
basic.pause(pulseDelay);
})
Notes:
- The LED visualization maps distance (0–100cm) into a column height.
- You can tune the display mapping by changing the
100cm max range.
7. Summary
- Use
robotPu.sonarDistanceCm()to measure distance in cm. - Use
input.isGesture(…)andinput.rotation(…)for motion sensing. - Use
input.soundLevel()for sound-reactive behaviors. - Use buttons for simple manual triggers during testing.