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

[Discussion] Handling of junction speeds and jerk #9917

Closed Sebastianv650 closed 4 years ago

Sebastianv650 commented 6 years ago

This is a follow-up to a topic which already was here a long time ago, but I can't find it anymore. If someone remebers it and can find the issue, you might link it here.

During the research for strange jerk behaviour today I stumbled around the suboptimal handling of junction speeds again. In one sentence: Marlins way of handling jerk and junction speeds leads to exceeded jerk in some daily situations. The attached test gcode and the results in the table should clarify things a bit. The gcode does the following things:

I printed the following values over serial:

I did two runs, first with X and Y jerk set to 5 and E jerk set to 1mm/s, and a second one switching the values. As you can see, as soon as we are switching between extruder only moves and XY moves things start to get wired. Same should be true for Z only moves and XY moves. The problem is that Marlin connects each segment by one single junction speed, which is not always what is needed. A simple example like the one from H13 in the table, lets assume a X Jerk of 1, an E jerk of 5. Let's do a print move along X followed by a prime move. What we want ist:

The two axis X and E are not linked, also their junction speeds shouldn't be linked. What Marlin does is in this case is:

jerk

It becomes crucial when we replace the first print move by a Z move. Z axis often have 0.x jerk values, but the final speed would be also 5mm/s due to the following retract move.

Conclusion:

Files: Marlin Junction speeds.zip

hoffbaked commented 6 years ago

I've been basing all my observations off the grbl code. If they're normalizing the values, I don't see it. Strange.

Sebastianv650 commented 6 years ago

I've been basing all my observations off the grbl code. If they're normalizing the values, I don't see it. Strange.

At this point, they are setting up the non-normalized vector even if it's already named unit_vec: https://github.com/gnea/grbl/blob/master/grbl/planner.c#L374 A few lines later, they normalize the vector and get the length of the move "at the same time": https://github.com/gnea/grbl/blob/master/grbl/planner.c#L387 This vector is baseline for all futher calculations like the junction speed.

Sebastianv650 commented 6 years ago

@hoffbaked with this sorted out, what do you think about your check for small movements now? Is it still a valid change? I had no time to check the result of this modification up to now, but with some luck I can do it this afternoon.

hoffbaked commented 6 years ago

Ah, tricky. : ) Yes, it definitely will plow through tiny rounded corners at impressive speeds without it.

hoffbaked commented 6 years ago

Incidentally, on the acos approximation, subtracting the .18 maximum error was probably a bit too conservative. I've been testing it on my machine with .05 with a bit less slowdown. As the angle approaches 180, the errors get magnified and it slows down more than it needs to in some cases. I've been meaning to try and find a little more accurate solution, but life has been pretty hectic.

Sebastianv650 commented 6 years ago

I plotted a graph to get a feeling for this limited szenario, using segment lengths from 0.2 to 0.95mm and junction agles from 140 to 170°:

grafik

The steep curve is the original junction speed value, the more flat one is the limited one. It definitly works as intended, thats nice to see. Nevertheless I still have that questionmark in mind if we realy need it. Sure, it will pass a high-resolution arc at whatever speed was set with G1 F command. But that's how it should be as we are saying the centrifugal force is the acceleration we are allowing based on axis limits and print / travel acceleration. The more segments, the closer we are on a perfect arc. A perfect arc can be driven at high speed, as no jerk occures at all. Slowdown should be only necessary if we have real corners, therefore we are not close to an arc.

I guess I have to do some test prints with and without that limiter active and see what I get.

Sebastianv650 commented 6 years ago

OK, I can see the need in test prints (40mm cubes with 1mm radius on the edges). While the jerk seems not to be "hard" to the machine, it still results in quite an amount of ringing.

So we can see the basic junction_deviation code as a speed limiter for corners of any kind (as the name suggests), und this add-on as a speed limiter for close to real world arcs.

Squid116 commented 6 years ago

Great investigations @sebastianv650 picture paints a thousand words!

Squid116 commented 6 years ago

I have just been trying to dial things in with the new code, would it be worth adding JUNCTION_DEVIATION_MM to M205? After a machine is initially set up it is unlikely to change, but it would make the process of getting all set up easier.

iosonopersia commented 6 years ago

In MK4duo we now have M205 J to set JUNCTION_DEVIATION_MM

Sebastianv650 commented 6 years ago

At the moment the JUNCTION_DEVIATION has a very basic implementation. Yes, definitly we need an M code to change the value and we should also have an LCD menu entry for it. On the other hand, X Y and Z jerk values should be removed from the LCD when the new version is used. E jerk is a special case, as linear advance needs it. So this one must be available in the menu if LA is enabled. Else, it should be also removed.

