Skip to content

Distance Sensor

An ultrasonic sensor that looks like a pair of eyes and measures the distance to objects ahead.

How it works, and range

It emits inaudible ultrasound and times the echo:

  • Range 5-200 cm (official spec: 50-2000 mm, accuracy ±2 cm).
  • The two "eyes" share 4 programmable LED segments (2 per eye) you can light up for status display.
  • When there's no target (too far, too close, sound-absorbing surface) it returns an invalid reading.

What it detects well

TargetResult
Flat hard surfaces (walls, model sides)✅ accurate
Surfaces facing the sensor✅ accurate
Angled surfaces (> ~30°)⚠️ echo bounces away, may miss
Thin poles, grids, soft fabric❌ unreliable

Word Blocks

wordblocks
(distance sensor [D] distance in cm)              ← reporter block (round value block)
<distance sensor [D] distance < [10] cm>           ← condition
wait until <distance sensor [D] distance < [10] cm>

Example 1: approach and slow down

Full speed toward the model, slow near it, avoid knocking it over:

wordblocks
when program starts
set movement motors [A+E]
set movement speed [80] %
start moving [forward]
wait until <distance sensor [D] distance < [20] cm>
set movement speed [25] %
start moving [forward]
wait until <distance sensor [D] distance < [6] cm>
stop moving

Example 2: keep distance (follow)

wordblocks
forever
  if <distance sensor [D] distance < [10] cm> then
    start moving [backward]
  else
    if <distance sensor [D] distance > [15] cm> then
      start moving [forward]
    else
      stop moving

Python

python
import runloop, distance_sensor
from hub import port

async def main():
    d = distance_sensor.distance(port.D)   # millimeters; -1 when no target
    if d != -1 and d < 100:                # under 10 cm
        pass

runloop.run(main())

Python returns millimeters

Word Blocks show cm; Python's distance() returns mm and -1 when nothing is detected. Check for -1 first, otherwise "-1 < 100" is always true and the robot thinks it has arrived.

FLL uses

  • Precise stops: more slip-proof than counting rotations, ideal for "stop 8 cm before the model".
  • Crash guard: a parallel stack doing "distance < 10 cm → emergency stop" during long sprints. Keep the threshold well above the 5 cm range floor (too close returns invalid readings, so < 5 may never fire) and leave braking distance at speed.
  • Localization: measure square-on to a wall whose position you know, and you know the robot's position along that axis (one-dimensional; angled walls give unreliable readings).

Common pitfalls

  • The sound cone spreads: the floor up close or a neighboring model can be "seen". Mount the sensor a bit higher, not at mat level.
  • Two robots' distance sensors can interfere (rare but real on back-to-back tables).
  • Sampling has latency - leave braking distance at high speed.

Python API quick reference

FunctionReturnsNotes
distance_sensor.distance(port.D)int, millimeters-1 when no target (too far, too close, absorbing surface) - always check first

The 4 LED segments around the eyes are also controllable from Python - see the distance_sensor light functions in the official API reference if you want status lights.

More examples

Two-stage approach, in Python

Fast toward the model, slow for the last stretch, stop at 8 cm. The closer_than helper builds a condition function that treats -1 as "not there yet". Note the timeouts are safety fallbacks, not distance triggers - if a stage times out, the program moves on without having reached that distance:

python
import runloop, motor_pair, distance_sensor
from hub import port

motor_pair.pair(motor_pair.PAIR_1, port.A, port.E)

def closer_than(mm):
    def check():
        d = distance_sensor.distance(port.D)
        return d != -1 and d < mm
    return check

async def main():
    motor_pair.move(motor_pair.PAIR_1, 0, velocity=600)
    await runloop.until(closer_than(200), 6000)   # 20 cm: slow down (6 s safety timeout)
    motor_pair.move(motor_pair.PAIR_1, 0, velocity=180)
    await runloop.until(closer_than(80), 4000)    # 8 cm: stop (4 s safety timeout)
    motor_pair.stop(motor_pair.PAIR_1)

runloop.run(main())

Crash guard running alongside the mission

Two coroutines: the mission drives while the guard polls the sensor and cuts the motors below 10 cm. A shared flag lets the guard exit on its own once the mission finishes:

python
import runloop, motor_pair, distance_sensor
from hub import port

motor_pair.pair(motor_pair.PAIR_1, port.A, port.E)
mission_done = False

async def mission():
    global mission_done
    await motor_pair.move_for_degrees(motor_pair.PAIR_1, 3600, 0, velocity=700)
    mission_done = True

async def guard():
    while not mission_done:
        d = distance_sensor.distance(port.D)
        if d != -1 and d < 100:                   # 10 cm emergency stop
            motor_pair.stop(motor_pair.PAIR_1)
            break
        await runloop.sleep_ms(20)

runloop.run(mission(), guard())

Next sensor: Force Sensor.

© 2026 FLL Knowledge Base · All rights reserved