Open mh-dm opened 2 weeks ago
Nice work again! Configurable bow was the biggest drawback to s-curve in my opinion! One more thing to pull into my test branch! Lol
This will be interesting to test on boards with an STM32G0 (such as SKR Mini E3 V3.0 and BTT Manta boards) because they are using the fallback implementation for S_CURVE_ACCELRATION and that section runs in 500 cycles on those boards since it doesn't have the umull instruction. Each multiplication on STM32G0 takes 52 cycles so this PR takes around 100 cycles off that 500.
Description
Add configurable 4th order motion support within
S_CURVE_ACCELERATION
alongside the existing 6th order motion support.Background
4th? 6th? What? Short explanation: by default (trapezoidal motion), you set an acceleration limit (example 500mm/s^2), and then whenever the gcode/instructions involve a change in speed it is achieved by accelerating (or decelerating) at that set limit for the required amount of time to achieve the desired speed change. The acceleration goes from 0 (at previous speed) ~instantly to 1x of set limit then back to 0 (at newly desired speed). Force is mass times acceleration which means sudden changes in forces whenever changing speed.
Trapezoidal motion, showing only X-axis. Most speed changes are at 500mm/s^2 acceleration limit.
However, with
S_CURVE_ACCELERATION
the acceleration will smoothly ramp up from 0, go to roughly 2x of the limit then smoothly ramp down to 0 exactly right to achieve the desired speed change. 2x? Yes. We must temporarily go over 1x to complete the same speed change in the same amount of time but while ramping from 0 acceleration. Overall, the average acceleration remains at the set acceleration limit.S_CURVE_ACCELERATION
6th order, showing reaching roughly 2x of the acceleration limitIt's "6th order" because the motion model is position over time as a 6th order polynomial function. However, the actual implementation works with velocity (derivative of speed) modeled as a 5th order polynomial.
Details
The problem, I might argue, is that it's "too smooth" for some applications, including 3d printers.
S_CURVE_ACCELERATION
6th order spends a lot of time around 0 slowly ramping up then it has to hit high acceleration levels. The solution would be a model with a lower order polynomial. So I did the math for a 4th order polynomial (3rd order in velocity) and this is the result:4th order, with
S_CURVE_FACTOR
of 0Note how it only reaches roughly 1.6x of the acceleration limit.
The 4th order motion allows some configuration: the acceleration will start at
S_CURVE_FACTOR
of the limit, ramp up to above 1x then smoothly back down toS_CURVE_FACTOR
of the limit exactly right to achieve the desired speed change.4th order, with
S_CURVE_FACTOR
of 0.25Note how it only reaches roughly 1.4x of the acceleration limit.
Benefits
Less smooth is more smooth™.
For 3d printing in particular, parts are printed line by line with direction changes/corners in between. Cornering is done with "jerk" or junction deviation, both of which involve basically instant speed changes. Basically instant speed change means high acceleration spikes. That doesn't pair that well with a very slowly smoothly ramping
S_CURVE_ACCELERATION
. It should pair better with a still smooth 4th order motion model that ramps up faster, like starting at a 0.25S_CURVE_FACTOR
. Lower peak acceleration should pair better with low-torque motors used in 3d printers.TL;DR
Enable
S_CURVE_ACCELERATION
, uncommentS_CURVE_FACTOR 0.25
and check whether you get less ringing and/or if the printer sounds better/quieter. Then check how much you can increase the acceleration limits before you get too much ringing.Acceleration only, this will have zero or minimal effect on ringing induced by jerk/junction deviation (but you don't know which type of ringing you have until you test). For the other kind of ringing I think you can try input shaping.
Configurations
This feature is not implemented for AVR. If interested I encourage you to have a go at implementing if you have a logic analyzer, an AVR board and are interested in assembly.
The graphs were obtained with a logic analyzer capturing 15M samples at 12Mhz, directly from the X-axis step/dir pins. (Just FYI my boards are LPC176x). Tiny note that captures were done with PRs #26881 and #27035 already applied. I did that to fix some issues that would pollute the captures a tiny bit.
Test gcode:
Related Issues