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

🟧 micro:bit Examples: Laser Ranger 2-ch

Back to Laser Ranger 2-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 about 40 mA for the two lasers, so the micro:bit 3V pin (limit about 90 mA on V1, 190 mA on V2) may do; use external 5 V if readings are unstable 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 8-ch ranger; to use two rangers change one with the "change device address" block (Device group) —
Ready time ready (F3 b0) once both lasers are initialised, about 1 s; a failed sensor reads 120 cm 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 2-ch × micro:bit
Sensor micro:bit
SDA P20
SCL P19
VCC 3V (or external 5 V)
GND GND (the servo battery − goes here too)

The values used on this page

Distances are in cm (0..120); 120 = nothing in front (or that sensor failed). "Left / right" is seen from behind the robot.

Block JavaScript Range Meaning Used in
distance 2-ch nearest (cm) mbc.tof2NearestCm() 0~120 the nearer of the two 1, 2, 3
distance 2-ch left / right (cm / mm) mbc.tof2Distance(MbcTofSide.Left, MbcDistUnit.Cm) 0~120 / 0~1200 one sensor on its own 1, 2, 4, 5
on distance 2-ch nearer than … cm mbc.onTof2Near(10, ...) 事件 fires once when the nearer distance drops below the limit, again only after it has gone away 2, 5
distance 2-ch average (mm) mbc.tof2AverageMm() 0~1200 (left + right) ÷ 2 in mm (not used here; swap it in for finer numbers) —
wait for device at … ready mbc.waitReady(mbc.ADDR_TOF, 3000) true / false waits up to 3 s, true once both lasers are up (Advanced → Device) 1

Example 1: How far is it

What this example does: An LED bar shows how close the object in front is: the closer, the more LEDs. Press A to show the left sensor in cm, B the right one. Use it to check the wiring and that both lasers work.

What you need

  • micro:bit V1 or V2 + USB cable
  • Laser Ranger 2-ch (Universal I2C edition) + 4-pin cable
  • a book or a board as the target

Wiring: As in the wiring table above: SDA → P20, SCL → P19, VCC → 3V, GND → GND.

Download: ex01_show_distance.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 2-ch × micro:bit example 1: how far is it (LED bar + number)
// What it does: the closer your hand, the more LEDs light; press A to show the left sensor in cm, B the right one.
// Wiring: sensor SDA → P20, SCL → P19, VCC → 3V (or external 5 V), GND → GND.
// 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 at power-on; nothing in front → all dark; hand at 60 cm → half lit; within 10 cm → almost all lit.

let busy = false

if (mbc.waitReady(mbc.ADDR_TOF, 3000)) {                  // ready once both laser sensors are up
    basic.showIcon(IconNames.Yes)
} else {
    basic.showIcon(IconNames.No)                          // no answer: check P19 / P20 and power
}

basic.forever(function () {
    if (busy) {
        basic.pause(100)
        return
    }
    let d = mbc.tof2NearestCm()                           // the nearer of the two, 0..120 cm, 120 = nothing in front
    led.plotBarGraph(120 - d, 120)                        // the closer, the longer the bar
    basic.pause(100)
})

input.onButtonPressed(Button.A, function () {
    busy = true
    basic.showNumber(mbc.tof2Distance(MbcTofSide.Left, MbcDistUnit.Cm))    // the left sensor (seen from behind the robot)
    busy = false
})
input.onButtonPressed(Button.B, function () {
    busy = true
    basic.showNumber(mbc.tof2Distance(MbcTofSide.Right, MbcDistUnit.Cm))   // the right sensor
    busy = false
})

Step by step

  1. mbc.waitReady(mbc.ADDR_TOF, 3000): wait for both lasers to initialise, tick; X if no answer within 3 s.
  2. basic.forever: every 0.1 s read mbc.tof2NearestCm() (the nearer of the two, 0..120).
  3. led.plotBarGraph(120 - d, 120): the bar-graph block. 120 − d makes nearer objects a bigger number, so more LEDs.
  4. Buttons A / B: mbc.tof2Distance(MbcTofSide.Left, MbcDistUnit.Cm) reads one sensor and basic.showNumber scrolls it; busy pauses the bar meanwhile.

