MarlinFirmware / Marlin

Marlin is an optimized firmware for RepRap 3D printers based on the Arduino platform. Many commercial 3D printers come with Marlin installed. Check with your vendor if you need source code for your specific machine.
https://marlinfw.org
GNU General Public License v3.0
16.18k stars 19.22k forks source link

[FR] Junction Deviation Tune Test #15511

Closed Roxy-3D closed 4 years ago

Roxy-3D commented 4 years ago

We have switched from Classic Jerk to Junction Deviation as the default basis to calculate Planner:: moves. The example Configuration.h files have been updated to have an accurate Junction Deviation value based on the file's Jerk and Default Acceleration numbers.

I'm looking for ideas to test the accuracy of that number. What tests can be put in place to check the correctness of the Junction Deviation number?

If reasonable ideas are presented, with enough detail to implement them... I'll code them up....

LinFor commented 4 years ago

I'm using this triangle model and attached script: https://www.thingiverse.com/thing:3463159 It consists of sections of a sharp change in direction along with even sections, which allows us to estimate both the magnitude of the influx at the corners and the mechanical ringing in straight sections after disturbances.

edwilliams16 commented 4 years ago

A solid triangular prism seems wasteful of printing time. It should be at least partially hollow and sliced with all the layers parallel to the edges. Time printing fill is wasted. A polygonal object with a greater range of angles might be a better test as classic jerk and J.D. handle angular dependence differently.
I think a simple post-processor on the G-code would be the easiest way (for me) to change the junction deviation with height. @LinFor Did your experiments work for tuning? I see the comments on thingiverse showed variable success.

This one has angles of 36, 72, 108 and 144 degrees. image

LinFor commented 4 years ago

@edwilliams16 of course, it prints without infill, in "vase" mode. Yes, in my case, with the naked eye there are differences in angles (bulging) and flat areas (ringing)

edwilliams16 commented 4 years ago

I was mislead by the pictures and missed:

Layer Height: 0.2mm
Shell
Wall Line Count: 1
Top Layers: 0
Bottom Layers: 2 or 3 (whatever you prefer)
Infill
Infill density: 0%

Did you try the same model varying classic jerk?

LinFor commented 4 years ago

No, I didn't try classic jerks... It's interesting to try

edwilliams16 commented 4 years ago

I spent a day attempting to tune junction deviation using a single shell like the above. I found it necessary to use linear advance or I got blobs on the acute angles, but I ended up with a value 75% of the one I obtained from @Roxy-3D 's tuning test. My best value of d the junction deviation was fairly close to the nominal default 0.4 j^2/a, though it was not very sensitive to the exact value. I did get curious about angular dependence as my acute angles and obtuse ones wouldn't really tune simultaneously, so I did some algebra, which I'll spare you for the moment. I assumed x and y jerk were equal and that the jerk algorithm is that the change in the x/y component at the corner should not exceed, respectively the x/y jerk. I can then get a cornering speed (normalized to jerk speed) as a function of the angle of turn, arising solely from the jerk/junction deviation limits. Cornering speed Using the nominal value d =0.414 j^2/a (j = jerk, a = printing acceleration), we see that the cornering speeds at 90 degrees are equal - that was how the factor of ~0.4 was derived. In both cases as the angle of turn goes to zero the junction speed becomes unlimited, but is ~1.8 times larger for the junction deviation case. In the case of a 180 degree course reversal, the junction speed is half the jerk in the jerk algorithm, but comes to a halt in the junction deviation case (I think the Marlin algorithm is tweaked here, to provide a minimum cornering speed?) Anyhow, it seems the main difference between the two algorithms, with a given acceleration is the angular dependence of the cornering speed. Junction deviation has a steeper dependence on cornering angle. This is illustrated in the next plot: Cornering_ratio This shows the ratio of the cornering speeds as a function of angle. Choosing d = 0.414 j^2/a makes the ratio one at 90 degrees (by design). Choosing d = 0.125 j^2/a makes the ratio one at small angles of turn. The bottom line here seems to be that one chooses between classic jerk and junction deviation by which works best over a range of turn angles. I have yet to do a corresponding series of experiments with classic jerk. One limitation of junction deviation seems to be that if you really need different x and y jerks, it doesn't account for this.

Reference: https://onehossshay.wordpress.com/2011/09/24/improving_grbl_cornering_algorithm/

I think @Sebastianv650 is one of the experts on this? I may have missed something important.

AnHardt commented 4 years ago

