Klipper3d / klipper

Klipper is a 3d-printer firmware
GNU General Public License v3.0
8.99k stars 5.17k forks source link

kin_shaper: minimal change to allow more shaper pulses #6460

Open Frix-x opened 5 months ago

Frix-x commented 5 months ago

Hello everyone,

I am submitting this PR to introduce a minor change to the kin_shape.c code that should have no impact, with the primary goal of allowing the definition of shapers with a larger number of pulses.

The reason for this change comes from some work we are doing with a couple of Voron contributors: my Shake&Tune module provides a way to measure vibrations at different speeds to get optimal settings for the slicer profiles. But we can also get some additional data from these measurements, like the main motor resonance. The idea is to add another input shaper filter to target this resonance and reduce its effect.

A first POC was done by using the [input_shaper] config targeting this motor resonance, and it resulted in generally lower motor noise, but it also removed the possibility to use IS for prints... So what we do now is to convolve our axis IS filter definition with a ZV filter targeting the motor resonance and define it using Dmitry's "custom" shaper in his edge branch. This method has already shown promising results on my test rig, significantly improving print quality by reducing VFAs and overall machine noise, even at high acceleration values, and also offering a bit more torque. These positive results have been replicated by some other users who have started to experiment with it.

However, the current problem is that I can't release a "plugin" very easily, since users would have to patch the kin_shaper.c file to increase the maximum number of pulses, causing their local repository to diverge from the main branch. This divergence is problematic in terms of the moonraker auto-update feature and would require reapplying the patch after every update, which is not really user-friendly...

As a side note, the choice of 25 pulses was made somewhat arbitrary. It was chosen to allow convolution of up to two instances of 3_hump_ei filters (each requiring 5 pulses), which should cover most cases. The current limit of 5 pulses only allows the use of two ZV filters at the same time, which I find quite limiting for general use, as most users will still want to run MZV, EI or the other standard filters... But 25 is not a fixed number and can be changed to whatever you prefer.

Finally, the whole motor filtering thing is a WIP and I'm not sure it's a good idea to integrate it into the main Klipper for now, but I'm really open to discussing it and how to do it properly. The only thing I need and that is included for now in this PR is the change from 5 to 25 max pulses in order to allow experimenting with it more easily with something like a Klipper extras plugin (that I may release in Shake&Tune).

Sineos commented 5 months ago

Ping @dmbutyugin

Zeanon commented 5 months ago

Out of curiosity, could you point us to the stuff you used for this cause I would be interested in testing this as well

dmbutyugin commented 5 months ago

I do not mind the change, as I don't think that increasing the allowed number of pulses will negatively affect the performance of existing shapers, and the impact on memory should be insignificant.

That said, I find it surprising that the input shaper can affect VFA. This is because input shaper does not change the constant speed motion in any way, and VFA (and the stepper noise) primarily manifests itself at a constant speed that happens to hit a resonance frequency of a system - either the motion system of the printer, or the stepper resonance itself. So, it would be great to learn about your experiments and their results.

Frix-x commented 5 months ago

By VFAs, I'm not talking about ghosting/ringing or transient behavior due to high acceleration on a harmonic oscillator such as our printer axis with heavy toolhead and springy belts (as we usually try to target with the input shaper system in Klipper -- thanks for that implementation, it works extremely well!) Here I'm only focusing on the natural resonance created directly by the motor shaft (+ following load) due to its pulsed behavior.

Stepper motors naturally exhibit small oscillations with each step, due to the inertia of the moving rotor, which causes the motor to slightly overshoot or undershoot the step position and oscillate until it "settles" at the correct step angle. When the frequency of these oscillations matches the natural frequency of the motor, resonance occurs, causing audible noise, vibration, and in extreme cases, lost steps or stalling.

Chopper drivers such as TMC drivers, which use modulation to vary the output voltage and current to the motor and precisely control the motor torque, reduce this problem greatly by intelligently controlling the motor, but the idea here is to improve it by also directly avoiding exciting the motor in its natural resonance frequency range.

So right now it's a very manual process...

  1. Get the natural resonant frequency of the motor: this can be calculated knowing the physical parameters of the motor, and our first tests were done with this theoretical number. This is not perfect because it doesn't take into account the mechanical load on the rotor shaft... But I just released a new motor frequency profile graph in my Shake&Tune package that should give a better measurement of this along with an estimated damping ratio.
  2. Then use this Python snippet to do the convolution using the A&T values returned by your shaper defs:
    def convolve(L, R):
    # Convolve A
    As = [a * b for a in L[0] for b in R[0]]
    # Sum up the times for each pulse
    Ts = [a + b for a in L[1] for b in R[1]]
    # sort by time
    C = sorted(list(zip(Ts, As)))
    # Rearrange into (A, T)
    return ([a for _, a in C], [t for t, _ in C])

    This can be used like the following example (for a ZV filter targeting the motor resonance and MZV filter targeting the axis resonance, but you can use whichever filter you prefer):

    >>> convolve(get_zv_shaper(motor_resonant_freq, motor_damping ratio), get_mzv_shaper(x_axis_freq, x_axis_damping_ratio))
    >>> convolve(get_zv_shaper(motor_resonant_freq, motor_damping_ratio), get_mzv_shaper(y_axis_freq, y_axis_damping_ratio))
  3. With the previous command you get the new A&T values and can use them with your bleeding edge branch in DangerKlipper as follows:
    [input_shaper]
    shaper_type_x: custom
    shaper_a_x: 0.29289321881345254, 0.2276188593372657, 0.3469455977320937, 0.26962509247495714, 0.2054865733548201, 0.15969171162661025
    shaper_t_x: 0.0, 0.0023549658271864084, 0.005978682955849367, 0.008333648783035774, 0.011957365911698733, 0.014312331738885142
    shaper_type_y: custom
    shaper_a_y: 0.29289321881345254, 0.2276188593372657, 0.3578149838556368, 0.27807212064843273, 0.2185635488426152, 0.16985434446656386
    shaper_t_y: 0.0, 0.0023549658271864084, 0.009323147260570564, 0.011678113087756972, 0.018646294521141128, 0.021001260348327534
    enabled_extruders: extruder

