CAN Protocol

Note

This document describes the CAN Protocol. For examples of usage, check out our CAN Bus Guide.

Overview

  • The ODrive CANSimple protocol uses standard 11-bit message identifiers.

    CANSimple Message ID

    CANSimple Message ID

  • Messages prefixed with Set_ are messages that the host can send to the ODrive.

  • Messages prefixed with Get_ are messages that the ODrive can send to the host. These messages can be enabled as Cyclic Messages or requested explicitly by the master. To explicitly request a message, the master sends a message with the RTR bit set, and the ODrive responds with the same ID and corresponding payload. (A message with of RTR=0 and an empty payload can also be used, but is susceptible to collisions with the ODrive’s response.)

  • All values are encoded in little endian (aka Intel format, aka least significant byte first).

  • Floats are encoded with the standard IEEE 754 Float format.

CAN Messages - click on the message name for details

CMD ID

Name

Direction

Signals

0x000

Get_Version

ODrive → Host

Protocol_Version

Hw_Version_Major

Hw_Version_Minor

Hw_Version_Variant

Fw_Version_Major

Fw_Version_Minor

Fw_Version_Revision

Fw_Version_Unreleased

0x001

Heartbeat

ODrive → Host

Axis_Error

Axis_State

Procedure_Result

Trajectory_Done_Flag

0x002

Estop

Host → ODrive

0x003

Get_Error

ODrive → Host

Active_Errors

Disarm_Reason

0x004

RxSdo

Host → ODrive

Opcode

Endpoint_ID

Reserved

Value

0x005

TxSdo

ODrive → Host

Reserved0

Endpoint_ID

Reserved1

Value

0x006

Address

Host → ODrive, ODrive → Host

Node_ID

Serial_Number

0x007

Set_Axis_State

Host → ODrive

Axis_Requested_State

0x009

Get_Encoder_Estimates

ODrive → Host

Pos_Estimate

Vel_Estimate

0x00b

Set_Controller_Mode

Host → ODrive

Control_Mode

Input_Mode

0x00c

Set_Input_Pos

Host → ODrive

Input_Pos

Vel_FF

Torque_FF

0x00d

Set_Input_Vel

Host → ODrive

Input_Vel

Input_Torque_FF

0x00e

Set_Input_Torque

Host → ODrive

Input_Torque

0x00f

Set_Limits

Host → ODrive

Velocity_Limit

Current_Limit

0x011

Set_Traj_Vel_Limit

Host → ODrive

Traj_Vel_Limit

0x012

Set_Traj_Accel_Limits

Host → ODrive

Traj_Accel_Limit

Traj_Decel_Limit

0x013

Set_Traj_Inertia

Host → ODrive

Traj_Inertia

0x014

Get_Iq

ODrive → Host

Iq_Setpoint

Iq_Measured

0x015

Get_Temperature

ODrive → Host

FET_Temperature

Motor_Temperature

0x016

Reboot

Host → ODrive

Action

0x017

Get_Bus_Voltage_Current

ODrive → Host

Bus_Voltage

Bus_Current

0x018

Clear_Errors

Host → ODrive

Identify

0x019

Set_Absolute_Position

Host → ODrive

Position

0x01a

Set_Pos_Gain

Host → ODrive

Pos_Gain

0x01b

Set_Vel_Gains

Host → ODrive

Vel_Gain

Vel_Integrator_Gain

0x01c

Get_Torques

ODrive → Host

Torque_Target

Torque_Estimate

0x01d

Get_Powers

ODrive → Host

Electrical_Power

Mechanical_Power

0x01f

Enter_DFU_Mode

Host → ODrive

Cyclic Messages

The ODrive can be configured to send some messages periodically without a request from the host. This is done by setting the desired send intervals in <odrv>.axis.config.can. An interval of 0 disables the message. If the ODrive is unaddressed (node_id = 0x3f), all cyclic messages are disabled regardless of their configured interval.

Message

Configuration (<odrv>.axis.config.can.[...])

Default Interval

Heartbeat

heartbeat_msg_rate_ms

100 ms

Get_Encoder_Estimates

encoder_msg_rate_ms

10 ms

