This page has moved into the new guide: Pathfinder 16-Way › micro:bit › MakeCode

🟧 micro:bit Examples: Line Follower 16-ch

Back to Line Follower 16-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 45 mA for 16 channels; external 5 V recommended, the micro:bit 3V pin (limit about 90 mA on V1, 190 mA on V2) must be tested 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 0x16, the same as the 8-ch; to connect an 8-ch and a 16-ch together change one address first —
Ready time ready immediately after power-on (F3 b0 is always 1) 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)

Line Follower 16-ch × micro:bit
Sensor micro:bit
SDA P20
SCL P19
VCC external 5 V (or try 3V)
GND GND (the servo battery − goes here too)

The values used on this page

"Left / right" always means sensor mounted on the robot, you standing behind it looking forward: line on the left = negative, channel 1 = far left.

Block JavaScript Range Meaning Used in
line position mbc.linePosition() −16~+16 which channel the line is under, 0 = centre, negative = left 1, 3, 4
fine line position mbc.linePositionFine() −100~+100 finer version of the position, same sign 5
line is seen mbc.lineSeen() true / false at least one channel sees the line 1, 3, 4, 5
line width mbc.lineWidth() 0~16 channels on the line, 0 = no line 1
last exit direction mbc.lineLastDirection() −16~+16 where the line was before it was lost, negative = left 5
on line lost / found / fork mbc.onLineEvent(...) 事件 fires once when the segment count becomes 0 / >0 again / ≥2 2, 5
calibrate auto (sweep for 5 s) mbc.lineCalibrate(MbcLineCalib.Auto) 命令 E7 sweep over black line and white surface for 5 s, saved in the sensor 2
is calibrating / calibration count mbc.lineCalibrating() / mbc.lineCalibrationCount() true / false、0~255 calibrating flag (F3 b2) and calibrations since power-on 2
follow black / white line mbc.lineSetColor(MbcLineColor.Black) 命令 E0/E1 black line on white (default) or white line on black 2
wait for device at … ready mbc.waitReady(mbc.ADDR_LINE, 3000) true / false waits up to 3 s, true when the sensor answers (Advanced → Device) 1

Example 1: Where is the line

What this example does: A column of LEDs follows the line: line on the left, column on the left; line centred, column in the middle. Press A to show the line position number, B the line width. Use it to check the wiring and that left / right are not swapped.

What you need

  • micro:bit V1 or V2 + USB cable
  • Line Follower 16-ch (Universal I2C edition) + 4-pin cable
  • a sheet of white paper with a strip of black electrical tape (about 2 cm wide)

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

Download: ex01_show_position.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

// Line follower 16-ch × micro:bit example 1: where is the line (an LED column follows the line)
// What it does: slide the sensor across a black line and a column of LEDs follows it; press A to show the line position number, B to show the line width.
// 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 (sensor found); line on the left → column on the left; centred → middle column; no line → an X.

const CH = 16                                              // channels: 8 on the 16-ch, 16 on the 16-ch
let busy = false                                          // pause the column while a button shows a number

if (mbc.waitReady(mbc.ADDR_LINE, 3000)) {                 // wait up to 3 s for the sensor to answer
    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
    }
    if (mbc.lineSeen()) {
        let pos = mbc.linePosition()                      // −CH (far left) .. +CH (far right), 0 = centre
        let x = Math.round(Math.map(pos, -CH, CH, 0, 4))  // map to LED column 0..4
        basic.clearScreen()
        for (let y = 0; y < 5; y++) {
            led.plot(x, y)                                // draw the whole column
        }
    } else {
        basic.showIcon(IconNames.No, 0)                   // no line seen
    }
    basic.pause(50)
})

input.onButtonPressed(Button.A, function () {
    busy = true
    basic.showNumber(mbc.linePosition())                  // line position: negative = line on the left (seen from behind the robot)
    busy = false
})
input.onButtonPressed(Button.B, function () {
    busy = true
    basic.showNumber(mbc.lineWidth())                     // line width: channels on the line, 0 = no line
    busy = false
})

Step by step

  1. const CH = 16: the channel count. On the 8-ch change it back to 8, nothing else.
  2. mbc.waitReady(mbc.ADDR_LINE, 3000): wait up to 3 s for the sensor to answer; tick if it does, X if not.
  3. basic.forever: repeat forever. First ask mbc.lineSeen() "is a line seen"; if not, show an X.
  4. Line seen: mbc.linePosition() reads −16..+16, Math.map turns it into LED column 0..4, and a loop of led.plot lights all 5 LEDs of that column.
  5. Buttons A / B: basic.showNumber scrolls the number; the busy variable pauses the column meanwhile so the two do not fight over the screen.

