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.2k stars 19.22k forks source link

[BUG] 2.1.2 Stepper motor stutters and skips at high speed due to new ISR calculation #25117

Closed ansonl closed 1 year ago

ansonl commented 1 year ago

See latest post at bottom for better summary and narrowed down bug in stepper.h and stepper.cpp.

Did you test the latest bugfix-2.1.x code?

Yes, and the problem still exists.

Bug Description

Marlin no longer properly offsets the printhead on a toolchange between switching nozzles that have a X offset between them.

#define HOTEND_OFFSET_X { 0.0, 19.00 } // (mm) relative X-offset for each nozzle
//#define HOTEND_OFFSET_Y { 0.0, 0.00 }  // (mm) relative Y-offset for each nozzle
#define HOTEND_OFFSET_Z { 0.0, -2 }      // (mm) relative Z-offset for each nozzle
#define EVENT_GCODE_TOOLCHANGE_T0 "G90\nG0 X210 F7200\nG0 Y165\nG0 X216\nG0 X216 Y183\nG0 X210" // Extra G-code to run while executing tool-change command T0
#define EVENT_GCODE_TOOLCHANGE_T1 "G0 X229 F7200\nG0 Y199\nG0 X234\nG0 Y184\nG0 X229" // Extra G-code to run while executing tool-change command T1

When Marlin switches to a tool T1 with a positive X offset it will move the printhead quickly in the negative X direction and return to the original position before running EVENT_GCODE_TOOLCHANGE_T1 to complete the toolchange. The DXU mechanical switching nozzle mechanism has a lever on the right side of the printhead that moves to the bed limit X_BED_SIZE to touch a hook on the right side of the case which causes a nozzle lift/lower.

As of 2.1.2 Marlin no longer moves the toolhead in the negative X direction for the same distance as the "return" movement in the positive X direction before running EVENT_GCODE_TOOLCHANGE_T1. This leads to a printhead collision with the side of the gantry since the final X offset from before -> after the offset adjustment (but before EVENT_GCODE_TOOLCHANGE_T1) is no longer 0 or equal to the new HOTEND_OFFSET_X.

The last working commit I found was on 10/30/22 on PR #24553

The commit history for the PR can viewed here: https://github.com/MarlinFirmware/Marlin/pull/24553/commits I have taken a video of the correct toolchange and the new bug toolchange that is linked below for each test.

As seen in the linked videos, the bugged toolchange initial offset adjustment does not move the full amount in negative X direction as it did in the correct toolchange. This seems to lead to the machine's real X position deviating from the software X position and it collides the side of the gantry.

The initial first toolchange from T0 -> T1 on both correct and bugged firmware does not have this problem when it is from the origin position right after homing. It is the second T0 -> T1 toolchange that this bug occurs in.

I found this bug while testing a version of PR#24553 synced to the current bugfix2.1.x and this PR has some additional definitions for Mechanical Switching nozzles and a bugfix in toolchange.cpp that prevents a bed collision. To my knowledge it doesn't modify the toolchange offset adjustment code.

Bug Timeline

New bug in 2.1.2

Expected behavior

Toolchange offset adjustment movements result in a final printhead offset equal to 0 or the HOTEND_OFFSET_X before running EVENT_GCODE_TOOLCHANGE_T1.

Actual behavior

Printhead runs into gantry when doing toolchange that is not from origin.

Steps to Reproduce

  1. Setup #define HOTEND_OFFSET_X { 0.0, 19.00 } and toolchange gcode that moves that printhead to the right limit ex: if bed X size is 216, move X to 234 which is derived from 216+19 since the toolchange gcode is run from the offsets of the target hotend.
  2. Home and move hotend so X position is < 19mm from right side of gantry limits.
  3. Run toolchange between T0 and T1 repeatedly.
  4. Printhead will collide with gantry limit due to first offset adjustment movement or offset adjustment not working correctly.

Version of Marlin Firmware

2.1.x

Printer model

Ultimaker Original+

Electronics

Ultimaker 2+ electronics

Add-ons

DXU hotend

Bed Leveling

MBL Manual Bed Leveling

Your Slicer

Cura

Host Software

OctoPrint

Don't forget to include

Additional information & file uploads

Configuration.zip

Mjankor commented 1 year ago

Sounds somewhat similar to my issue. What happens if you do it with input shaper turned off (assuming it was on)?

ansonl commented 1 year ago

@Mjankor I have input shaping turned off. The input shaping X and Y defines are commented out for my config. Haven't tried it with it turned on yet, not sure if I might run out of ram on atmega256 with it.

ansonl commented 1 year ago

I got a slow motion recording of the strange stuttering of the initial movement when switching extruders to a second extruder that is offset in the positive direction (19.00mm). https://youtube.com/shorts/BPpDyL0Bj_o?feature=share It looks like a 2 quick movements are called before the normal adjust offset movement. 1 quick movement in the same direction as the wipe and and 1 quick movement in the opposite direction before it starts the normal wipe movement. The sound in the video is not loud, but it's very loud in real life.

The toolchange gcode that runs to change to the second offset extruder also does not run in the offset of the second offset extruder like it used to (and should). It appears to run within the offsets of the first extruder.

Both the 2 quick movements and the normal offset movement do not happen when do_blocking_move_to_xy(destination, planner.settings.max_feedrate_mm_s[X_AXIS]); is commented out in tool_change() toolchange.cpp. I don't see any recent changes since September that could be the issue so far...

ansonl commented 1 year ago

@Mjankor @tombrazier
I have narrowed down the stepper motor problem to changes in module/stepper.h and module/stepper.cpp made after September 2022.

I merged in every change in the release version of Marlin 2.1.2 and this offset issue only occurs when the new stepper.h and stepper.cpp are used. I believe that it is related to changes in #24797 and #24951. I noticed that the new changes modify a lot of frequency calculations even with input shaping turned off so they must be incompatible with AVR/Atmega256/A4988 stepper motor driver/other component on the Ultimaker Ultimainboard v2.1.4. Looks related to issue #25134 with a similar workaround to reverting any stepper.cpp changes in the input shaping commit.

The stepper motor seems to be loudly skipping when moving quickly for the tool change offset adjustment to another hotend offset and then the software position gets out of sync with the real life position leading to collisions with bed limits and grinding. https://youtube.com/shorts/V2q6s6j2uzM?feature=share

tombrazier commented 1 year ago

It's not obvious to me how the changes in stepper.cpp / stepper.h could cause this. Are you able to selectively apply changes (leaving out all the ones that are conditionally compiled based on HAS_SHAPING or INPUT_SHAPING_X or INPUT_SHAPING_Y? See which actual change it is that makes the difference.