I think it's just a question of time until I or someone finds a free slot.

thinkyhead commented 6 years ago

M205 J sounds like a good plan. I'll add that soon.

thinkyhead commented 6 years ago

I see that the max_jerk array is completely unused when JUNCTION_DEVIATION is enabled, with one exception. The max_jerk[E_AXIS] is still used if LIN_ADVANCE is enabled. Is that value important to retain while JUNCTION_DEVIATION is in use, or could it be substituted? Asking because if max_jerk can be dropped when JUNCTION_DEVIATION is active, then it saves some SRAM and EEPROM space.

thinkyhead commented 6 years ago

I'm just working on M205 J and the LCD edit option… What's a good range of values for the planner.junction_deviation_mm setting?

Squid116 commented 6 years ago

@thinkyhead 0.01 to 0.3 is the range I have tested with. The lower end being more realistic. 0.3 is getting very sloppy on the corners.

Sebastianv650 commented 6 years ago

I'm using the default 0.02. As we are already at 0.0x level, maybe we need even 3 digits some day to get even lower?

@thinkyhead in theory it should be possible to replace max_jerk[E_AXIS] for LA with the equivalent term from junction_deviation. This would be:

max_ejerk [mm/s] = SQRT(SQRT(0.5) * max_acceleration_mm_per_s2[E_AXIS] * junction_deviation_mm) / (1 - SQRT(0.5))

In reality, max_acceleration_mm_per_s2[E_AXIS] is often not set properly (10000 for example) so it will result in some issue threads I think. But in the end that's "just" a problem with a bad configuration.

thinkyhead commented 6 years ago

@Sebastianv650 — Based on your comment I've added a new planner variable that gets recalculated whenever junction_deviation_mm is updated.

gloomyandy commented 6 years ago

Given that a lot of configurations have an E acceleration of 10000, what would be a sensible starting setting for typical extruders? So for instance I have an e3d Titan Aero, but have no idea what acceleration figure to set or how to go about tuning it? I'm happy to run some tests if anyone has a recommended process? @Sebastianv650 @thinkyhead ?

Sebastianv650 commented 6 years ago

@thinkyhead oh no I just realized I made a mistake with the brackets in the equation above while I calculated the acceleration for @gloomyandy using it! Instead of

max_ejerk [mm/s] = SQRT(SQRT(0.5) * max_acceleration_mm_per_s2[E_AXIS] * junction_deviation_mm) / (1 - SQRT(0.5))

it should be

max_ejerk [mm/s] = SQRT((SQRT(0.5) * max_acceleration_mm_per_s2[E_AXIS] * junction_deviation_mm) / (1 - SQRT(0.5)))

It's the same equation used by the junction deviation code, but with a fixed sin_theta value of 0.707 (=SQRT(0.5)) and a SQRT in front of all as we don't need the squared speed for this example.

@gloomyandy I would start by searching for an acceleration which results in realistic speeds for "ejerk" with your used JUNCTION_DEVIATION_MM value. Given the formula from above and a junction deviation value of 0.02mm, this would result in an max. e acceleration of 2100mm/s² for what would have been an ejerk before of 10mm/s.

gloomyandy commented 6 years ago

Hi, thanks for the update I will give 2100 a go and work from there. A quick question about the brackets error. Will this be likely to have impacted the tests I've been running using the linear advance test program to determine the best K to use(I was using a very recent bugfix-2.0.x with junction deviation enabled), should I run those tests again once the above change has been made?

Also on a related topic. When using a combination of junction deviation and linear advance, what is likely to be the best setting for JUNCTION_DEVIATION_INCLUDE_E, does it make sense to enable it or not?

thinkyhead commented 6 years ago

@Sebastianv650 — Thanks for the correction! I've applied the patch to both bugfix branches.

frech-tech commented 6 years ago

Hi,

great work with the junction deviation! I just go through the math behind the junction deviation and linear advance. Since the max. velocity calculations for linear advance are not squared (like for the junction deviation), the calculations for the MAX_E_JERK is: SQRT(SQRT(SIN(Theta/2)) max_acceleration_mm_per_s2[_EINDEX] junction_deviation_mm) / (1 - SIN(Theta/2)) You spitted this calc using max_e_jerk_factor: max_e_jerk_factor SQRT(SQRT(0.5) junction_deviation_mm RECIPROCAL(1.0 - SQRT(0.5))) and MAX_E_JERK (max_e_jerk_factor max_acceleration_mm_per_s2[_EINDEX]) But shouldn't it be like this? of did I get something wring? MAX_E_JERK (max_e_jerk_factor SQRT(max_acceleration_mm_per_s2[_EINDEX]))

