This page has moved into the new guide: Ranger 8-Way › micro:bit › MakeCode

🟧 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)

Laser Ranger 8-ch × micro:bit
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

  1. mbc.waitReady(mbc.ADDR_TOF, 5000): the 8 lasers need 2–4 s to come up, so wait up to 5 s.
  2. forever: read dir = mbc.tof8NearestDirection() (−7..+7) and d = mbc.tof8Nearest(Cm).
  3. Draw only if dir is within ±7 and d < 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.
  4. for (y = 5 − h; y < 5; y++) led.plot(x, y): draw h LEDs from the bottom up.
  5. ±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

  1. ALARM_CM = 20, sound = true. B flips sound and shows S (sound) or M (muted).
  2. forever: read the nearest distance d and direction dir.
  3. d < 20 and Math.abs(dir) <= 7 (really something there): dir < −2 the three left sensors → left arrow + Note.C; dir > 2 the three right sensors → right arrow + Note.G; middle → up arrow + Note.C5.
  4. Each music.playTone is wrapped in if (sound), so muted means arrows only.
  5. 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 / 2 to −3 / 3 for 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

  1. forever: read direction dir and nearest distance d, default angle = 90.
  2. Something there (|dir| <= 7 and d < 120): angle = 90 + dir × 12, 12° per step, ±7 → 6°..174°.
  3. pins.servoWritePin(AnalogPin.P1, angle) every 50 ms.
  4. Button A: for n = 1..8, showString("S" + n) then showNumber(mbc.tof8Sensor(n, Cm)); busy pauses 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 × 12 to 90 − 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

  1. function drive(left, right): left wheel P1, right wheel P2, −100..100, positive = forward; the right servo is mirrored so it subtracts.
  2. A: running = true; B: stop.
  3. forever: side = mbc.tof8Sensor(1, Cm) (far left), front = mbc.tof8Front(Cm) (average of S4 and S5).
  4. front < 15: wall ahead → drive(40, −40) spin right, right arrow.
  5. Otherwise err = side − 15: positive = too far from the wall; turn = err × 3 limited 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 × 3 to × 2, or basic.pause(30) to 50.
  • It does not turn enough at corners? → While turning it only watches front and goes straight once that is clear. Change front < 15 to front < 25 to turn earlier.
  • Follow the right wall instead? → tof8Sensor(1, ...) → tof8Sensor(8, ...), drive(50 − turn, 50 + turn) → drive(50 + turn, 50 − turn), and spin left drive(−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

  1. mbc.onTof8Near(STOP_CM, ...): event, each time something comes inside 12 cm dodges + 1 and a skull flashes.
  2. forever: read near = nearest distance and open = mbc.tof8OpenDirection() (most open direction, negative = left).
  3. near < 12: drive(−40, −40) back for 0.4 s; open < 0 → drive(−40, 40) spin left for 0.5 s, else spin right.
  4. Otherwise turn = open × 8 (limited to ±40), drive(50 + turn, 50 − turn): open on the left (negative) → left wheel slower → veer left.
  5. 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? → × 8 is 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

Email for a quoteBuying Guide