Best way to drive ODrive externally

Okay, so I think someone needs to explain me the idea of ODrive, back to the basics. I just can’t get my head around how to control it properly.

We are developing a 4-axis robotic arm, with 4x 150kV standard motor and 2 ODrives 3.6. The plan is to control it from an external PC, running inverse kinematics (well maybe in the future).

What’s the proper way to control something like that? The PC would do the inverse kinematics and calculate the desired position for each axis at every point in time and would stream it to the odrive, while the odrive picks up the desired position and moves each axis to it, say with a frequency of 1000Hz.

Our current plan is to have an Arduino in the middle. It is connected to the PC via UDP/Ethernet, receives the desired positions, and passes it on to the 2 odrives via the UART native interface. It seemed like the single best way to stream a lot of data into the odrives in real time from an arduino. However, it seems that this approach is not fast enough, I may have to rework the code but it seems like the Arduino with the current code can’t go higher than 125Hz and that with only one ODrive and without UDP yet. This results in a lot of noise and vibrations, so this can’t be the way to go.

But what else? The ASCII protocoll wasn’t even considered. SPI or I2C aren’t really implemented as far as i know. We looked at the CAN interface, but it probably wouldn’t have been any faster than UART. What else? USB? This also can’t be the way to go. You can’t run realtime control over usb. I think i never had a time where usb worked for over an hour, already the usb driver itself makes it unusable for real time control in my opinion, be it windows or linux. And then there’s only the step direction interface. But wouldn’t you need 4 or 6 pins for each odrive? We also need at least 2 end stops per odrive.

So what i don’t understand is how everyone does it. We are using the UART native protocol, but it seems like only 3 or 4 other people in the world use it besides us. I have seen so many projects online, all of which work perfectly, but i never brought to knowledge how the odrive is controlled. What about all those CNC mills? Those 3D printers? What about Mach3? I know ODrive can be used with Mach3, but how? Additional hardware and step/dir interface?

I’m thinking about @Dev255 and his solar powered CNC mill, i looked into his projects for quite a bit, but i couldn’t find out how it works, i only know that it used odrive, Arduino and Mach3, but it seems like the Arduino is an addition to Mach3, so not inbetween.

I’ve also seen a lot of odrive 3d printers, how are all of those controlled?

We also can’t use the built-in trap traj because all 4 axis need to be synchronized globally and we need inverse kinematics, so even the acceleration may be different and non-constant for every axis. There’s no way around a single computer doing the kinematics and the odrives getting the position.

Another way to do it is to only do speed control. I’ve seen this done that way quite a lot in industry. The control pc would to PID control itself, control the speed or torque of the odrive and control the encoder estimate. This would however completely eliminate the odrive as a controller and would only use the odrive as a conventional ESC for low speeds.

But the thing is that odrive IS apparently being used in industry and many many hobby projects, many of which require a single controller for multiple odrives, such as CNCs, because a cnc can’t really use trap traj, it needs to to all calculations in one place.

Can anyone explain to me how odrive is supposed to be used properly and what would be the best way for us?

1 Like

I just read in another forum that this person must wait until CAN is fully implemented, if usb is not real time enough. It was from 2018.

Nowadays, how fast is CAN, is it a lot faster than UART or USB? Our target frequency would be around 500 - 1000 Hz for setting the desired position of each axis, all other endpoints are not that important. The current approach is to always transfer 3 packets, 2x the desired position and one optional packet, which cycles through all the ones we need.

We wanted to use ROS and MoveIT for inverse kinematics, but we didn’t see a direct way for doing it and so we thought it’s too hard and moved it back in our to-do list until it eventually fell off completely. How would we use ROS moveit to control 2 odrives simultaneously? If that’s straight-forward, it might even be a lot less pain than our current plan, because our current plan does not yet include any good way to do IK.

Well, i think we need some help because we are kind of stuck with our configuration, which is probably not the best to begin with and many parts of it are still open. It’s our diploma thesis for school and it’s slowly coming to and end, so it should slowly start to work until the deadline.