What you should see

  • Power-on: a tick (sensor found).
  • Sensor on the paper with the line under its centre: middle column; A shows 0.
  • Move the sensor right (the line is now on its left): the column moves left; A shows a negative number.
  • Lift it off the paper: X.

FAQ

  • The column moves the opposite way to the line? → The sensor is mounted backwards (channel 1 must be on the left of the robot). Turn the sensor 180°, do not change the code.
  • The column never leaves the middle? → Not calibrated yet: run example 2 and press A for auto calibration, or every value is 0 (check whether example 1 showed the X).
  • 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: Lost-line alarm + one-key calibration

What this example does: Line seen → happy face; line gone → sad face and a beep. Press A for the 5-second auto calibration (LED counts 5 4 3 2 1), B to switch black / white line mode. It uses the "event" blocks: they fire the moment the line is lost, instead of asking all the time.

What you need

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

Wiring: Same as example 1.

Download: ex02_line_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

// Line follower 16-ch × micro:bit example 2: lost-line alarm + one-key calibration
// What it does: line seen → happy face; line lost → sad face and a beep. Press A for the 5-second auto calibration (LED countdown), B to switch black / white line.
// Wiring: sensor SDA → P20, SCL → P19, VCC → 3V (or external 5 V), GND → GND. On a V1 connect a buzzer or headphones to P0 for sound (V2 has a speaker).
// Setup: a sheet of white paper with a strip of black tape. Extension and paste steps as in example 1.
// You see: sensor over the line → happy; lifted away → sad + beep; press A → 5 4 3 2 1, the calibration count, then a tick.

let white = false                                         // white-line mode on?

mbc.lineSetColor(MbcLineColor.Black)                      // start in black-line mode (the default)
basic.showIcon(IconNames.Happy)

mbc.onLineEvent(MbcLineEvent.Lost, function () {          // fires once when the segment count drops to 0
    basic.showIcon(IconNames.Sad, 0)
    music.playTone(Note.C, music.beat(BeatFraction.Half)) // low C for half a beat
})
mbc.onLineEvent(MbcLineEvent.Found, function () {         // line found again
    basic.showIcon(IconNames.Happy, 0)
})

input.onButtonPressed(Button.A, function () {
    mbc.lineCalibrate(MbcLineCalib.Auto)                  // sweep the sensor over black line and white paper for 5 s
    for (let i = 5; i > 0; i--) {
        basic.showNumber(i)                               // countdown
        basic.pause(1000)
    }
    while (mbc.lineCalibrating()) {                       // wait until the calibrating flag clears
        basic.pause(100)
    }
    basic.showNumber(mbc.lineCalibrationCount())          // calibrations done since power-on
    basic.showIcon(IconNames.Yes)
})

input.onButtonPressed(Button.B, function () {
    white = !white
    mbc.lineSetColor(white ? MbcLineColor.White : MbcLineColor.Black)   // black line on white ↔ white line on black
    basic.showString(white ? "W" : "B")
})

Step by step

  1. mbc.lineSetColor(MbcLineColor.Black): start in black-line mode (command E0).
  2. mbc.onLineEvent(MbcLineEvent.Lost, ...): runs once when the segment count drops from >0 to 0 → sad face + music.playTone for half a beat. Found is the line coming back → happy face.
  3. Button A: mbc.lineCalibrate(MbcLineCalib.Auto) sends command E7 and the sensor starts its 5-second calibration; a for loop counts down meanwhile.
  4. while (mbc.lineCalibrating()): while the calibrating flag (F3 b2) is still 1 wait another 0.1 s; continue when it clears.
  5. mbc.lineCalibrationCount(): shows how many calibrations finished since power-on, proving it really ran.
  6. Button B: the white variable flips and lineSetColor switches between black (E0) and white (E1); the screen shows B or W.

What you should see

  • Sensor over the line: happy. Lifted away: sad + one beep (only once, not continuous).
  • Press A and sweep the sensor over black line and white paper a few times within 5 s → the count (1 the first time) → a tick. Positions are more accurate afterwards.
  • Press B, W shows: now only a white line on black is treated as a line.

FAQ

  • The count never shows after A? → The calibrating flag never clears, usually because the sensor is not connected (with all-zero reads lineCalibrating() is false and it skips straight on). Run example 1 first and look for the tick.
  • No sound when the line is lost? → A V1 needs a buzzer; on a V2 make sure the speaker is not turned off in MakeCode.

Example 3: A steering servo follows the line

What this example does: A 9 g servo acts as a steering wheel: line on the left, the servo turns left, the further off-centre the bigger the turn (80° at the outermost channel); line lost, back to centre. The first example where the sensor moves something. Press A to show the angle.