What you should see

  • Power-on: a tick.
  • Nothing in front: all dark (120).
  • Board at 60 cm: half lit; move in to 10 cm: almost all lit.
  • A and B: the two numbers should be about the same (board square-on).

FAQ

  • Always 120? → Target too far (over 120 cm), too small or too dark (black felt reflects nothing). Try a white book.
  • A or B is always 120? → That laser did not initialise or has failed. Read status bit 1 (any sensor failed) with the advanced Device blocks, then power-cycle.
  • 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: Parking sensor

What this example does: Starts beeping inside 40 cm, faster the closer you get; inside 10 cm an X appears (event block, once per approach). Press A to see whether the object is more to the left or the right.

What you need

  • Everything from example 1
  • On a V1 also a buzzer or headphones on P0

Wiring: Same as example 1.

Download: ex02_parking_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 2-ch × micro:bit example 2: parking sensor (faster beeps when closer)
// What it does: starts beeping inside 40 cm, faster as you get closer; inside 10 cm it shows an X. Press A to see whether the object is more to the left or the right.
// Wiring: sensor SDA → P20, SCL → P19, VCC → 3V, GND → GND. 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: hand approaching → beep … beep … beepbeepbeep; inside 10 cm → X; press A → an arrow toward the nearer side.

mbc.onTof2Near(10, function () {                          // fires once each time the nearer distance drops below 10 cm
    basic.showIcon(IconNames.No, 0)
})

basic.forever(function () {
    let d = mbc.tof2NearestCm()                           // 0..120 cm
    if (d < 40) {
        led.plotBarGraph(40 - d, 40)
        music.playTone(Note.A, 100)                       // beep for 0.1 s
        basic.pause(d * 10)                               // 30 cm waits 0.3 s, 10 cm waits 0.1 s: closer = faster
    } else {
        basic.showIcon(IconNames.Happy, 0)                // all clear
        basic.pause(100)
    }
})

input.onButtonPressed(Button.A, function () {
    let l = mbc.tof2Distance(MbcTofSide.Left, MbcDistUnit.Cm)
    let r = mbc.tof2Distance(MbcTofSide.Right, MbcDistUnit.Cm)
    if (l < r) {
        basic.showArrow(ArrowNames.West)                  // the left sensor is nearer
    } else if (r < l) {
        basic.showArrow(ArrowNames.East)
    } else {
        basic.showArrow(ArrowNames.North)                 // equal: straight ahead
    }
})

Step by step

  1. mbc.onTof2Near(10, ...): an event block. Runs once when the nearer distance first drops below 10 cm → X. It fires again only after the object has moved away and come back.
  2. basic.forever: read d = mbc.tof2NearestCm().
  3. d < 40: draw the bar with led.plotBarGraph, music.playTone(Note.A, 100) beeps for 0.1 s, then basic.pause(d * 10): 30 cm waits 0.3 s, 10 cm waits 0.1 s, so closer = faster.
  4. d >= 40: happy face, silence.
  5. Button A: compare the two sensors and show an arrow toward the nearer one; equal → up arrow.

What you should see

  • Hand approaching slowly: happy → beeping starts → faster and faster.
  • Inside 10 cm: an X flashes (then the bar carries on).
  • Hand to the left, press A: left arrow.

FAQ

  • The X only flashes briefly? → Normal, the next forever pass redraws the bar. To keep it longer add basic.pause(500) inside the event.
  • The beeping sounds choppy? → Try Note.C5 instead of Note.A and 50 instead of 100, or drop the sound and keep only the bar.

Example 3: Automatic barrier (servo)

What this example does: Something inside 15 cm → the barrier opens (servo to 90°); 2 s after it leaves the barrier closes (0°). A / B raise / lower the threshold by 5. Teaches "move the motor only when the state changes".

What you need

  • Everything from example 1
  • one 9 g servo (SG90) with a lolly stick as the barrier
  • a 4.8–6 V battery pack and jumper wires

