FTDI DTR + LED
Status: ✅ proven (library-level / community)
A USB-to-serial (FTDI) adapter can act as a VLL emitter: an LED wired to the DTR pin is toggled from the browser via the Web Serial API (port.setSignals({dataTerminalReady})), pulsing light at the LEGO sensor in the VLL timing.
This is exactly how lego-blockly drives VLL:
unit = 20 ms,preamble = 1000 ms, VLL checksum identical, bits/stop per VLL — Visible Light Link.- Busy-wait (
performance.now()) for precise sub-ms pulse timing — far steadier than a phone torch.
macOS-native: bitbang with pylibftdi (recommended) ⭐
Jorge Pereira's vllftdi.py (github.com/JorgePe/mindstorms-vll) does it without a browser: from pylibftdi import BitBangDevice, set direction = 0xFF, then toggle a pin (bb.port = 0/1) with time.sleep() for the VLL timing (init 0.4 s, start 0.02 s, bit0 40/20 ms, bit1 20/40 ms, stop 20/60/120 ms; VLL checksum 7-((n+(n>>2)+(n>>4))&7); frame (chksum<<7)+code). Runs on Linux and macOS → simplest Mac path, no microcontroller.
- Setup:
brew install libftdi·pip3 install pylibftdi. Useauto_detach=False(avoids segfaults; the Apple FTDI driver may need detaching). - LED on a bitbang pin (e.g. D0/TXD) → resistor → LED → GND.
Parts
- Genuine FTDI FT232R/FT232H adapter — a few $. ⚠️ Not a CH340/CP2102 clone (those don't bitbang via libftdi).
- LED + resistor (~220 Ω visible, ~150 Ω for red/IR — sensor is red-biased) between the pin and GND.
Best for
A near-zero-cost hardware emitter — driven from the browser (Web Serial DTR, lego-blockly) or straight from Python on a Mac (pylibftdi, JorgePe). No firmware to flash.