Question about sending CAN commands to ODrive


In this thread this example structure of CAN data to be sent to ODrive. The example is about position control setpoint.

To set axis0 position to 100000 :
Axis ID = 0x03
Command ID = 0x00A

CAN Message ID: = 0x03 << 5 + 0x00A = 0x6A
Data length = 8

Data Frame:
< Signal : Pos Setpoint : 32 bit signed int >
[0] = (uint32_t)100000
[1] = (uint32_t)100000 >> 8
[2] = (uint32_t)100000 >> 16
[3] = (uint32_t)100000 >> 24

< Signal : Vel FF : 16 bit signed int >
[4] = 0
[5] = 0

< Signal : Current FF : 16 bit signed int >
[6] = 0
[7] = 0

The part I don’t understand is that in the ODrive CAN frame documentation I read:

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

Upper 6 bits - Node ID - max 0x3F
Lower 5 bits - Command ID - max 0x1F

I am confused, because I think the above example constructs the message ID in this way:

CAN Message ID: = Axis ID << 5 + Command ID

which seems to reserve the first 5 bits to the axis ID, and then the rest (of, I suppose 16 total bits given the hex notation, making it 11 left) to the command ID. So according to my understanding we are reserving 16 bits for the CAN message, 5+11 bits. The documentation defines 6+5 bits. Is any of that wrong? Or it’s my understanding? :slight_smile:

I also note another possible inconsistency, as in the documentation I read the node IDs have to always be defined larger than 32:

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.

but in the example I read the node is given a value of 0x03. I suppose that was just for the example, but in our project we should choose it following the docs?

In our project we are setting up 2 odrives, with 2 motors each (total of 4 motors) and we would like to steer them with CAN. We managed to configure them, but now we are struggling with sending the right messages to them. It feels like the CAN C libraries we are using assume we’d be sending bytes. The docs have these 11 bits though, and your example something maybe different.

I look forward to your answer! Thanks in advance.

1 Like

CAN 2.0a IDs are 11 bits long, not 16. By doing Axis ID << 5, We’re taking 6 bits (Axis ID) and moving it to the left 5 places, which leaves the lower 5 bits for Command ID. We typically do this in a 16-bit int, and the upper 5 bits are ignored.

Don’t worry about the CAN IDs, that bit is only for CANOpen deconfliction and you don’t have any CANOpen nodes on your bus.