Skip to content

Color Sensor ​

The most important sensor in FLL, period. Line following, line detection and mat-mark recognition all depend on it.

What it measures ​

ModeReadingNotes
Color8 colors (black, white, red, yellow, green, blue, ...) plus no-color; note the Word Blocks dropdown and the Python color constants use slightly different name sets (Python has AZURE, ORANGE), check the official references for eachDiscrete color recognition
Reflected Light0-100%Sensor shines light and measures the reflection. Line following uses this
Ambient Light0-100%Passive brightness, rarely used in FLL

Mounting ​

  • Facing down, about 16 mm above the mat (the official optimal reading distance, roughly 5 LEGO plates). Too high = noisy readings, too low = scraping.
  • Mount at the front of the chassis, ahead of the wheel axle - the further forward, the earlier the correction.
  • For two-sensor line following, mount them side by side about one line-width apart.
  • Shield it: surround the sensor with LEGO pieces to block ambient light. Venue spotlights are brutal.

Word Blocks ​

wordblocks
<color sensor [C] color = [black]>          ← Sensors category condition
(color sensor [C] reflected light)           ← reporter block (round value block)
wait until <color sensor [C] color = [black]>

Example 1: drive to the black line ​

wordblocks
when program starts
set movement motors [A+E]
start moving [forward]
wait until <color sensor [C] reflected light < [30]>
stop moving

Example 2: count lines ​

wordblocks
set [lines] to [0]
start moving [forward]
repeat until <(lines) = [3]>
  wait until <color sensor [C] reflected light < [30]>
  change [lines] by [1]
  wait until <color sensor [C] reflected light > [60]>    ← key: wait to EXIT the line, or one line counts many times
stop moving

Python ​

python
import runloop, color_sensor, color
from hub import port

async def main():
    # read color (returns constants like color.BLACK)
    if color_sensor.color(port.F) == color.BLACK:
        pass
    # read reflected light 0-100
    value = color_sensor.reflection(port.F)

runloop.run(main())

Threshold calibration: not optional ​

The 30 in "reflected light < 30 means black" cannot be copied - measure it on your mat under your lighting:

  1. Write a loop that shows reflected light on the matrix: forever → write (reflected light).
  2. Read a value on the black line (say 12) and one on white mat (say 85).
  3. Threshold = middle: (12 + 85) / 2 ≈ 48. Black is < 48, white is > 48.

Recalibrate at every new venue

Lighting, mat wear and sensor height all shift readings. First thing on competition day: re-measure black and white. Store thresholds in variables so there's one place to edit.

Common pitfalls ​

  • Color mode is unreliable at speed: readings flicker when moving fast. Line following always uses reflected light.
  • Colored artwork on the mat fools "find the black line": dark blue and dark green reflect little light too. Combine with position (drive a known distance before arming line detection).
  • Two sensors reading differently is normal: calibrate each separately.

Python API quick reference ​

All functions live in the color_sensor module and take a port from from hub import port.

FunctionReturnsNotes
color_sensor.color(port.F)int color constantCompare against the color module constants; color.UNKNOWN / -1 when nothing is detected
color_sensor.reflection(port.F)int, 0-100Reflected light intensity - the line-following workhorse
color_sensor.rgbi(port.F)(R, G, B, I) tuple, each 0-1024Raw color channels plus overall intensity, for custom color logic

Python color constants (import color): BLACK, MAGENTA, PURPLE, BLUE, AZURE, TURQUOISE, GREEN, YELLOW, ORANGE, RED, WHITE, UNKNOWN. The name set differs from the Word Blocks dropdown - check the official references when porting programs.

More examples ​

Calibration helper: capture black and white with the hub buttons ​

Put the sensor on the line, tap LEFT; put it on white mat, tap RIGHT. The hub beeps on each capture and shows the suggested threshold.

python
import runloop, color_sensor
from hub import port, button, light_matrix, sound

black = None
white = None

async def main():
    global black, white
    while black is None or white is None:
        if button.pressed(button.LEFT):
            black = color_sensor.reflection(port.F)
            sound.beep(330, 150, 100)
            await runloop.until(lambda: not button.pressed(button.LEFT))
        if button.pressed(button.RIGHT):
            white = color_sensor.reflection(port.F)
            sound.beep(660, 150, 100)
            await runloop.until(lambda: not button.pressed(button.RIGHT))
        await runloop.sleep_ms(50)
    threshold = (black + white) // 2
    print("black", black, "white", white, "threshold", threshold)
    await light_matrix.write(str(threshold))

runloop.run(main())

Stop at the Nth line ​

Counts line entries by waiting for black then back to white, so one line is never counted twice. Stops just after leaving line number n.

python
import runloop, motor_pair, color_sensor
from hub import port

BLACK = 40
WHITE = 60
motor_pair.pair(motor_pair.PAIR_1, port.A, port.E)

async def stop_at_line(n, velocity=360):
    motor_pair.move(motor_pair.PAIR_1, 0, velocity=velocity)
    for _ in range(n):
        await runloop.until(lambda: color_sensor.reflection(port.F) < BLACK)
        await runloop.until(lambda: color_sensor.reflection(port.F) > WHITE)
    motor_pair.stop(motor_pair.PAIR_1)

async def main():
    await stop_at_line(3)

runloop.run(main())

Custom color logic with rgbi ​

When color() flickers between two similar colors, raw channels let you write your own rule. Watch the console while holding different objects under the sensor:

python
import runloop, color_sensor
from hub import port

def is_reddish(sample):
    r, g, b, i = sample
    return i > 80 and r > 2 * g and r > 2 * b

async def main():
    while True:
        sample = color_sensor.rgbi(port.F)
        print(sample, "reddish:", is_reddish(sample))
        await runloop.sleep_ms(200)

runloop.run(main())

FAQ ​

My thresholds stopped working at the venue - what happened? ​

Venue lighting, mat wear and sensor height all shift readings. First thing on competition day: re-measure black and white on site. Keep thresholds in variables so there is one place to edit.

Color mode or reflected light mode? ​

Always reflected light for line following and line detection - color mode flickers when the robot moves fast. Use color mode only for discrete color checks at rest or low speed.

My two color sensors read differently - are they broken? ​

No - unit variation is normal. Calibrate black/white thresholds for each sensor separately.

Applications continue in Line Following. Next sensor: Distance Sensor.

© 2026 FLL Knowledge Base · All rights reserved