ansonl commented 1 year ago

@tombrazier I found that the stuttering and skipping occurs when the changes for #define ISR_LOOP_CYCLES(R) are applied to stepper.h.

The code changes I made were the addition of

line 129

  // Input shaping base time
  #if HAS_SHAPING
    #define ISR_SHAPING_BASE_CYCLES 290UL
  #else
    #define ISR_SHAPING_BASE_CYCLES 0UL
  #endif

line 213

// The loop takes the base time plus the time for all the bresenham logic for R pulses plus the time
// between pulses for (R-1) pulses. But the user could be enforcing a minimum time so the loop time is:
#define ISR_LOOP_CYCLES(R) ((ISR_LOOP_BASE_CYCLES + MIN_ISR_LOOP_CYCLES + MIN_STEPPER_PULSE_CYCLES) * (R - 1) + _MAX(MIN_ISR_LOOP_CYCLES, MIN_STEPPER_PULSE_CYCLES))

// Model input shaping as an extra loop call
#define ISR_SHAPING_LOOP_CYCLES(R) ((TERN0(HAS_SHAPING, ISR_LOOP_BASE_CYCLES) + TERN0(INPUT_SHAPING_X, ISR_X_STEPPER_CYCLES) + TERN0(INPUT_SHAPING_Y, ISR_Y_STEPPER_CYCLES)) * (R) + (MIN_ISR_LOOP_CYCLES) * (R - 1))

line 243

#define ISR_EXECUTION_CYCLES(R) (((ISR_BASE_CYCLES + ISR_S_CURVE_CYCLES + ISR_SHAPING_BASE_CYCLES + ISR_LOOP_CYCLES(R) + ISR_SHAPING_LOOP_CYCLES(R) + ISR_LA_BASE_CYCLES + ISR_LA_LOOP_CYCLES)) / (R))

The issue is present with both old and new values of #define ISR_BASE_CYCLES of 752UL and 1000UL. Input shaping is not enabled in my configuration.

I tested every change to stepper.h and stepper.cpp by reverting the commits 6d87daf, b4feb4f, f3108e8 and then selectively applying changes for the remaining commits of input shaping ONEand input shaping TWO.

I have uploaded my changes to both file as gists so you can compare the before and after code in stepper.h.

