-
-
Notifications
You must be signed in to change notification settings - Fork 5.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Experiment with s-curves #2030
Experiment with s-curves #2030
Conversation
Suggestion for an object that would more easily demonstrate ringing: A 5mm by 40mm by 40mm calibration object, with a dashed series of 0.2mm high x 0.5mm x 0.5mm recessed pockets going up the middle of one face. Then every other 0.2mm slice doesn't have the 'recessed pcoket, making every other 0.2mm line straight (and have little to no expected ringing). With a script that generates a calibration modification as a function of every 0.4mm of Z, it should be relatively easy for a user to iterate through 4 or so objects, measuring the Z height of each in turn where the best results occurred, and inputting that result into the generation of the next object. |
@KevinOConnor
so if I have measured the ringing on Y to be 39Hz then spring_y_smooth_time: is |
0d6ff48
to
076caa1
Compare
@BlackStump - FWIW, I still need to come up with a good tuning methodology. To retest what I last did (which showed a small improvement) then a 39Hz (25.64ms resonance) would be a 6.41ms quarter wave time. So, -Kevin |
Actually, a -Kevin |
After further thought, I no longer think the motion planning on this branch makes sense. The code should be adding in the "belt spring offset" over the smooth_time period, but it does not smooth the acceleration over the smooth_time period. I don't think that will be productive. I'll keep this open for a few days to see if I can improve the math. I don't think there's value in testing this branch currently. -Kevin |
A few thoughts: The problem arises from discontinuity of acceleration with AO=2. Then your code can be used as-is with 'normal' S-curves to compensate toolhead displacement during acceleration/deceleration. You can try to get rid of discontinuity of acceleration, this requires computing X(t) as X_base(t) + (A_smth(t) - A_inst(t)) * t^2/2 + A_smth(t) * spring_coeff; the problem is the current code does not have access to instant acceleration A_inst(t) on the rail, it can probably be approximated in the same manner as A_smth(t) right now but with t_diff much smaller than cs->smooth_time; I'm not sure if this will lead to any precision issues around points where acceleration changes. Strictly speaking, there is no need to smoothen the acceleration - it is only one of the options. The real issue with AO=2 is that the force kicks in during accel/decel and can cause the vibrations. If we command X(t) = X_base(t) + X_spr(t) just before acceleration, and that X_spr creates the necessary force to match the subsequent acceleration - it should be good enough. X_spr(t) = A_base(t) * spring_coeff can be computed using second order forward derivative of X_base before the acceleration, and second order backward derivative - after the acceleration. An interesting case is acceleration right after deceleration (or deceleration right after acceleration). I think (though I may have missed some corner cases) it can be handled in a generic manner as such: compute forward and backward derivatives, and if they are of the same sign - take the one with the max absolute value, otherwise take the sum as A_base(t). I did not think it through what should be the smoothing time however, though I suspect it should be the half of the ringing period rather than the quarter of it. |
I'm not sure I understand. The step generation code does have access to the instantaneous acceleration (as well as instantaneous velocity). Unfortunately, using those values leads to artefacts because both of those values are not continuous. That's the primary gain to using the calculated position - it's always going to be a continuous value.
Totally agree. Alas, the big issue with the bezier curve implementation (AO=4, AO=6) is that it does the wrong thing in many common situations - for example, it "double accelerates" on two back-to-back accel g-code segments, and it does a slow decel into an instantaneous velocity change on cornering. FWIW, I've reworked the code on this branch and I am now seeing good results locally. However, I remain unsure if the math is sane - I fear my results may only be improving the test prints. More testing is needed - but I also think a new test model is needed - so it's slow going. The key insight to the updated code is that it never makes sense to have a With the above observation, tuning becomes much easier - on the new code one can run: I also wrote some software to graph what the code does for the settings I found for my Makergear M2 printer's Y axis (SMOOTH_Y=.019): The graphing script is in scripts/graph_motion.py on this test branch. One will notice that the resulting axis velocity is still linear and it still has some instantaneous velocity jumps. However, the overall velocity curve does somewhat resemble an s-curve and the positional offset being added does look smooth. There are still some quirks introduced during instantaneous velocity shifts during cornering (modelled in the deceleration part of the graph). -Kevin |
I meant, there is only move_get_coord, which gives the coordinate. Velocity and acceleration currently must be computed using finite differences.
Agree on this one, the current implementation has this issue.
Do you mean here that it's sort of pointless to do a smooth deceleration when followed by the cornering with instant velocity change?
TBH, I initially though of this code as being problematic: FWIW, I suppose the smooth and balance parameters should be chosen such that the toolhead offset (from the chart) is equal to max_accel / (2 pi F)^2 with F - ringing frequency on that axis. |
The code on this branch has the ability to walk the trapezoid motion queue (it's in trapq.c). So, it can look at all the moves, the move accelerations, velocities, etc.
Yes.
Yes - that's what I initially was thinking as well. However, I came to the conclusion that it only makes sense to "pre-load the spring" over a time frame that directly correlates with the acceleration. For example, it wouldn't make sense for the pre-load acceleration rate to exceed the the move acceleration and it wouldn't make sense for the pre-load acceleration to be drastically less than the move acceleration - either of these would just cause more stress on the spring. That led me to instead think of it in terms of a "velocity smoother". -Kevin |
Instead of printing test objects; have you considered using a physics simulation of the printer head to visualize the output? Shouldn’t be more complex than a square mass in a frame held by two springs that have the elasticity of 100mm of GT belt. |
I think stepper motor springiness is more than a decent Kevlar or steel reinforced belt. Also with a belt I think a lot of the "springiness" comes from it not being supported and sagging. On a Shapoko mill the belts are supported and I think it is much stiffer than 3D printer. Also I would expect an unsupported belt mounted on its edge to be stiffer than one rotated 90 degrees from that. |
FYI, this development branch is a follow up from the many discussions in #57 - a simulator was developed as well as a test procedure with a phone accelerometer. -Kevin |
Good point. FWIW, I also consider experimenting with explicit cornering by approximating corners with arcs (for AO=2) and/or bezier curves (for AO=2,4,6) with fixed precision. As a positive, it should work well with constant acceleration mode too. High-level estimation even gives reasonable cornering velocities: e.g. for square corner a good v_c = max_accel / (2 pi F) * \sqrt(\sqrt(2)-1)) with an arc and v_c = max_accel / (2 pi F) with a bezier curve of second order. But it's not easy to predict how will, or rather how should the velocity, acceleration and etc. behave as the toolhead passes through a bezier curve.
A very interesting idea! Looking forward to it! I also think it would be great to run these ideas through some simulation. Of course, a simulation can never replace a real-world testing, because we cannot simulate the whole complex dynamic of the printer with unknown frame rigidity, etc. But it can help discard or compare the ideas - if something does not work in simulation - that's a bad sign :) And we can test on wider range of parameters to see if good results are due to lucky combination of parameters, or if they are consistently reproducible with different parameters. |
e1ceafd
to
abdd62f
Compare
Sounds intriguing. However, most of that "went over my head".
I agree. I looked briefly at @Islandman93's simulator, but wasn't sure how to go about enhancing it for other types of kinematics. Maybe there's some format that we could use as input/output to a simulator so that we could reuse the simulation and generation code. -Kevin |
FYI, I've updated this branch to the "positional smoother" idea. I'm seeing noticeable, but modest improvements on benchmark prints with this code. To test:
-Kevin |
I just printed a square_notch_tower using the recommended TUNING_TOWER COMMAND using 100mm/s speed and saw the smooth_y output showing that TUNING_TOWER COMMAND appeared to be working however I really can't see /any/ difference in the tower. Every layer looks the same. Is that an indication that my max_accel is too low (ie can really get resonances to show up)? Or does the MCU need to be rebuilt/flashed. The MCU is current with current master. I'm using an Ender 3 with max_accel of 1500. I've tuned my PA with the other changes in this branch and corners look awesome and I've been able to enable many of the 'banned' slicer features without issue. Awesome things happening in klipper-land! |
I think I see now what I was missing. I thought I was looking for 'ringing' on the flat surface. It looks like its more the 'squareness' in the corner section 'notch' without any curves. Before realizing this I bumped max_accel to 4000 and that did change how the print turned out however with two towers to compare against and knowing better what I need to look for they both resulted in the same value for smooth_y which for me was ~0.0465. Unfortunately when I put that in the printer section the MCU immediately crashes with |
I got it to print... I think there is a relationship between max_accel and smooth_time. If smooth_time is > 0.0400 the MCU crashes, less then that it works. If I drop accel down to 2000 it breaks at 0.0200. Thanks again for this awesome project.... does mean I print more calibration cubes and benchy's then 'real' projects but I'm amazed and what this can do. |
I tried to print with this patch and did not get good results,
It didnt seem to do much for the ringing but it did have a big effect on the notches |
I've done some more tests on a basic calibration cube and getting nearly perfect results with almost 0 ringing and sharp corners. PA and both smooth values tuned. 100mm/s speed with 4000mm/s/s accel. One thing that I noticed and maybe this is a coincidence but both of my smooth values are very close to 0.040 with accell at 4000.... I'm if I halve the smooth values to 0.0200 I get ringing and obove 0.0400 MCU crashes. I'm retesting now with accel of 2000 to see if ringing goes away. Possible that whatever the smooth_times are effecting should scale with accel and the real value needs to be a factor of that value based on corning angle/speed. Is that what Junction Deviation does/is in marlin? |
@BlackStump where can I get the model you're using to test? |
My current settings. I'm getting 'perfect' benchys and calibration cubes. Seems like I can't go any higher the 0.0325 on y_smooth_time without mcu crashes. Thought I'd set that higher at one point but no go however I'm very impressed with my results.
|
@mattkenn4545 - Thanks. Can you attach the klipper log file from an attempt that causes an mcu failure? Could you post a "before and after" picture of a print - a print with smooth_x/y set next to the same print with smooth_x/y at zero (but code and configuration otherwise unchanged)? @BlackStump - Thanks. My initial reaction is that pressure_advance should be tuned first and that 6K accel is too high to calibrate with. My suspicion is that this branch will do better at cancelling high/mid frequencies, but only indirectly reduce low frequencies. (That is, only reduce low frequencies by virtue of reducing some high frequencies that could otherwise excite a low frequency.) I need to see if I can come up with a tuning methodology that exploits that (and then verify it locally). -Kevin |
@KevinOConnor thanks Kevin, I will retry after tuning PA and dropping accel. |
Here are some text prints z, y and z faces of a calibration cube. Speed is 100mm/s, 4000mm/s/s max_accel Ender 3 First is y_smooth_time: 0.0325 x_smooth_time: 0.0400 and PA of 0.440 The first does appear to need PA tunned down just a bit (corners are a bit round) but other then some elephant's foot due to the first layer being a bit too close to the bed I think it looks amazing and in person it's next to impossible to feel any ridges/imperfections. Not absolutely perfect but getting there. I was able to print the makers muse new v2 tolerance test with no raft at 100mm/s and free everything (down to 0.15mm). The most interesting thing I thought was the z-face lines being 'squiggly' on the non-smooth_time'd cubes. This might be a less time/plastic consuming way to tune those settings. Ie a flat print with lots of accel and speed going at a 45' tool path. If there is a 'Junction Deviation` type missing variable maybe that variable could be tuned with different tool path angles? |
@mattkenn4545 |
FYI, this m2 printer is old and has several deficiencies. I don't consider results on it to be a "good benchmark". I'm actually surprised it can produce anything at 7000 accel. For those that are curious, the following are some of the deficiencies I've identified on this printer: the X rail may not be straight; the belt pulleys aren't geared and may be introducing wobble with each 2mm tooth; the hotend uses a peek insulator which has some flexibility when hot; the extruder motor itself is bound to the x rail only by friction; the control board has old a4984 steppers which only support 8 microsteps; the Y axis is very heavy and only constrained by two linear rails one on side of the printer - it is likely to have X, Y, Z and rotational wobble; the direct drive extruder pulls the filament all the way from the filament spool - any regular snags caused by the filament spool turning might show up as a pattern in the print. -Kevin |
@BlackStump Very interesting (and strange)! I have a few questions about your tests:
|
@dmbutyugin sorry it was late last night and I should have included all that info but I wanted to get the pictures on because of timezone, ie I am sleeping when most of you folks are awake. The artifact is on front run of Y at the end before it does a short x then the return y run, and only on that one end corner (a backwards L on the bed) No I did not use the tuning tower so it was fixed parameters for all prints only shaper parameters changed. Pressure advanced was used it was initially 0.36 I dropped it a tad to 0.34 but I was resisting changing to many parameters. pa was enabled for all tests. I will include the gcode - sliced s3d vase mode I changed frequency on the whim of the accelerometer-acceleration test done prior ...the misguided idea was to see if changing would make a difference. There was no ringing to speak of, I want to use the same parameters that I had been using with the scurve-smoothing branch git show (caveat coming) |
@BlackStump OK, thanks! And which side is up on the picture? So, if I understood you correctly, the prints were printed as a whole with no parameters changing? (except this small decrease in PA?) Also, maybe when you have time, you could re-print the test model with the config measured for your params with Pressure Advance disabled?
Generally, I suspect this could be some layer instability that can happen when printing a single wall sharp corner at high velocity and acceleration - i.e. the filament can be pulled by the nozzle around the corner, and because it is a single wall, it can move into a corner a bit. |
Y is up, correct printed as a whole no parameters changed during the print. |
as requested PA disabled the better print is same PA disabled but with this tuning tower command
I will reslice at a slower speed 140mm/s is pushing the envelope with a single perm wall
|
You don't even need to reslice - just run |
@dmbutyugin |
@dmbutyugin - FYI, I connected two different adxl345 sensors to my makergear m2 printer. (The picture shows one sensor wired to the toolhead, and if you look in the rear right corner of the bed you can see the sensor attached to the bed (not currently wired).) I ran two tests - one gathering the data from the sensor attached to a corner of the bed (vib-y.csv and vib-x.csv). I then moved the wires to a sensor attached to the toolhead (vib-th-x.csv and vib-th-y.csv). Due to the way the toolhead sensor was mounted, the reported x is actually z, the reported y is actually x, and the reported z is actually y. If I'm reading this data correctly, the vibrations on this printer are a mess. It seems the main issue is not directly due to X vibrations nor Y vibrations. Instead, it would seem just about any vibration causes the cantilevered bed to vibrate up/down and side-to-side. -Kevin |
@dmbutyugin I have included in the zip the parameters I used printed at 120mm/s, I would be happy to use any of the three |
@BlackStump Thanks! It is hard to tell from the pictures, but I guess the quality is pretty comparable between different versions. The only interesting this is that
If you observed this with |
@dmbutyugin |
@BlackStump Thanks for all your testing! It would appear that in your case the resonance are very 'well-behaving' - that is, there is a single strong resonance per axis. So ZV and MZV shapers work as good as EI and ZVD. You can likely just use ZV shaper, or MZV which is more robust than ZV for resonance frequency changes/imprecise measurements (though this is less of concern for you, I suppose). EI and ZVD shapers are even more robust than MZV, but they have more smoothing than MZV and ZV shapers. And you can use shaper_freq == resonance freq for a given axis. |
@dmbutyugin you are welcome print quality has certainly improved using your branches. By the way I did a test print using max accel =10000 and shaper_type ei |
Could the accelerometer also help in determining the best possible |
@Sineos No, unfortunately, I do not think so. However, I think we may be able to suggest @KevinOConnor BTW, I also published a script |
@BlackStump, @Sineos Since you've already had some success in using accelerometer, could you try one more test using a newly added test? On
and attach the 2 generated files here in the archive? This won't do any good for you right now - just run the test generate those raw measurements. I am trying some experiments with FFT to detect resonances, but I feel that I need more data, preferably from other printers too. |
@dmbutyugin corexy |
After the initial vibration test, I tore down my entire printer and implemented following modifications:
The results are quite drastic: X Axis Please find all the raw data including the requested new measurement here: https://drive.google.com/file/d/1ipeWnuznC2aWX4qyfM0EnBjk5Mx00RGP/view?usp=sharing |
I'm closing this PR as I feel confident that there are superior alternatives to my code on this particular branch. I believe the input-shaping code by @dmbutyugin is superior (and his input-smoothing work as well). The discussion on this ticket has gotten a bit long, so I think it makes sense to move the discussion to the newer tickets focused on the new methodology (see #3025 and #3027). Thanks everyone for their participation! |
This branch contains the code to implement an experiment with s-curves to try and reduce "ringing" (aka "ghosting") on prints. This is just a test, and is likely only of interest to other developers.
The current Klipper code uses a standard "trapezoid" velocity motion planner. PR #1776 changes that planner to implement "s-curves" during acceleration:
This branch attempts a different approach:
That is, instead of implementing the curves within the time allotted for normal acceleration, the code permits acceleration leading up to and after the nominal acceleration time. This does result in the steppers taking a "path" that deviates from the commanded path - but it is done with the high-level thinking that it actually results in the toolpath more closely following the commanded path.
For example, it is currently believed that "ringing" is the result of the toolhead not following the "stepper path":
And thus commanding the steppers to take a deviated path could result in an improved overall toolhead path:
This code is an experiment. It defines new
spring_x
,spring_x_smooth_time
,spring_y
,spring_y_smooth_time
config settings that define the new s-curves. The duration of the s-curve is controlled by the smooth_time settings. The amount of deviation is determined by the spring parameters and the amount of estimated acceleration. (The code uses estimated acceleration instead of the nominal acceleration, and thus does not have the "double acceleration" type issues with the bezier s-curve implementation.) Different s-curves may be used for x and y axes.There are several caveats with this code:
I was able to tune this on my Makergear M2 printer (a "bed slinger"). The results were a noticeable, but small improvement. I suspect an improved calibration routine may yield better results. The calibration method I used was: print a tuning tower and measure the resonance, set the smooth_time parameters based on 1/4th the resonance time, print a tuning tower with changing spring value for each level (eg,
TUNING_TOWER COMMAND=SET_SPRING PARAMETER=SPRING_Y START=0 FACTOR=.000010
, measure the point of least resonance, and finally test on typical xyz calibration cubes.-Kevin