Source code for openbricks.drivers.st3032

# SPDX-License-Identifier: MIT
"""
ST-3032 (Feetech STS3032) serial bus servo.

Smaller sibling of the ST-3215 — same SCS protocol, same 4096-count
12-bit magnetic encoder, same operating modes (0 = position,
1 = wheel), same default 1 Mbps bus. The only differences are
mechanical / electrical.

Full datasheet: ``docs/datasheets/feetech_sts3032.pdf`` (model
ST-3032-C062, Edition A/0 2025-11-30). Headline specs at typical
12 V operation, all ±10% per Feetech::

    Working voltage      9–14 V (typ 12 V)        ST-3215 typ 6–12.6 V
    No-load speed        0.067 s/60° = 148 RPM = 888 °/s
                         (``ST3032Motor`` defaults ``max_dps`` to
                         this — the ST-3215's protective 600 default
                         capped the wire command well below what the
                         servo can do)
    Stall torque         10 kg·cm (139 oz·in)     ST-3215 ~30 kg·cm
    Stall current        1.6 A
    Rated torque         3.3 kg·cm (1/3 of stall)
    Rated current        500 mA
    No-load current      100 mA
    Idle current         20 mA
    Kt                   6.3 kg·cm/A
    Size                 23 × 12 × 27.5 mm        ST-3215 larger
    Weight               20.6 g
    Gear                 1/205, coreless motor
    Backlash             ≤ 1.0°
    Over-temp shutdown   80 °C
    Over-current         > 80 % stall for 2 s
    Max position update  1 ms

Because the wire protocol is identical, ``ST3032`` and ``ST3032Motor``
are thin marker subclasses of ``ST3215`` / ``ST3215Motor`` with no
behavioural override. Use them when your bench actually carries an
ST-3032 — the typed name documents the hardware and gives us a place
to specialise defaults later (lower max_dps, torque caps) if hardware
testing surfaces a real difference.

ST-3032 and ST-3215 instances on the same UART share the bus
registry, so mixing them on one daisy chain is fine — each servo is
addressed by its 1-byte ID regardless of model.

⚠ Voltage rail: an ST-3032 will brown out below ~9 V. Don't share a
6 V bus with ST-3215s; budget a separate 12 V rail.
"""

from openbricks.drivers.st3215 import (
    ST3215,
    ST3215Motor,
    _DEFAULT_STEPS_PER_DPS,
)

# Datasheet no-load speed at typical 12 V: 0.067 s/60° = 888 °/s.
# Used as ``ST3032Motor``'s ``max_dps`` default so the driver-side
# clamp sits AT the servo's ceiling instead of 288 °/s under it —
# ``max_dps`` is a wire-command clamp, and the inherited ST-3215
# default (600) silently capped top speed on the bench.
ST3032_NO_LOAD_DPS = 888.0


[docs] class ST3032(ST3215): """One ST-3032 in position-servo mode (Servo interface). Behaves identically to ``ST3215`` — see that class for the full API. Subclassed only to let user code spell the actual hardware in place. """
[docs] class ST3032Motor(ST3215Motor): """One ST-3032 in wheel/continuous-rotation mode (Motor interface). Behaves identically to ``ST3215Motor`` — see that class for ``run_speed`` / ``angle`` / ``run_angle`` semantics — except for ONE specialised default: ``max_dps`` matches the ST-3032's datasheet no-load speed (888 °/s) instead of the ST-3215's 600, so the driver clamp can't cap the servo below its own spec. """ # ST-3032 @ 12 V: 10 kg·cm ~= 980 mNm (datasheet §5-3). STALL_TORQUE_MNM = 980.0 def __init__(self, servo_id, uart_id=1, tx=14, rx=41, baud=1_000_000, dir_pin=None, invert=False, steps_per_dps=_DEFAULT_STEPS_PER_DPS, max_dps=ST3032_NO_LOAD_DPS, accel_dps2=1500.0, raise_on_stall=False, stall_idle_ms=1000): super().__init__( servo_id, uart_id=uart_id, tx=tx, rx=rx, baud=baud, dir_pin=dir_pin, invert=invert, steps_per_dps=steps_per_dps, max_dps=max_dps, accel_dps2=accel_dps2, raise_on_stall=raise_on_stall, stall_idle_ms=stall_idle_ms)