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: object

A 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 Motor API (1.21.0): run(speed) is degrees per second, closed loop; the raw-duty command is dc(duty). Additional openbricks methods (coast, run_speed) remain as aliases.

Units

  • duty is -100..100 (percent duty cycle, sign = direction).

  • speed is degrees per second at the output shaft (closed-loop only).

  • angle is degrees at the output shaft (closed-loop only).

run(speed)[source]

Run at speed degrees per second, closed loop — Pybricks Motor.run(). Non-blocking. Concrete: delegates to run_speed() (the openbricks alias), so open-loop drivers surface its NotImplementedError.

BREAKING (1.21.0): before Pybricks parity this method took percent power. That command is now dc(duty) — a script still calling run(30) for power gets 30 deg/s instead (slow, not dangerous) or NotImplementedError on 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.0 run().

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 to coast(), so every driver gets it for free.

brake()[source]

Stop with active braking (both terminals shorted).

coast()[source]

Stop by cutting drive power (motor free-wheels).

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 — pick brake or coast instead.

angle()[source]

Return the current shaft angle in degrees.

reset_angle(angle=0)[source]

Set the current angle to angle degrees.

run_speed(deg_per_s)[source]

Hold a target speed (closed loop).

run_angle(deg_per_s, target_angle, wait=True)[source]

Rotate by target_angle degrees at deg_per_s. Blocks if wait; otherwise returns immediately and the caller polls done() to advance the move and detect completion.

done()[source]

Return True if no non-blocking move is in flight or the active run_angle(wait=False) move has reached its target. Drivers that don’t support non-blocking moves always return True (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]

True when the motor is pushing as hard as it can but cannot reach its commanded speed — Pybricks Motor.stalled(). Drivers with load feedback implement it.

run_time(speed, time_ms, then='hold', wait=True)[source]

Run at speed deg/s for time_ms ms, then stop with the then flavour — Pybricks Motor.run_time(). wait=False is not supported (no background timer is allocated for it); pass wait=True or sequence it yourself.

run_target(speed, target_angle, then='hold', wait=True)[source]

Run to the ABSOLUTE target_angle (degrees, in the reset_angle frame) at up to speed deg/s — Pybricks Motor.run_target(). Built on the relative run_angle: the delta is measured from angle() at call time.

run_until_stalled(speed, then='coast', duty_limit=None)[source]

Run at speed deg/s until stalled(), apply the then flavour, and return the angle where it stalled — Pybricks Motor.run_until_stalled() (its default then is Stop.COAST).

duty_limit (percent, 0 < limit <= 100) caps the motor’s torque for the duration of the run — the Pybricks gripper- homing pattern: drive gently into the end stop without crushing it. The cap is applied before the motion starts and restored afterwards, stall or not. Drivers opt in via _duty_limit_push / _duty_limit_pop (the ST3215/ ST3032 serial servos implement it as a temporary torque- limit register write; their stall detection scales to the cap).

class openbricks.interfaces.Servo[source]

Bases: object

A position-controlled servo (angle-addressable).

move_to(angle_deg, speed=None, wait=True)[source]

Move to absolute angle in degrees.

angle()[source]

Read back the current angle.

class openbricks.interfaces.IMU[source]

Bases: object

A 3-axis inertial measurement unit.

The expected unit convention is:
  • heading/yaw/pitch/roll in degrees

  • angular_velocity in degrees / second

  • acceleration in m / s^2

heading()[source]

Return heading (yaw) in degrees, wrapped to [-180, 180).

angular_velocity()[source]

Return (wx, wy, wz) in deg/s.

acceleration()[source]

Return (ax, ay, az) in m/s^2.

class openbricks.interfaces.ColorSensor[source]

Bases: object

An RGB-ish color sensor.

rgb()[source]

Return (r, g, b) each in 0..255.

ambient()[source]

Return ambient / clear-channel intensity in 0..100.

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.

class openbricks.distance.DistanceSensor[source]

Bases: object

A forward-facing range sensor (HC-SR04 / VL53L0X).

distance_mm()[source]

Distance ahead in millimetres; -1 if no echo / out of range.