Thoughts on ODrive Architecture


I was doing some thinking in the car the other day about the overall architecture of ODrive and its place in the world of machine control. I came to the conclusion that developing ODrive’s software capabilities in a “modular” way would give us both direction and, ultimately, a useful product. Don’t read too much into the exact implementations I outline below, they’re just there to try to help the reader visualize my explanations.

Modular Ecosystem

Imagine ODrive as a system that can load these different “modules” independently. One user needs it to operate as a servo drive for a single motor, so he only enables that module. Another user needs a “Motion Controller” that talks CAN, so she disables all the motor outputs and uses it to coordinate 6 motors on a robot arm. A third user is a hobbyist and wants ODrive to handle his 3D printer, so he enables both motor axes, the motion controller, and the PLC modules. This lets him setup everything through a Jupyter / Python interface, and stream GCode to it from his favourite slicer. ODrive takes care of the rest.

Input / Output

One neat aspect of this is that the modules don’t need to know or care that the other modules are enabled. They can be imagined as black boxes with inputs and outputs. For example, the Motion Controller module knows it has a servo drive at CAN Node 0, so it sends data over the CAN interface to Node 0 telling it to move 100mm at a certain speed. In reality, Node 0 is on the same board and handled by the same processor, which reads the echoed CAN data and interprets it as if it were coming from an external CAN source completely transparently. Want to put Node 0 on a different ODrive board? Hook it up to the CAN bus, disable Node 0 on Board 0, enable Node 0 on Board 1, and everything keeps working.

Servo Drives as modules

We can even think of ODrive as TWO servo drives. Two instances of a “Servo Drive” module can run on the same . They will have different Node IDs (for CAN or UART), their own place to save parameters in, etc. They don’t need to know about each other. In light of future plans for a single motor ODrive, the software would be identical. Just spin up one instance of the Servo module instead of 2.


CAN / UART / USB / Other comms interfaces will have to be shared between the modules. These can be their own “Modules” that route data based on origin, type, enabled modules, etc. STEP/DIR coming over GPIO from a TinyG board would be parsed and interpreted, then dispersed to the correct modules. The same command sent from the ODrive to another module on ODrive wouldn’t have to go over GPIO at all, it could simply be routed from one software register to another.


If the architecture is structured as above, we won’t be stepping on each others’ toes when developing different modules. The person working on Gimbal Motor Mode should never have to worry about the trajectory generation code, because it’s encapsulated down to a black box with an API between them. This greatly simplifies development.

Kinematics within the ODrive?

Loock at LinuxCNC HAL.
We implemented an easier version for STMBL. It allows boot and runtime configuration of the system, setting and monitoring of signals (floats) and timing analysis.
system configuration
signal monitoring
timing analysis


Your module system sounds useful for a good amount of people. I am not sure it’s something I would use as I would want full access to use any/all functions available, anytime without thinking about enabling/choosing modules. Of course I could be completely misunderstanding your concept here.

On the communications side, I’ve been meaning to post on something related.
Your comments mention nodes on a CAN and sharing between modules. I’m assuming you would also mean sharing between controllers.

What I would like to see is perhaps much simpler for most to implement, and that is an addressable packet serial mode. I’ve used this with a brushed motor motion controller (Roboclaw) and it worked really well. In its simplest form it allows you to daisy-chain multiple ODrives together in multi-unit mode by connecting tx/rx pins between them. Then each ODrive gets assigned an address (1-8 for example) so that anytime you issue a serial command, instead of just passing the motor to issue the command to, you also issue the controller address. The correct controller will take the command based on the address. I’m assuming the result here would be similar to a CAN, but issuing a serial command I’m going to assume would be much easier to get started.

v [motor] [velocity] [current]
v 0 2400 0
now becomes
v [controller-address] [motor] [velocity] [current] now becomes
v 3 0 2400 0

I don’t know enough about the actual firmware programming or the electronics to know how difficult this would be, but I think this would be worth looking into.

I’m not sure what sort of backgrounds or familiarity anyone here has with other motion controllers, but I think it would be very beneficial for some to take a look at the Roboclaw as that device and company (ION Motion Control) have been around for a while in the brushed motor market and really have things figured out, IMO. I’m not saying ODrive should copy the Roboclaw, but I think a lot can be learned, especially if there is any interest in having users switch their existing brushed motor applications to the ODrive.


I am not sure it’s something I would use as I would want full access to use any/all functions available

The problem is when functions are mutually exclusive. This isn’t the case for thing like UART vs CAN, but it is for things like closed-loop stepper vs closed-loop BLDC control. Another more relevant example would be controlling the position of an end-effector for a robot, which requires a completely different control scheme than if you’re trying to close the loop on each motor’s position independently.

I say modularizing the firmware is a good idea, if only to make the it more granular and accessible to modification.


I just ordered a RoboClaw 2x30A Motor Controller.


If you have any questions, feel free to reach out. As I mentioned before I’m hoping to be able to replace my brushed applications with ODrives so I’m very interested in sharing any experience I have.
I’m going to recommend a decent encoder like the CUI AMT encoders, as I got some bad results from some cheaper hall effect encoders on Servocity motors and it caused a lot of headaches diagnosing it.