Ranger 8-Way (TOF8) × micro:bit × MakeCode
Interactive tutorialmicro:bit
First time? Try the interactive tutorial in your browser first, then follow the steps below with your hub.
This page covers MakeCode (blocks / JavaScript) only: how to set it up for the Ranger 8-Way (TOF8) on BBC micro:bit V1 / V2, how to read every value, the commands it supports and examples. Use the switcher above to change product, host or software.
Which edition and how to connect
Get the Universal I2C edition and connect it to the I2C header of a micro:bit breakout (SDA = P20, SCL = P19), factory address 0x29. It must use an external 5 V supply (8 lasers measure at once, more current than the micro:bit 3V pin can supply), not the micro:bit 3V pin; share the supply GND with the micro:bit.
Setup
What you need
- Sensor: Ranger 8-Way (TOF8) (Universal I2C edition). SPIKE and EV3 editions run different firmware and cannot be read by a micro:bit.
- Board: BBC micro:bit V1 or V2, plus a breakout board or crocodile-clip adapter to reach P19 / P20.
- Software: MakeCode for micro:bit in the browser (makecode.microbit.org, blocks / JavaScript); the offline app (Windows / Mac) also works, but adding an extension the first time needs internet.
- Extension: pxt-mbc-sensors v2 (MIT, nothing to download, just paste the URL).
Important
Bench test pending: extension v2.0.5 compiles in MakeCode (V1 + V2) but has not yet been checked block by block on real hardware. Block names follow the GitHub release.
Install the software
- Open makecode.microbit.org → New Project.
- Traditional Chinese block names are included: switch the editor language (gearwheel → Language) if you prefer.
Make the software see the sensor
- Click Advanced → Extensions at the bottom of the toolbox (also in the gearwheel menu).
- Paste
https://github.com/contactmbcrobot/pxt-mbc-sensorsinto the search box and press Enter. - Click the mbc-sensors card. An "MBC Sensors" category appears with six groups: Line, Distance, Gamepad, IMU, Camera and Device.
- To use an example: switch to JavaScript at the top right → paste the example → download the
.hexand drag it onto the MICROBIT drive.
Tip
No approval, no download: teachers just hand the URL to students. To pin a version, paste
https://github.com/contactmbcrobot/pxt-mbc-sensors#v2.0.5.
Wiring
The micro:bit I2C pins are fixed: P19 = SCL, P20 = SDA (on the edge connector, so you need a breakout board or clip adapter). On the MBC 4-pin sensor cable TX goes to SCL and RX to SDA, exactly as when wiring to an Arduino.
| Sensor | micro:bit | Note |
|---|---|---|
| SCL (TX) | P19 | I2C clock |
| SDA (RX) | P20 | I2C data |
| VCC | 3V or external 5 V | power-hungry products must not draw from the micro:bit 3V pin |
| GND | GND | with external power, share GND with the micro:bit |
- 3V pin current: V1 about 90 mA, V2 about 190 mA; on batteries the rail can drop to just over 2 V. Ranger 8-way, Controller PS4 / PS5 and the SharpShot must use external 5 V; other products can try 3V first, with external 5 V recommended on batteries.
- Logic level: MBC product I2C lines are 3.3 V, compatible with the micro:bit without a level shifter.
- This product's factory address is
0x29; products with different addresses can share the same P19 / P20 bus.
Wait 2~4 seconds after power-on
The Ranger 8-Way needs no calibration; plug it in and go. After power-on, wait 2~4 seconds for the 8 lasers to get ready; meanwhile everything reads 120 (cm). Start your program with a short wait before reading distances.
| Channel | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
|---|---|---|---|---|---|---|---|---|
| Facing | left | left-front 60° | left-front 30° | front | front | right-front 30° | right-front 60° | right |
The table assumes the sensor faces forward with the components up. Put your hand on the robot's left: example 1 should show a negative direction. If it shows a positive one, the sensor is mounted the other way, and "turn left" / "turn right" in the examples must be swapped too.
Important
The Ranger 8-Way must use external 5 V power (8 lasers ranging at once draw more than the 3V pin can supply); it cannot run from the micro:bit 3V pin. Share GND between the external supply and the micro:bit.
First test
- Check the wiring first with the "Device → wait for device at 0x29 ready" or "device at 0x29 is ready" block.
- Download the
.hexof example 1 on this page to the micro:bit. - If the number on the LEDs changes with what is in front of the sensor, everything is connected.
FAQ
- Values are always 0? With no device connected the reporter blocks return 0 (the internal −32768 is filtered), every yes / no block returns false, and nothing throws. Check in order: wiring (SDA = P20, SCL = P19) → external power on → "device at … is ready" is true.
- On a V1, the compass and accelerometer stop working too? On V1 the external I2C bus is shared with the onboard accelerometer, so a sensor holding SDA low also kills them. V2 has a separate external bus.
- Works on and off? STM32 products (Pathfinder, Ranger, PS2, IMU) clock-stretch, and the nRF52 on the V2 has a known clock-stretching issue (errata 219), so V1 and V2 both need a bench test. ESP32 products (PS4, SharpShot) do not stretch; the extension already waits 2 ms after writing the value id.
- Two products of the same kind? They share an address: first change one with "Device → change device at … to address …" (applied after reboot), then tell the extension with that product's "use address" block.
Reading values
After adding pxt-mbc-sensors, find the blocks in the MBC Sensors category; the JavaScript form is shown too, address 0x29.
nearest distance (cm) nearCm
| Range | Meaning |
|---|---|
0~120 cm |
smallest of the 8 distances, 0~120 cm (a failed sensor counts as 120); 120 = nothing around |
(distance 8-ch nearest \([cm v]\) :: #00A4E4)
let nearCm = mbc.tof8Nearest(MbcDistUnit.Cm) // nearest distance (cm):0~120 cmRelated block "on distance 8-ch nearer than 10 cm"
mbc.onTof8Near(10, function () {
})Returns 0 when the sensor does not answer; check with "device at … is ready" first.
nearest direction nearDir
| Range | Meaning |
|---|---|
-8~+8 |
direction of the nearest object: −7 (left) to +7 (right), 0 = straight ahead, negative = left; ±8 = nothing around (keeps the last side) |
(distance 8-ch nearest direction :: #00A4E4)
let nearDir = mbc.tof8NearestDirection() // nearest direction:-8~+8Returns 0 when the sensor does not answer; check with "device at … is ready" first.
farthest distance (cm) farCm
| Range | Meaning |
|---|---|
0~120 cm |
largest of the 8 distances, 0~120 cm (a failed sensor always reads 120 and looks 'farthest') |
(distance 8-ch most open \(cm\) :: #00A4E4)
let farCm = mbc.tof8OpenCm() // farthest distance (cm):0~120 cmReturns 0 when the sensor does not answer; check with "device at … is ready" first.
farthest direction farDir
| Range | Meaning |
|---|---|
-7~+7 |
direction of the most open side: −7 to +7, 0 = straight ahead, negative = left; 0 when all 8 read 120 |
(distance 8-ch most open direction :: #00A4E4)
let farDir = mbc.tof8OpenDirection() // farthest direction:-7~+7Returns 0 when the sensor does not answer; check with "device at … is ready" first.
front distance (cm) frontCm
| Range | Meaning |
|---|---|
0~120 cm |
average of sensors 4 and 5 (both facing forward), 0~120 cm; EV3 mode 3 and SPIKE mode 6 carry the same thing in mm; 0x22 'C' is min(4, 5), not the average (see 10) |
(distance 8-ch front \([cm v]\) :: #00A4E4)
let frontCm = mbc.tof8Front(MbcDistUnit.Cm) // front distance (cm):0~120 cmReturns 0 when the sensor does not answer; check with "device at … is ready" first.
nearest distance (mm) nearMm
| Range | Meaning |
|---|---|
0~1200 mm |
smallest of the 8 mm readings, 0~1200 (failed sensor counts as 1200); 1200 = nothing around |
(distance 8-ch nearest \([mm v]\) :: #00A4E4)
let nearMm = mbc.tof8Nearest(MbcDistUnit.Mm) // nearest distance (mm):0~1200 mmReturns 0 when the sensor does not answer; check with "device at … is ready" first.
init bitmap initOk
| Range | Meaning |
|---|---|
0~255 bit |
bit0 = sensor 1 (left) … bit7 = sensor 8; 1 = initialised at power-on (8 sensors take |
No dedicated block; in JavaScript read it with mbc.readValue(address, id) (−32768 when nothing answers). Related block: "distance 8-ch sensor 1 is OK".
let initOk = mbc.readValue(0x29, 0x07) // init bitmap:0~255 bitfault bitmap fault
| Range | Meaning |
|---|---|
0~255 bit |
bit0 = sensor 1 … bit7 = sensor 8; 1 = currently failing (I2C error or no update for 200 ms); its distance reads 120 / 1200 |
No dedicated block; in JavaScript read it with mbc.readValue(address, id) (−32768 when nothing answers). Related block: "distance 8-ch sensor 1 is OK".
let fault = mbc.readValue(0x29, 0x08) // fault bitmap:0~255 bitfront distance (mm) frontMm
| Range | Meaning |
|---|---|
0~1200 mm |
average of sensors 4 and 5 (the two facing forward), 0~1200 mm; 1200 = nothing ahead. cm version is 05 |
(distance 8-ch front \([mm v]\) :: #00A4E4)
let frontMm = mbc.tof8Front(MbcDistUnit.Mm) // front distance (mm):0~1200 mmReturns 0 when the sensor does not answer; check with "device at … is ready" first.
sensor 1~8 distance (cm) distCm
| Range | Meaning |
|---|---|
0~120 cm |
distance of each sensor 1 |
(distance 8-ch sensor (1) \([cm v]\) :: #00A4E4)
let distCm = mbc.tof8Sensor(1, MbcDistUnit.Cm) // sensor 1~8 distance (cm):0~120 cm (N = 1~8)Returns 0 when the sensor does not answer; check with "device at … is ready" first.
sensor 1~8 distance (mm) distMm
| Range | Meaning |
|---|---|
0~1200 mm |
distance of each sensor 1 |
(distance 8-ch sensor (1) \([mm v]\) :: #00A4E4)
let distMm = mbc.tof8Sensor(1, MbcDistUnit.Mm) // sensor 1~8 distance (mm):0~1200 mm (N = 1~8)Returns 0 when the sensor does not answer; check with "device at … is ready" first.
Examples
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
More questions
- Cannot find the MBC blocks? In MakeCode Extensions, paste https://github.com/contactmbcrobot/pxt-mbc-sensors.
Still stuck? Contact us with your software and a screenshot of the program.
Downloads
- MakeCode extension pxt-mbc-sensors (paste this URL in MakeCode Extensions)
- Download centre (libraries, firmware, catalogue for every product)
Sources
- Host and software list:
_build/guides.json - Values and commands:
_build/protocol/tof8.json(single source of truth) - Setup:
_build/guides/software/microbit-makecode.en.md、_build/guides/product/tof8/microbit-makecode.en.md - Examples:
sensors/tof8/microbit-examples.md