For some of these, if you use them on Desktop (Windows, MacOS), you need the LEGO ScratchLink software as a bridge. Alternatively, some of these extensions support a custom (Websocket) bridge.
For most of these, you must disable Sandbox Mode in TurboWarp.
For iOS, you might try them in Scrub App which provides a ScratchLink-like functionality (https://github.com/bricklife/Scrub) (this is untested yet).
| Category | Files |
|---|---|
| LEGO Spike Prime | legospikeprime_btc_scratchlink.js, legospikeprime_ble.js, legospike_ble.js, legospike_bridge.js |
| LEGO Boost | legoboost_scratchlink.js, legoboost_ble.js, legoboost_turbowarp.js |
| LEGO EV3 | ev3_btc.js, ev3_lms_transpile.js, ev3_transpile.js |
| LEGO NXT | legonxt_transpile_universal.js, legonxt_transpile_scratchlink.js, legonxt_transpile_direct.js, legonxt_transpile_bridge.js, legonxt-direct.js, legonxt_turbowarp.js |
| Math/Utilities | csp.js, planetemaths.js, arrays.js, gamepad.js |
| Python Bridges | nxt_bridge.py, ev3_ondevice_bridge.py, lego_bridge.py |
Extension: legospikeprime_btc_scratchlink.js
Note for this you need the older 2.x firmware which works with Bluetooth Classic (BTC).
You can switch firmwares by running upgrade from Spike Prime app, or downgrade or use dfu-util/pybricksdev (backup/restore).
This is work in progress and I could not yet test it:
- Extension:
legospike_ble.js - Alternative:
legospikeprime_ble.js
For this you need the newer firmware (you can upgrade from Spike Prime app).
Extension: legoboost_scratchlink.js (requires ScratchLink installed)
Alternatives:
legoboost_ble.js- Direct BLE connectionlegoboost_turbowarp.js- Bridge-based connection
ev3_lms_transpile.js - Allows streaming mode (direct command execution) and transpiling to lmsasm, which can then be compiled to bytecode that should run on the EV3 Brick. Compilation needs internet connectivity as it uses a REST API which wraps NBC and lmsasm at https://lego-compiler.vercel.app/ (source). Use with caution!
ev3_btc.js - Connects to the original firmware with streaming mode only.
With ev3dev, you have Linux on the device and can do lots of cool things.
Python Bridge: ev3_ondevice_bridge.py - Supports both streaming mode (direct command execution) and transpiling code blocks to Python scripts with on-device execution.
Extension: ev3_transpile.js - Required for transpilation features.
legonxt_transpile_universal.js β - Should include all connection option, ScratchLink, BTC and Bridge. Gives you the option to transpile code blocks to NXC and then compile them to RXE files which the NXT Brick can run directly. Must be thoroughly tested though.
legonxt_transpile_scratchlink.js β RECOMMENDED - Works with ScratchLink and gives you the option to transpile code blocks to NXC and then compile them to RXE files which the NXT Brick can run directly.
Alternatives:
legonxt_transpile_direct.js- Direct connection (incomplete)legonxt_transpile_bridge.js- Bridge-based (incomplete)
Compilation needs internet connectivity, using REST API at https://lego-compiler.vercel.app/ (source).
legonxt-direct.js - Direct Bluetooth control (pair NXT via device Bluetooth settings first)
legonxt_turbowarp.js - Uses WebSocket bridge
Python Bridge: nxt_bridge.py - Main WebSocket bridge (keep running)
Legacy/Debug Files:
lego_bridge.py- Older bridge attemptnxt-diag.py- Connection diagnosticsnxt-pybluez-bridge.py- Experimental alternative bridgereset_nxt.sh- Reset pairing on macOStest_bt.py- Bluetooth discovery test
csp.js- Simple Constraint-Satisfaction-Problem solverplanetemaths.js- Additional math operations (rewritten from CodePM extension)arrays.js- Array/vector/tensor handling
gamepad.js - Gamepad support (untested)
Control LEGO Mindstorms NXT robots directly from TurboWarp using Bluetooth. This project provides both a WebSocket bridge for remote access and a direct Web Serial API extension for local connections.
- Continuous motor power control (-100% to 100%)
- Precise angle-based movement (degrees/rotations)
- Position tracking and reset
- Brake and coast modes
- Touch Sensor: Boolean press detection
- Light Sensor: Brightness readings (0-1023) with LED control
- Sound Sensor: Loudness measurement in dB/dBA mode
- Ultrasonic Sensor: Distance measurement (0-255 cm) via I2C
- Clear screen and update display
- Draw text with 5Γ7 bitmap font (A-Z, 0-9, symbols)
- Draw pixels, lines, rectangles (filled/outline)
- Built-in patterns (checkerboard, stripes, grid, dots, border)
- Screen capture (returns base64 BMP image)
- Play tones (200-14000 Hz)
- Musical notes (C4-B5)
- Battery voltage monitoring (mV)
- Connection status
- LEGO Mindstorms NXT brick (NXT 1.0 or 2.0)
- Bluetooth connection (built-in NXT Bluetooth)
- macOS, Windows, or Linux computer
- Python 3.8+ (for WebSocket bridge)
- Chrome/Edge 89+ (for Web Serial API)
- Python packages:
websockets,pyserial
pip install websockets pyserial-
Pair NXT via Bluetooth (see macOS Setup below)
-
Run the bridge:
python nxt_bridge.py- Load extension in TurboWarp:
- Load
legonxt_turbowarp.jsas a custom extension - Use the "connect to [URL]" block with
localhost:8080
- Load
- Pair NXT via Bluetooth
- Load extension
legonxt-direct.jsin TurboWarp Desktop - Connect and select
/dev/cu.NXT(macOS) or appropriate COM port
Critical Steps (Bluetooth connection drops frequently on macOS):
- Forget existing pairing (if any):
blueutil --disconnect 00-16-53-XX-XX-XX
blueutil --unpair 00-16-53-XX-XX-XX-
Turn NXT off and back on
-
Re-pair with PIN 1234:
blueutil --pair 00-16-53-XX-XX-XX
# Enter PIN: 1234- Verify connection:
python nxt-diag.pyYou should hear a beep and see battery data!
reset_nxt.sh script:
chmod +x reset_nxt.sh
./reset_nxt.sh-
Pair NXT via Bluetooth settings You probably must first enable "Advanced" Discovery in Windows 11:
- Open Settings (Win + I)
- Go to Bluetooth & devices > Devices
- Scroll down to Device settings
- Change Bluetooth devices discovery from "Default" to "Advanced"
- Enter the NXT Bluetooth PIN: default = 1234
Note you might also do this in Windows Terminal:
btpair -u- Note the COM port
- Run the bridge
You can inspect the COM port at /dev/rfcomm0
| File | Description |
|---|---|
legonxt_turbowarp.js |
Lego NXT over local Python Bridge (Full feature set) β |
legonxt-direct.js |
Lego NXT Direct Bluetooth Connection (Development version) |
legonxt_transpile_scratchlink.js |
NXT Transpilation via ScratchLink (Scratch β NXC β RXE) β |
legonxt_transpile_direct.js |
NXT Transpilation Direct (Incomplete) |
legonxt_transpile_bridge.js |
NXT Transpilation Bridge (Incomplete) |
| File | Description |
|---|---|
nxt_bridge.py |
WebSocket bridge - Polling-based for reliable communication β |
nxt-diag.py |
Diagnostic tool - Test Bluetooth connection |
nxt-pybluez-bridge.py |
PyBluez alternative bridge (experimental) |
reset_nxt.sh |
Quick reset script for macOS pairing |
test_bt.py |
Bluetooth discovery test |
when flag clicked
connect to [localhost:8080]
wait until <connected?>
motor [A] power [75] %
wait (2) seconds
motor [A] [brake]
setup ultrasonic [S4]
forever
say (join [Distance: ] (ultrasonic [S4] distance (cm)))
end
clear screen
draw text [HELLO NXT] at x:[10] y:[10]
draw line from x:[0] y:[0] to x:[99] y:[63]
π₯οΈ update display
wait (3) seconds // Display update takes 1-3 seconds
- Load
legonxt_transpile_scratchlink.js - Build your program with Scratch blocks
- Use "transpile project to NXC" block
- Use "compile NXC to .rxe" block (requires internet)
- Use "upload program to NXT" block
draw pattern [checkerboard]
wait (2) seconds
draw pattern [smile]
Cause: Bluetooth connection not established
Solution:
- Run
blueutil --unpair <MAC-address> - Turn NXT off/on
- Re-pair with PIN 1234
- Test with
python nxt-diag.py
Cause: Bluetooth RFCOMM channel dropped
Solution:
- Run
./reset_nxt.shto reset connection - Wait 10 seconds after pairing before testing
Cause: Missing updateDisplay() method
Solution:
- Ensure you're using
legonxt_turbowarp.js(latest version) - Call "π₯οΈ update display" block after drawing operations
- Wait 2-3 seconds for display update to complete
Cause: Must install python package pyserial
Solution:
pip install pyserialmacOS: Use /dev/cu.NXT (NOT e.g. /dev/cu.Bluetooth-Incoming-Port)
Windows: Check Device Manager for COM port number
Linux: Try /dev/rfcomm0 or create with rfcomm bind
- Update time: 1-3 seconds per display update
- Strategy: Batch all drawing operations, call
updateDisplay()once - Buffer size: 800 bytes (100Γ64 pixels Γ· 8 bits)
// Good pattern (faster)
clearScreen();
drawText('Line 1', 0, 0);
drawText('Line 2', 0, 10);
drawRect(0, 0, 100, 64, false);
updateDisplay(); // Single 1-3s operation
// Bad pattern (slower)
drawText('Line 1', 0, 0);
updateDisplay(); // 1-3s wait
drawText('Line 2', 0, 10);
updateDisplay(); // Another 1-3s wait[2-byte length (LE)] [command type] [opcode] [payload...]
Command Types:
0x00: Direct command (with reply)0x80: Direct command (no reply)0x01: System command (with reply)0x02: Reply telegram
Key Opcodes:
0x03: PLAY_TONE0x04: SET_OUT_STATE (motors)0x05: SET_IN_MODE (sensors)0x07: GET_IN_VALS (read sensor)0x0B: GET_BATT_LVL (battery)0x0F/0x10: LS_WRITE/LS_READ (I2C)0x94/0x95: READ_IO_MAP/WRITE_IO_MAP (display)
- Resolution: 100Γ64 pixels (monochrome)
- Module ID:
0xA0001(little-endian) - Offset: 119
- Format: 800 bytes, 8 vertical pixels per byte
- Bit order: LSB = top pixel, MSB = bottom pixel
This project is licensed under the GNU General Public License v3.0.
Happy building! π€