Wiring: Sensor as in example 1. 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_servo_gate.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 2-ch × micro:bit example 3: automatic barrier (servo)
// What it does: something inside 15 cm → the barrier opens (servo to 90°); 2 s after it leaves the barrier closes (0°). A / B raise / lower the threshold by 5.
// Wiring: sensor SDA → P20, SCL → P19, VCC → 3V, 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 lolly stick as the barrier.
// You see: hand in front → barrier lifts, tick; hand away for 2 s → barrier drops, X.

let limit = 15                                            // inside this many cm counts as 'something there'
let lastSeen = -10000                                     // time (ms) something was last seen
let open = false

pins.servoWritePin(AnalogPin.P1, 0)                       // start closed
basic.showIcon(IconNames.No)

basic.forever(function () {
    let d = mbc.tof2NearestCm()
    if (d > 0 && d < limit) {
        lastSeen = control.millis()                       // remember the time
    }
    let wantOpen = control.millis() - lastSeen < 2000     // keep open for 2 s after the last sighting
    if (wantOpen != open) {                               // move the servo only when the state changes
        open = wantOpen
        pins.servoWritePin(AnalogPin.P1, open ? 90 : 0)
        basic.showIcon(open ? IconNames.Yes : IconNames.No, 0)
    }
    basic.pause(50)
})

input.onButtonPressed(Button.A, function () {
    limit = Math.constrain(limit + 5, 5, 100)
    basic.showNumber(limit)
})
input.onButtonPressed(Button.B, function () {
    limit = Math.constrain(limit - 5, 5, 100)
    basic.showNumber(limit)
})

Step by step

  1. limit = 15: the threshold; lastSeen: when something was last seen; open: is the barrier open now.
  2. At start pins.servoWritePin(AnalogPin.P1, 0) closes it.
  3. forever: if d is below the threshold, lastSeen = control.millis() (note the time in ms).
  4. wantOpen = now − lastSeen < 2000: seen within the last 2 s → "should be open".
  5. wantOpen != open: only when the wanted state differs from the current one move the servo and change the icon, so the servo does not twitch.
  6. A / B: limit ± 5, kept between 5 and 100 with Math.constrain, and the new threshold is shown.

What you should see

  • Power-on: barrier at 0°, X.
  • Hand within 15 cm: barrier lifts to 90°, tick.
  • Hand away: drops after 2 s, X.
  • Press A: shows 20, now it opens inside 20 cm.

FAQ

  • The barrier keeps opening and closing? → The object sits right at the threshold. Raise the threshold, or change 2000 to 3000 to keep it open longer.
  • Servo jitters, micro:bit resets? → Power the servo from the battery pack with a common ground, never from the 3V pin.

Example 4: Follow-me car

What this example does: The car keeps 20 cm from the object in front: too far → forward, too close → back, object to the left (right sensor farther) → turn left. A = start, B = stop. The difference between the two lasers is the direction.

What you need

  • A two-wheel car: two continuous-rotation servos (e.g. FS90R) as wheels plus a caster
  • the ranger at the front facing forward
  • a 4.8–6 V battery pack
  • an A4-sized board as the "person"

Wiring: Sensor as in example 1, mounted at the front facing forward. 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_follow_me.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 2-ch × micro:bit example 4: follow-me car
// What it does: the car keeps 20 cm from the object in front (your hand or a board): too far → forward, too close → back, object to the left → turn left. A = start, B = stop.
// Wiring: sensor SDA → P20, SCL → P19, VCC → 3V, 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 facing forward.
// You see: after A hold your hand 20 cm in front: move it back and the car follows, move it closer and the car reverses; take it away (over 60 cm) and the car stops with a puzzled face.

