CAN Protocol

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

Configuring ODrive for CAN

Configuration of the CAN parameters should be done via USB before putting the device on the bus.

To set the desired baud rate, use <odrv>.can.config.baud_rate = <value>.

Each axis looks like a separate node on the bus. Thus, they both have the two properties can_node_id and can_node_id_extended. The node ID can be from 0 to 63 (0x3F) inclusive, or, if extended CAN IDs are used, from 0 to 16777215 (0xFFFFFF). If you want to connect more than one ODrive on a CAN bus, you must set different node IDs for the second ODrive or they will conflict and crash the bus.

Example Configuration

odrv0.axis0.config.can_node_id = 3
odrv0.axis1.config.can_node_id = 1
odrv0.can.config.baud_rate = 500000
odrv0.save_configuration()
odrv0.reboot()

Transport Protocol

We’ve implemented a very basic CAN protocol that we call “CAN Simple” to get users going with ODrive. This protocol is sufficiently abstracted that it is straightforward to add other protocols such as CANOpen, J1939, or Fibre over ISO-TP in the future. Unfortunately, implementing those protocols is a lot of work, and we wanted to give users a way to control ODrive’s basic functions via CAN sooner rather than later.

CAN Frame

At its most basic, the CAN Simple frame looks like this:

  • Upper 6 bits - Node ID - max 0x3F (or 0xFFFFFF when using extended CAN IDs)

  • Lower 5 bits - Command ID - max 0x1F

To understand how the Node ID and Command ID interact, let’s look at an example

The 11-bit Arbitration ID is setup as follows:

can_id = axis_id << 5 | cmd_id

For example, an Axis ID of 0x01 with a command of 0x0C would be result in 0x2C:

0x01 << 5 | 0x0C = 0x2C

Messages

CAN Messages

CMD ID

Name

Sender

Signals

Start byte

Signal Type

Bits

Factor

Offset

0x000

CANOpen NMT Message**

Master

0x001

ODrive Heartbeat Message

Axis

Axis Error (active_errors | disarm_reason)

Axis Current State

0

4

Bitfield

Unsigned Int

32

8

0x002

ODrive Estop Message

Master

0x003

Get Error*

Axis

active_errors

disarm_reason

0

4

Bitfield

Bitfield

32

32

0x006

Set Axis Node ID

Master

Axis CAN Node ID

0

Unsigned Int

32

1

0

0x007

Set Axis Requested State

Master

Axis Requested State

0

Unsigned Int

32

1

0

0x008

Set Axis Startup Config

Master

  • Not yet implemented -

0x009

Get Encoder Estimates*

Master

Encoder Pos Estimate

Encoder Vel Estimate

0

4

IEEE 754 Float

IEEE 754 Float

32

32

1

1

0

0

0x00A

Get Encoder Count*

Master

Encoder Shadow Count

Encoder Count in CPR

0

4

Signed Int

Signed Int

32

32

1

1

0

0

0x00B

Set Controller Modes

Master

Control Mode

Input Mode

0

4

Signed Int

Signed 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

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

1

1

0

0

0x010

Start Anticogging

Master

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*

Axis

Iq Setpoint

Iq Measured

0

4

IEEE 754 Float

IEEE 754 Float

32

32

1

1

0

0

0x015

Get Temperatures*

Axis

Inverter Temperature

Motor Temperature

0

4

IEEE 754 Float

IEEE 754 Float

32

32

1

1

0

0

0x016

Reboot ODrive

Master***

0x017

Get Bus Voltage and Current

Master***

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 Position 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

0x700

CANOpen Heartbeat Message**

Slave

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

Note

  • * These messages 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.

  • ** These CANOpen messages are reserved to avoid bus collisions with CANOpen devices. They are not used by CAN Simple.

  • *** These messages can be sent to either address on a given ODrive board.

Cyclic Messages

Cyclic messages are sent by ODrive on a timer without a request. As of firmware verion 0.5.4, the Cyclic messsages are:

ID

Name

Rate (ms)

0x001

ODrive Heartbeat Message

100

0x009

Encoder Estimates

10

These can be configured for each axis, see e.g. axis.config.can.

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.

Interoperability with CANopen

You can deconflict with CANopen like this:

  • odrv0.axis0.config.can.node_id = 0x010 - Reserves messages 0x200 through 0x21F

  • odrv0.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.