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.17k stars 19.21k forks source link

[bugfix 2.0] unexpected pauses in movement #12540

Closed Bob-the-Kuhn closed 5 years ago

Bob-the-Kuhn commented 5 years ago

I'm finally getting my home built printer back into working order.

When I tried to do the linear advance calibration pattern I noticed that the X axis stepper was stopping during the slow speed to high speed transition. It was accelerating to slow speed, cruising at slow speed, decelerating to what looks like a full stop and then immediately accelerating to the high speed.

I've disabled linear advance but the problem is still there.

I've run just the following with the same results:

G1 X116 Y125 F2100 ; move to start
G1 X136 Y125   F1020 ; print line
G1 X176 Y125   F2100 ; print line

The X and Y behave the same.

I don't know how long this has been happening. I'm pretty sure I've been seeing this in prints since I started doing prints about a month ago. Some of my circles have obvious blobs at the end of the straight line segments.

I'm running:

Here are my config files: Configuration_files.zip

Ludy87 commented 5 years ago

M502 and M500, then try again.

thinkyhead commented 5 years ago

I’ll check out your config tomorrow. Meanwhile, disable lots of features and reset the EEPROM to see if any other features are interacting in weird ways with the motion system.

simon-jouet commented 5 years ago

I'm actually seeing the same issue, not sure since when this is happening. I also have linear advance enabled, I will try to disable it for the next print to check if I see something. I'm running 4260282df7eb206317ba1f26c2a441ccb303482d on a RAMPS 1.4 (until I put an esp32 on this one too :))

I've attached my config too, and I checked quickly through @Bob-the-Kuhn config to check what we have in common and it's not overwhelming... I'm running a coreXY with TMC2130 on all axes while bob is running a cartesian with A4988/DRV8825 from the looks of it. What i'm seeing in common is the BLTouch and FAN_KICKSTART_TIME (and probably more but I've been through this quickly).

Here is a fairly terrible video (and the print looks much worse than it is) https://www.youtube.com/watch?v=vksR6-Z16q4 You can see the "scar" on the print every time the printer stops at the same spot. Looking through the sliced model it corresponds to some travel moves

For the bottom right scar image

For the top left scar image

Configuration.zip

EDIT: Sorry I already had commented out linear advance in the config but it was enabled in the video + screenshots above

EDIT2: Just started a second print with linear advance and fan_kickstart_time disabled and i'm getting the same thing at the same spots. Here is a second video with the three perimeters and a slight stop for each one https://www.youtube.com/watch?v=DFxVdbzRVEc (no linear advance, no kickstart)

Bob-the-Kuhn commented 5 years ago

I've copied all my non UBL stuff over to the current config files so that everything is in the usual spot.

No change in behavior.

No bed leveling and no linear advance,.

Configuration_files_simplified.zip

Bob-the-Kuhn commented 5 years ago

I'm pretty sure we have a bug in the planner reverse pass when speed is increasing.

Here's the gcode I'm using:

    G1 X96 Y125 F1900 ; move to start
    G1 X140 Y125   F1500 ; print line
    G1 X176 Y125   F2100 ; print line
    G1 X216 Y125   F1500  ; print line
    G1 X256 Y125   F2100

repeat as desired    

Here's the junction speeds I'm seeing after the reverse pass:

    G1 X96 Y125 F1900 ; nominal_rate: 12573
          ;transition rate: 199 (jerk rate - direction change)
    G1 X140 Y125   F1500 ; nominal_rate: 9926
          ;transition rate: 497  (should be 9926)
    G1 X176 Y125   F2100 ; nominal_rate: 13896
          ;transition rate: 9926
    G1 X216 Y125   F1500 ; nominal_rate: 9926
          ;transition rate: 497 (should be 9926)
    G1 X256 Y125   F2100 ; nominal_rate: 13896
          ;transition rate: 199 (jerk rate - direction change)
    G1 X96 Y125 F1900 ; nominal_rate: 12573 (back to the start)
thinkyhead commented 5 years ago

We’ll have to stare hard at the acceleration handling in the forward and reverse pass methods and see what’s going on. I’d like to pull in @ejtagle to help us scrutinize the code. He has a knack for seeing implications that less motion-savvy contributors might miss.

xenovacivus commented 5 years ago

Hi, I copied the config (as close as I could) and plotted the X position output for that gcode. Looks like the speed is going to zero between moves, even though they're in the same direction: bob_gcode_config1 Interestingly, increasing DEFAULT_XJERK from 0.5 to 5 gives this result: bob_gcode_xy_jrk_5 And increasing DEFAULT_XJERK to 10 gives this: bob_gcode_xy_jrk_10

The reductions in speed are nearly gone with a DEFAULT_XJERK of 10 (the first dip in speed is due to the XY move from X=0,Y=0 to X=96,Y=125). That probably points to a very specific portion of the planner code :)

