Extension protocol v9.0
Exact wire format for your own client. Read the session lifecycle first; register layouts define field sizes, offsets and ranges. An instruction and a block selector are separate packet fields even when their numeric values coincide.
This section describes the exact messages exchanged between the host and servo. It is intended for readers connecting their own software.
Message format and number encoding
Each message is a packet: a sequence of bytes containing the destination, command, data, and a checksum used to detect transmission errors. Extension commands use the standard STS packet format:
Request: FF FF ID LENGTH INSTRUCTION PARAMETERS... CHECKSUM
Response: FF FF ID LENGTH LEGACY_ERROR EXT_STATUS DATA... CHECKSUM
- Request
LENGTH = parameter_bytes + 2. - Response
LENGTH = data_bytes + 3; the extension status occupies the first response parameter, separately from the normal legacy error byte. CHECKSUM = ~(ID + LENGTH + instruction_or_error + all_parameter_bytes) & 0xFF. The response sum includesEXT_STATUSand any data.- A field occupying several bytes sends the least significant byte first
(little-endian). For example, the number 256 is sent as
00 01in two bytes. u8,u16, andu32are nonnegative whole numbers occupying 1, 2, and 4 bytes.i16andi32occupy 2 and 4 bytes and can also represent negative numbers. Signed extension values use two’s complement: for example, −1 isFF FFin ani16field. This differs from the legacy encoding of signed values.- Q8 means a value is multiplied by 256 before transmission so fractions can be represented as whole numbers. Divide by 256 when reading it. For example, position 1000 counts is sent as 256000, and gain 4.5 is sent as 1152.
- Position is in encoder counts and velocity is in counts/s. The host handles any conversion to joint angles, including changes of direction or zero position.
- Unicast means a message addressed to one servo. Broadcast uses ID
0xFEand reaches all servos. Broadcast extension commands never generate replies.
Example: read the 8-byte capabilities block from servo ID 1:
FF FF 01 04 90 90 08 D2
A selector identifies a complete register block, such as configuration or feedback. Access it with extension READ/WRITE and the exact block size listed below. Reading or writing just part of a block is unsupported, and the legacy READ/WRITE commands cannot access these blocks.
Instructions
The parameter sizes below exclude the packet header and checksum. In a reply,
EXT_STATUS reports whether the extension command succeeded, separately from
LEGACY_ERROR, the servo’s normal error byte. A successful read adds the requested
data after EXT_STATUS; writes, other commands, and failed reads have no extra
data.
| Instruction | Name | Parameters | Broadcast |
|---|---|---|---|
0x90 |
READ | selector:u8, count:u8 |
No useful response |
0x91 |
WRITE | selector:u8, block... |
Not accepted |
0x99 |
GRAVITY | 6 bytes, below | Not accepted |
0x9A |
TARGETS | session:u16 + 1–6 entries of 9 bytes |
Accepted |
Instruction numbers 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, and 0x98, and selectors 0xA1, 0xA3,
0xB0, 0xBA, 0xE0, and 0xF0, are reserved and must not be used.
| Extension status | Meaning |
|---|---|
0 |
OK |
1 |
Invalid length, selector, or field value |
2 |
Command cannot be accepted in the current state |
3 |
Reserved |
4 |
Reserved |
5 |
Unsupported instruction |
A session mismatch returns a state failure. Inspect both the legacy error byte and extension status.
Sessions and sequence numbers
The host assigns each session a number from 1 to 65535 and includes it in control commands. This lets the servo check that a command belongs to the current session. Choose a new number for each startup; setup numbers are not stored permanently.
A sequence number counts accepted commands in order, allowing the host and servo to identify missing, repeated, or out-of-order commands.
TARGETS has a per-servo motion sequence counter. GRAVITY has a separate counter. Both start at zero when torque enable starts control; normally send 1 first. Numbers increase through 65535 and then wrap to 0, without ending the session. Gaps are allowed: after 10, the servo may accept 12 even if 11 was lost or rejected. Equal or older numbers are rejected without changing the current command.
For an exact comparison, calculate distance = (incoming − accepted) & 0xFFFF.
A command is newer only when 1 ≤ distance ≤ 32767. A jump of exactly 32768 is
ambiguous and rejected. Keep the gap from the last accepted command below 32768;
if command history is uncertain, turn torque off, prepare a new session ID, and enable torque again.
Do not reuse queued packets from an earlier session or counter cycle.
Acceptance still requires valid fields, current sensor readings, and a feasible movement. A rejected command does not advance its counter. These commands replace absolute targets; they are not a waypoint queue. To visit every waypoint, wait for each arrival before sending the next destination.
When sending a group target, read each servo’s feedback to verify its accepted sequence. Each servo decides independently whether it can accept its target; one may reject it while the others start moving.
TARGETS — 0x9A
The first two parameter bytes contain the shared session. Each following entry has this layout; offsets are relative to the start of that entry:
| Offset | Type | Field |
|---|---|---|
| 0 | u8 |
Servo ID, 1–253 |
| 1 | u16 |
Newer motion sequence for this servo |
| 3 | i32 |
Destination position, Q8 counts |
| 7 | u16 |
Maximum speed, counts/s, nonzero |
The parameter length is 2 + 9 × entry_count, at most 56 bytes. IDs must be
unique. Each servo checks the format and required fields of all entries
before handling its own. A servo that is not listed does nothing. A listed servo
checks its session, sequence, readiness, and whether the movement can stay within
its limits. An accepted target starts immediately and stays active until replaced
or disarmed. Values are capped at the configured limits as described under
S-curve motion.
GRAVITY — 0x99
| Offset | Type | Field / constraint |
|---|---|---|
| 0 | u16 |
Current session |
| 2 | u16 |
Newer gravity sequence |
| 4 | i16 |
Desired gravity effort; magnitude ≤ configured output limit |
The parameter length is exactly 6 bytes. Requires an armed session with motor power on, ready hardware, no reported fault, and recent sensor readings. It does not advance the motion sequence. The requested value remains active until replaced or disarmed.
Check a client implementation
Check length, checksum, Legacy error and Extension status separately. Confirm group TARGETS through each listed servo’s feedback: successful broadcast transmission is not acceptance. If sequence history is uncertain, release torque and prepare a new session rather than blindly continuing an old packet queue.
The existing driver encodes and decodes through host/servo-driver/registers/ArmCodec.js and host/servo-driver/bus/ArmExtension.js. Firmware implements the wire format in firmware/app/arm_extension.c.
Documentation home · Source revision: a995f77. Extension 9.0.