[stepper code with all changes applied not dependent on input shaping] (https://gist.github.com/ansonl/fb4c8b9d7733965faf8ceee983d4b571)

[stepper code with all changes applied not dependent on input shaping + ISR_LOOP_CYCLES changes in stepper.h ] https://gist.github.com/ansonl/74a9f42fbe410c4197f27c65e7748b30

ansonl commented 1 year ago

@tombrazier I think that ISR_LOOP_CYCLES(R) includes an extra addition of MIN_ISR_LOOP_CYCLES, MIN_STEPPER_PULSE_CYCLES. When I change it to below, the stepper motor skipping is gone with input shaping turned off.

#define ISR_LOOP_CYCLES(R) ((ISR_LOOP_BASE_CYCLES) * (R - 1) + _MAX(MIN_ISR_LOOP_CYCLES, MIN_STEPPER_PULSE_CYCLES))

https://github.com/MarlinFirmware/Marlin/pull/24951/files/f2c06afa72850c3dfaa5a905d75a734613b1483d#r1064159829

If input shaping is enabled the motor skipping is still present after this change but reduced. Skipping occurs when the fast movement done such as moving to new tool offset with:

do_blocking_move_to_xy(destination, planner.settings.max_feedrate_mm_s[X_AXIS]);

I tested a ringing tower with input shaping + single extruder and the input shaping works great, by the way!

Videos of skipping behavior: stepper motor no longer skipping with input shaping turned off after ISR_LOOP_CYCLES change stepper motor still skipping with input shaping turned on but reduced skipping after ISR_LOOP_CYCLES change

stepper motor skipping with input shaping turned off before ISR_LOOP_CYCLES change

ultimaker input shaping

tombrazier commented 1 year ago

Man those A4988s are noisy!

From https://github.com/MarlinFirmware/Marlin/pull/24951#pullrequestreview-1239797708:

ISR_LOOP_CYCLES(R) revised as below fixes skipping stepper motor driver (A4988) on AVR with tested with input shaping off and on.

I suspect this change to ISR_LOOP_CYCLES is just masking the real issue. Decreasing that value should not have the effect described unless something else is going on (or I'm confused, which is also a possibility).

Is there a reason that #define ISR_BASE_CYCLES 1000UL was changed from 752UL?

Yes. I retested these values and found they have changed due to changes in the stepper code over the years. The stepper code is supposed to keep stepper CPU usage below 50% but this was not happening. In some cases (notably on the BTT SKR Mini v3) this resulted in reboots due to the watchdog timer.

I tested a ringing tower with input shaping + single extruder and the input shaping works great, by the way!

Well that at least is good to know.

My guess is this is related to the A4988s rather than the AVR because I developed IS on my AVR machine with no problem. I think it's probably about high speed moves - so only indirectly related to the tool changer which generates a high speed move to the left. Specifically, I think what is happening is that the stepper ISR is now generating double pulses where it was previously generating single pulses.

Can you confirm that the problem only occurs for high speed moves? If so, does it go away if you reduce steps/mm?

If you apply the change in https://github.com/tombrazier/Marlin/tree/25117 you can also see on the serial port whether the stepper module is single, double, triple, etc. stepping. Are you able to do that?

ansonl commented 1 year ago

I tried doing moves of different lengths and feedrates and can confirm that the problem only occurs for higher speed moves. I started hearing skipping at feedrate above 7000mm/min if I did a move such as G0 F8000 X100 so this problem can be observed outside of the toolchange.

When monitoring, the serial connection the multistep serial echo, I get multistep values of 1, 2, 4, 8, 16, 32. The value seems to increase with feedrate and movement length. Something like G0 F18000 X160 from X = 0 echos 1->32 and then back down to 1 from 32 in consecutive powers of 2. The skipping gets worse when the feedrate is faster and the movement length is shorter.

tombrazier commented 1 year ago

Wow 32 is really high. What is the maximum you get without the changes to ISR_LOOP_CYCLES?

And I see in your config you have 80mm/s for X and Y. Is this also the M92 setting?

ansonl commented 1 year ago

I tried printing multistep with both versions of ISR_LOOP_CYCLES and get the same behavior where the multistep goes from 1->32 and 32->1.

80mm/s is also the M92 setting. I originally used some values from the official ultimaker config and they currently print as M92 X80.00 Y80.00 Z200.00 E369.00.

elbarsal commented 1 year ago

I can confirm I have the same issue with high speed movements and input shaping. Running on bugfix-2.1.x, everything is fine at commit d4d1112ae8bb65d8b7c9f74d1a8586b893e57b1d (Fix missing va_end...) but then fails in commit 89334caa526f2d300eee834d34d06d8f837a57d5 (Input Shaping improvements (#24951)).

Before the problem, I can G0 X70 F9000 with no problem at all, after, it maxes out at F5500 and misses steps above that.

I'm using an Azteeg X3 Pro (a ramps based ATmega2560 board) and DRV8825 drivers by Kliment. My Y axis has a fancy "CoolMuscle" closed-loop interface that acts like a stepper driver and it too is affected (stutters, but doesn't actually lose steps since it is closed loop).

Not sure how much that helps, but if I can add any more information or testing let me know.

ansonl commented 1 year ago

@tombrazier Were you able to find the issue with ISR_LOOP_CYCLES based on the multistep response from 1>2>4>8>16>32?

The multistep calculation in Stepper::calc_timer_interval in stepper.cpp appears to accommodate a normal max value for multistep up to 128 (1<<7) depending on the step_rate.

cbagwell commented 1 year ago

Here is a debug idea in case its more CPU related instead of faster step pulses related.

When you reverted value in ISR_LOOP_CYCLES, one of main things it did was allow more steps per ISR. Since the values are meant to be worst case and if I recall AVR doesn't have watchdog timers then you probably do have some CPU free to do some extra steps.

I don't pretend to fully know what's going on in the stepper code but I've noticed even on a SKR Mini E3 V3 that when these ISRs are right on an maximum edge for CPU that it can present itself as stutter.

I think a safer option than pushing the CPU to its limits in worst case (by lowering ISR_LOOP_CYCLES) to solve stutter that its better to see if you can reduce the need for more steps in the first place. In this case, the easiest option is to remove ADAPTIVE_STEP_SMOOTHING option from your config or maybe as a test you could change the logic to only use 33% of CPU instead of 50%:

-#define MIN_STEP_ISR_FREQUENCY (MAX_STEP_ISR_FREQUENCY_1X / 2)
+#define MIN_STEP_ISR_FREQUENCY (MAX_STEP_ISR_FREQUENCY_1X / 3)

But this is also where my experience is inverse of yours. You've lowered cycle counts so what it thinks should be 50% CPU is going to actually use more CPU instead which I would think introduces more stutter than solves.

ansonl commented 1 year ago

@cbagwell I tested it with ADAPTIVE_STEP_SMOOTHING turned off and got the same stuttering result with the new input shaping ISR_LOOP_COUNT so there seems to be no difference with or without Adaptive step smoothing.

cbagwell commented 1 year ago

Thanks. Its good data to have. I was hoping it was more CPU related as that more straight forward to solve. Looks like it will be a hard one to solve correctly.

tombrazier commented 1 year ago

if I recall AVR doesn't have watchdog timers

It does. But we still don't want to max out the CPU in the stepper ISR.

I don't pretend to fully know what's going on in the stepper code but I've noticed even on a SKR Mini E3 V3 that when these ISRs are right on an maximum edge for CPU that it can present itself as stutter.

As I understand it, the issue is not so much stuttering as lost steps.

I think a safer option than pushing the CPU to its limits in worst case (by lowering ISR_LOOP_CYCLES) to solve stutter that its better to see if you can reduce the need for more steps in the first place.

I think this is probably the most sensible approach. However it means losing functionality that did work previously.

I suspect what is going on is that in the moves where the problems are occurring the old code did something like 16 steps per ISR and the new code is doing 32 steps per ISR. The motor was just able to keep up with a sudden burst of 16 steps but it can't keep up with a burst of 32. i.e. the machine is operating right at the margins and the new code pushes it over the edge.

The objective of the code in question is to keep the stepper ISR CPU usage <= 100%. (Not to be confused with ADAPTIVE_STEP_SMOOTHING which will try to get the CPU usage to as high as possible without going over 50%. That is not happening in this case.)

The code adopts a worst case scenario approach when assessing CPU usage. So there is actually overhead in most cases and I think in the old code the CPU usage was very high but still < 100% because of this overhead. The code changes correct the CPU usage calculations and now CPU usage is well below 100% but steps per ISR are too high. One option is to intentionally allow the stepper ISR to target more than 100% CPU.

To test this please change the definition for ISR_EXECUTION_CYCLES in stepper.h to:

#define CPU_OVER_USAGE 150
#define ISR_EXECUTION_CYCLES(R) ((((ISR_BASE_CYCLES + ISR_S_CURVE_CYCLES + ISR_SHAPING_BASE_CYCLES + ISR_LOOP_CYCLES(R) + ISR_SHAPING_LOOP_CYCLES(R) + ISR_LA_BASE_CYCLES + ISR_LA_LOOP_CYCLES)) / (R)) * (CPU_OVER_USAGE) / 100)

And play around with the value of CPU_OVER_USAGE. That will at least give us info. Whether this is the "right" solution is open to question. I think if the machine is operating at its margins a better approach is to reduce max speed. Another option is to play with MAXIMUM_STEPPER_RATE.

ansonl commented 1 year ago

@tombrazier I tested the changes to ISR_EXECUTION_CYCLES with the input shaping off and adaptive step smoothing on. When CPU_OVER_USAGE is increased, the stuttering is more noticeable. I was not able to reduce the stuttering/rough movement completely. Results with different CPU_OVER_USAGE:

CPU_OVER_USAGE result
150 Very loud stuttering, lost steps visibly noticeable
100 Loud stuttering, does not seem to loose steps immediately (not sure why)
90 Loud stuttering
80 Loud stuttering
75 Stuttering
70 Rough movement sound
50 Rough movement sound

Even at CPU_OVER_USAGE set to 50, the movement is audibly rougher (like a very quiet stutter) vs my modified ISR_LOOP_CYCLES when I tested a movement from G0 F18000 X150 to G0 F18000 X120.

My modified ISR_LOOP_CYCLES from above again for reference

//Modified ISR_LOOP_CYCLES
#define ISR_LOOP_CYCLES(R) ((ISR_LOOP_BASE_CYCLES) * (R - 1) + _MAX(MIN_ISR_LOOP_CYCLES, MIN_STEPPER_PULSE_CYCLES))
//Pre-input shaping ISR_LOOP_CYCLES
#define ISR_LOOP_CYCLES (ISR_LOOP_BASE_CYCLES + _MAX(MIN_STEPPER_PULSE_CYCLES, MIN_ISR_LOOP_CYCLES))

I'm not read up on stepper motors and ISR, my initial reasoning for the modified ISR_LOOP_CYCLES was that the original pre-input shaping version of the code looked like the _MAX(MIN_STEPPER_PULSE_CYCLES, MIN_ISR_LOOP_CYCLES) was only added to ISR_LOOP_BASE_CYCLES one time. Without understanding how the stepper and ISR cycles interact, I thought the relationship between the MIN_STEPPER_PULSE_CYCLES and MIN_ISR_LOOP_CYCLES in the original code meant that the maximum of the two was added to ISR_LOOP_BASE_CYCLES either 1 or R times - but not both at the same time?

thinkyhead commented 1 year ago

I'm not sure what Ulendo.io will be bringing to the table next month, but it may obviate some of these issues. Once we have their updates to the Input Shaping implementation, then we will look at optimization in concert with their developers. In the meantime, I have been mulling over how to move the Input Shaping logic into the same block as the regular stepper logic so that there can be a shorter pulse delay, somewhat optimizing the performance. Perhaps that can be attacked and refined with help from the simulator, since it allows us to examine the inner workings in the most complete detail.

cbagwell commented 1 year ago

That's a bit of a surprise that the full range of max CPU values didn't make any differences.

For the extra data points, I would still try the recommendation on adding MAXIMUM_STEPPER_RATE to your Configuration_adv.h and lower the max rate that way as a way to prevent pushing the A4988's to their limits. The A4988 defaults to 500000 so try maybe 400000?

Also, here is something to try to confirm it is the multisteps themselves that are pushing the A4988's to their limit.

Another side effect of less accurate ISR_EXECUTION_CYCLES (when you reverted to older values) is that it thinks it has more CPU cycles free and so will less aggressively step up from 16X to 32X multistep. With the new accurate values it will do more in a for() loop to prevent running out of CPU cycles and push the A4988 harder for longer.

If you make this change to Marlin/src/module/stepper.cpp to cap out multisteps to 16X then it will introduce extra interrupt latency that might give the A4988 the break they need. If it works then I think it helps us confirm the reason lowering ISR_LOOPS_CYCLES is working for you.

    // Select the proper multistepping
    uint8_t idx = 0;
-    while (idx < 7 && step_rate > (uint32_t)pgm_read_dword(&limit[idx])) {
+    while (idx < 5 && step_rate > (uint32_t)pgm_read_dword(&limit[idx])) {
      step_rate >>= 1;
      multistep <<= 1;
      ++idx;
    };

Your CPU_OVER_USAGE change should have been indirectly changing this 32X threshold but its also changing a few other code behavior as well so it would be nice to test multistep reduction part in isolation.

MusicJelly commented 1 year ago
#define ISR_SHAPING_LOOP_CYCLES(R) ((TERN0(HAS_SHAPING, ISR_LOOP_BASE_CYCLES) + TERN0(INPUT_SHAPING_X, ISR_X_STEPPER_CYCLES) + TERN0(INPUT_SHAPING_Y, ISR_Y_STEPPER_CYCLES)) * (R) + (MIN_ISR_LOOP_CYCLES) * (R - 1))

maybe need modify to

#define ISR_SHAPING_LOOP_CYCLES(R) ((TERN0(HAS_SHAPING, ISR_LOOP_BASE_CYCLES) + TERN0(INPUT_SHAPING_X, ISR_X_STEPPER_CYCLES) + TERN0(INPUT_SHAPING_Y, ISR_Y_STEPPER_CYCLES)) * (R) + (TERN0(HAS_SHAPING, MIN_ISR_LOOP_CYCLES)) * (R - 1))

If we disable "input shaping", "ISR_EXECUTION_CYCLES(R)" is wrong because it plus the "ISR_SHAPING_LOOP_CYCLES(R)" which is nonzero.

tombrazier commented 1 year ago

@MusicJelly I think you're right. If shaping is disabled ISR_EXECUTION_CYCLES(R) should definitely be zero. Well done for unravelling all those brackets!

I'll raise a PR for this regardless. But I think I'll also try to replicate the problems and see if I can nail them down.

tombrazier commented 1 year ago

I have been mulling over how to move the Input Shaping logic into the same block as the regular stepper logic

@thinkyhead that would be good. I vaguely think it would be good if the end of pulse logic was generated separately all at the end of the ISR. Or, at least, the end of the last pulse if there are multiple pulses. I think this would also help straighten out the ESP32 logic.

Incidentally I think the wait between high and low happens even if SQUARE_WAVE_STEPPING is enabled. Something else I vaguely think we should check out.

MusicJelly commented 1 year ago

@tombrazier I find this bug while I deal with a reboot exception. And find other bug.

In this function

uint32_t Stepper::calc_timer_interval(uint32_t step_rate, uint8_t &loops)

In some condition. step_rate will greater than MAX_STEP_ISR_FREQUENCY_128X. Then you will get a small interval and 128 loop. But the _MIN_STEP_PERIOD_NS or (_MIN_PULSE_HIGH_NS +_MIN_PULSE_LOW_NS) is greater than interval / 128.

So, the stepper isr will always into. And the watchdog timer will timeout. Then you will get a reboot.

You can replicate the problems. LARGE _MIN_STEP_PERIOD_NSand HIGH step_rate.

EG: The stepper driver is TB6560which have 15000 MAXIMUM_STEPPER_RATE and 30 MINIMUM_STEPPER_PULSE. And after subdivision the step is 300 step/mm. Then move with 100mm/s. Then wait it finished. The MAX_STEP_ISR_FREQUENCY_1X and MAX_STEP_ISR_FREQUENCY_128X is about 12000 Hz. But We give it 30000 Hz step_rate. Then MCU is reboot.

It usually occurs at HOME Z. With a home_z_safely, It will do_blocking_move_to_xy with 100mm/s.

But there is a way to avoid it.
Uncomment DISABLE_MULTI_STEPPING. Because the _MIN_PULSE_LOW_NSwill short out with use MAX_STEP_ISR_FREQUENCY_1X stepper_rate. Reboot is avoided. But another problem will appear. It will wait at move end.

Here is my solution:

diff --git a/Marlin/src/HAL/AVR/math.h b/Marlin/src/HAL/AVR/math.h
index 7dd1018f..b1ce9129 100644
--- a/Marlin/src/HAL/AVR/math.h
+++ b/Marlin/src/HAL/AVR/math.h
@@ -66,7 +66,7 @@ FORCE_INLINE static uint16_t MultiU24X32toH16(uint32_t longIn1, uint32_t longIn2
     A("add %[tmp2], r1")
     A("adc %A[intRes], %[tmp1]")
     A("adc %B[intRes], %[tmp1]")
-    A("lsr %[tmp2]")
+    A("lsl %[tmp2]")
     A("adc %A[intRes], %[tmp1]")
     A("adc %B[intRes], %[tmp1]")
     A("mul %D[longIn2], %A[longIn1]")
diff --git a/Marlin/src/module/stepper.cpp b/Marlin/src/module/stepper.cpp
index 46b21a20..aa06220b 100644
--- a/Marlin/src/module/stepper.cpp
+++ b/Marlin/src/module/stepper.cpp
@@ -2144,6 +2144,7 @@ uint32_t Stepper::block_phase_isr() {

       // Are we in acceleration phase ?
       if (step_events_completed <= accelerate_until) { // Calculate new timer value
+        uint32_t step_rate;

         #if ENABLED(S_CURVE_ACCELERATION)
           // Get the next speed to use (Jerk limited!)
@@ -2151,20 +2152,20 @@ uint32_t Stepper::block_phase_isr() {
                                    ? _eval_bezier_curve(acceleration_time)
                                    : current_block->cruise_rate;
         #else
-          acc_step_rate = STEP_MULTIPLY(acceleration_time, current_block->acceleration_rate) + current_block->initial_rate;
-          NOMORE(acc_step_rate, current_block->nominal_rate);
+          acc_step_rate = step_rate = STEP_MULTIPLY(acceleration_time, current_block->acceleration_rate) + current_block->initial_rate;
+          NOMORE(step_rate, current_block->nominal_rate);
         #endif

         // acc_step_rate is in steps/second

         // step_rate to timer interval and steps per stepper isr
-        interval = calc_timer_interval(acc_step_rate << oversampling_factor, steps_per_isr);
+        interval = calc_timer_interval(step_rate << oversampling_factor, steps_per_isr);
         acceleration_time += interval;

         #if ENABLED(LIN_ADVANCE)
           if (current_block->la_advance_rate) {
             const uint32_t la_step_rate = la_advance_steps < current_block->max_adv_steps ? current_block->la_advance_rate : 0;
-            la_interval = calc_timer_interval(acc_step_rate + la_step_rate) << current_block->la_scaling;
+            la_interval = calc_timer_interval(step_rate + la_step_rate) << current_block->la_scaling;
           }
         #endif

diff --git a/Marlin/src/module/stepper.h b/Marlin/src/module/stepper.h
index b279f2b9..c28df327 100644
--- a/Marlin/src/module/stepper.h
+++ b/Marlin/src/module/stepper.h
@@ -50,7 +50,7 @@
 #endif

 // Disable multiple steps per ISR
-//#define DISABLE_MULTI_STEPPING
+#define DISABLE_MULTI_STEPPING

 //
 // Estimate the amount of time the Stepper ISR will take to execute
@@ -219,7 +219,7 @@
 #define ISR_LOOP_CYCLES(R) ((ISR_LOOP_BASE_CYCLES + MIN_ISR_LOOP_CYCLES + MIN_STEPPER_PULSE_CYCLES) * (R - 1) + _MAX(MIN_ISR_LOOP_CYCLES, MIN_STEPPER_PULSE_CYCLES))

 // Model input shaping as an extra loop call
-#define ISR_SHAPING_LOOP_CYCLES(R) ((TERN0(HAS_SHAPING, ISR_LOOP_BASE_CYCLES) + TERN0(INPUT_SHAPING_X, ISR_X_STEPPER_CYCLES) + TERN0(INPUT_SHAPING_Y, ISR_Y_STEPPER_CYCLES)) * (R) + (MIN_ISR_LOOP_CYCLES) * (R - 1))
+#define ISR_SHAPING_LOOP_CYCLES(R) ((TERN0(HAS_SHAPING, ISR_LOOP_BASE_CYCLES) + TERN0(INPUT_SHAPING_X, ISR_X_STEPPER_CYCLES) + TERN0(INPUT_SHAPING_Y, ISR_Y_STEPPER_CYCLES)) * (R) + (TERN0(INPUT_SHAPING_Y, MIN_ISR_LOOP_CYCLES)) * (R - 1))

 // If linear advance is enabled, then it is handled separately
 #if ENABLED(LIN_ADVANCE)
tombrazier commented 1 year ago

@MusicJelly Several comments/questions:

MusicJelly commented 1 year ago

@tombrazier

MusicJelly commented 1 year ago

@tombrazier My stepper driver have a large subdivide. So my step setting is about 300 step/mm. Then with a 100mm/s speed. I can get a 30000Hz step_rate. Also _MIN_STEP_PERIOD_NSlimit the max step_rate. Like TB6560, MAXIMUM_STEPPER_RATEis 15000. So the problem occurred.

tombrazier commented 1 year ago

It's to fix the rounding algorithm. (num >> 24) . Like float 0.5 ( 1.2 ≈ 1 and 1.8 ≈ 2 ), lsl and lsr affect the carry flag. It's to fix for 8 bit AVR MCU.

Goodness, that LSR bug has been in Marlin since the first commit! It comes from Sprinter!

https://github.com/kliment/Sprinter/blob/b6820141eae692a854e495139e2406d6e5a9e1af/Sprinter/Sprinter.pde#L2919-L2983

Check my logic please:

@MusicJelly I think you have not contributed to Marlin before. If I am right, I really think this should be your first PR.

tombrazier commented 1 year ago

@MusicJelly I am going to have to think more about the acc_step_rate change. Haven't got my head round it yet.

@ansonl I think I managed to replicate your problem and #25335 solves it. The latter is based on @MusicJelly's suggested change to ISR_EXECUTION_CYCLES.

MusicJelly commented 1 year ago

@tombrazier Yes, this's my first comment in GitHub.

I have never contributed my code to Marlin. But I think I contributed a lot indirectly to marlin.

I work in China and work with marlin from marlin v1.0 since 2014 year. I independently developed the Unexpected power outages and resume for marlin in 2014 year. I independently developed the Nine-buttons keyboard for malin in 2015 year. I independently developed the Quick pause for malin in 2015 year. I independently developed the Fliament runout for malin in 2015 year. I independently developed the DWIN screen for marlin in 2016 year. I independently developed the UDisk for marlin in 2016 year. (With chip CH376S) I independently develop the WIFI until now. I independently map a new mainboard with mcu STM32F446 and develop it unitl now. And Filter Fan, Chamber Fan, And so on ...

Many features were implemented by the world first. My code is in my local PC. And somtimes, our customer will ask me the code. Before, my boss is not allowed. I can provide them to our customer since 2019 year.

But Marlin is very mature now so trade secrets have lost their value. Many of our peers already have these features through Marlin.

My boss has come around a bit. He knows we should improve our service to get more customers.

Yes, we are a 3D printer company. If you know many printer. I think you can guess our brand. (Sorry, I can't say that publicly, I have boss.)

I have find many bugs in marlin and marlin dont fix it still now. I think no people find them, like acc_step_rate. I want to open source my code. Contribute directly to marlin. And let more people know us, know our brand. I'll convince my boss to do that this year.

A person is too tired, can't find all the bugs. I'm tired of it.

MusicJelly commented 1 year ago
  • The bug is also in MultiU16X8toH16().

Yes, it should be.

change

tombrazier commented 1 year ago

My english is soo poor.

Your English is 100,000 times better than my Chinese!

I'm not familiar with github, In fact, I learn git from last year.

I can guide you if necessary. I think it would be good if you were able to contribute to Marlin and I also think you should get the credit in the commit log. But I understand your difficulty with convincing your boss.

It sounds like you are doing a good job of helping your boss to understand how open source should work. If it helps, according to the terms of the GNU General Public License if a company makes any changes to Marlin that are delivered to a customer then that customer has a right to see the source code as well. So if your changes have ever been released to the public then the source code should be available as well.

Anyway, what should we do with the math.h changes? Would you like me to submit a PR or do you think you can convince your boss to let you do it?

tombrazier commented 1 year ago

For the record, I have confirmed the math.h LSR bugs with the following code:

        SERIAL_ECHOLNPGM("MultiU24X32toH16(1, 0x01800000) ", MultiU24X32toH16(1, 0x01800000));
        SERIAL_ECHOLNPGM("MultiU24X32toH16(1, 0x01010000) ", MultiU24X32toH16(1, 0x01010000));
        SERIAL_ECHOLNPGM("MultiU16X8toH16(1, 0x0180) ", MultiU16X8toH16(1, 0x0180));
        SERIAL_ECHOLNPGM("MultiU16X8toH16(1, 0x0101) ", MultiU16X8toH16(1, 0x0101));

It should give the following output:

MultiU24X32toH16(1, 0x01800000) 2
MultiU24X32toH16(1, 0x01010000) 1
MultiU16X8toH16(1, 0x0180) 2
MultiU16X8toH16(1, 0x0101) 1

But instead it gives:

MultiU24X32toH16(1, 0x01800000) 1
MultiU24X32toH16(1, 0x01010000) 2
MultiU16X8toH16(1, 0x0180) 1
MultiU16X8toH16(1, 0x0101) 2

i.e. the wrong bit from the factional part of the result is being used for rounding up or down.

@MusicJelly's proposed change to using LSL corrects this.

MusicJelly commented 1 year ago

@tombrazier You can submit a PR, Please.

quiret commented 1 year ago

Good job. You impress me, @MusicJelly

Please convice your boss. But I want Marlin FW users to know that your company is important.

ansonl commented 1 year ago

@tombrazier I tested the updated ISR_SHAPING_LOOP_CYCLES in #25335 both with and without Input Shaping enabled.

There is no more motor skipping when Input Shaping is disabled. The existing ISR_LOOP_CYCLES worked fine with the new ISR_SHAPING_LOOP_CYCLES with Input Shaping disabled. There is still loud motor skipping when Input Shaping is enabled. The motor skipping is reduced but still there when I substitute the existing

#define ISR_LOOP_CYCLES(R) ((ISR_LOOP_BASE_CYCLES + MIN_ISR_LOOP_CYCLES + MIN_STEPPER_PULSE_CYCLES) * (R - 1) + _MAX(MIN_ISR_LOOP_CYCLES, MIN_STEPPER_PULSE_CYCLES))

with the version I created

#define ISR_LOOP_CYCLES(R) ((ISR_LOOP_BASE_CYCLES) * (R - 1) + _MAX(MIN_ISR_LOOP_CYCLES, MIN_STEPPER_PULSE_CYCLES))

Both versions of ISR_LOOP_CYCLES were tested with the new ISR_SHAPING_LOOP_CYCLES with Input Shaping enabled. It seems like the ISR_LOOP_CYCLES returns a much too high value in the existing version and a slightly too high value in my version when Input Shaping is enabled.

tombrazier commented 1 year ago

Thank you @ansonl. I think the issue when IS is enabled is that you have exceeded the capability of your hardware. A4988s require a lot of time for step pulses and during this time the processor just spins uselessly.

In addition, I think you have S_CURVE_ACCELERATION enabled which adds quite a lot of stepper ISR workload. S-Curve will have limited or no obvious benefit when using IS.

Taken together I think there is just not enough CPU time to go around.

Testing with my own AVR based printer (with TMC steppers) I also see the issue with a lower maximum linear speed even without using S-Curve. This hasn't bothered me too much because IS improves acceleration so much and, anyway, my current extruder can't keep up with faster print moves. But YMMV.

tombrazier commented 1 year ago

@MusicJelly My previous response has me thinking about what you were saying about disabling multistepping. I think perhaps we need a limit to multistepping because if the stepper motor is instructed to do more than 45° of rotation in a very short time, this is likely to result in missed steps. With my motors using 16x microstepping I am guessing that my limit for multistepping is around 16.

tombrazier commented 1 year ago

@ansonl I have pushed another commit to #25335 correcting another error in counting.

ansonl commented 1 year ago

@tombrazier Thank, high speeds with IS on (both with and without S curve enabled) seem to work well with the latest commit in #25335. I had to decrease my DEFAULT_MAX_FEEDRATE from 300 to 250 as a trade off to decrease the skipping with IS enabled. The motors don't seem to skip when moving the printhead to do a toolchange at 250mm/s but I'll find out if any skipping shows up over time.

I usually print at 50mm/s with travel speed of ~150mm/s which don't suffer from any skipping. The only time max feedrate is actually needed is when I do a toolchange during the two movements where Marlin automatically moves the printhead to adjust for hotend offsets.

Idea: Would it be possible to dynamically disable IS before Marlin adjusts for hotend offsets and reenable IS afterwards? Hotend offset adjustment occurs in do_blocking_move_to_xy() in tool_change.cpp.

Since hotend offset adjustment is run before EVENT_GCODE_TOOLCHANGE_T1 would running M593 F0 before and restoring the stored values with M593 F40 X\nM593 F45 Y after hotend offset adjustment do the equivalent?

tombrazier commented 1 year ago

@MusicJelly I now understand what you were saying about acc_step_rate. calc_timer_interval() has

NOMORE(step_rate, uint32_t(MAX_STEP_ISR_FREQUENCY_1X))

and so it can return a larger interval than expected. So the acceleration and deceleration curves are not symmetrical because of the NOMORE(). And, as a separate problem, interval can get so large that acc_step_rate overflows.

If multi-stepping is enabled, there should really also be

NOMORE(step_rate, uint32_t(MAX_STEP_ISR_FREQUENCY_128X))
dc740 commented 1 year ago

H I just filed a new bug (didn't find this before).

I can confirm that https://github.com/MarlinFirmware/Marlin/pull/25335 does NOT fix the problem for me.

My details are here (with a few workarounds): https://github.com/MarlinFirmware/Marlin/issues/25369

I'm not able to reach the same speeds as before. I'm using DRV8825 with fast decay mod and 1/32 microstepping (I don´t know how this is related, but I saw a mention on this thread)

j-be commented 1 year ago

I think I am hit by this bug as well. After upgrading from 2.1.1 to 2.1.2 I cannot print with Linear Advance K values above 1. My TPU value is K=2.3 and at that point the extruder is going completely nuts and retracts more than it pushes forward, hence completely starving the nozzle. Printing PLA with K=0.55 still works fine though.

I have a BigTreeTech SKR Mini E3 v2 (TMC2209 in UART mode). My config is here, commit history here shows what I changed over stock.

Applying the patch proposed in #25335 has no effect, the problem persists.

I can quite quickly and deterministically reproduce the issue and am comfortable applying patches to C code. In other words, if you need guinea pigs: I'm happy to help :smile:

EDIT: I forgot to mention: the config for my 2.1.1 build and my 2.1.2 build should be functionally identical, except for those things, that changed in the default example from 2.1.1 to 2.1.2

EDIT2: I also forgot to add: mostly stock Ender 3 Pro. The only major changes are the afore mentioned SKR Mini E3 v2 and I swapped the extruder for a VoronM4, hence ESteps are quite high compared to stock, i.e. 565.

er1z commented 1 year ago

2.1.2, RAMPS, 2560. TMC on X, Y, E; Z + E1 (Z2) are working under DRV8825.

The same setup, after upgrade from 2.0.x made Z travelling shuttering as described (other axes work well). I decreased feed rate of Z from 4 to 2 and start so far, moves smoothly.

tombrazier commented 1 year ago

I have been working on a bunch of stepper ISR optimisations and also a new algorithm for dynamically calculating multi-stepping. The latter replaces all the cycle counting macros which are inaccurate, difficult to maintain and target a worst case scenario. I hope this deals with all the stuttering issues.

Needs testing. Any takers?

er1z commented 1 year ago

@tombrazier, #25474 and compile: is this enough? Can take my chance because on 2.1.1 it's still imperfect and may be this will solve my problems.

edit: basically, I'm asking if should I define MAX7219_DEBUG_MULTISTEPPING or just to compile as is?

tombrazier commented 1 year ago

@er1z Compile as is.

MAX7219_DEBUG_MULTISTEPPING is for if you have a MAX7219 panel for debugging and want to see real time what multistepping level is being used.

er1z commented 1 year ago

Ok, gonna check it and back with the insights tomorrow CEST.

er1z commented 1 year ago

Ok, tested it and seems that the main issue is finally solved, thank you very much!

The only thing I encountered is with linear advance stuttering as object is further from X=0. But don't know if it's related to this issue or should I file another one as AFAIR it also happened in 2.1.1. Here's a plot:

image

I was printing each of these objects separately. They're 20x20x20 boxes with no infill, no top layer. Ticks are marking correctly printed objects, where crosses — issues with (I guess) LA. One cross: it happened at the very last few layers (and only X-back side), double cross: since first layer.

In these recordings, 0,0 is front right. https://youtu.be/aTCfg8wfiu0 https://youtube.com/shorts/o1FELI6Z9bI

GCode: CFFFP_untitled.gcode.txt

Some insights: I'm using bilinear meshing, here's what was used:

Send: M420 V1 T1
Recv: Bilinear Leveling Grid:
Recv:       0      1      2      3
Recv:  0 +0.009 +0.040 +0.030 +0.035
Recv:  1 -0.023 +0.009 +0.020 +0.014
Recv:  2 +0.010 +0.015 +0.023 +0.018
Recv:  3 +0.032 +0.042 +0.015 -0.008

And the configuration:

#
# Marlin Firmware
# config.ini - Options to apply before the build
#
[config:base]
ini_use_config                           = minimal

# Load all config: sections in this file
;ini_use_config                          = all
# Load config file relative to Marlin/
;ini_use_config                          = another.ini
# Download configurations from GitHub
;ini_use_config                          = example/Creality/Ender-5 Plus @ bugfix-2.1.x
# Download configurations from your server
;ini_use_config                          = https://me.myserver.com/path/to/configs
# Evaluate config:base and do a config dump
;ini_use_config                          = base
;config_export                           = 2

[config:minimal]
motherboard                              = BOARD_RAMPS_14_EFB
serial_port                              = 0
baudrate                                 = 115200
;
use_watchdog                             = on
thermal_protection_hotends               = on
thermal_protection_bed                   = on
thermal_protection_hysteresis            = 4
thermal_protection_period                = 40
;
bufsize                                  = 4
block_buffer_size                        = 16
max_cmd_size                             = 96
;
extruders                                = 1
temp_sensor_0                            = 1
;
temp_hysteresis                          = 3
heater_0_mintemp                         = 5
heater_0_maxtemp                         = 275
;preheat_1_temp_hotend                    = 180
;
bang_max                                 = 255
pidtemp                                  = on
pid_k1                                   = 0.95
pid_max                                  = BANG_MAX
;pid_functional_range                     = 10
;
default_kp                               = 41.01
default_ki                               = 7.36
default_kd                               = 57.11
;
x_driver_type                            = TMC2130
y_driver_type                            = TMC2130
z_driver_type                            = TMC2130
z2_driver_type                           = TMC2130
e0_driver_type                           = DRV8825
;
x_bed_size                               = 190
x_min_pos                                = 0
x_max_pos                                = X_BED_SIZE
;
y_bed_size                               = 186
y_min_pos                                = 0
y_max_pos                                = Y_BED_SIZE

z_min_pos                                = 0
z_max_pos                                = 200
;
x_home_dir                               = -1
y_home_dir                               = -1
z_home_dir                               = -1
;
use_xmin_plug                            = on
use_ymin_plug                            = on
use_zmin_plug                            = on
use_zmax_plug                            = on
;
x_min_endstop_inverting                  = true
y_min_endstop_inverting                  = true
z_max_endstop_inverting                  = true
z_min_probe_endstop_inverting            = false
z_min_endstop_inverting                  = false
z_min_probe_uses_z_min_endstop_pin       = on
bltouch                                  = on
nozzle_to_probe_offset                   = { 25, -20, -0.55 }
probing_margin                           = 10
xy_probe_feedrate                        = 133*60
z_probe_feedrate_fast                    = 4*60
z_probe_feedrate_slow                    = Z_PROBE_FEEDRATE_FAST / 2

z_probe_offset_range_min                 = -20
z_probe_offset_range_max                 = 20

;
default_axis_steps_per_unit              = { 80, 80, 4000, 675*2 }
axis_relative_modes                      = { false, false, false, false }
default_max_feedrate                     = { 300, 300, 3, 25 }
default_max_acceleration                 = { 3000, 3000, 100, 10000 }
;
homing_feedrate_mm_m                     = { (50*60), (50*60), (4*60) }
;homing_bump_divisor                      = { 2, 2, 4 }
;
x_enable_on                              = 0
y_enable_on                              = 0
z_enable_on                              = 0
e_enable_on                              = 0
;
invert_x_dir                             = false
invert_y_dir                             = true
invert_z_dir                             = true
invert_e0_dir                            = false

disable_x                                = false
disable_y                                = false
disable_z                                = false
disable_e                                = false
;

default_nominal_filament_dia             = 1.75
;
junction_deviation_mm                    = 0.013
;
default_acceleration                     = 3000
default_travel_acceleration              = 3000
default_retract_acceleration             = 3000
;
;
;[config:basic]
bed_overshoot                            = 10
busy_while_heating                       = on
default_ejerk                            = 5.0
default_keepalive_interval               = 2
;default_leveling_fade_height             = 0.0
disable_inactive_extruder                = on
display_charset_hd44780                  = JAPANESE
eeprom_settings                          = on
eeprom_boot_silent                       = on
eeprom_chitchat                          = on
endstoppullups                           = on
;extrude_maxlength                        = 200
extrude_mintemp                          = 170
host_keepalive_feature                   = on
host_action_commands             = on
hotend_overshoot                         = 15
jd_handle_small_segments                 = on
lcd_info_screen_style                    = 0
lcd_language                             = en
max_bed_power                            = 255
;mesh_inset                               = 0
min_software_endstops                    = on
max_software_endstops                    = on
min_software_endstop_x                   = on
min_software_endstop_y                   = on
min_software_endstop_z                   = on
max_software_endstop_x                   = on
max_software_endstop_y                   = on
max_software_endstop_z                   = on
;preheat_1_fan_speed                      = 0
;preheat_1_label                          = "PLA"
;preheat_1_temp_bed                       = 70
prevent_cold_extrusion                   = on
prevent_lengthy_extrude                  = on
printjob_timer_autostart                 = on
;probing_margin                           = 10
show_bootscreen                          = on
;soft_pwm_scale                           = 0
string_config_h_author                   = "(none, default config)"
temp_bed_hysteresis                      = 3
temp_bed_residency_time                  = 10
temp_bed_window                          = 1
temp_residency_time                      = 10
temp_window                              = 1
validate_homing_endstops                 = on
;xy_probe_feedrate                        = (133*60)
z_clearance_between_probes               = 5
z_clearance_deploy_probe                 = 10
z_clearance_multi_probe                  = 5
;
;[config:advanced]
arc_support                              = on
auto_report_temperatures                 = on
autotemp                                 = on
autotemp_oldweight                       = 0.98
bed_check_interval                       = 5000
default_stepper_deactive_time            = 1
default_volumetric_extruder_limit        = 0.00
;disable_inactive_e                       = true
;disable_inactive_x                       = true
;disable_inactive_y                       = true
;disable_inactive_z                       = true
;e0_auto_fan_pin                          = -1
;encoder_100x_steps_per_sec               = 80
;encoder_10x_steps_per_sec                = 30
encoder_rate_multiplier                  = on
;extended_capabilities_report             = on
;extruder_auto_fan_speed                  = 255
;extruder_auto_fan_temperature            = 50
;fanmux0_pin                              = -1
;fanmux1_pin                              = -1
;fanmux2_pin                              = -1
faster_gcode_parser                      = on
;homing_bump_mm                           = { 5, 5, 2 }
max_arc_segment_mm                       = 1.0
min_arc_segment_mm                       = 0.1
min_circle_segments                      = 72
n_arc_correction                         = 25
serial_overrun_protection                = on
;slowdown                                 = on
;slowdown_divisor                         = 2
temp_sensor_bed                          = 1
thermal_protection_bed_hysteresis        = 2
thermocouple_max_errors                  = 15
tx_buffer_size                           = 0
watch_bed_temp_increase                  = 2
watch_bed_temp_period                    = 60
watch_temp_increase                      = 2
watch_temp_period                        = 20
auto_bed_leveling_bilinear               = on
restore_leveling_after_g28               = on
lcd_bed_leveling                         = on
reverse_encoder_direction                = on
individual_axis_homing_menu              = on
individual_axis_homing_submenu           = on
reprap_discount_full_graphic_smart_controller = on
st7920_delay_1                           = DELAY_NS(0)
st7920_delay_2                           = DELAY_NS(250)
st7920_delay_3                           = DELAY_NS(250)
z2_use_endstop                           = _ZMAX_
microstep_modes                          = { 16, 16, 16, 16, 16, 16 }
lin_advance                              = on
lin_advance_k                            = 0.11

x_cs_pin                                 = 44
y_cs_pin                                 = 66
e0_cs_pin                                = 64
z_cs_pin                                 = 59
z2_cs_pin                                = 63

tmc_use_sw_spi                           = on
tmc_sw_mosi                              = 40
tmc_sw_miso                              = 65
tmc_sw_sck                               = 42

tmc_debug                                = on
hold_multiplier                          = 1
monitor_driver_status                    = on
grid_max_points_x                        = 4

z_safe_homing                            = on
dc740 commented 1 year ago

I'll test it ASAP. (no promises on the date though. It could be today, or over the weekend, depending on availability)