openbricks is a MicroPython firmware you flash to a commodity ESP32 board. Wire up off-the-shelf servos and sensors, and drive robots with a clean Python API — motor control runs at 1 kHz in native C inside the firmware.
from openbricks.drivers.st3032 import ST3032Motor from openbricks.robotics import DriveBase left = ST3032Motor(servo_id=1, tx=14, rx=6) right = ST3032Motor(servo_id=2, tx=14, rx=6, invert=True) db = DriveBase(left, right, wheel_diameter_mm=56, axle_track_mm=114) db.straight(500) # millimetres db.turn(90) # degrees
An openbricks-powered robot on a WRO-style mission mat — line following on the 10-channel reflectance bar, gyro turns on the ICM-45686, branch counting, and back to base. One minute, real time, no cuts.
The same robot with the drivebase in continuous
mode: each straight() and curve() ends
with then=Stop.NONE, so moves hand their speed straight
to the next one and the run flows through the course without
stopping between segments.
Pybricks gives LEGO users a delightful Python API, but only on LEGO hubs with LEGO motors. openbricks takes the same shape — a custom MicroPython firmware with the robotics library baked into the runtime — and targets parts you can buy anywhere.
The motor scheduler, trapezoidal trajectory planner, state observer, and 2-DOF drivebase controller are compiled C inside the image, ticking at 1 kHz off a hardware timer. Python is for your program, not the hot path.
ESP32-S3 and classic ESP32 boards, Feetech serial-bus servos, DC gear motors with encoders, and I2C sensors from any electronics shop. No proprietary hubs, no vendor lock-in.
One CLI does it all: openbricks flash over USB, then run, upload, stop, and log over BLE — plus a MuJoCo-backed simulator so you can develop without a robot on the desk.
Same programming model, different ceiling. Owning the whole runtime — firmware, tooling, and simulator — lets openbricks ship things a LEGO hub can't.
Every program run — prints, tracebacks, how it started and
ended — is tee'd to flash on the hub. openbricks log
pulls any of the last 10 runs back over BLE, so a
failure on the competition table is debuggable after the fact,
no laptop attached at the time.
The MuJoCo-backed sim runs your program unchanged — same imports, same DriveBase — against a quantitative motor model, and the color sensor reads printed mat artwork byte-accurately. Tune a line follower before the robot exists.
The ICM-45686 is sampled over SPI inside the 1 kHz native control tick — heading integrates in C with no Python in the loop. Gyro bias calibrates itself whenever the robot sits still and persists across boots, so power-on-and-go starts straight.
Daisy-chained serial-bus servos report position, speed, load,
and temperature back over one UART — and a dead or disconnected
wheel raises a loud error naming the exact motor, instead of a
robot that quietly veers. Re-ID a servo from the hub itself with
openbricks servo-id.
Reflectance bars, laser rangefinders, color sensors behind an I2C mux, OLEDs, LED strips — a dozen drivers ship frozen into the firmware, and new hardware just implements one small interface. No waiting for a vendor to bless a part.
The full documentation ships inside the CLI —
openbricks docs opens the same Sphinx build as
docs.openbricks.dev, entirely offline. Competition venues with no
Wi-Fi stop mattering.
Full walkthrough in the installation guide.
pipx install 'openbricks[sim]'
CLI + simulator. Drop [sim] for flash/run/log only.
openbricks flash --name RobotA
Port and chip auto-detected; the newest signed firmware downloads itself.
openbricks run -n RobotA main.py
Pushed over BLE, output streamed back live. Or try it first in the sim: openbricks sim run main.py
Every driver ships frozen into the firmware — import openbricks and go. New components just implement one of the abstract interfaces. Wiring notes in the hardware guide.
| Component | Type | Module |
|---|---|---|
| ST-3032 (Feetech STS3032) | Serial bus servo — recommended drive motor | drivers.st3032 |
| ST-3215 | Serial bus servo — arms / grippers | drivers.st3215 |
| JGB37-520 / MG370 | DC gear motors with quadrature encoders | drivers.jgb37_520, drivers.mg370 |
| L298N / TB6612FNG | H-bridge motor drivers | drivers.l298n, drivers.tb6612 |
| ICM-45686 | 6-axis IMU on SPI — read inside the 1 kHz control tick, the use_gyro heading source | drivers.icm45686 |
| BNO055 | 9-DOF IMU (legacy I2C option) | drivers.bno055 |
| QTRX-HD-15A | 10-channel reflectance bar — line following & edge alignment | drivers.qtr |
| TCS34725 | RGB + clear color sensor | drivers.tcs34725 |
| HC-SR04 / VL53L0X / VL53L1X | Ultrasonic & laser distance sensors | drivers.hcsr04, drivers.vl53l0x, drivers.vl53l1x |
| TCA9548A | 8-channel I2C multiplexer | drivers.tca9548a |
| SSD1306 | OLED display | drivers.ssd1306 |
| WS2812 / WS2812B | Addressable RGB LED strip / stick | drivers.ws2812 |