Skip to article

Extension protocol v9.0

Checked 2026-11-01

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.

Extension-protocol unicast request and response

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 includes EXT_STATUS and any data.
  • A field occupying several bytes sends the least significant byte first (little-endian). For example, the number 256 is sent as 00 01 in two bytes.
  • u8, u16, and u32 are nonnegative whole numbers occupying 1, 2, and 4 bytes. i16 and i32 occupy 2 and 4 bytes and can also represent negative numbers. Signed extension values use two’s complement: for example, −1 is FF FF in an i16 field. 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 0xFE and 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.