CAN Protocol¶
The register command set is intended for use in real-time applications. It provides multiple levels of conciseness, and is possible to operate at over 1kHz on the provided FD-CAN communications bus.
Common definitions:
- endian-ness: All primitive types are in least significant byte first
- varuint: A sequence of one or more uint8 values, in least significant byte first order. For each value, the 7 LSBs contain data and if the MSB is set, it means there are more bytes remaining. At most, it may represent a single uint32 and thus 5 bytes is the maximum valid length.
- float: An IEEE 754 32-bit floating point number.
CAN Format¶
Communication with moteus is conducted via CAN-FD frames with a 1Mbit standard bitrate and a 5Mbit data bitrate.
CAN ID¶
The ID is structured as a 16 bit number, with the high 8 bits being the "source" and the low 8 bits being the "destination". The destination is the 7 bit servo ID with 0 as the highest bit. The source is an arbitrary 7 bit number, with the high bit being 1 if moteus should reply to the message.
The CAN frame must be an extended one if the ID would be greater than 0x7fff, but otherwise whether or not a frame is extended is not considered.
Example:
ID: 0x8001 * Send from source 0 * To destination 1 * 16th bit is set, so a reply is requested
ID: 0x100 * Send from source 1 * To destination 0 * No reply is requested
Subframes¶
Each CAN-FD frame contains one or more "subframes". A short description of the allowable subframe types are described below. The canonical reference is located at multiplex/format.h
Any extra trailing padding bytes required in the CAN-FD frame should be set to NOP (0x50).
Write Registers¶
0x00, 0x04, 0x08, 0x0c - write (int8|int16|int32|float)
- varuint=> number of registers (may be optionally encoded as a non-zero 2 LSBS of the subframe type)
- varuint=> start register number
- N x (int8|int16|int32|float) => values
Read Registers¶
0x10, 0x14, 0x18, 0x1c - read (int8|int16|int32|float)
- varuint=> number of registers (may be optionally encoded as a non-zero 2 LSBs)
- varuint=> start register number
Reply¶
0x20, 0x24, 0x28, 0x2c - reply (int8|int16|int32|float)
- varuint=> number of registers (may be optionally encoded as a non-zero 2 LSBs)
- varuint=> start register number
- N x (int8|int16|int32|float) => values
Errors¶
0x30, 0x31 - write/read error
- varuint=> register number
- varuint=> error number
NOP¶
0x50 - no operation
Example¶
A single CAN-FD frame can be used to command the servo, and initiate a query of certain registers. An example frame might look like the following, encoded in hex with annotations.
- 01- write a single int8 register (number of registers is encoded in the 2 LSBs)
- 00- start register number "Mode"
- 0a- "position" mode
- 07- write 3x int16 registers (number of registers is encoded in the 2 LSBs)
- 20- register 0x020
- 6000- position = 0x0060 = 96 = 3.456 degrees
- 2001- velocity = 0x0120 = 288 = 25.92 dps
- 50ff- feedforward torque = 0xff50 = -176 = 1.76 N*m
- 14- read int16 registers
- 04- read 4 registers
- 00- starting at 0x000 (so 0x000 Mode, 0x001 Position, 0x002 Velocity, 0x003 Torque)
- 13- read 3x int8 registers
- 0d- starting at 0x00d (so 0x00d Voltage, 0x00e Temperature, 0x00f Fault code)
Thus the whole CAN-FD message would be (in hex):
01000a07206000200150ff140400130d
To send this using the fdcanusb converter to a device configured at the default address of 1, you could write.
can send 8001 01000a07206000200150ff140400130d
The 80 in ID is used for two purposes.  The high bit being set
forces the device to respond (otherwise it will not respond, even if
query commands are sent).  The remaining bits are the "ID" to respond
to.  In response to this command, a possible response from the servo
would look like:
rcv 100 2404000a005000000170ff230d181400
Decoded, that means:
- 
100from device "1" to device "0"
- 
24reply with int16 values
- 044 registers
- 00starting at register 0
- 0a00in mode 10 - Position
- 5000position is 0x0050 = 80 = 2.88 degrees
- 0001velocity is 0x0100 = 256 = 23.04 dps
- 70fftorque is 0xff70 = -144 = -1.44 Nm
- 23reply with 3 int8 values
- 0dstarting at register 0x00d
- 18voltage is 12V
- 14temperature is 20C
- 00no fault