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