If someone’s interested we might even share the project in its own thread. I do think it’s quite interesting, as this robotic arm looks very cool without enclosures, is pretty large and incredibly powerful.

CAN is fast enough to set positions (and/or torques) for a few axes at 1000Hz, yes, depending on number of axes.
Check it with the cangen and canbusload programs on Linux. Use cangen to generate packets of the specified size at the specified frequency, and use canbusload to monitor the bus load. You don’t even need a real CAN bus, you can use a vcan device and specify the bitrate to canbusload. PM me if that’s not clear.

But, for something that is ‘very large and incredibly powerful’ ODrive is probably definitely not your best choice. I would pick an industrial servo drive from someone like Elmo, Copley, Moog or Ingenia, which have IEC 61508 and EN 13850 SIL-3 rated safety systems, including Safe Torque Off, and category 0, 1, and 2 stop.
They also include EtherCAT, which is much faster than CAN, especially for large multi-axis systems. (I have used this for real-time control of 32 axes at 4kHz for a haptic (telerobotic) manipulator system. 8 axes per arm, two arms on the master, two arms on the slave, one EtherCAT-based control system.)

1 Like

Thank you for your response. CAN sounds interesting, the problem is that we would like to configure the odrives from code, which is not possible with CAN, so we would another communication separately. Maybe i will check it out in the future.

Do you think simply plugging both USBs into the PC and running a C++ program will work at such a frequency? When the project was planned I had an affinity against using usb for a real time control application, because that’s asking for trouble. But now after thinking a lot more it’s definitely not robust but probably the easiest way to get from C++ inverse kinematics to the ODrives.

Well no that’s not what i meant, it’s definitely not ‘very large and incredibly powerful’ xD. It’s a pretty compact 4-axis robotic arm, may fit into a 20x40x60 cm box when it’s finished, but when fully extended it has a reach of almost 1.5 m. True, sounded like it’s 5m tall and can lift hundreds of kilograms.

Ours will be able to lift a few kilograms, but the special thing about it is that it is mounted on a Festo Robotino, that is a mobile industrial robot (around Ø50cm x 30cm high). So that equals a robotic arm which can basically move anywhere. Due to the 150kV motors it is quite powerful in relation - but not in the ODrive world, here this kind of power is nothing special :wink:

Yes i thought of EtherCAT because I really like it, but the problem is that you need special EtherCAT-slave hardware. All of that is way too expensive for our project, it’s only a proof of concept and for teaching.

Btw, i just saw Odrive with ethercat interface - #6 by Roiki1. Apparently the idea was to implement EtherCAT into ODrive. But as far as I know the EtherCAT-slave must have special hardware because the Ethernet frame which the EtherCAT frame is carried needs to be read and written while it’s going through, you essentially need a very special, ultra-fast realtime Ethernet slave. Those chips are very expensive as far as i know. Just wanted to add that because I think it’s very not-straight forward to implement that.

Another idea was even to use an industrial inverse kinematics controller from Beckhoff which would talk to an EtherCAT slave, which could take the commands in real time and supply the ODrives. I even talked to a guy from Beckhoff - the developers of EtherCAT - and even he said it’s possible to make your own EC slave, but it’s a lot of work and probably not worth it, because you need special hardware and a dedicated software stack.

But actually my main question in this thread still hasn’t been answered: How is everyone doing it?

In other words, what would you say is the most used interface in the odrive community?

I also use UART with the Native Interface, controlling two ODrives with a Jetson Nano. I actually only get about 60Hz, it’s not optimal, but fast enough for my project.
I also tried USB, but it’s only about 25% faster in my case and not as reliable.

What I don’t understand: Why do you need such a high frequency to control a robotic arm?

I had it running at 100Hz today and it made really bad vibrations, so much that i was almost scared it would damage the tiles it was standing on. I then simply tried changing the frequency but i couldn’t get it higher than 125Hz without modifying anything. It was better with 125Hz, definitely usable, but not optimal.

The problem is that this was with only one odrive and without UDP and if i remember correctly to the experiments, the UDP part is actually the slowest. So i had doubts that when everything is built together it would get even slower and slower when all features are added. That’s why i started from the beginning, thinking if it’s even the right approach.

