CAN Protocol
Note
This document describes the CAN Protocol. For examples of usage, check out our CAN Guide!
CAN Frame
At its most basic, a CAN Simple message ID is 11 bits, interpreted as follows:
Upper 6 bits - Node ID - max 0x3F
Lower 5 bits - Command ID - max 0x1F
For example, an Axis ID of 0x01
with a command of 0x0C
would be result in a message ID 0x2C
:
can_id = axis_id << 5 | cmd_id
0x01 << 5 | 0x0C = 0x2C
Messages
See the .dbc file for the description of all messages. We recommend the free CANdb++ software from Vector for viewing and editing this database.
CMD ID |
Name |
Sender |
Signals |
Start Byte |
Signal Type |
Bits |
Factor |
Offset |
---|---|---|---|---|---|---|---|---|
0x000 |
Get_Version |
ODrive_Axis0 |
Protocol_Version Hw_Version_Major Hw_Version_Minor Hw_Version_Variant Fw_Version_Major Fw_Version_Minor Fw_Version_Revision Fw_Version_Unreleased |
0 1 2 3 4 5 6 7 |
Unsigned Int Unsigned Int Unsigned Int Unsigned Int Unsigned Int Unsigned Int Unsigned Int Unsigned Int |
8 8 8 8 8 8 8 8 |
1 1 1 1 1 1 1 1 |
0 0 0 0 0 0 0 0 |
0x001 |
Heartbeat |
ODrive_Axis0 |
Axis_Error Axis_State Procedure_Result Trajectory_Done_Flag |
0 4 5 6 |
Unsigned Int Unsigned Int Unsigned Int Unsigned Int |
32 8 8 1 |
1 1 1 1 |
0 0 0 0 |
0x002 |
Estop |
Master |
||||||
0x003 |
Get_Error |
ODrive_Axis0 |
Active_Errors Disarm_Reason |
0 4 |
Unsigned Int Unsigned Int |
32 32 |
1 1 |
0 0 |
0x004 |
RxSdo |
None |
Endpoint_ID |
1 |
Unsigned Int |
16 |
1 |
0 |
0x005 |
TxSdo |
None |
Endpoint_ID |
1 |
Unsigned Int |
16 |
1 |
0 |
0x006 |
Set_Axis_Node_ID |
Master |
Axis_Node_ID |
0 |
Unsigned Int |
32 |
1 |
0 |
0x007 |
Set_Axis_State |
Master |
Axis_Requested_State |
0 |
Unsigned Int |
32 |
1 |
0 |
0x009 |
Get_Encoder_Estimates |
ODrive_Axis0 |
Pos_Estimate Vel_Estimate |
0 4 |
IEEE 754 Float IEEE 754 Float |
32 32 |
1 1 |
0 0 |
0x00b |
Set_Controller_Mode |
Master |
Control_Mode Input_Mode |
0 4 |
Unsigned Int Unsigned Int |
32 32 |
1 1 |
0 0 |
0x00c |
Set_Input_Pos |
Master |
Input_Pos Vel_FF Torque_FF |
0 4 6 |
IEEE 754 Float Signed Int Signed Int |
32 16 16 |
1 0.001 0.001 |
0 0 0 |
0x00d |
Set_Input_Vel |
Master |
Input_Vel Input_Torque_FF |
0 4 |
IEEE 754 Float IEEE 754 Float |
32 32 |
1 1 |
0 0 |
0x00e |
Set_Input_Torque |
Master |
Input_Torque |
0 |
IEEE 754 Float |
32 |
1 |
0 |
0x00f |
Set_Limits |
Master |
Velocity_Limit Current_Limit |
0 4 |
IEEE 754 Float IEEE 754 Float |
32 32 |
1 1 |
0 0 |
0x011 |
Set_Traj_Vel_Limit |
Master |
Traj_Vel_Limit |
0 |
IEEE 754 Float |
32 |
1 |
0 |
0x012 |
Set_Traj_Accel_Limits |
Master |
Traj_Accel_Limit Traj_Decel_Limit |
0 4 |
IEEE 754 Float IEEE 754 Float |
32 32 |
1 1 |
0 0 |
0x013 |
Set_Traj_Inertia |
Master |
Traj_Inertia |
0 |
IEEE 754 Float |
32 |
1 |
0 |
0x014 |
Get_Iq |
ODrive_Axis0 |
Iq_Setpoint Iq_Measured |
0 4 |
IEEE 754 Float IEEE 754 Float |
32 32 |
1 1 |
0 0 |
0x015 |
Get_Temperature |
ODrive_Axis0 |
FET_Temperature Motor_Temperature |
0 4 |
IEEE 754 Float IEEE 754 Float |
32 32 |
1 1 |
0 0 |
0x016 |
Reboot |
Master |
||||||
0x017 |
Get_Bus_Voltage_Current |
ODrive_Axis0 |
Bus_Voltage Bus_Current |
0 4 |
IEEE 754 Float IEEE 754 Float |
32 32 |
1 1 |
0 0 |
0x018 |
Clear_Errors |
Master |
||||||
0x019 |
Set_Absolute_Position |
Master |
Position |
0 |
IEEE 754 Float |
32 |
1 |
0 |
0x01a |
Set_Pos_Gain |
Master |
Pos_Gain |
0 |
IEEE 754 Float |
32 |
1 |
0 |
0x01b |
Set_Vel_Gains |
Master |
Vel_Gain Vel_Integrator_Gain |
0 4 |
IEEE 754 Float IEEE 754 Float |
32 32 |
1 1 |
0 0 |
0x01c |
Get_Torques |
ODrive_Axis0 |
Torque_Target Torque_Estimate |
0 4 |
IEEE 754 Float IEEE 754 Float |
32 32 |
1 1 |
0 0 |
0x01d |
Get_Controller_Error |
ODrive_Axis0 |
Controller_Error |
0 |
Unsigned Int |
32 |
1 |
0 |
0x01f |
Enter_DFU_Mode |
Master |
Note
Messages labeled GET_ are call & response. The Master node sends a message with the RTR bit set, and the axis responds with the same ID and specified payload.
The CANopen NMT message is reserved by CANSimple. It is not currently used or implemented.
All multibyte values are little endian (aka Intel format, aka least significant byte first).
Cyclic Messages
Cyclic messages are sent by ODrive on a timer without a request.
The cycle times can be configured for each axis, see axis.config.can
. A cycle time of 0
disables the message.
Watchdog
Each valid CAN message resets the ODrive Watchdog. If CAN communication is disrupted and the watchdog expires, the axis will be put into IDLE.
See axis.config.enable_watchdog
for more information.
DBC Files
The CANSimple .dbc file for each firmware version can be downloaded here.
Interoperability with CANopen
You can deconflict with CANopen like this:
odrv0.axis0.config.can.node_id = 0x010
- Reserves messages 0x200 through 0x21Fodrv0.axis1.config.can.node_id = 0x018
- Reserves messages 0x300 through 0x31F
It may not be obvious, but this allows for some compatibility with CANOpen. Although the address space 0x200 and 0x300 correspond to receive PDO base addresses, we can guarantee they will not conflict if all CANopen node IDs are >= 32. E.g.:
CANopen nodeID = 35 = 0x23
Receive PDO 0x200 + nodeID = 0x223, which does not conflict with the range [0x200 : 0x21F]
Be careful that you don’t assign too many nodeIDs per PDO group. Four CAN Simple nodes (32*4) is all of the available address space of a single PDO. If the bus is strictly ODrive CAN Simple nodes, a simple sequential Node ID assignment will work fine.