xenovacivus commented 5 years ago

TL;DR: potential fixes: change code in planner or enable JUNCTION_DEVIATION.

I took a look at the planner code (the block for HAS_CLASSIC_JERK), and it looks like this behavior is somewhat by design. I'm no expert in the "classic jerk" code, but it appears the goal is to limit jerk when the direction of travel changes. For example, this gcode has a 45 degree bend at X = 10:

G1 X0 F600
G1 X10 Y10   ; x_vel = 7.071 mm/s
G1 X20       ; x_vel = 10 mm/s

The velocity of the X axis will be 7.071mm/s between 0 and 10, then 10mm/s from 10 to 20. The roughly 3mm/s jump in X velocity can't happen instantly, otherwise there would be a discontinuity in acceleration. So either the slack is taken up in somewhat forgiving stepper motors, steps are lost, or the planner limits the change in acceleration. This is where "DEFAULT_*JERK" parameters come into play. If DEFAULT_XJERK is set to 3mm/s or greater, the transition will occur with no change. But if it's set to, say, 1mm/s, the junction velocity is scaled such that the velocity jump is less than 1mm/s. The effect is deceleration on X from 7.071mm/s to ~2.3mm/s at X=10, a jump to ~3.3mm/s, then accelerating back to 10mm/s for the rest of the travel.

The problem is that the classic jerk calculations rely on a change in axis velocity to indicate a change in direction - this only works if nominal speed remains the same. But if nominal speed changes without a direction change, the classic jerk calculation will also (unnecessarily) limit the junction velocity. The following gcode, which has no direction change, will result in the same limit as above.

; Velocity limit at X = 10
G1 X0 F424  ; 7.071 mm/s
G1 X10
G1 F600     ; 10 mm/s
G1 X20

Interestingly, if the change in velocity is negative instead of positive, the drop in velocity doesn't happen (also seen in the graphs above - only increases in velocity results in a velocity limit).

; No velocity limit
G1 X0 F600  ; 10 mm/s
G1 X10
G1 F424     ; 7.071 mm/s
G1 X20

This is because of this code in planner.cpp (which also hints at a fix):

        float v_exit = previous_speed[axis] * smaller_speed_factor,
              v_entry = current_speed[axis];

A quick fix might be:

        float v_exit = previous_speed[axis] * nominal_speed / previous_nominal_speed,
              v_entry = current_speed[axis];

And running this gcode (with all axis 100 steps/mm for easy debugging):

G92 X0 Y0 Z0 E0 ; Set Position
G1 F424  ; 7.071 mm/s
G1 X10
G1 F600  ; 10 mm/s
G1 X20
G1 F424  ; 7.071 mm/s
G1 X30
G1 F600
G1 X40      ; x_vel = 10mm/s
; Should see transition speed of 1mm/s here
G1 X50 Y10  ; x_vel = 7.071mm/s
; Also transition speed of 1mm/s here
G1 X60      ; x_vel = 10mm/s

Results in this motion profile. All the velocities are expected - the two drops in velocity are required to limit jerk on the 45 degree intersections. slow-fast-slow-angle

I haven't tested the fix above in any more complicated situations - and some of the other code around there looks a bit sketchy; I think it could use a bit of cleanup.