Get_Iq

iq_msg_rate_ms

disabled

Get_Error

error_msg_rate_ms

disabled

Get_Temperature

temperature_msg_rate_ms

disabled

Get_Bus_Voltage_Current

bus_voltage_msg_rate_ms

disabled

Get_Torques

torques_msg_rate_ms

disabled

Watchdog

The ODrive’s watchdog timer can be used as a safety feature to disable the motor when CAN communication is disrupted.

See axis.config.enable_watchdog on how to enable the watchdog timer.

The watchdog is reset by every Set_Input_Pos, Set_Input_Vel and Set_Input_Torque message, as well as when entering CLOSED_LOOP_CONTROL through Set_Axis_State.

DBC Files

DBC files are machine-readable database files that describe CAN message formats.

The CANSimple .dbc file for each firmware version can be downloaded here.

Several tools and libraries exist to ingest DBC files. For example you can use the free CANdb++ software from Vector to view the database.

Broadcast

New in Firmware 0.6.9

The node ID 0x3f is a special broadcast address. When the host sends a message with this ID, it is received by all ODrives on the bus. If the broadcast message yields a response (typically Get_ messages with RTR=1), each ODrive responds with its own node_id.

If an ODrive is configured with node_id = 0x3f, it does not send out any cyclic messages or responses, except for the special message Address.

Discovery & Addressing

New in Firmware 0.6.9

By default, an unconfigured ODrive starts with node_id = 0x3f, which represents an unaddressed state. In this state the ODrive does not send any cyclic messages (heartbeats, feedback, …).

The node ID can be configured:

  • Over USB using odrivetool or in the GUI.

  • Via CAN using automatic enumeration based on the Address (0x06) message. An interactive script for this is provided in Setting up the ODrive (CAN only) which should be sufficient for most commissioning scenarios.

    Otherwise, a user application can implement its own procedure based on the use cases below.

Use cases:

  • Enumerate all ODrives on the bus:

    Send (node_id = 0x3f, cmd_id = 0x06, RTR=1).

    All ODrives that are already addressed (node_id != 0x3f) will respond immediately with their serial number and node_id.

    All unaddressed ODrives (node_id == 0x3f) will respond after a small random delay, averaging 250 ms between each message.

  • Assign a new node ID (N) to an ODrive with unknown node ID and known serial number (SN):

    Send (node_id = 0x3f, cmd_id = 0x06, Node_ID = N, Serial_Number = SN).

    If the ODrive was at its default configuration, it will now start periodically sending Heartbeat and Get_Encoder_Estimates messages.

  • Assign a new node ID (new_N) to an ODrive with known node ID (old_N) and unknown serial number:

    Send (node_id = old_N, cmd_id = 0x06, Node_ID = new_N, Serial_Number = 0).

Furthermore, the Identify field in Clear_Errors can be used to blink the status LED. This allows for setting up an interactive procedure that lets the user associate newly discovered unconfigured ODrives with their location in a multi-axis robot.

Interoperability with CANopen

ODrives can coexist with CANopen devices on the same bus if caution is taken with the node ID assignment.

The following table lists the valid combinations of node IDs for both CANopen and CANsimple.

CANOpen node IDs

ODrive CANSimple node IDs

32 … 127

0x10, 0x18, 0x20, 0x28

64 … 127

0x10, 0x11, 0x18, 0x19, 0x20, 0x21, 0x28, 0x29

96 … 127

0x10, 0x11, 0x12, 0x18, 0x19, 0x1A, 0x20, 0x21, 0x22, 0x28, 0x29, 0x2A

Messages

Get_Version

  • Command ID: 0x00

  • Direction: ODrive → Host

Start Byte

Name

Type

Description

0

Protocol_Version

uint8

Always reported as 2

1

Hw_Version_Major

uint8

hw_version_major

2

Hw_Version_Minor

uint8

hw_version_minor

3

Hw_Version_Variant

uint8

hw_version_variant

4

Fw_Version_Major

uint8

fw_version_major

5

Fw_Version_Minor

uint8

fw_version_minor

6

Fw_Version_Revision

uint8

fw_version_revision

7

Fw_Version_Unreleased

