Interfaces
Core interfaces
Abstract interfaces for openbricks components.
MicroPython doesn’t ship full typing.Protocol support, so these are plain
base classes. Drivers should subclass the appropriate interface and fill in
every method. The higher-level modules (robotics, config) only depend
on these interfaces, never on concrete drivers — that’s what makes the system
plug-and-play.
If you add a new category of component (e.g. a distance sensor), add its interface here.
- class openbricks.interfaces.Motor[source]
Bases:
objectA bidirectional motor.
Implementations range from an open-loop H-bridge driver (L298N) to a closed-loop geared motor with quadrature encoder (JGB37-520).
The method names and semantics follow the Pybricks Prime
MotorAPI (1.21.0):run(speed)is degrees per second, closed loop; the raw-duty command isdc(duty). Additional openbricks methods (coast,run_speed) remain as aliases.Units
dutyis -100..100 (percent duty cycle, sign = direction).speedis degrees per second at the output shaft (closed-loop only).angleis degrees at the output shaft (closed-loop only).
- run(speed)[source]
Run at
speeddegrees per second, closed loop — PybricksMotor.run(). Non-blocking. Concrete: delegates torun_speed()(the openbricks alias), so open-loop drivers surface itsNotImplementedError.BREAKING (1.21.0): before Pybricks parity this method took percent power. That command is now
dc(duty)— a script still callingrun(30)for power gets 30 deg/s instead (slow, not dangerous) orNotImplementedErroron open-loop drivers.
- dc(duty)[source]
Run at a fixed raw duty cycle (-100..100), open loop — Pybricks
Motor.dc(). Non-blocking. This is the pre-1.21.0run().
- stop()[source]
Stop and let the motor spin freely; it gradually stops from friction. Pybricks
Motor.stop()semantics — the default of the three stop flavours (stop/brake/hold), and a concrete method: it delegates tocoast(), so every driver gets it for free.
- hold()[source]
Stop and actively hold the current shaft angle via closed-loop control. Only motors with position-mode hardware (e.g. ST-3215) or a software position loop implement this; open-loop drivers raise
NotImplementedError— pickbrakeorcoastinstead.
- run_angle(deg_per_s, target_angle, wait=True)[source]
Rotate by
target_angledegrees atdeg_per_s. Blocks ifwait; otherwise returns immediately and the caller pollsdone()to advance the move and detect completion.
- done()[source]
Return
Trueif no non-blocking move is in flight or the activerun_angle(wait=False)move has reached its target. Drivers that don’t support non-blocking moves always returnTrue(a wait=True call is finished before returning to the caller, by definition).
- speed()[source]
Measured shaft speed in degrees per second — Pybricks
Motor.speed(). Closed-loop drivers implement it (encoder observer / servo present-speed register).
- load()[source]
Measured torque at the shaft in mNm — Pybricks
Motor.load(). Drivers with load feedback (serial servos) implement it; the value is derived from the servo’s load register and its datasheet stall torque, so treat it as an estimate.
- stalled()[source]
Truewhen the motor is pushing as hard as it can but cannot reach its commanded speed — PybricksMotor.stalled(). Drivers with load feedback implement it.
- run_time(speed, time_ms, then='hold', wait=True)[source]
Run at
speeddeg/s fortime_msms, then stop with thethenflavour — PybricksMotor.run_time().wait=Falseis not supported (no background timer is allocated for it); passwait=Trueor sequence it yourself.
- run_target(speed, target_angle, then='hold', wait=True)[source]
Run to the ABSOLUTE
target_angle(degrees, in thereset_angleframe) at up tospeeddeg/s — PybricksMotor.run_target(). Built on the relativerun_angle: the delta is measured fromangle()at call time.
- run_until_stalled(speed, then='coast', duty_limit=None)[source]
Run at
speeddeg/s untilstalled(), apply thethenflavour, and return the angle where it stalled — PybricksMotor.run_until_stalled()(its defaultthenis Stop.COAST).duty_limitis not supported — the serial servos’ torque limiting is a per-servo register, not a per-call parameter; passNone.
- class openbricks.interfaces.Servo[source]
Bases:
objectA position-controlled servo (angle-addressable).
Distance sensors
Distance-sensor interface, kept separate from interfaces.py.
Why split: openbricks/__init__.py eagerly imports the four core
interfaces (Motor / Servo / IMU / ColorSensor) so that every
import openbricks pays them. The observer’s variance test runs
close to the MicroPython heap ceiling, so adding even a small class
to interfaces.py tips it over. Distance-sensor users explicitly
import this module.