Another Question: Did you you use a 90 degree angle (theta) for the extruder, because this represent a "stop"?

Sebastianv650 commented 6 years ago

@JackDaFlow you have the same bracket error in your first equation I did initialy. Everything has to be SQRT(), not only the upper part of the fraction.

MAX_E_JERK (max_e_jerk_factor * SQRT(max_acceleration_mm_per_s2[_EINDEX]))

That's true. I have not looked into the code this moment, but this version results in the wanted value.

Another Question: Did you you use a 90 degree angle (theta) for the extruder, because this represent a "stop"?

Yes.

gloomyandy commented 6 years ago

So to clarify the current code looks like..

      #if ENABLED(JUNCTION_DEVIATION)
        #define MAX_E_JERK (max_e_jerk_factor * max_acceleration_mm_per_s2[_EINDEX])
      #else
        #define MAX_E_JERK max_jerk[E_AXIS]
      #endif

does it need to be changed to:

      #if ENABLED(JUNCTION_DEVIATION)
        #define MAX_E_JERK (max_e_jerk_factor *SQRT( max_acceleration_mm_per_s2[_EINDEX]))
      #else
        #define MAX_E_JERK max_jerk[E_AXIS]
      #endif

It looks like it should be possible to avoid the repeated calls to SQRT if so...

thinkyhead commented 6 years ago

At this point I think we've got it sorted in both branches! Anything more to discuss or should we close this thread?

gloomyandy commented 6 years ago

I think there are still some documentation issues around. Like for instance when should you enable JUNCTION_DEVIATION_INCLUDE_E? Does this interact with linear advance? Does it make sense to enable both?

thinkyhead commented 6 years ago

Sounds like we will need to gain more experience to be able to answer those questions.

Squid116 commented 6 years ago

@Sebastianv650 mentioned removing the JUNCTION_DEVIATION_INCLUDE_E here: https://github.com/MarlinFirmware/Marlin/pull/10906

I tend to agree, I think it should always be enabled and the option removed.

lrpirlet commented 6 years ago

@Sebastianv650

I am somewhat puzzled… I used to have in my working configuration the following acceleration setting…

#define DEFAULT_MAX_ACCELERATION      { 3000, 3000, 100, 10000 } //tuning lrp 3000, 3000, 100, 10000 } Tested ok except E axis

/**
 * Default Acceleration (change/s) change = mm/s
 * Override with M204
 *
 *   M204 P    Acceleration
 *   M204 R    Retract Acceleration
 *   M204 T    Travel Acceleration
 */
#define DEFAULT_ACCELERATION                  1500    // X, Y, Z and E acceleration for printing moves
#define DEFAULT_RETRACT_ACCELERATION  3000    // E acceleration for retracts
#define DEFAULT_TRAVEL_ACCELERATION    3000    // X, Y, Z acceleration for travel (non printing) moves 

/**
 * Default Jerk (mm/s)
 * Override with M205 X Y Z E
 *
 * "Jerk" specifies the minimum speed change that requires acceleration.
 * When changing speed and direction, if the difference is less than the
 * value set here, it may happen instantaneously.
 */
#define DEFAULT_XJERK                 10.0 
#define DEFAULT_YJERK                 10.0
#define DEFAULT_ZJERK                  0.3
#define DEFAULT_EJERK                  5.0

I put your formula in excel max_ejerk [mm/s] = SQRT((SQRT(0.5) max_acceleration_mm_per_s2[E_AXIS] junction_deviation_mm) / (1 - SQRT(0.5)))

For a junction deviation = 0.02, this formula gives me either a max acceleration of 517,9 for an ejerk of ~5,0 or an ejerk of ~12,0 for a max acceleration of 3000

Obviously, one or several of my values were out of tune… Max acceleration was too high, the sloop of speed change was ok for the retract… should I conclude that my ejerk was too small??? I am driving a 3mm abs filament thru a greg wade extruder with a couple of gears with a ratio of 37-13...

I feel uneasy, did I miss something??? is that "calculated ejerk" value anything but limit or is that value actively used?? Of course I will conduct some testing and learn from my mistakes, but if you could help me make some educated guess, I would be quite thankful.

lrpirlet commented 6 years ago

@Sebastianv650 Typing my question above led me to think from another perspective… Could it be that a 2mm retract is not enough of a move to go past the physical acceleration induced by the ejerk value???

If so, should I limit the max acceleration to 1500 leading to an Ejerk of 8,5???? I will be using S-curve-acceleration so this should allow my printer to allow higher number for moves (not higher overall speed I now predict)

ejerk funtcion of junction deviation.xlsx