Alternatively, you could enable JUNCTION_DEVIATION in Configuration_adv.h, which is an alternative approach to corner handling. In theory, it's a more robust (and mathematically accurate) approach to motion at speed over a change in direction.

ejtagle commented 5 years ago

If the problem is CLASSIC_JERK, i vote for removal of that option. JUNCTION_DEVIATION is a superior algorithm, and maintaining obsolete and buggy code does not make sense at all. (Besides, CLASSIC_JERK is not correct, as it is NOT real jerk what is limited, rather than, what is "allowed" is instantaneous jumps in speed. The only reason, as far as i know, of keeping CLASSIC_JERK are Delta printers, where JUNCTION_DEVIATION has some issues...

Bob-the-Kuhn commented 5 years ago

Way over my head on the mechanical movement.

Switching to JUNCTION_DEVIATION appears to have solved the problem.

Bob-the-Kuhn commented 5 years ago

Thanks

thinkyhead commented 5 years ago

As long as Junction Deviation has no lingering interactions with things like Linear Advance, I'm happy to see it supersede the classic jerk implementation, or at least make it enabled by default. Maybe there's still some vague reason why someone might want to use old-school jerk…?

ejtagle commented 5 years ago

@thinkyhead : Unfortunately, there is a reason to keep the old jerk code around: Delta printers, and probably SCARA printers also.

The reason is the following: The junction deviation code, as it is right now, operates on MOTOR/ACTUATOR coordinates. Those coordinates happen to be the same as X/Y/Z axis coordinates, thus the motion vector that can be formed from movements of actuators/motors is exactly the same as the motion vector of the print head, But that only holds on cartesian bots. For Delta/scara, the relationship between the print head motion vector and the actuator movements is highly non linear, thus Junction deviation is not effective at limiting "junction deviation" and "motor jerk", and the only algorithm that works is the classic JERK algorithm

richfelker commented 5 years ago

This issue seems to be the cause of layer shifts too - see https://github.com/MarlinFirmware/Marlin/issues/12403#issuecomment-519305409

richfelker commented 5 years ago

For Delta printers, it seems like the motor acceleration/jerk should be bounded by some function of the cartesian-coordinate acceleration/jerk, in which case it should be possible to choose acceleration and junction deviation settings that preclude motion that's not mechanically possible, no?

thinkyhead commented 4 years ago

This issue seems to be the cause of layer shifts too

Are you saying you tried the change suggested by @xenovacivus and it fixed layer shifting for you? I'm not sure I'm ready to commit to that suggestion, since there is a clear intent to prevent smaller_speed_factor from exceeding 1.0.

Currently, we 're using the smaller of the previous_nominal_speed and the current nominal_speed (vmax_junction) for our dividend.

      const float previous_nominal_speed = SQRT(previous_nominal_speed_sqr);
      vmax_junction = _MIN(nominal_speed, previous_nominal_speed);

      // Now limit the jerk in all axes.
      const float smaller_speed_factor = vmax_junction / previous_nominal_speed;

The change as described seems sensible, but it raises some questions since it can result in a smaller_speed_factor larger than 1.0. I don't know if that will be further limited by what follows, or whether it could cause unusual behavior at certain junctions.

If the problem is CLASSIC_JERK, i vote for removal of that option

We are enabling JUNCTION_DEVIATION by default for all but deltas. And maybe what we should do is get rid of the JUNCTION_DEVIATION option and replace it with CLASSIC_JERK. Then users will only have old-style jerk if they specifically enable it.

richfelker commented 4 years ago

I was saying switching to junction deviation fixed the layer shifts. I have not tried the proposed change to classic jerk. I did try greatly reducing the jerk setting with classic jerk before I tried switching to junction deviation, and even then it still had layer shifts. Note that I do use very small tolerances in my slicer (Cura) resulting in lots of very small segments; this may be relevant to behavior of classic jerk. (On some level it's not clear how classic jerk with very small segments doesn't effectively yield infinite acceleration, but I suppose it must avoid that somehow, at least historically, since it worked on the old-Marlin-based firmware that shipped with my printer.)

thinkyhead commented 4 years ago

Going forward, hopefully this will help! #15481

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.