I'm currently on a buisness trip and don't have access to a printer to give some example immediately. However, I just bought some piezo-electrical microphones to try to measure the noise by taping them directly on the motors. But since the global machine noise is significantly different by ears, I've no doubt that there is a noticeable effect on them. Just not sure about "how" and "how much". Regarding the torque, I've no tool to record this, but I could try to run some TEST_SPEED and see how it behave... Not sure this will be very scientific though but it could give some more insights...

Regarding print results, here is an example of a cube printed by andrewmcgr (from our discord conversation since I don't have access to my results right now) and saying this:

The result is that I can push the accelerations really, really high without ringing; I have a cube in front of me that was done at 9k and shows absolutely no ringing, which I have not been able to do before with this printer. For reference, the shaper calibration recommended max accel 4200 for mzv on Y.

image

dmbutyugin commented 5 months ago

OK, as I mentioned, I do not mind this particular change, as it seems harmless.

The rest of the discussion about the application perhaps better suites Klipper Discourse rather than Github. That said, VFAs themselves (Vertical Fine Artifacts) are caused by irregularities in the stepper motion due to detent forces, imbalances in the rotor, magnets, and such. That, as well as vibrations caused by individual (micro)steps cannot be compensated by input shaper. However, indeed one can imagine that accelerations and decelerations could excite vibrations in the steppers too, and those ones could, perhaps, be improved by the input shaper. So, I wonder, what are the typical stepper resonance frequencies are we talking about here? And would you be able to see them in the resonance testing charts? Or are they of too high frequency and don't show up there?

BTW, if you're using my experimental branch anyways, you could give input smoothers a try. These can be thought of as 'smooth' versions of the more classical input shapers, but one of the benefits they have is a better behavior at higher frequencies - they tend to considerably reduce the vibrations at the frequencies much higher than the configured one (e.g. 3x-4x). And one particular smoother - smooth_si - cancels all vibrations above the specified frequency, at least in theory, so using that smoother would not require any tuning or measurements of the stepper own frequencies - as long as they are higher than the configured frequency. The tuning script in that branch supports these smoother for convenience of (auto-)tuning. The only downside of the smoothers is that they are computationally more expensive, so I'd say RPi4 or equivalent would be recommended to allow fast prints. And perhaps it would make sense to enable high-precision stepping, but probably it'd work OK without that too.

The result is that I can push the accelerations really, really high without ringing; I have a cube in front of me that was done at 9k and shows absolutely no ringing, which I have not been able to do before with this printer. For reference, the shaper calibration recommended max accel 4200 for mzv on Y.

Unfortunately, from this sentence it is not clear what was the issue that 'I have not been able to do before with this printer.' Was it skipped steps or something else? FWIW, the recommendation to not exceed a certain acceleration from the tuning script does not come from the remaining ringing considerations, but rather to avoid excessive smoothing in prints. You could, in general, go above the limit acceleration, if one doesn't particularly care about that defect. For instance, this particular demonstrated print may not have ringing, but it definitely has gaps between the perimeters and the top infill lines, which is likely to be caused by excessive smoothing and distortion of the toolhead printing trajectory.

github-actions[bot] commented 4 months ago

Thank you for your contribution to Klipper. Unfortunately, a reviewer has not assigned themselves to this GitHub Pull Request. All Pull Requests are reviewed before merging, and a reviewer will need to volunteer. Further information is available at: https://www.klipper3d.org/CONTRIBUTING.html

There are some steps that you can take now:

  1. Perform a self-review of your Pull Request by following the steps at: https://www.klipper3d.org/CONTRIBUTING.html#what-to-expect-in-a-review If you have completed a self-review, be sure to state the results of that self-review explicitly in the Pull Request comments. A reviewer is more likely to participate if the bulk of a review has already been completed.
  2. Consider opening a topic on the Klipper Discourse server to discuss this work. The Discourse server is a good place to discuss development ideas and to engage users interested in testing. Reviewers are more likely to prioritize Pull Requests with an active community of users.
  3. Consider helping out reviewers by reviewing other Klipper Pull Requests. Taking the time to perform a careful and detailed review of others work is appreciated. Regular contributors are more likely to prioritize the contributions of other regular contributors.

Unfortunately, if a reviewer does not assign themselves to this GitHub Pull Request then it will be automatically closed. If this happens, then it is a good idea to move further discussion to the Klipper Discourse server. Reviewers can reach out on that forum to let you know if they are interested and when they are available.

Best regards, ~ Your friendly GitIssueBot

PS: I'm just an automated script, not a human being.

Frix-x commented 4 months ago

Sorry, I haven't been very available the last few days and haven't had time to do any real experiments on this to get more insightful data.

OK, as I mentioned, I do not mind this particular change, as it seems harmless.

The rest of the discussion about the application perhaps better suites Klipper Discourse rather than Github.

Yes, I agree, and that's why this PR is only about this change and nothing more. The rest is a bit too early and might even be bullshit, but I had to talk about it to share the reason for the PR. Increasing the maximum number of pulses could be useful for other projects as well. For example, another idea I want to experiment with is trying multi-mode shapers to target multiple peaks efficiently (as in this paper for example), but that's another topic and just an idea for now.

I'll open a thread on Klipper discourse later today to discuss it with you and the community :)