Servo health & characterisation
Every Feetech STS servo reports its own supply voltage, case temperature, supply current and a byte of protection flags, next to the position/speed/load block the drivers already read. Since 3.3.0 that block is one call away, and two bundled programs turn it into the two questions a team actually asks about a servo: what does this particular unit do, and is it still doing it.
health()
from openbricks.drivers.st3032 import ST3032Motor
m = ST3032Motor(servo_id=3, uart_id=1, tx=14, rx=41)
h = m.health()
print(h.voltage, "V", h.temperature, "C", h.current, "A", h.flags)
health() returns a ServoHealth tuple:
Field |
Meaning |
|---|---|
|
supply rail at the servo, volts (0.1 V resolution) |
|
case temperature, °C |
|
supply current, amps (6.5 mA resolution) |
|
the protection flags currently set, as names — |
|
the raw status byte |
It works on position servos (ST3215 / ST3032) and wheel-mode
motors alike, adopted by a DriveBase or on their own bus. It
raises OSError when the bus is silent rather than returning
nothing — a health check that can’t reach the servo is the failure
it exists to catch. On an adopted motor the four registers are staged
through the native bus pump, which takes a few milliseconds: read it
for a log line, not inside a control loop.
The ST-3032’s own protections, from its datasheet, are the numbers to read the fields against: it cuts torque above 80 °C, flags over-voltage outside 9–14 V, and latches overload after 2 s above 80 % of stall (re-issuing a command clears it). Nominal current is 100 mA free-running, 500 mA at rated load, 1.6 A stalled.
Dynamometer: what does this servo do?
examples/st3032_dyno.py characterises one servo against a second
one, the way actuator labs do it with a load motor — minus the load
cells. Couple two ST-3032s horn to horn with a rigid coupler and bolt
the pair down. The servo under test drives at a fixed duty; the load
servo opposes it with a duty that steps up from 0 to 30 %; at each
step the program averages the driven servo’s speed and supply
current. The current above the unloaded baseline, times the motor
constant (6.3 kg·cm/A, ST3032Motor.KT_MNM_PER_A), is the shaft
torque, so the sweep yields a torque–speed line, and a DC motor
behind a gearbox droops linearly — the fit’s intercepts are the
unit’s no-load speed and stall torque at that duty, scaled
to 100 % in the summary. A gentle reversal against the held load
servo at the end measures the pair’s combined gear play.
load_duty_pct,speed_dps,current_a,torque_mnm
0,262.4,0.118,0.0
5,251.0,0.151,20.4
...
# --- dyno summary ---
servo 1 at 30 % duty: no-load 263 dps, stall 226 mNm (2.30 kg.cm), droop -1.16 dps per mNm
scaled to 100 % duty: stall ~753 mNm, datasheet 980; no-load ~877 dps, datasheet 888
combined gear play of the pair: 0.95 deg (datasheet <= 1.0 per servo)
Run it on every servo you own and keep the summary lines. The
numbers are not lab-grade — the torque rides on a datasheet
constant, and the stall figure is an extrapolation from a 30 % sweep
(the bench cap; raise DUTY and LOAD_STEPS only with the pair
bolted down) — but they are consistent, which is what matters:
the unit whose no-load speed or stall sits well off its siblings is
the one to keep out of the drive pair, and a pair that measures
alike will track alike under DriveBase. The simulator’s servos are
ideal velocity loops, so there is nothing to feed these numbers
into; they are for choosing and comparing hardware.
Soak test: is it still good?
examples/st3032_soak_test.py runs one servo through ±90° swings
for an hour (DURATION_MIN) and every REPORT_EVERY cycles logs
health() plus the servo’s gear play — one target approached from
below and from above under hold, the difference between the two rest
angles. The summary is the drift from the first report to the last:
# --- soak summary ---
1780 cycles: temperature +14 C (peak 46 C, shutdown at 80), current +0.021 A, play +0.08 deg, supply dipped to 11.4 V
What to look for: a temperature that keeps climbing instead of levelling off, play that grows through the run, current that rises at the same speed and load, or any protection flag at all. Each is a servo to retire — or a wiring/battery problem to fix — before it shows up on the mat. Feetech’s own life test is 50 000 cycles at a fifth of stall torque; an hour is a couple of thousand, enough to expose a unit that is already going.