What you need

  • Everything from example 1, calibrated once with example 2
  • one 9 g servo (SG90)
  • a 4.8–6 V battery pack (4 × AA) 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_steer_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

// Line follower 16-ch × micro:bit example 3: a steering servo follows the line
// What it does: a 9 g servo (SG90) acts as a steering wheel: line on the left → servo turns left, further off-centre → bigger turn; line lost → back to centre. Press A to show the angle.
// 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 (common ground).
// Setup: the black-line sheet from example 2, calibrated once.
// You see: move the sensor so the line is on its left → the servo arm swings one way; line on the right → the other way; lift it away → back to 90°.

const CH = 16                                              // channels: 8 on the 16-ch, 16 on the 16-ch
const GAIN = Math.idiv(80, CH)                            // degrees per channel: the outermost channel gives ±80°
let angle = 90

basic.forever(function () {
    if (mbc.lineSeen()) {
        angle = 90 + mbc.linePosition() * GAIN            // line on the left (negative) → angle below 90
    } else {
        angle = 90                                        // no line: centre
    }
    angle = Math.constrain(angle, 0, 180)
    pins.servoWritePin(AnalogPin.P1, angle)               // 0..180°
    basic.pause(30)
})

input.onButtonPressed(Button.A, function () {
    basic.showNumber(angle)
})

Step by step

  1. GAIN = Math.idiv(80, CH): degrees per channel. 5° on the 16-ch, 10° on the 8-ch, so the outermost channel is 80° either way.
  2. Line seen: angle = 90 + position × GAIN; line on the left (negative) gives less than 90, on the right more than 90.
  3. No line: angle = 90, centre.
  4. Math.constrain(angle, 0, 180): a servo only goes 0..180°, clamp anything beyond.
  5. pins.servoWritePin(AnalogPin.P1, angle): send the angle to the servo on P1, every 30 ms.

What you should see

  • Line centred: servo at 90°.
  • Move the sensor right (line on its left): the arm swings one way, more the further off-centre.
  • Lift it off: back to 90°. A shows 90.

FAQ

  • The servo jitters or the micro:bit keeps resetting? → Never power the servo from the micro:bit 3V pin: use the battery pack, with battery − joined to micro:bit GND.
  • It turns the wrong way? → Change 90 + ... to 90 - ..., it depends on how the servo is mounted.

Example 4: Line-following car (three-way)

What this example does: Press A to drive: line on the left → turn left, on the right → turn right, centred → straight; line lost → stop. Press B to stop. Only three actions, the easiest line follower to understand.

What you need

  • A two-wheel car: two continuous-rotation servos (e.g. FS90R) as wheels plus a caster
  • the line follower at the front, 0.5–1 cm above the floor
  • a 4.8–6 V battery pack
  • a black-line track (white paper + black tape, no sharp bends)

Wiring: Sensor as in example 1, mounted at the front 0.5–1 cm above the floor. 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_simple_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

// Line follower 16-ch × micro:bit example 4: line-following car (three-way)
// What it does: press A to drive: line on the left → turn left, on the right → turn right, centred → straight; line lost → stop. Press B to stop.
// Wiring: sensor SDA → P20, SCL → P19, VCC → 3V, GND → GND. Left continuous-rotation servo signal → P1, right → P2; both servos powered from a 4.8–6 V battery pack whose − is joined to micro:bit GND.
// Setup: a two-wheel car (two continuous-rotation servos as wheels), the sensor at the front 0.5–1 cm above the floor, a black-line track.
// You see: after A the arrow points up and the car follows the line; the arrow points the way it turns; off the line → sad face, stop.

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
    }
    if (!mbc.lineSeen()) {
        drive(0, 0)                                       // stop when the line is lost
        basic.showIcon(IconNames.Sad, 0)
    } else {
        let pos = mbc.linePosition()                      // negative = line on the left
        if (pos < 0) {
            drive(20, 60)                                 // left slow, right fast = turn left
            basic.showArrow(ArrowNames.West, 0)
        } else if (pos > 0) {
            drive(60, 20)                                 // turn right
            basic.showArrow(ArrowNames.East, 0)
        } else {
            drive(50, 50)                                 // straight
            basic.showArrow(ArrowNames.North, 0)
        }
    }
    basic.pause(20)
})

