How to use CAN bus in velocity mode

Hi

I’m a complete novice at this so please bear with me.

I’m making a 4x4 off-road electric wheelchair (I have Multiple Sclerosis but like going on hikes with friends)

I’ve got two odrive 56v boards in velocity mode controlling 4 hoverboard motors and I’m using an Arduino to generate the desired velocity of each wheel in revolutions/second based on the input from a joystick.

I was initially going to send this via serial to the odrives however I’m concerned about ground loops. That leaves CAN bus which I’ve got no experience with.

What is the best way for me to send the revolutions per second to my odrives via CAN? I can’t quite seem to get my head around the documentation for CAN protocol.

(please keep in mind that I am not an experienced programmer at all and barely managed to figure out the arduino stuff).

You’ll need to find an appropriate CAN library for your device, and then you will first configure the odrive to use velocity mode (easiest to do over USB, then save the configuration). Then you’ll send can messages by doing something like:

msg.id = axis_id << 5 | 0x00D;
msg.length = 8;

float desired_velocity = <whatever>;
memcpy(&msg.data[0], &desired_velocity, 4);
memcpy(&msg.data[4], 0, 4);

Thanks so much for getting back to me.

I’ve ordered an MCP2515 board for my Arduino because it looks lie the most commonly supported.

Do you know of any good resources for learning CAN? - your code went a little over my head which shows I need to do further reading. I assume it’s because I haven’t gotten my head around the concept of “packets” as I’m only used to the “stream” of serial communication.

1 Like

https://www.kvaser.com/can-protocol-tutorial/ is a pretty good intro to CAN.

Your serial stream is a sequence of 8-bit data packets.
CAN has packets that are a little larger and have message ID numbers so that the receiver can know what the message type is (and also so the priority system can work), and it has some clever mechanisms for noise-immunity and multi-way bus arbitration with a priority system. That’s pretty much it.

If two CAN nodes start transmitting a message at once, then the one with the lowest-valued message “wins” i.e. the other transmitters agree to halt transmission and let the lower-valued message through, because of the way that 0 bits overwrite 1 bits in CAN… But you don’t really need to worry about that.

It’s a lot like UDP over Ethernet really. When you send a CAN message, you first give it an ID and some data (up to 8 bytes) and then you place it in a queue.
The CAN driver then takes care of it from that point forward. If you are recieving a CAN message, then you fetch it out of a queue of incoming packets (the length of which is usually 0, but if your code is too slow to fetch all of the messages out of the queue as they arrive, then the higher priority packets skip the queue)
The ID tells you what to do with it (you need to agree with yourself in advance what the IDs will mean, but they should be unique to a function e.g. axis0 position input) and similarly you need to agree with yourself what the format of the data is.
But when all that is done, you have an extremely robust control system bus.

1 Like

Did you check out the CAN guide? :smiley: CAN Bus Guide for ODrive — ODrive Documentation 0.0 documentation