PWM problem with servos

Basic Information:

Printer Model: Voron 2.4 / ERCF
MCU / Printerboard: BTT Octopus / EASY-BRD
klippy.log

Fill out above information and in all cases attach your klippy.log file. Pasting your printer.cfg is not needed
When pasting code or config snippets use the code tags </> in the menu above

Describe your issue:

I have been developing a new driver for the Voron ERCF (Enraged Rabbit Carrot Feeder) and have been debugging an issue with reliably driving servos with Klipper. The problem occurs at the time the servo is turned off by setting WIDTH=0. Messages appear to be sent to the controlling mcu correctly but the last PWM pulse can be shortened (presumably the mcu immediately turns off the pulse). Obviously a shorter last pulse isn’t important for controlling fans and the like but most servos with start the adjustment to the new position. This causes a “kick” movement (and is particularly problematic of ERCF).

A discord post containing the oscilloscope traces demonstrating this can be found here: Discord

Shouldn’t the mcu respect the pulse width previously set and on receiving an WIDTH=0 command wait before lowering the output?

As you have indicated, the current Klipper code does not schedule new servo commands in a way that ensures it does not overlap with a retransmission of the previous command. It is possible to implement it, but I do not know of anyone currently working on it.

-Kevin

Kevin, I appreciate the confirmation of the problem. At the moment we are working around it with an adjustable “dwell” of 0-20ms that can be tuned to place the servo-off between pulses. It’s not ideal and probably not completely reliable.

How could I submit a bug/feature request to at least put this on the radar? I’m able to work on the python side, the don’t have the setup on work on the firmware side.

Synchronizing the updates to avoid overlap does not require new mcu C code. It does require host Python code. You can look at how klippy/extras/bltouch.py tracks updates to avoid that issue, but in general the bltouch.py code is quite a bit more complex than you likely need.

As for reporting it, this is the right place. I don’t know if/when a developer will take it up.

-Kevin

Got it and thanks for the pointer. I can take it from here… :pray:

Just to close out this thread. I’ve built a new servo driver for Klipper and I’m currently packaging it with the ERCF software. It solves all the problems folks have been having with servo “kickback”. I also added an optional “DURATION” attribute to send a PWM synchronized burst which is typical of the servo control we do (i.e. servo is not left on). I can build a PR request but not sure how to go about this with the Klipper project…

Create a PR in GitHub - Klipper3d/klipper: Klipper is a 3d-printer firmware and please make sure to mind the points in Contributing to Klipper - Klipper documentation (especially but not limited to the signed-off)

Thanks for your contribution!

@moggieuk sorry to bother you about this, but any chance of porting this back to mainline klipper? currently don’t have an ERCF, but the servo driver would solve my kickback problems on my Switchwire’s Klicky probe (that keeps causing my prints to fail because of kickback)

Hi! Yeah, I’m sorry, I haven’t forgotten, I’ve just been swamped with other projects (ERCFv2 launch, major Happy Hare update, KlipperScreen, etc, etc). I have a LOT of PRs to create and track.

BUT my servo module is entirely backwards compatible. You can simply include mmu_servo.py in klipper extra’s and then define your servo with `[mmu_servo]’ instead of ‘[servo]’. With digital servos just sending a 200ms or so pulse train is sufficent for it to make the move (assuming of course you don’t need it to stay active to hold position)