What target positions are you sending to the odrive? If they are constant over time, I don’t see how that would cause any vibrations.

No, i was testing it with a simple sine wave as the input. It only made vibrations when moving at a high speed, when the target position changes a lot between cycles.

Maybe you could work against that a bit by tuning the motor differently, but that’s not really the main goal

USB, obviously. :slight_smile:
USB is the fastest and most full-featured of all the interfaces to ODrive, and that will never change.

However, USB is a polling-based protocol - the Host is always in charge - the host polls the device, and a USB device cannot issue interrupts to the host. The maximum polling rate of USB is 1000 Hz, AFAIK.
On top of that, the operating system itself has a fixed rate that it will schedule tasks - for high throughput, the kernel should switch tasks at a low rate, and for low latency, it should switch at a high rate. Linux for example by default has a kernel tick rate of 400 Hz, maybe 2kHz if you configure it. I don’t know what Windows does.

Whereas CAN drivers do trigger interrupts, so the latency can be lower, especially if you have real-time scheduling enabled in the kernel, where an interrupt can cause the kernel to suspend its own threads to allow a high-priority task to run. (this is what preempt-RT does, and it is worth noting that for all the overhead of Linux, it runs on much faster processors than simpler RTOS like FreeRTOS that runs on ODrive itself, so while the immediate latency is higher on x86, the overall latency from trigger to compute output, can be lower)

In an ideal world I would have both USB and CAN - USB for configuration and CAN for control - or (even better) I would upgrade the CAN protocol to be as full-featured as the USB protocol. I hear that the ODrive devs are working on this for V4, but it will NOT be open-source. :confused:

Also, depending on what you need to configure, you can always add your own CAN commands. The CANsimple protocol is really ‘simple’. You can add your own commands for configuration etc pretty easily.

Indeed EtherCAT slave hardware is specialised, it’s not the same as Ethernet hardware because it employs this special ‘wormhole routing’ instead of store-and-forward, for low-latency. That said, a servo drive from Elmo or Beckhoff would cost about $400 per axis. That’s a lot less than the $2000 per axis that the likes of Parker, Kollmorgen or Siemens would charge, but it’s a lot more than the $50 per axis that you get with ODrive.
Texas Instruments have/had a development kit for an EtherCAT slave - AM335. Possibly that could be combined with ODrive - although I think it would be simpler to implement the servo control on the TI chip itself tbh.

Anyway, I suggest that you try the CAN interface. It’s certainly MUCH faster than 100Hz, it should get you pretty close if not all the way to the 1kHz that you want.

BTW I’m glad that your “large and incredibly powerful” robot is not large or powerful enough to kill anybody :stuck_out_tongue_closed_eyes: but nevertheless please be careful with robots, they can be quite dangerous. :slight_smile:


Yeah, it’s already dangerous enough at that size :stuck_out_tongue:

I am currently taking a look at ROS and MoveIT, because that’s what we planned from the beginning, but then it kind of slipped from the todo list. I’ll see how difficult it is to get the odrive controlled from C++/ROS, because that’s actually the direct way, everything else is just inbetween.

Afterwards I might try the UDP part again and test the max speed on the Arduino and take a look at CAN. We might get away with configuring it, i just liked the idea that nothing is permanent on the odrive and all configuration is hard-coded in C++ and loaded at startup, just for reliability. It depends if everything we need can be done from CAN (resetting and homing), because we for example do not want it to home automatically on startup for safety reasons, only when you tell it to.

The idea was to have the Arduino inbetween and connect it to the PC with Ethernet, because then you have a single, robust, wired interface to the PC and it is completely universal to every device.

I still hate the idea of using usb. I am studying automation technology and control theory in school and it just hurts my heart to use something like usb for real time control. I would love it if CAN works, just because we can say that we used CAN :stuck_out_tongue: . Nevertheless, I will do some more experiments the following days, we’ll see how it goes.

But that will be tomorrow, it’s already 1:17 a.m. here in Austria

If you want to set the position continuously to a trajectory, you should try INPUT_MODE_POS_FILTER with input_filter_bandwidth tuned.

