Hi,
I’m the author of the repo linked by the OP. I’ve been working on a similar, but separate, effort. I mostly agree with everything you said. I also think that due to the heavy computational demands of high bandwidth FOC motor drives, it’s not a great candidate to integrate into the Klipper MCU firmware. I’m more of the mindset to add Klipper support to the servo firmware.
The driver implementation I’m using is of similar form factor to most of the nema17 servo stepper boards, it uses an STM32g431 MCU, along with an ST L6226 driver, which I’ve found is pretty happy driving 2.5A into a NEMA17 in FOC, this uses an MT6835 21 bit encoder. I’ve also used an STM32F401 with a pair of DRV8876 drivers, with a CUI capacitive encoder. The higher resolution encoder works better in some ways, but there’s no clear winner in my opinion.
I also am not sure a basic PID loop is sufficient for the servo loop to have enough bandwidth. I think a higher order controller will make this work much better. My project is based on the SimpleFOC arduino library, which by default uses a cascaded position/velocity/current PID control loop, this works ok-ish, particularly if you use a velocity feed forward term. Graphing the following error during a move with velocity feed forward enabled, the constant velocity portion of the move has approx zero following error. The constant accel portions have some following error, but the ends of the accel portions have a lot, this is due to the integrators needing to build up some error to get the load moving. This is where an accel feed forward term will help. This is the reason I’ve tried writing my own implementation of the MCU protocol, then I can use the information in the step queue to calculate the various feed forward terms without doing a finite difference on the step/dir interface. It’s incomplete at the moment, I’ve gotten to the point where the MCU is just about configured by the host, but some life things came up and I haven’t touched it in a while. As this isn’t functional yet, I’ve used step/dir and a single finite difference to get velocity, I haven’t tried to get accel from finite difference but I assume it’ll be noisy, it still might be an improvement though.
Stability of the controller is also impacted by load resonances, so the simple PID controller is heavily restricted in bandwidth by the mechanical resonances. I’ve never designed a real full state controller, but I’ve wanted to, so I’m going to try it for this. A sort of “learning” controller is an interesting idea, and I actually know of some like that used in industry, but I don’t think it’s the best choice here. The ones I know of restrict themselves to only working for the exact move commands that it’s learned. Instead I think some form of LQG with integral action is the way to go, but I’m unsure if this is computationally feasible to implement on the microcontroller, I think I’m just going to have to try and see.
An alternative is to use a notch filter in the servo loop and in the motion planner, but again this reduces control bandwidth.
That’s a lot of text, so to sum up my opinions on this, as someone who has spent significant time working on it. Getting Klipper to move the servo is easy, step/dir works. It even works pretty well in some cases, but having velocity/accel info is very worthwhile. The control system to get the servo to match the performance of the stepper when working within the limitations of open-loop stepper control is challenging. Once you start asking for move parameters outside the open-loop capabilities, anything that isn’t a print failure is a win.