Sebastianv650 commented 6 years ago

@lrpirlet I'm not sure if I understand you problem. Is it because your initial max acceleration values don't result in the ejerk values you had before junction_deviation using the equation? That's fine, as they were not linked in any means by the "legacy" jerk / acceleration code.

You can think of the junction deviation = 0.02 being the new jerk value. Given an acceleration, it results in junction jerk speeds. So you can still tune jerk and acceleration separate from each other, but linked by this value.

For linear advance, this ejerk speed value is used as the upper speed limit at which pressure corrections can occur.

Could it be that a 2mm retract is not enough of a move to go past the physical acceleration induced by the ejerk value???

The length of a move and the acceleration are not linked. If you mean top speed: With 3000mm/s² you can reach about 110mm/s even when starting from 0mm/s speed after 2mm.

If so, should I limit the max acceleration to 1500 leading to an Ejerk of 8,5?

A typical retract speed of 40mm/s is reached after 0.25mm @ 3000mm/s² even without any jerk. So if you want to reach an ejerk of 8.5mm, even an max. e acceleration of 1500mm/s² will not limit your printing speed noticeable.

lrpirlet commented 6 years ago

@Sebastianv650 Thanks, what makes me wonder, is that we use to be able to set INDEPENDENTLY max speed and jerk… When coming from a well tuned version 1.? to the bugfix_2.0.x version I did try to match my old parameters to the new… And here is a hardcoded relation...

Using the new features, I feel like facing a completely new firmware with nearly no relation with the old one… Trying to understand the interaction between the new features is quite a challenge… I do not want to keep hanging on the "good old way of doing things" when what I see could really solve some of the problems I am facing today…

Question was and is really: what is a good approach when the examples do NOT use the new features, I did try to understand from a theorycal side… I better have to jump in practical side and make mistakes, I guess…

Anyway, I do appreciate your help… thanks again.

thinkyhead commented 6 years ago

I presume we'll have to document the updated (i.e., corrected) meaning of the jerk parameters for 1.1.9 and give recommendations for the appropriate values to use. And we should also update the configurations with reasonable values. @lrpirlet — What values are working well for you now, and what values were you using before?

lrpirlet commented 6 years ago

@thinkyhead

Sorry, I have no experience yet… My heated bed shorted, the FET melted shorted, the RAMPS printed board heavily smoked, the fuse did not (completely) fuse… I am waiting a new bed, a new RAMPS... Not sure to get it before the holliday so not before 3 weeks or so...

I can still move the axis of the printer, I think I could extrude, but with ABS, there is no chances to get anything but a big mess…

To answer your question, the max acceleration for X, Y Z seems to be compatible (I did run a dryrun print). At completion, I was able to move the hot end back to the exact same place marked before execution. So no steps lost…

For E, I will limit the DEFAULT_MAX_ACCELERATION to 1500 giving an equivalent ejerk of about 8,5... I hope the extruder will bear with it… I may have to drop down to 500 if I really need an équivalent ejerk of 5... For what concerns retraction, that used to need 40*60 (2400), I was thinking to use LA and completely forget retraction…

AGAIN, NO EXPERIENCE YET... but I feel uneasy with E axis

Itox001 commented 6 years ago

I was starting to use junction deviation, currently set my initial parameters according to the equation:

max_ejerk [mm/s] = SQRT((SQRT(0.5) * max_acceleration_mm_per_s2[E_AXIS] * junction_deviation_mm) / (1 - SQRT(0.5)))

Using my old jerk values and the default junction deviation value of 0.02 I derived my accelerations, this seemed to work fine for x, y and e, it resulted in sensible values and printer seems to be pretty happy with it. But what hapens with the Z axis? Using my old jerk of 0.4, the formula results in an acceleration of 3.3 mm/s^2. This doesn´t seem right. Is this calculated differently?

The older acceleration I used in Z, 1500 mm/s^2, leads to a jerk of 8.5. I see on a post above that it was said that this values are fine if they are different becuase they are not linked to previous value. But then, what should it be set to?

Sebastianv650 commented 6 years ago

@Itox001 your z axis will most likely be just happy with the values. Prior to all this changes even if you had set the z jerk to 0.4 the real jerk in about 50% of the situations was the XY jerk value. That's because this jerk was only applied to the entry speed, but the end of the move should have ended at z jerk speed also.

boelle commented 4 years ago

@Sebastianv650 @Roxy-3D

has the new JD calc's not made this one "surplus" or is it still relavant?

boelle commented 4 years ago

this one has gone stale and discussion could continue on discord

Marlin Discord server. Join link: https://discord.gg/n5NJ59y

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.