🟧 micro:bit Examples: Laser Ranger 8-ch
Back to Laser Ranger 8-ch × micro:bit | Product page | Reference
This page is for people who have never written code. The 5 examples start with "show a value on the LEDs" and build up to "drive a car". Everything is written for the MakeCode web editor with the MBC extension pxt-mbc-sensors v2: switch to JavaScript, paste an example and it runs; switch back to Blocks to see which blocks it becomes.
Important
- Extension pxt-mbc-sensors v2 has not been verified on hardware yet. Every example on this page compiles with the MakeCode CLI (once for V1, once for V2); value directions, ready times and power are still to be confirmed on a real board, see "to be tested" in the hardware checklist below.
- Use the Universal I2C edition of the product. The SPIKE and EV3 editions have different firmware and cannot be read by a micro:bit.
Software
| Editor | micro:bit V1 | micro:bit V2 | How |
|---|---|---|---|
| MakeCode web editor (makecode.microbit.org, Blocks / JavaScript) | ✔ (less memory, but every example here fits) | ✔ | New Project → gear → Extensions → paste https://github.com/contactmbcrobot/pxt-mbc-sensors → switch to JavaScript (top) → paste the example → Download the .hex and drag it onto the MICROBIT drive |
| MakeCode offline app (Windows / Mac) | ✔ | ✔ | Same; adding the extension the first time needs internet |
| Python Editor (MicroPython) | — | — | no MBC module yet |
- Sound: V2 has a built-in speaker; a V1 needs a buzzer or headphones on P0.
- Servos / motors: the examples use
pins.servoWritePin: one 9 g servo (SG90) on P1; for driving, two continuous-rotation servos (e.g. FS90R), left wheel P1, right wheel P2. Always power servos from an external 4.8–6 V battery pack whose − is joined to the micro:bit GND (common ground); never drive servos from the micro:bit 3V pin. - Block names: with the editor language set to English the blocks read as in the tables below; the tables also give the JavaScript call.
Before you start: hardware checklist (to be tested)
The micro:bit is a 3.3 V board. Each check must pass before an MBC product is connected; "to be tested" marks items extension v2 has not yet confirmed on real hardware.
| Check | This product | Status |
|---|---|---|
| Voltage | MBC products use 3.3 V I2C levels: connect straight to P19 / P20, no level shifter | ✔ |
| Power | 8 lasers draw over 100 mA: external 5 V is required, never the micro:bit 3V pin (about 90 mA limit on V1) | to be tested |
| I2C pull-ups | the micro:bit already has 4.7 kΩ; if the product also has pull-ups, check the low level stays ≤ 0.3×VDD | to be tested |
| Clock stretching | the STM32 slave stretches the clock by default; the V2 (nRF52833) has a known issue with stretching, test on V1 and V2 | to be tested |
| Address clash | factory address 0x29, the same as the 2-ch ranger; to use two rangers change one with the "change device address" block (Device group) | — |
| Ready time | initialising the 8 lasers takes 2–4 s after power-on, then F3 b0 = 1; example 1 waits up to 5 s with "wait for device ready" | to be tested |
If you read nothing: check the wiring (SDA = P20, SCL = P19) → the external power → whether the "device at … is ready" block (Device group, advanced) returns true.
Wiring (the same for every example)
| Sensor | micro:bit |
|---|---|
| SDA | P20 |
| SCL | P19 |
| VCC | external 5 V (required) |
| GND | GND (the servo battery − goes here too) |
The values used on this page
The 8 lasers are 30° apart: S1 far left, S4 / S5 straight ahead, S8 far right (seen from behind the robot). Distances 0..120 cm, 120 = nothing that way. Directions −7..+7: 0 = straight ahead, negative = left.
| Block | JavaScript | Range | Meaning | Used in |
|---|---|---|---|---|
| distance 8-ch nearest (cm / mm) | mbc.tof8Nearest(MbcDistUnit.Cm) |
0~120 | the smallest of the 8 | 1, 2, 3, 5 |
| distance 8-ch nearest direction | mbc.tof8NearestDirection() |
−7~+7(±8 = 沒東西) | where the nearest object is | 1, 2, 3 |
| distance 8-ch most open direction | mbc.tof8OpenDirection() |
−7~+7 | the farthest (most open) direction | 5 |
| distance 8-ch front (cm) | mbc.tof8Front(MbcDistUnit.Cm) |
0~120 | average of S4 and S5 | 4 |
| distance 8-ch sensor n (cm) | mbc.tof8Sensor(1, MbcDistUnit.Cm) |
0~120 | one sensor, 1 = far left .. 8 = far right | 3, 4 |
| on distance 8-ch nearer than … cm | mbc.onTof8Near(12, ...) |
事件 | fires once when the nearest distance drops below the limit | 5 |
| wait for device at … ready | mbc.waitReady(mbc.ADDR_TOF, 5000) |
true / false | waits up to 5 s, true once all 8 are up (Advanced → Device) | 1 |
Example 1: Radar view
What this example does: One LED column: its left / right position = direction of the nearest object, its height = how close (closer = taller). Press A to show the nearest distance (cm), B the direction (−7..+7).
What you need
- micro:bit V1 or V2 + USB cable
- Laser Ranger 8-ch (Universal I2C edition) + 4-pin cable
- an external 5 V supply (power bank or battery pack)
- a book as the target
Wiring: As in the wiring table above: SDA → P20, SCL → P19, VCC → external 5 V, GND → GND (the external supply − must also go to micro:bit GND).
Download: ex01_radar.ts (right-click, save) → MakeCode New Project → gear → Extensions → paste https://github.com/contactmbcrobot/pxt-mbc-sensors → switch to JavaScript (top) → select all, delete, paste the file → Download and drag the .hex onto the MICROBIT drive.
Code
// Distance sensor 8-ch × micro:bit example 1: radar view (where the nearest object is and how close)
// What it does: one LED column: its left / right position = direction of the nearest object, its height = how close (closer = taller). Press A to show the nearest distance (cm), B the direction (−7..+7).
// Wiring: sensor SDA → P20, SCL → P19, VCC → external 5 V (8 lasers draw too much for the micro:bit 3V pin), GND → GND (common ground).
// Setup: MakeCode new project → Extensions → paste https://github.com/contactmbcrobot/pxt-mbc-sensors → switch to JavaScript, paste this whole file → download to the micro:bit.
// You see: a tick after 2–4 s (all 8 lasers up); hand front-left → column on the left; straight ahead → middle; closer = taller; nothing around → all dark.
let busy = false
if (mbc.waitReady(mbc.ADDR_TOF, 5000)) { // the 8 lasers take about 2–4 s to start
basic.showIcon(IconNames.Yes)
} else {
basic.showIcon(IconNames.No) // no answer: check P19 / P20 and the external power
}
basic.forever(function () {
if (busy) {
basic.pause(100)
return
}
let dir = mbc.tof8NearestDirection() // −7 (far left) .. +7 (far right), 0 = straight ahead; ±8 = nothing around
let d = mbc.tof8Nearest(MbcDistUnit.Cm) // the nearest of the 8, 0..120 cm
basic.clearScreen()
if (dir >= -7 && dir <= 7 && d < 120) {
let x = Math.round(Math.map(dir, -7, 7, 0, 4)) // direction → column 0..4
let h = Math.round(Math.map(d, 0, 120, 5, 1)) // distance → height 1..5
for (let y = 5 - h; y < 5; y++) {
led.plot(x, y)
}
}
basic.pause(50)
})
input.onButtonPressed(Button.A, function () {
busy = true
basic.showNumber(mbc.tof8Nearest(MbcDistUnit.Cm))
busy = false
})
input.onButtonPressed(Button.B, function () {
busy = true
basic.showNumber(mbc.tof8NearestDirection())
busy = false
})Step by step
mbc.waitReady(mbc.ADDR_TOF, 5000): the 8 lasers need 2–4 s to come up, so wait up to 5 s.forever: readdir = mbc.tof8NearestDirection()(−7..+7) andd = mbc.tof8Nearest(Cm).- Draw only if
diris within ±7 andd < 120:x = Math.map(dir, −7, 7, 0, 4)turns the direction into column 0..4;h = Math.map(d, 0, 120, 5, 1)turns the distance into a height of 1..5. for (y = 5 − h; y < 5; y++) led.plot(x, y): draw h LEDs from the bottom up.- ±8 or 120 = nothing around:
basic.clearScreen().
What you should see
- A tick 2–4 s after power-on.
- Book front-left at 30 cm: column on the left, about 4 high; move it straight ahead: middle column.
- Move it 1 m away: 1 LED left; remove it: all dark.
FAQ
- An X at power-on? → The external 5 V is off, or its − is not joined to micro:bit GND. This product cannot run from the micro:bit 3V pin.
- The column is on the wrong side? → The sensor is mounted backwards (S1 must be on the left). Turn it 180°, do not change the code.
- An X right at power-on (sensor not found)? → Check SDA = P20 and SCL = P19 are not swapped, that the external power is on, and with crocodile clips that no clip touches the neighbouring pad.
- All zeros in the simulator? → Normal. The MakeCode simulator has no real I2C, every read is 0; download to the micro:bit to see real values.
- No sound on a V1? → The V1 has no speaker; connect a buzzer or headphones between P0 and GND.
Example 2: Left / centre / right alarm
What this example does: Something inside 20 cm: on the left → left arrow + low note, ahead → up arrow + high note, on the right → right arrow + middle note; nothing → happy face. B toggles the sound.
What you need
- Everything from example 1
- On a V1 also a buzzer or headphones on P0
Wiring: Same as example 1.
Download: ex02_sector_alarm.ts (right-click, save) → MakeCode New Project → gear → Extensions → paste https://github.com/contactmbcrobot/pxt-mbc-sensors → switch to JavaScript (top) → select all, delete, paste the file → Download and drag the .hex onto the MICROBIT drive.
Code
// Distance sensor 8-ch × micro:bit example 2: left / centre / right alarm
// What it does: something inside 20 cm: on the left → left arrow + low note, ahead → up arrow + high note, on the right → right arrow + middle note; nothing → happy face. B toggles the sound.
// Wiring: sensor SDA → P20, SCL → P19, VCC → external 5 V, GND → GND (common ground). On a V1 connect a buzzer or headphones to P0 for sound (V2 has a speaker).
// Setup: extension and paste steps as in example 1.
// You see: move your hand around the front of the sensor and the arrow and pitch change side; hand far away → happy face, silence.
const ALARM_CM = 20
let sound = true
input.onButtonPressed(Button.B, function () {
sound = !sound
basic.showString(sound ? "S" : "M") // S = sound on, M = muted
})
basic.forever(function () {
let d = mbc.tof8Nearest(MbcDistUnit.Cm)
let dir = mbc.tof8NearestDirection()
if (d < ALARM_CM && Math.abs(dir) <= 7) {
if (dir < -2) { // the three left sensors
basic.showArrow(ArrowNames.West, 0)
if (sound) {
music.playTone(Note.C, 200)
}
} else if (dir > 2) { // the three right sensors
basic.showArrow(ArrowNames.East, 0)
if (sound) {
music.playTone(Note.G, 200)
}
} else { // straight ahead (sensors 4 and 5)
basic.showArrow(ArrowNames.North, 0)
if (sound) {
music.playTone(Note.C5, 200)
}
}
} else {
basic.showIcon(IconNames.Happy, 0)
}
basic.pause(100)
})Step by step
ALARM_CM = 20,sound = true. B flipssoundand shows S (sound) or M (muted).forever: read the nearest distancedand directiondir.d < 20andMath.abs(dir) <= 7(really something there):dir < −2the three left sensors → left arrow +Note.C;dir > 2the three right sensors → right arrow +Note.G; middle → up arrow +Note.C5.- Each
music.playToneis wrapped inif (sound), so muted means arrows only. - Nothing: happy face. One pass every 0.1 s.
What you should see
- Hand on the left at 15 cm: left arrow, low note repeating.
- Move it straight ahead: up arrow, high note.
- Move it away: happy, silent. Press B → M, now only arrows.
FAQ
- The direction flickers? → When two lasers read nearly the same distance the nearest direction flips between them. Change
−2/2to−3/3for a wider middle zone. - No sound? → A V1 needs a buzzer; make sure the screen shows S, not M.
Example 3: Radar head (a servo points at the nearest object)
What this example does: A servo with a paper arrow keeps pointing at the nearest object; nothing around → back to centre. Press A to show the 8 sensors in cm one by one (S1 → S8).
What you need
- Everything from example 1
- one 9 g servo (SG90) with a paper arrow
- a 4.8–6 V battery pack and jumper wires
Wiring: Sensor as in example 1 (external 5 V). Servo orange (signal) → P1, red → external 4.8–6 V battery +, brown → battery −, and run a second wire from battery − to micro:bit GND (common ground).
Download: ex03_pan_servo.ts (right-click, save) → MakeCode New Project → gear → Extensions → paste https://github.com/contactmbcrobot/pxt-mbc-sensors → switch to JavaScript (top) → select all, delete, paste the file → Download and drag the .hex onto the MICROBIT drive.
Code
// Distance sensor 8-ch × micro:bit example 3: radar head (a servo points at the nearest object)
// What it does: a servo with an arrow keeps pointing at the nearest object; nothing around → back to centre. Press A to show the 8 sensors in cm one by one (S1 = far left .. S8 = far right).
// Wiring: sensor SDA → P20, SCL → P19, VCC → external 5 V, GND → GND. Servo orange (signal) → P1, red → external 4.8–6 V battery +, brown → battery − joined to micro:bit GND.
// Setup: a 9 g servo (SG90) with a paper arrow.
// You see: move your hand from left to right and the arrow follows; take it away → back to 90°.
let busy = false
basic.forever(function () {
if (busy) {
basic.pause(100)
return
}
let dir = mbc.tof8NearestDirection() // −7..+7, negative = left; ±8 = nothing
let d = mbc.tof8Nearest(MbcDistUnit.Cm)
let angle = 90
if (Math.abs(dir) <= 7 && d < 120) {
angle = 90 + dir * 12 // 12° per step: ±7 → 6°..174°
}
pins.servoWritePin(AnalogPin.P1, angle)
basic.pause(50)
})
input.onButtonPressed(Button.A, function () {
busy = true
for (let n = 1; n <= 8; n++) {
basic.showString("S" + n) // sensor n
basic.showNumber(mbc.tof8Sensor(n, MbcDistUnit.Cm))
}
busy = false
})Step by step
forever: read directiondirand nearest distanced, defaultangle = 90.- Something there (
|dir| <= 7andd < 120):angle = 90 + dir × 12, 12° per step, ±7 → 6°..174°. pins.servoWritePin(AnalogPin.P1, angle)every 50 ms.- Button A:
for n = 1..8,showString("S" + n)thenshowNumber(mbc.tof8Sensor(n, Cm));busypauses the servo loop meanwhile.
What you should see
- Move your hand from left to right: the arrow follows.
- Take it away: back to 90°.
- Press A: S1 … number … S2 … up to S8; the sensor facing your hand reads the smallest number.
FAQ
- The arrow turns the wrong way? → The servo is mounted the other way: change
90 + dir × 12to90 − dir × 12. - The servo jumps about? → As in example 2, the nearest direction flips between two sensors. Add a simple filter:
angle = (angle + newAngle) / 2.
Example 4: Wall following (left wall)
What this example does: The car follows the wall on its left: the leftmost sensor S1 keeps it 15 cm from the wall (too far → drift left, too close → veer right); a wall within 15 cm ahead → spin right. A = start, B = stop.
What you need
- A two-wheel car: two continuous-rotation servos (e.g. FS90R) as wheels plus a caster
- the 8-ch ranger at the front (S1 facing left)
- a 4.8–6 V battery pack (servos) and external 5 V (sensor)
- a wall or a row of boxes
Wiring: Sensor as in example 1 (external 5 V), mounted at the front: S1 facing left, S4 / S5 straight ahead, S8 facing right. Left continuous-rotation servo signal → P1, right → P2; both servo red wires to the 4.8–6 V battery pack +, brown to battery −, and battery − also to micro:bit GND.
Download: ex04_wall_follow.ts (right-click, save) → MakeCode New Project → gear → Extensions → paste https://github.com/contactmbcrobot/pxt-mbc-sensors → switch to JavaScript (top) → select all, delete, paste the file → Download and drag the .hex onto the MICROBIT drive.
Code
// Distance sensor 8-ch × micro:bit example 4: wall following (left wall)
// What it does: the car follows the wall on its left, using the leftmost sensor (S1) to stay 15 cm from it; a wall within 15 cm ahead → spin right. A = start, B = stop.
// Wiring: sensor SDA → P20, SCL → P19, VCC → external 5 V, GND → GND. Left continuous-rotation servo signal → P1, right → P2; servos on a 4.8–6 V battery pack whose − is joined to micro:bit GND.
// Setup: a two-wheel car with the sensor at the front (S1 facing left, S4 / S5 facing forward); a wall or a row of boxes.
// You see: after A the car runs along the left wall, drifting back when too far and away when too close; at a corner ahead it turns right and carries on.
const WALL_CM = 15
let running = false
// left servo P1, right servo P2 (continuous rotation); left / right = −100..100, positive = forward
function drive(left: number, right: number): void {
left = Math.constrain(left, -100, 100)
right = Math.constrain(right, -100, 100)
pins.servoWritePin(AnalogPin.P1, Math.round(90 + left * 0.9)) // 90 = stop, 180 = full forward, 0 = full reverse
pins.servoWritePin(AnalogPin.P2, Math.round(90 - right * 0.9)) // the right servo is mounted mirrored, so subtract
}
input.onButtonPressed(Button.A, function () {
running = true
basic.showArrow(ArrowNames.North, 0)
})
input.onButtonPressed(Button.B, function () {
running = false
drive(0, 0)
basic.showIcon(IconNames.No, 0)
})
basic.forever(function () {
if (!running) {
basic.pause(100)
return
}
let side = mbc.tof8Sensor(1, MbcDistUnit.Cm) // sensor 1 = far left
let front = mbc.tof8Front(MbcDistUnit.Cm) // straight ahead (average of sensors 4 and 5)
if (front < WALL_CM) {
drive(40, -40) // wall ahead: spin right
basic.showArrow(ArrowNames.East, 0)
} else {
let err = side - WALL_CM // positive = too far from the wall
let turn = Math.constrain(err * 3, -30, 30)
drive(50 - turn, 50 + turn) // too far → left wheel slower → drift left
if (turn > 5) {
basic.showArrow(ArrowNames.NorthWest, 0)
} else if (turn < -5) {
basic.showArrow(ArrowNames.NorthEast, 0)
} else {
basic.showArrow(ArrowNames.North, 0)
}
}
basic.pause(30)
})Step by step
function drive(left, right): left wheel P1, right wheel P2, −100..100, positive = forward; the right servo is mirrored so it subtracts.- A:
running = true; B: stop. forever:side = mbc.tof8Sensor(1, Cm)(far left),front = mbc.tof8Front(Cm)(average of S4 and S5).front < 15: wall ahead →drive(40, −40)spin right, right arrow.- Otherwise
err = side − 15: positive = too far from the wall;turn = err × 3limited to ±30;drive(50 − turn, 50 + turn): too far → left wheel slower → drift left; too close → the opposite. The arrow shows north-west / north-east / north.
What you should see
- Car about 15 cm to the right of the wall, nose parallel: press A and it runs along the wall.
- Push it away from the wall: it drifts back; push it closer: it veers away.
- A corner ahead: it turns right and follows the new wall.
FAQ
- It snakes? → Change
× 3to× 2, orbasic.pause(30)to 50. - It does not turn enough at corners? → While turning it only watches
frontand goes straight once that is clear. Changefront < 15tofront < 25to turn earlier. - Follow the right wall instead? →
tof8Sensor(1, ...)→tof8Sensor(8, ...),drive(50 − turn, 50 + turn)→drive(50 + turn, 50 − turn), and spin leftdrive(−40, 40)at a wall ahead.
Example 5: Auto explore (all together)
What this example does: The car keeps steering toward the most open direction; something inside 12 cm → back up and spin toward the open side; a skull flashes and a counter goes up (event) the moment something comes inside 12 cm. A = start, B = stop and show the count.
What you need
- The car from example 4
- a few boxes arranged as a simple maze
Wiring: Same as example 4.
Download: ex05_explore.ts (right-click, save) → MakeCode New Project → gear → Extensions → paste https://github.com/contactmbcrobot/pxt-mbc-sensors → switch to JavaScript (top) → select all, delete, paste the file → Download and drag the .hex onto the MICROBIT drive.
Code
// Distance sensor 8-ch × micro:bit example 5: auto explore (head for the most open direction, all together)
// What it does: the car keeps steering toward the most open direction; something inside 12 cm → back up and spin toward the open side; a skull flashes and a counter goes up each time. A = start, B = stop.
// Wiring: as example 4 (sensor P19 / P20, external 5 V; left wheel P1, right wheel P2, servos on their own battery, common ground).
// Setup: the two-wheel car and a few boxes arranged as a maze.
// You see: after A the car wanders between the boxes without hitting them; press B to stop and see how many times it dodged.
const STOP_CM = 12
let running = false
let dodges = 0
// left servo P1, right servo P2 (continuous rotation); left / right = −100..100, positive = forward
function drive(left: number, right: number): void {
left = Math.constrain(left, -100, 100)
right = Math.constrain(right, -100, 100)
pins.servoWritePin(AnalogPin.P1, Math.round(90 + left * 0.9)) // 90 = stop, 180 = full forward, 0 = full reverse
pins.servoWritePin(AnalogPin.P2, Math.round(90 - right * 0.9)) // the right servo is mounted mirrored, so subtract
}
mbc.onTof8Near(STOP_CM, function () { // event: once each time something comes inside 12 cm
dodges += 1
basic.showIcon(IconNames.Skull, 0)
})
input.onButtonPressed(Button.A, function () {
dodges = 0
running = true
basic.showArrow(ArrowNames.North, 0)
})
input.onButtonPressed(Button.B, function () {
running = false
drive(0, 0)
basic.showNumber(dodges)
})
basic.forever(function () {
if (!running) {
basic.pause(100)
return
}
let near = mbc.tof8Nearest(MbcDistUnit.Cm)
let open = mbc.tof8OpenDirection() // most open direction −7..+7, negative = left
if (near < STOP_CM) {
drive(-40, -40) // back up for 0.4 s
basic.pause(400)
if (open < 0) {
drive(-40, 40) // open side on the left → spin left
} else {
drive(40, -40)
}
basic.pause(500)
} else {
let turn = Math.constrain(open * 8, -40, 40) // open on the left (negative) → left wheel slower → veer left
drive(50 + turn, 50 - turn)
basic.showArrow(ArrowNames.North, 0)
}
basic.pause(30)
})Step by step
mbc.onTof8Near(STOP_CM, ...): event, each time something comes inside 12 cmdodges + 1and a skull flashes.forever: readnear = nearest distanceandopen = mbc.tof8OpenDirection()(most open direction, negative = left).near < 12:drive(−40, −40)back for 0.4 s;open < 0→drive(−40, 40)spin left for 0.5 s, else spin right.- Otherwise
turn = open × 8(limited to ±40),drive(50 + turn, 50 − turn): open on the left (negative) → left wheel slower → veer left. - B: stop and
showNumber(dodges).
What you should see
- Press A: the car wanders between the boxes, heading for open space.
- About to hit: skull, back up, turn, carry on.
- Press B: shows the dodge count.
FAQ
- It keeps turning and never goes straight? →
× 8is too strong, change to× 4. - Stuck in a dead end? → Change the reverse time 400 to 800 and the spin 500 to 900 (about 180°).
Next steps
- Every block, value and hardware note: Laser Ranger 8-ch × micro:bit
- What each value id means: Reference
- Extension source and issues: https://github.com/contactmbcrobot/pxt-mbc-sensors