uint8

fw_version_unreleased

Heartbeat

  • Command ID: 0x01

  • Direction: ODrive → Host

Start Byte

Name

Type

Description

0

Axis_Error

uint32

<axis>.active_errors | <axis>.disarm_reason

4

Axis_State

uint8

<axis>.current_state

5

Procedure_Result

uint8

<axis>.procedure_result

6

Trajectory_Done_Flag

uint8

<axis>.controller.trajectory_done (0: false, 1: true)

Estop

  • Command ID: 0x02

  • Direction: Host → ODrive

  • Empty Payload

Causes the axis to disarm with ESTOP_REQUESTED.

Get_Error

  • Command ID: 0x03

  • Direction: ODrive → Host

Start Byte

Name

Type

Description

0

Active_Errors

uint32

active_errors

4

Disarm_Reason

uint32

disarm_reason

RxSdo

  • Command ID: 0x04

  • Direction: Host → ODrive

Start Byte

Name

Type

Description

0

Opcode

uint8

0: read, 1: write

1

Endpoint_ID

uint16

Endpoint ID as found in flat_endpoints.json

3

Reserved

uint8

4

Value

uint32

Data type and length depend on endpoint ID

Sent by the host to read or write from/to arbitrary parameters. See Arbitrary Parameter Access for details.

TxSdo

  • Command ID: 0x05

  • Direction: ODrive → Host

Start Byte

Name

Type

Description

0

Reserved0

uint8

1

Endpoint_ID

uint16

Endpoint ID as found in flat_endpoints.json

3

Reserved1

uint8

4

Value

uint32

Data type and length depend on endpoint ID

Sent by the ODrive in response to an RxSdo with Opcode=READ. See Arbitrary Parameter Access for details.

Address

  • Command ID: 0x06

  • Direction: Host → ODrive, ODrive → Host

Start Byte

Name

Type

Description

0

Node_ID

uint8

node_id

1

Serial_Number

uint48

ODrive → Host: Serial number of the sending ODrive

Host → ODrive: The serial number that shall be associated with the specified Node_ID

Main section: Discovery & Addressing.

When an ODrive receives this message (subject to receive filters, that means node_id contained in the message ID must matches its own or be 0x3f), it takes the following action:

  • RTR=1 (or empty payload): Respond with own serial number and node_id.

  • Matching Serial_Number: Take on the new Node_ID.

  • Mismatching Serial_Number but matching Node_ID: Go to unaddressed state (node_id = 0x3f).

  • Mismatching Serial_Number and mismatching Node_ID: Ignore message.

Serial_Number == 0 is considered a wildcard that always matches.

Responses on this message are sent even if the ODrive is unaddressed (node_id = 0x3f). In this case, the response is sent after a random delay to avoid collisions.

Set_Axis_State

  • Command ID: 0x07

  • Direction: Host → ODrive

Start Byte

Name

Type

Description

0

Axis_Requested_State

uint32

requested_state

Get_Encoder_Estimates

  • Command ID: 0x09

  • Direction: ODrive → Host

Start Byte

Name

Type

Unit

Description

0

Pos_Estimate

float32

rev

<axis>.pos_vel_mapper.pos_rel or <axis>.pos_vel_mapper.pos_abs,

depending on ODrive.Controller.Config.absolute_setpoints

4

Vel_Estimate

float32

rev/s

<axis>.pos_vel_mapper.vel

This message is sent by the ODrive periodically by default. See also Cyclic Messages.

Set_Controller_Mode

  • Command ID: 0x0b

  • Direction: Host → ODrive

Start Byte

Name

Type

Description

0

Control_Mode

uint32

control_mode

4

Input_Mode

uint32

input_mode

Set_Input_Pos

  • Command ID: 0x0c

  • Direction: Host → ODrive

Start Byte

Name

Type

Unit

Description

0

Input_Pos

float32

rev

input_pos

4

Vel_FF

int16

0.001 rev/s

input_vel

6

Torque_FF

int16

0.001 Nm

input_torque

Set_Input_Vel

  • Command ID: 0x0d

  • Direction: Host → ODrive

Start Byte

Name

Type

Unit

Description