Interesting. Infinit speeds are obviously crap. The junction between two segments, where direction does not differ, is limited by the lower commanded velocity (of the both segments). The lower commanded velocity can't be exceeded at any angle - has to be clipped. Turning 180° always includes a complete physical stop of all axes. Because our motion is not continuous but in steps, we have to care about the last/first step doesn't last forever. Clipping to a minimal speed is required (and done). (A completely (real)jerk free motion is impossible when moving in steps.) If the jerk-speed is different for the axes, the "circle" deforms to an "ellipse". We could either scale the axes to deform the "ellipse" back to a "circle" - and scale back the result, or simplify things by using the smaller of the jerk-speeds (what the suggested formula (for converting the configs) does).

edwilliams16 commented 4 years ago

Infinite speeds are obviously crap. The junction between two segments, where direction does not differ, is limited by the lower commanded velocity (of the both segments). The lower commanded velocity can't be exceeded at any angle - has to be clipped.

True. I was isolating the effect of the jerk/junction deviation constraint where you enter and exit the corner at the same speed. If there's no change in direction, there's no constraint. So my curves are clipped at some value from above, depending on some other constraint.

Quoting the algorithm above:

To then find the absolute maximum velocity through the junction, just apply: min(vjunction, min(entry, v_exit), to guarantee the junction speed never exceeds either the entry or exit speeds at the junction.

I'm just computing the vjunction term.

If the jerk-speed is different for the axes, the "circle" deforms to an "ellipse". We could either scale the axes to deform the "ellipse" back to a "circle" - and scale back the result, or simplify things by using the smaller of the jerk-speeds (what the suggested formula (for converting the configs) does).

I assume the code does the latter at present? Doing the former would be a challenge if you want to avoid any trig functions. (EDIT No, you don't need trig - I think it can all be done with the dot product of the scaled displacement vectors and some second parameter.)

Turning 180° always includes a complete physical stop of all axes. Because our motion is not continuous but in steps, we have to care about the last/first step doesn't last forever.

Good point. But does this issue only arise when the desired velocity continuously goes through zero? I've always assumed that you could command a discontinuous reversal of velocity as long the change does not exceed the jerk. (i.e a constant rate stream of forward steps followed by a stream of reverse steps.)

Is there an equivalent to Smoothieware's "minimum planner speed" in Marlin? As described in https://reprap.org/forum/read.php?1,739819 If so there is also a floor on the cornering speed from junction deviation when making sufficiently acute angle turns (approaching 180 degrees in my angle convention, approaching 0 degrees in Paul Wanamaker's convention.)

AnHardt commented 4 years ago

I assume the code does the latter at present?

Yes. For the "ellipse / ellipsoid" a parameter per axis would be required. We only have one describing a "circle / sphere".

Is there an equivalent to Smoothieware's "minimum planner speed" in Marlin?

Yes. MINIMUM_PLANNER_SPEED

But does this issue only arise when the desired velocity continuously goes through zero? I've always assumed that you could command a discontinuous reversal of velocity as long the change does not exceed the jerk. (i.e a constant rate stream of forward steps followed by a stream of reverse steps.)

Pardon. I don't really understand what you are talking about.

All segments have a minimum length (MIN_STEPS_PER_SEGMENT) Als segments have a commanded velocity > 0 All segments have only one direction The commanded velocity is constant for a segment Stepper direction is set at the begin of the segment and does not change (except maybe for the extruder with LinearAdvance (but that's done behind the planner)) So it is impossible to cross zero speed inside a segment!

After the initial planing for each of the segments we have, at least, the information about its commanded target speed, the maximum speed it can begin with (cornering speed) and the allowed acceleration = deceleration. Now we put these segments into the planner buffer. A first move after having an empty buffer has to start from stand still (zero -> MINIMUM_PLANNER_SPEED). All newly appended segments have to end with a stop (zero -> MINIMUM_PLANNER_SPEED) When having enough segments in the buffer we try to connect the segments (reverse and forward path). It's tried to optimize the speeds (maximize) without violating any of the constrains. Because we normally (if not using jerk-speed and target speed is below of that) can't start a segment with target speed we can divide each segment in 3 sub segments: acceleration, cruse, deceleration. However. After optimizing we have the numbers at what step the acceleration ends and from what step on to decelerate (both of the numbers can be 0 or maxsteps and equal to omit one or more of the phases). Step is an integer and times are integer (using a counter) so we have some inaccuracies (rounding) making possible the deceleration starts a step to early or time is increased a tiny bit to much - resulting in a last step with zero or negative speed. That is caught an replaced by MINIMUM_PLANNER_SPEED. (With S-curve-acceleration we seemingly have the opposite effect - at least sometimes, still being to fast when no steps are left. That's much harder to correct.)

Zero -> MINIMUM_PLANNER_SPEED is used when starting from stop, or ending a move sequence, or max_junction_speed is that low (180° turn = all axes are changing directions or are not involved (standing still).

edwilliams16 commented 4 years ago

Does anyone know how to generate the data for plots like this: https://user-images.githubusercontent.com/2166982/49217003-4d6b2b80-f381-11e8-8575-4b535c9093a7.png from https://github.dyf62976.workers.dev/MarlinFirmware/Marlin/issues/12540 ? or does it need hardware - oscilloscopes etc.

The planner code is somewhat opaque. It would be useful (for me!) to verify what it actually does!

Roxy-3D commented 4 years ago

Ed: I've only been skimming this thread because I don't have time to dig in yet. But I have this thread open as a tab in my browser so I don't forget about it and so I can see what is happening. (I fully intend to understand everything that has been said here as soon as I have some time.)

We can easily get the data and generate plots like that. Please tell us what you are thinking and why those types of plots will be helpful. With a little bit more information, I may be able to understand the barrier and get us the data you want.

AnHardt commented 4 years ago

When we compare two machines with the same adjustments for jerk-speed or JD and observe the one is ringing more than the other, we tend to reduce the values for the more ringing machine. But if it comes to skipping steps the more ringing, more elastic, less stiff machine is able to handle higher cornering speeds without loosing steps. An other interesting question is related to resonances. What happens when we try to print a square wave like pattern and the distances meet the wavelength of the ringing?

edwilliams16 commented 4 years ago

@AnHardt Thanks for taking the time for the explanation. @Roxy-3D I'd like to be able to make velocity plots, so I don't have to pester you all with questions that I could easily answer myself if I had the right tools, given the only real documentation seems to be the code itself!

Since we are talking ringing, here's a typical test piece:

_KS29654l In this one, I kept the acceleration and junction deviation fixed and varied the print speed (~90, 30, 60 mm/sec from top to bottom) The wavelength is pretty much proportional to the speed, implying that the ringing is at a constant temporal frequency. I need to write a little analysis software to get line-outs from the png to get some real measurements, which are complicated a bit by the acceleration/deceleration phases and what looks like some beating between different wavelengths. This inspired me to use my iphone as a vibration analyzer (vibSensor is the app. Parenthetically, I'm a little bit concerned about the 100Hz sampling frequency. If there's substantial vibration above the 50 Hz Nyquist frequency, the data will be aliased. I should probably look for an audio spectrum analyzer app to see what's happening at higher frequencies.). It shows a vibration peak at ~30 Hz which is roughly consistent with the ringing data wavelengths. I installed some dampers on the x and y stepper motor mounts which knocked down the mean square vibration by about ~2 but did reduce the stepper noise considerably. Didn't make an obvious visible change to the ringing on the test piece though. I should note that the ripples in the test piece are quite small, barely perceptible to the touch but visible in the right raking light, making them tricky to photograph. I don't have any good ideas as to how to measure their amplitude. Likewise the vibrations of my machine frame are quite small, barely perceptible to a fingertip.
image Here's some typical vibration data. I need to clamp the phone so the x/y axes are parallel to the machine axes in the future. The easy way I took ended up at 45 degrees so the x and y vibrations are mixed up. My Rigidbot moves the bed in y and the extruder on a gantry in x, so they very likely have different resonances.

As to a square wave test test piece - at 60 mm/sec and 30 Hz, a 2 mm wavelength should excite the resonance on my machine. I haven't looked to see how sharp the resonance is, though with numerical data, it could be estimated from the observed damping rate.

edwilliams16 commented 4 years ago

I ran SpectrumView (an audio spectrogram) on my iphone listening to it print the above shell. The main noise associated with tracing around the perimeter is the pulsation you see at 90 Hz. This aliases to 10 Hz on the vibration spectrum in my previous post, so that little data peak is likely bogus. I don't see the 30 Hz in the audio, but that sound wouldn't radiate very well. I show the non-printing spectrogram for comparison - so that noise at 800 Hz and below in both plots is my power supply fan. You should mentally subtract the pics. I would judge that the vibration data is probably good and not aliased. image Spectrogram when printing image Spectrogram fans only

EDIT: An additional facton: the resonant frequencies of my stepper motors, calculated from their (unloaded) moments of inertia and holding torque are 88 and 81 Hz for x and y respectively. Maybe that is source of the ~ 90 Hz pulses in the audio spectrum.

AnHardt commented 4 years ago

Wow. Great pictures and data.

In time the ringing has to be a damped cos function. The wavelength depends on movement speed. On the photo the increasing wavelength during acceleration is well visible. For provoking skiped steps the square-wave idea is probably crap. Because the amplitude has to be largest at the corner ( cos(0) ) a 180° turn represents the worst case. All consecutive amplitudes are lower and 0 is the time/way easiest to get exactly. For a really bad shaking machine we should simply move back and forth with slowly increasing distance. Hopefully skipping steps will damp the oscillation before the machine falls apart. However. What can we win when knowing the resonance frequency per axis? We could try to avoid that frequency by varying speed and/or acceleration (not way). But determining the exact duration of a move is expensive. Currently we don't have that number anywhere in Marlin.

At the stepper motor the maximum possible amplitude is 2 full steps. Beyond that it will skip. For belt drive axes spring constant and length of the belt and driven weight are likely to be the most contributing factors. Only very weak frames are likely to contribute much. For spindle driven axes i suppose the max magnitude to be the backlash. No idea about the frequency. (is ringing observer on spindel axes? On 3D-printers? CNCs?) (Could make sense, on single spindele driven z-axes, to place the layer change close to the spindle - smaller amplitude.)

For the factors of damping i currently have no real idea. Friction is the keyword here. Besides of friction in the barings, the drag of the print-head will contribute (depending mostly on if extruding or not, but likely also on how much the extrusion is squished (width/height ratio)).

Sorry for having more question (to myself) than answers today.

AnHardt commented 4 years ago

Back to a test for JD-

The important part of the test is: Does it skip or not? "How much does it ring at what JD" is secondary. As a rule of thumb: "Lower speed for lower ringing" seems to be reasonable. So a matter of taste. Adjust it to your needs. If ringing is to much reduce speed. If speed is to low pay it with more ringing.

A more detailed (quantifying) ringing test makes only sense when trying to improve the hardware.

edwilliams16 commented 4 years ago

The default junction deviation value for my machine is d=0.043 That gave perfectly acceptable results, but I ended up with d=0.050 as my favorite value. I ran d down to 0.015 without observing skipping, but corner quality was uglier. So I actually haven't made the machine skip.

AnHardt commented 4 years ago

Having slept a bit i realize, while moving back and forth is good for finding the resonance frequency it is not using the JD-value at all. JD Plot At 180° the result of the JD-calculation is always 0 - independent from the JD value.

edwilliams16 commented 4 years ago

Maybe a good way to excite the resonance is to ramp the speed up and down in a sawtooth, while traveling in a straight line. That way junction deviation limits don't enter since you aren't changing direction.

For example, something like alternating 1 mm segments commanded at 55 and 65 mm/sec, with an acceleration of 600 mm/sec^2 gives a 30 Hz oscillation of the velocity.

Roxy-3D commented 4 years ago

Maybe a good way to excite the resonance is to ramp the speed up and down in a sawtooth, while traveling in a straight line. That way junction deviation limits don't enter since you aren't changing direction.

From a firmware perspective... We can do this fairly easily. The trick would be to know where the resonance starts and where it dampens... We could do this.

What ever we do needs to be more sophisticated and complete than this. But if we were to add an M-Code to help tune this stuff... One of the modes could be a resonance test where we start pushing the nozzle back and forth and the user could indicate (with a press of the encoder wheel) when things are resonating too much. And at higher speeds... another click when the resonance starts to dampen.

Knowing those numbers (and a few other important numbers) could get us a long way up the curve.

edwilliams16 commented 4 years ago

@Roxy3D As @AnHardt said above, a quantitative measure of ringing would be most useful for testing your hardware. I don't think you readily can use it to improve printing. I have yet to try a shaking test on my machine.

Roxy-3D commented 4 years ago

I think everybody is in agreement that resonance is a limiting condition. I think we could sweep the speed of the nozzle along an axis and try to trigger a resonance.

My question is: Is it likely the user will be able to see (or hear) the resonance well enough that we can have them tell us "That speed is causing problems."

Bumpfish commented 4 years ago

I have been trying to calibrate using a 20x20x1mm square. I intentionally underextruded a print to see what was happening. You can see the underextrusion in the walls, but overextrusion in the wall corners. The bottom/top layer patter in Cura was set to Line. You can see the overextrusion on each line fill. Let me know if this helps, and I can add more information regarding my testing. extrusion at 50percent

edwilliams16 commented 4 years ago

@Bumpfish Are you using linear advance? I found I needed it with junction deviation to fix what you are seeing. There's a test pattern generator for it at http://marlinfw.org/tools/lin_advance/k-factor.html

Bumpfish commented 4 years ago

@edwilliams16 I am not. I will try it now. Thanks for the tip and the test generator link.

Bumpfish commented 4 years ago

Results were best with K = 0.

edwilliams16 commented 4 years ago

For me, K=0.16 was optimum and fixed blobbing in the corners - but it does vary with filament material and temperature (and Bowden vs. direct).

shitcreek commented 4 years ago

@edwilliams16, just wanted to add that Linear Advance must to be calibrated for each filament type, extruder, temp (I'm able to get away with 15* differences without having to alter the K value), and nozzle size.

github-actions[bot] commented 4 years ago

This issue is stale because it has been open 30 days with no activity. Remove stale label / comment or this will be closed in 5 days.

github-actions[bot] commented 4 years ago

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.