Step by step

  1. function drive(left, right): every driving example on this page uses it. Numbers −100..100, positive = forward. Left wheel 90 + left × 0.9 (90 stop, 180 full forward); the right servo is mounted mirrored, so 90 − right × 0.9.
  2. Button A: running = true; button B: running = false and drive(0, 0).
  3. basic.forever: when not running do nothing (return).
  4. !mbc.lineSeen(): line lost → stop and sad face, so the car does not run off the track.
  5. pos < 0 (line on the left) → drive(20, 60): left slow, right fast = turn left. pos > 0 the other way. pos == 0 → both wheels equal, straight.

What you should see

  • Press A: up arrow, the car follows the line; in bends the arrow points the way it turns.
  • Lift the car: sad face, both wheels stop.
  • Press B: X, stop.

FAQ

  • The car reverses after A? → Both servos are mounted the other way: in drive change + left to - left and - right to + right. Only one wheel wrong → change only that line.
  • The car wiggles along the line? → Change 60 / 20 to 50 / 30 (gentler turns), or use the proportional control of example 5.
  • It never fully stops, the wheels creep? → "Stop" on a continuous-rotation servo is not always exactly 90: adjust the trim screw on the servo, or try 88..92 instead of 90.

Example 5: Smooth line following + stop at the 3rd crossing (all together)

What this example does: Proportional control on the fine position: the correction is as big as the error, so the car does not wiggle; crossings (fork event) are counted and the car stops at the 3rd; when the line is lost the car spins back using the last exit direction. Everything learned so far, reading values, events and driving, in one program.

What you need

  • The car from example 4
  • a black-line track with 3 crossings

Wiring: Same as example 4.

Download: ex05_smooth_follow_stop.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

// Line follower 16-ch × micro:bit example 5: smooth line following + stop at the 3rd crossing (all together)
// What it does: proportional control on the fine position, so the car steers smoothly; counts crossings and stops at the 3rd; when the line is lost it spins back using the last exit direction. 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: a black-line track with 3 crossings.
// You see: after A the car follows smoothly, the LEDs show 1, 2, 3 at each crossing and the car stops with a tick at 3; lift the track away and the car turns toward where the line went, then carries on when it finds it.

const SPEED = 50
const KP = 0.5                                            // fine position ±100 → correction ±50
let running = false
let crossings = 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.onLineEvent(MbcLineEvent.Fork, function () {          // segment count ≥ 2: crossing or fork
    if (!running) {
        return
    }
    crossings += 1
    basic.showNumber(crossings)
    if (crossings >= 3) {
        running = false
        drive(0, 0)
        basic.showIcon(IconNames.Yes)
    }
})
mbc.onLineEvent(MbcLineEvent.Lost, function () {
    if (!running) {
        return
    }
    if (mbc.lineLastDirection() < 0) {                    // the line left on the left → spin left to find it
        drive(-30, 30)
    } else {
        drive(30, -30)
    }
    basic.showIcon(IconNames.Confused, 0)
})

input.onButtonPressed(Button.A, function () {
    crossings = 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 && mbc.lineSeen()) {
        let err = mbc.linePositionFine()                  // −100..+100, negative = line on the left
        let turn = err * KP                               // line on the left → negative turn → left wheel slows = turn left
        drive(SPEED + turn, SPEED - turn)
    }
    basic.pause(20)
})

Step by step

  1. KP = 0.5: fine position −100..+100 × 0.5 = correction −50..+50. Bigger = sharper steering.
  2. basic.forever: while running and the line is seen, err = fine position, turn = err × KP, drive(SPEED + turn, SPEED − turn). Line on the left (negative) → left wheel slows, right speeds up = smooth left turn.
  3. onLineEvent(Fork): segment count ≥ 2 (a crossing) → crossings + 1 shown on the LEDs; at 3 running = false, stop, tick.
  4. onLineEvent(Lost): mbc.lineLastDirection() < 0 means the line left on the left → drive(−30, 30) spin left; otherwise spin right. The forever loop leaves the motors alone while no line is seen, so it keeps spinning until the line is back.
  5. A: reset the count and start; B: stop.

What you should see

  • Press A: the car follows smoothly, steadier than example 4.
  • Each crossing: the LEDs show 1, 2, 3; at 3 the car stops with a tick.
  • Pull the track away from under the car: puzzled face, the car spins toward the side the line went; put it back and it carries on.

FAQ

  • One crossing counted twice? → Too slow: the segment count bounced twice while crossing. Raise SPEED, or add basic.pause(500) inside the Fork handler so one crossing is not counted again.
  • The car still wiggles? → Lower KP from 0.5 to 0.3; if it still does, change basic.pause(20) to 10 (faster updates).
  • It spins forever looking for the line? → The line is too far away. It only spins, it does not move forward; to search in an arc change the Lost handler to something like drive(10, 40).

Next steps

Email for a quoteBuying Guide