0

Input_Vel

float32

rev/s

input_vel

4

Input_Torque_FF

float32

Nm

input_torque

Set_Input_Torque

  • Command ID: 0x0e

  • Direction: Host → ODrive

Start Byte

Name

Type

Unit

Description

0

Input_Torque

float32

Nm

input_torque

Set_Limits

  • Command ID: 0x0f

  • Direction: Host → ODrive

Start Byte

Name

Type

Unit

Description

0

Velocity_Limit

float32

rev/s

vel_limit

4

Current_Limit

float32

A

current_soft_max

Set_Traj_Vel_Limit

  • Command ID: 0x11

  • Direction: Host → ODrive

Start Byte

Name

Type

Unit

Description

0

Traj_Vel_Limit

float32

rev/s

vel_limit

Set_Traj_Accel_Limits

  • Command ID: 0x12

  • Direction: Host → ODrive

Start Byte

Name

Type

Unit

Description

0

Traj_Accel_Limit

float32

rev/s^2

accel_limit

4

Traj_Decel_Limit

float32

rev/s^2

decel_limit

Set_Traj_Inertia

  • Command ID: 0x13

  • Direction: Host → ODrive

Start Byte

Name

Type

Unit

Description

0

Traj_Inertia

float32

Nm/(rev/s^2)

inertia

Get_Iq

  • Command ID: 0x14

  • Direction: ODrive → Host

Start Byte

Name

Type

Unit

Description

0

Iq_Setpoint

float32

A

Iq_setpoint

4

Iq_Measured

float32

A

Iq_measured

Get_Temperature

  • Command ID: 0x15

  • Direction: ODrive → Host

Start Byte

Name

Type

Unit

Description

0

FET_Temperature

float32

deg C

<axis>.motor.fet_thermistor.temperature

4

Motor_Temperature

float32

deg C

<axis>.motor.motor_thermistor.temperature

Reboot

  • Command ID: 0x16

  • Direction: Host → ODrive

Start Byte

Name

Type

Description

0

Action

uint8

0: reboot()

1: save_configuration()

2: erase_configuration()

3: enter_dfu_mode2()

Reboots the ODrive according to Action. This requires the axis to be in IDLE.

Get_Bus_Voltage_Current

  • Command ID: 0x17

  • Direction: ODrive → Host

Start Byte

Name

Type

Unit

Description

0

Bus_Voltage

float32

V

vbus_voltage

4

Bus_Current

float32

A

ibus

Clear_Errors

  • Command ID: 0x18

  • Direction: Host → ODrive

Start Byte

Name

Type

Description

0

Identify

uint8

identify

Equivalent to calling clear_errors().

Set_Absolute_Position

  • Command ID: 0x19

  • Direction: Host → ODrive

Start Byte

Name

Type

Unit

Description

0

Position

float32

rev

pos_estimate

See also Custom User Reference Frame.

Set_Pos_Gain

  • Command ID: 0x1a

  • Direction: Host → ODrive

Start Byte

Name

Type

Unit

Description

0

Pos_Gain

float32

(rev/s) / rev

pos_gain

Set_Vel_Gains

  • Command ID: 0x1b

  • Direction: Host → ODrive

Start Byte

Name

Type

Unit

Description

0

Vel_Gain

float32

Nm / (rev/s)

vel_gain

4

Vel_Integrator_Gain

float32

Nm / rev

vel_integrator_gain

Get_Torques

  • Command ID: 0x1c

  • Direction: ODrive → Host

Start Byte

Name

Type

Unit

Description

0

Torque_Target

float32

Nm

effective_torque_setpoint

4

Torque_Estimate

float32

Nm

torque_estimate

Get_Powers

  • Command ID: 0x1d

  • Direction: ODrive → Host

Start Byte

Name

Type

Unit

Description

0

Electrical_Power

float32

W

electrical_power

4

Mechanical_Power

float32

W

mechanical_power

Enter_DFU_Mode

  • Command ID: 0x1f

  • Direction: Host → ODrive

  • Empty Payload

Puts the ODrive into DFU mode (see ODrive Firmware Deployment System). Equivalent to calling enter_dfu_mode2().