const TARGET = 20                                         // distance to keep (cm)
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.showIcon(IconNames.Happy, 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 l = mbc.tof2Distance(MbcTofSide.Left, MbcDistUnit.Cm)
    let r = mbc.tof2Distance(MbcTofSide.Right, MbcDistUnit.Cm)
    let d = Math.min(l, r)                                // the nearer one
    if (d >= 60) {
        drive(0, 0)                                       // too far: object gone, stop
        basic.showIcon(IconNames.Confused, 0)
    } else {
        let speed = Math.constrain((d - TARGET) * 4, -60, 60)   // farther than 20 cm → positive = forward; nearer → negative = back
        let turn = Math.constrain((r - l) * 2, -30, 30)         // right sensor farther → object is to the left → turn left
        drive(speed - turn, speed + turn)
        if (turn < -5) {
            basic.showArrow(ArrowNames.East, 0)
        } else if (turn > 5) {
            basic.showArrow(ArrowNames.West, 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: read left l and right r, d = Math.min(l, r).
  4. d >= 60: object gone → stop, puzzled face.
  5. speed = (d − 20) × 4: at 30 cm → +40 forward; at 10 cm → −40 back; Math.constrain keeps it within ±60.
  6. turn = (r − l) × 2: right farther → object to the left → positive turn → drive(speed − turn, speed + turn) left wheel slower = turn left. The arrow shows the direction.

What you should see

  • Press A, board 20 cm in front: car still, up arrow.
  • Move the board back: the car follows; bring it closer: the car reverses.
  • Move the board left: the car turns left.
  • Take the board away: stop, puzzled face.

FAQ

  • The car oscillates back and forth? → Change × 4 to × 3, or basic.pause(30) to 60.
  • It turns the wrong way? → Sensor mounted backwards (left and right swapped): change (r − l) to (l − r).
  • The car reverses after A? → Servos mounted the other way: flip the signs in drive.

Example 5: Obstacle-avoiding car (all together)

What this example does: The car drives forward; something inside 15 cm → back up, spin toward the more open side, carry on; the LEDs count the detours and a skull flashes (event) the moment something comes inside 15 cm. A = start, B = stop.

What you need

  • The car from example 4
  • a few boxes as obstacles

Wiring: Same as example 4.

Download: ex05_obstacle_avoid.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 2-ch × micro:bit example 5: obstacle-avoiding car (all together)
// What it does: the car drives forward; something inside 15 cm → back up, spin toward the more open side, carry on; the LEDs count the detours. A = start, B = stop.
// Wiring: as example 4 (sensor P19 / P20, left wheel P1, right wheel P2, servos on their own battery, common ground).
// Setup: the two-wheel car and a few boxes as obstacles.
// You see: after A the car drives, backs up before an obstacle, turns and continues; the number goes up by 1 each detour; a skull flashes the moment something comes inside 15 cm.

const STOP_CM = 15
let running = false
let detours = 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.onTof2Near(STOP_CM, function () {                     // event: flash once each time something comes inside 15 cm
    basic.showIcon(IconNames.Skull, 0)
})

input.onButtonPressed(Button.A, function () {
    detours = 0
    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 l = mbc.tof2Distance(MbcTofSide.Left, MbcDistUnit.Cm)
    let r = mbc.tof2Distance(MbcTofSide.Right, MbcDistUnit.Cm)
    if (Math.min(l, r) < STOP_CM) {
        detours += 1
        drive(-50, -50)                                   // back up for 0.4 s
        basic.pause(400)
        if (l > r) {
            drive(-40, 40)                                // left is more open → spin left
        } else {
            drive(40, -40)                                // spin right
        }
        basic.pause(500)
        basic.showNumber(detours)
    } else {
        drive(50, 50)                                     // clear ahead: straight
        basic.showArrow(ArrowNames.North, 0)
    }
    basic.pause(30)
})

Step by step

  1. STOP_CM = 15: inside this is an obstacle.
  2. mbc.onTof2Near(STOP_CM, ...): event, a skull flashes once per approach (runs separately from the main loop).
  3. forever: read l and r; Math.min(l, r) < STOP_CM → avoid.
  4. Avoid: detours + 1, drive(−50, −50) back for 0.4 s; l > r (left more open) → drive(−40, 40) spin left for 0.5 s, else spin right; show the count.
  5. Clear: drive(50, 50) straight, up arrow.

What you should see

  • Press A: the car drives; near a box → skull → back up → turn → shows 1 → carries on.
  • Box front-left: turns right; front-right: turns left.
  • Press B: stop.

FAQ

  • It does not turn enough and still hits? → Change basic.pause(500) to 700 to turn longer, or STOP_CM to 20 to react earlier.
  • Stuck going back and forth in a corner? → Neither side is open. Change the reverse time 400 to 800 to back up further before turning.

Next steps

Email for a quoteBuying Guide