1 Like

Hey that sounds interesting, I thought of that if such a feature exists. Thanks i will certainly try that, maybe the frequency can be lowered then.

damn, that pos filter is working well :hot_face:

It’s working so well, no vibrations at all at 125Hz, exactly what we needed. Thanks for the advice.
I’m going to continue as planned, with the Arduino as the interface between Ethernet and UART native. We’ll see, maybe the frequency can be turned down even lower if it’s not necessary to be that high.

1 Like

There are already some people using ROS to send/recieve ODrive CAN commands - it is much simpler to do this than to include the ODrive Python libraries - and you can do it from a C/C++ node, and it is not ‘connection-oriented’ like USB. CAN packets are fire-and-forget.
I think that is your best way forward.

What configuration do you need to do at runtime? Changing gains, velocity and torque limits maybe? It should be very easy for you to add CAN commands for these to the firmware.

I’ve looked into the CAN specification and I think all settings we strictly need are available. As i said, i just liked the idea of loading the parameters once on startup, just for robustness, because that means the odrive is not in charge of remembering settings and it would make sure that all odrive boards are configured equally and can be reconfigured easily without any unplugging. Not strictly necessary tho.

You are constantly talking about CAN in Linux / ROS / C++. How is that meant to work? Are there USB to CAN adapters? Or how is the CAN signal supposed to get out of Linux? I’m talking about the hardware interface.

We bought some of these just for testing, these are Arduino UART to CAN adapters AFAIK, haven’t tried them yet.

These are great: It’s even isolated too.

Don’t bother with UART-to-CAN, go for a native socketcan device like that one ^.

On Linux, those work out-of-the-box. Plug it in, and you get a network device called can0.
To bring it up: sudo ip link set dev can0 type can bitrate 500000; sudo ip link set dev can0 up
Then to dump frames to the terminal: candump -L can0

To write a C program to send/recieve CAN frames is trivial: Example C SocketCAN Code – Beyondlogic

There is also a driver for Windows for these things, but it only works in Python.

1 Like

Ah, i see, so it’s like a network interface. That makes it certainly usable as a realtime control in contraversy to usb.

Sound very interesting, i might investigate this in the future. Some time ago i already tried quite a bit getting position output from a CNC system like linuxcnc or Mach3 for example, although i didn’t quite know enough back then to get it working.

I imagine it should work quite well, taking realtime output from a CNC system and passing it on to the ODrives. Back then I did a lot in this direction, because I wanted to use a proper CNC interpreter for my homemade Arduino CNC with DC servos, another old project of mine, i might actually share this project as well, tho it has nothing to do with ODrive. However, it’s a 3 axis CNC machine based on an Arduino MKR Vidor 4000, where i programmed the FPGA to take homemade encoder signals and drive the DC motors to their position. It drives 3 DC servo motors, where each axis is controlled by a PID with 20kHz.

I basically made my own gcode interpreter on the Arduino with fully featured 3D trajectory control, with the same interface as GRBL, so that it can be used with the postprocessor and control software for GRBL. I basically remade the base idea of GRBL, but for servos instead of stepper motors. The problem is that GRBL runs over USB Serial and i wanted to change that, i really liked the idea of using realtime Ethernet.

But that was long ago, maybe i would be more successful nowadays. I would really like to upgrade my DIY CNC to a proper controller with realtime capable communication. If that works it could be easily adapted to run ODrive over a CAN network interface.

By the way, talking of CNC, there isn’t a ready to use solution for a CNC interpreter where i can simply get the axis desired position with some software and send it to whatever i want, right?

I tried hacking into systems like Mach3 or linuxcnc by connecting to Ethernet based controller hardware, but I wrote software to trick the system into thinking it’s actually such a commercial hardware module. This software would basically redirect the output to whatever system is used.

I saw so many CNCs and 3D printers, i still haven’t figured out how they work. I think some of them use special hardware boards that drive the ODrive with step/dir. Such a software that takes input from a CNC system virtually doesn’t exist, right? If so, please let me know! Hope it’s clear what i’m after…