flash force Wiki
Interactive browser →
Wiki / Protocols
#protocol#vll#reference#micro-scout#ir

VLL — Visible Light Link

No carrier at all, just light on and off, and it runs one way. A brick with a light sensor counts flashes. Bright and dark alternate, and the RATIO of the two says which bit it was, so the sender's clock can drift by a third and the brick still reads it. That tolerance is why a phone torch works. The Micro Scout, Code Pilot and Scout share one code set.

Frame

One command = 10 bits = 3-bit checksum + 7-bit data, wrapped in init/start/stop:

  1. Init / preamble — light ON ≈ 400 ms (some impls use 1000 ms, see Implementations below) before anything.
  2. Start — OFF 20 ms.
  3. Checksum — 3 bits, MSB first (see Checksum below).
  4. Data — 7 bits, MSB first.
  5. Stop — ON 20 ms, OFF 60 ms, ON 120 ms (some impls: just ON 20 / OFF 60).

The frame transmits [checksum:3 bits][data:7 bits], both MSB first.

Bit encoding (unit = 20 ms)

BitLight ONLight OFF
040 ms (2 units)20 ms (1 unit)
120 ms (1 unit)40 ms (2 units)

Total per bit = 60 ms either way (only the ON/OFF ratio differs).

Checksum

A 3-bit checksum is prepended (MSB first) to each 7-bit data value:

function checksum(n) {        // n = 7-bit data value
  return 7 - ((n + (n >> 2) + (n >> 4)) & 7);
}

Verified against all 27 commands in rcxvll.nqh (pbrick) and used verbatim by Flash Force, lego-blockly and elecbrick (Doug Eaton).

Commanddata nchecksum
Motor forward07
Motor reverse16
Beep 142
Beep 585
Run program334
Delete program343

Direct commands

The 7-bit data values themselves. The Micro Scout shares this codebase with Code Pilot and Scout.

CodeBinaryAction
00000000Motor forward
10000001Motor reverse
100001010Stop motors (see note)
40000100Beep 1
50000101Beep 2
60000110Beep 3
70000111Beep 4
80001000Beep 5
330100001Run stored program
340100010Delete stored program
701000110"Next" (official spec; no effect on device)
711000111Reset (official spec; no effect on device)

Script commands

CodeActionCodeAction
16Motor fwd 0.5 s24Beep 1
17Motor fwd 1 s25Beep 2
18Motor fwd 2 s26Beep 3
19Motor fwd 5 s27Beep 4
20Motor rev 0.5 s28Beep 5
21Motor rev 1 s29Wait for light
22Motor rev 2 s30Seek light
23Motor rev 5 s31Code (talk to another brick)
32Keep alive

Build a program = Delete (34), then script steps 16–32, then Run (33).

Notes and gaps

Implementations

Four independent implementations agree on the core protocol:

SourceChecksumbit0/bit1PreambleEmitter
Flash Forceyes40/20 · 20/40400 msphone torch
rcxvll.nqh (pbrick)yessame400 msLEGO 9V light brick on RCX
lego-blocklyyessame1000 msLED on a serial control line
elecbrick (Doug Eaton)yessameopcode generator

The protocol is identical everywhere; the tunable parts are preamble length and stop-bit tail (reliability knobs).

Practical

Invisible light works too

Confirmed on hardware, 19 July 2026: a full frame over invisible infrared programmed a Micro Scout at 30 to 40 cm on direct aim, from the bridge's own infrared LED. Better range than the visible path, and nothing to watch — the brick just obeys.

The sensor is silicon, so it answers to near-infrared from 700 to 1100 nm, and it carries no infrared-cut filter. A 940 nm television remote sets it off, which is the one-minute proof: run a light-reactive program, Seek Light or Light Control, and blast the sensor with a remote. If it reacts, infrared gets through, and 850 nm will do better.

850 nm gives the strongest response and only a faint dark-red glow. 940 nm is fully invisible, but weaker, so go brighter or closer.

⚠️ LEGO's own tower sent VLL on a VISIBLE red LED, and its 940 nm emitter was the RCX serial channel instead. Read the precedent the wrong way round and you conclude infrared cannot carry VLL.

Driving the light

A pin, a resistor, the diode: resistor between pin and anode, cathode to ground. A 5 mm LED at 10 to 15 mA is inside what a pin will give, and the sensor is millimetres away, so nothing needs driving hard. About 220 ohm suits a visible LED, about 150 ohm a red or infrared one, whose forward voltage is lower — which also matters at 3.3 V, where a white LED comes out dim. The sensor is red-biased, so red wins twice.

⚠️ DRIVE IT BASEBAND — plain on and off, no carrier. A 38 kHz modulated LED is never decoded, and that was the real bug behind an old "the onboard infrared is too weak" conclusion: a stray carrier, not brightness. Power Functions (IR) and the 76 kHz IR family need the light modulated; this needs it bare.

The trade-off is aim: VLL wants point-blank and straight on, which suits something held in the hand.

Sources