Host-hub communication for LEGO Spike Prime on Linux

Oktober 2022 (republished in March 2026)

This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.

This post was written in 2022 and has not been updated since (up to fixing some typos).

LEGO stopped production of its popular robot programming set Mindstorms EV3 in 2021. Its follow-ups are named LEGO Spike Prime (for teaching environments) and LEGO Robot Inventor (for private customers). From the technical point of view both sets are equivalent, same hub, almost equivalent software for programming and controlling the hub, slightly different set of bricks.

The EV3 worked well in combination with a Linux host. For Spike’s programming app there is no native Linux support according to LEGO’s website. But some searching and fiddling reveals full Linux compatibility! Here we document all the relevant information for

Some information provided here may be found in the web (references below), some seem to be new.

Connecting the hub to a Linux machine

The hub can be connect via USB or Bluetooth. In both cases it ends up as a serial device in Linux. On the hub side a MicroPython interpreter is running and sends/receives outputs/inputs to/from the Linux host machine.

Establishing an USB connection

Simply connect the hub to your machine’s USB port. A new device will show up, usually named /dev/ttyACM0. Check last line of sudo dmesg after connecting the hub to get the correct device name (reference).

Establishing a Bluetooth connection

Use your system’s tools to connect to the hub and find the hub’s MAC address (something looking like 34:08:E2:8D:5C:1F). Connection may fail, but succesful pair and trust suffice. Then run sudo rfcomm connect /dev/rfcomm0 34:08:E2:8D:5C:1F (reference).

Disconnect via sudo rfcomm release /dev/rfcomm0 34:08:E2:8D:5C:1F.

Setting access rights

The serial device (USB and Bluetooth) is owned by user root and group dialout. To make it accessible by normal users, do one of the following:

Replace /dev/ttyACM0 by /dev/rfcomm0 in case of Bluetooth.

Test connection

Install the screen tool and run screen /dev/ttyACM0 115200 (for USB) or screen /dev/rfcomm0 for Bluetooth. You should see lots of numbers (not well formatted) and numbers should change when you move or shake the hub.

To quit screen press Ctrl+A, then D.

Parallel USB and Bluetooth connections are possible.

The hub’s modes of operation

Turning the hub on it boots (extremly fast) and starts a Python program, which feeds the serial interface with status information (lots of numbers) and provides high-level communication (file transfer from the host, button handling, light matrix,…). Hitting Ctrl+C on the host (in a screen session) stops this program and provides access to the underlying interactive MicroPython interpreter. Here usual MicroPython programming is possible for controlling the hub and attached motors and sensors.

Thus, the hub has two modes: either it run’s its own Python program providing high-level functionality or it provides an interactive interpreter.

Holding the left button while turning on the hub directly enters the interpreter without starting the high-level interface (reference). In this mode the hub does not react to button events (except power down) and communication with the (non-Linux) Spike App is not possible.

Spike Web App

LEGO provides the Spike Web App very similar to the Android App. It runs in Chromium and Chrome, but not in Firefox. Seems to work on Linux without problems, but only via USB connection. Support for Bluetooth serial devices in Chromium/Chrome is still under development.

Pushing and running programs without Spike App

There exist several more or less experimental projects providing open source tools for communicating with the Spike hub. One is LEGO Hub Toolkit. With this tool one can list all programs on the hub, push programs to the hub, and start/stop programs on the hub.

LEGO Hub Toolkit throws some errors due to incorrect paths. Replacing

log_filename = os.path.dirname(__file__) + "/logs/hubstatus.log"

by

log_filename = os.path.dirname(__file__) + "logs/hubstatus.log"

(no slash) in all source files solves the problem.

Host Python to hub Python communication and vice versa

Both USB and Bluetooth provide a bidirectional serial connection between host and hub. On the hub side in low-level mode the MicroPython interpreter is connected to the serial port. In high-level mode programs running on the hub may connect to the serial port and communicate with the host.

Connect host Python program to serial port

Python programs on the host may use whatever library functions to connect to the serial port. Here we use pyserial. The following quick-and-dirty code snipped demonstrates basic usage:

# assuming low-level mode (MicroPython interpreter on hub)

import serial

# USB:
connection = serial.Serial('/dev/ttyACM0', 115200, timeout=0.1)

# Bluetooth:
#connection = serial.Serial('/dev/rfcomm0', timeout=0.1)

# send command to the interpreter
connection.write(('# some Python command' + '\r').encode())

# fetch output
lines = connection.readlines()
for line in lines:
    print(line.decode())

connection.close()

Connect hub Python program to serial port

LEGO’s hub module provides functions for connecting to the serial port. If the hub is in high-level mode (which we assume here), the hub contiuously sends status information to the host. Messages from our Python program will be mixed into this stream of numbers and the host will have to extract them.

Here comes some experimental code for sending messages to the host:

import hub

# USB:
connection = hub.USB_VCP()
connection.init(flow=hub.USB_VCP.CTS | hub.USB_VCP.RTS)

# Bluetooth:
#connection = hub.BT_VCP()

def print_host(message, start_pattern='<<<', end_pattern='>>>'):
    connection.write(start_pattern + message + end_pattern)
    
print_host('some message to the host')

Note that start and end patterns are necessary to find the messages in the stream of status information on the host machine.

Some ideas

With the Python programmable bidirectional serial connection between hub and host complex scenarios can be realized (all not tested at time of writing):

Other useful resources