浏览代码

⚡️ Improve Sensorless homing/probing for G28, G33 (#21899)

lujios 3 年前
父节点
当前提交
05ebde3812
没有帐户链接到提交者的电子邮件

+ 2
- 4
Marlin/src/MarlinCore.cpp 查看文件

@@ -828,10 +828,8 @@ void idle(bool no_stepper_sleep/*=false*/) {
828 828
 
829 829
   // Run StallGuard endstop checks
830 830
   #if ENABLED(SPI_ENDSTOPS)
831
-    if (endstops.tmc_spi_homing.any
832
-      && TERN1(IMPROVE_HOMING_RELIABILITY, ELAPSED(millis(), sg_guard_period))
833
-    ) LOOP_L_N(i, 4) // Read SGT 4 times per idle loop
834
-        if (endstops.tmc_spi_homing_check()) break;
831
+    if (endstops.tmc_spi_homing.any && TERN1(IMPROVE_HOMING_RELIABILITY, ELAPSED(millis(), sg_guard_period)))
832
+      LOOP_L_N(i, 4) if (endstops.tmc_spi_homing_check()) break; // Read SGT 4 times per idle loop
835 833
   #endif
836 834
 
837 835
   // Handle SD Card insert / remove

+ 0
- 7
Marlin/src/feature/tmc_util.h 查看文件

@@ -360,13 +360,6 @@ void test_tmc_connection(LOGICAL_AXIS_DECL(const bool, true));
360 360
   #if ENABLED(IMPROVE_HOMING_RELIABILITY)
361 361
     extern millis_t sg_guard_period;
362 362
     constexpr uint16_t default_sg_guard_duration = 400;
363
-
364
-    struct motion_state_t {
365
-      xy_ulong_t acceleration;
366
-      #if HAS_CLASSIC_JERK
367
-        xy_float_t jerk_state;
368
-      #endif
369
-    };
370 363
   #endif
371 364
 
372 365
   bool tmc_enable_stallguard(TMC2130Stepper &st);

+ 15
- 3
Marlin/src/gcode/calibrate/G28.cpp 查看文件

@@ -167,12 +167,15 @@
167 167
   motion_state_t begin_slow_homing() {
168 168
     motion_state_t motion_state{0};
169 169
     motion_state.acceleration.set(planner.settings.max_acceleration_mm_per_s2[X_AXIS],
170
-                                 planner.settings.max_acceleration_mm_per_s2[Y_AXIS]);
170
+                                 planner.settings.max_acceleration_mm_per_s2[Y_AXIS]
171
+                                 OPTARG(DELTA, planner.settings.max_acceleration_mm_per_s2[Z_AXIS])
172
+                               );
171 173
     planner.settings.max_acceleration_mm_per_s2[X_AXIS] = 100;
172 174
     planner.settings.max_acceleration_mm_per_s2[Y_AXIS] = 100;
175
+    TERN_(DELTA, planner.settings.max_acceleration_mm_per_s2[Z_AXIS] = 100);
173 176
     #if HAS_CLASSIC_JERK
174 177
       motion_state.jerk_state = planner.max_jerk;
175
-      planner.max_jerk.set(0, 0);
178
+      planner.max_jerk.set(0, 0 OPTARG(DELTA, 0));
176 179
     #endif
177 180
     planner.reset_acceleration_rates();
178 181
     return motion_state;
@@ -181,6 +184,7 @@
181 184
   void end_slow_homing(const motion_state_t &motion_state) {
182 185
     planner.settings.max_acceleration_mm_per_s2[X_AXIS] = motion_state.acceleration.x;
183 186
     planner.settings.max_acceleration_mm_per_s2[Y_AXIS] = motion_state.acceleration.y;
187
+    TERN_(DELTA, planner.settings.max_acceleration_mm_per_s2[Z_AXIS] = motion_state.acceleration.z);
184 188
     TERN_(HAS_CLASSIC_JERK, planner.max_jerk = motion_state.jerk_state);
185 189
     planner.reset_acceleration_rates();
186 190
   }
@@ -259,7 +263,7 @@ void GcodeSuite::G28() {
259 263
   reset_stepper_timeout();
260 264
 
261 265
   #define HAS_CURRENT_HOME(N) (defined(N##_CURRENT_HOME) && N##_CURRENT_HOME != N##_CURRENT)
262
-  #if HAS_CURRENT_HOME(X) || HAS_CURRENT_HOME(X2) || HAS_CURRENT_HOME(Y) || HAS_CURRENT_HOME(Y2)
266
+  #if HAS_CURRENT_HOME(X) || HAS_CURRENT_HOME(X2) || HAS_CURRENT_HOME(Y) || HAS_CURRENT_HOME(Y2) || (ENABLED(DELTA) && HAS_CURRENT_HOME(Z))
263 267
     #define HAS_HOMING_CURRENT 1
264 268
   #endif
265 269
 
@@ -287,6 +291,11 @@ void GcodeSuite::G28() {
287 291
       stepperY2.rms_current(Y2_CURRENT_HOME);
288 292
       if (DEBUGGING(LEVELING)) debug_current(PSTR("Y2"), tmc_save_current_Y2, Y2_CURRENT_HOME);
289 293
     #endif
294
+    #if HAS_CURRENT_HOME(Z) && ENABLED(DELTA)
295
+      const int16_t tmc_save_current_Z = stepperZ.getMilliamps();
296
+      stepperZ.rms_current(Z_CURRENT_HOME);
297
+      if (DEBUGGING(LEVELING)) debug_current(PSTR("Z"), tmc_save_current_Z, Z_CURRENT_HOME);
298
+    #endif
290 299
   #endif
291 300
 
292 301
   #if ENABLED(IMPROVE_HOMING_RELIABILITY)
@@ -497,6 +506,9 @@ void GcodeSuite::G28() {
497 506
     #if HAS_CURRENT_HOME(Y2)
498 507
       stepperY2.rms_current(tmc_save_current_Y2);
499 508
     #endif
509
+    #if HAS_CURRENT_HOME(Z) && ENABLED(DELTA)
510
+      stepperZ.rms_current(tmc_save_current_Z);
511
+    #endif
500 512
     #if HAS_CURRENT_HOME(I)
501 513
       stepperI.rms_current(tmc_save_current_I);
502 514
     #endif

+ 15
- 1
Marlin/src/gcode/calibrate/G33.cpp 查看文件

@@ -71,7 +71,9 @@ float lcd_probe_pt(const xy_pos_t &xy);
71 71
 
72 72
 void ac_home() {
73 73
   endstops.enable(true);
74
+  TERN_(SENSORLESS_HOMING, probe.set_homing_current(true));
74 75
   home_delta();
76
+  TERN_(SENSORLESS_HOMING, probe.set_homing_current(false));
75 77
   endstops.not_homing();
76 78
 }
77 79
 
@@ -384,6 +386,12 @@ static float auto_tune_a() {
384 386
  *      V3  Report settings and probe results
385 387
  *
386 388
  *   E   Engage the probe for each point
389
+ *
390
+ * With SENSORLESS_PROBING:
391
+ *   Use these flags to calibrate stall sensitivity: (e.g., `G33 P1 Y Z` to calibrate X only.)
392
+ *   X   Don't activate stallguard on X.
393
+ *   Y   Don't activate stallguard on Y.
394
+ *   Z   Don't activate stallguard on Z.
387 395
  */
388 396
 void GcodeSuite::G33() {
389 397
 
@@ -417,6 +425,12 @@ void GcodeSuite::G33() {
417 425
 
418 426
   const bool stow_after_each = parser.seen_test('E');
419 427
 
428
+  #if ENABLED(SENSORLESS_PROBING)
429
+    probe.test_sensitivity.x = !parser.seen_test('X');
430
+    TERN_(HAS_Y_AXIS, probe.test_sensitivity.y = !parser.seen_test('Y'));
431
+    TERN_(HAS_Z_AXIS, probe.test_sensitivity.z = !parser.seen_test('Z'));
432
+  #endif
433
+
420 434
   const bool _0p_calibration      = probe_points == 0,
421 435
              _1p_calibration      = probe_points == 1 || probe_points == -1,
422 436
              _4p_calibration      = probe_points == 2,
@@ -587,7 +601,7 @@ void GcodeSuite::G33() {
587 601
 
588 602
     // print report
589 603
 
590
-    if (verbose_level == 3)
604
+    if (verbose_level == 3 || verbose_level == 0)
591 605
       print_calibration_results(z_at_pt, _tower_results, _opposite_results);
592 606
 
593 607
     if (verbose_level != 0) { // !dry run

+ 1
- 0
Marlin/src/module/delta.cpp 查看文件

@@ -254,6 +254,7 @@ void home_delta() {
254 254
   current_position.z = DIFF_TERN(HAS_BED_PROBE, delta_height + 10, probe.offset.z);
255 255
   line_to_current_position(homing_feedrate(Z_AXIS));
256 256
   planner.synchronize();
257
+  TERN_(SENSORLESS_PROBING,endstops.report_states());
257 258
 
258 259
   // Re-enable stealthChop if used. Disable diag1 pin on driver.
259 260
   #if ENABLED(SENSORLESS_HOMING) && DISABLED(ENDSTOPS_ALWAYS_ON_DEFAULT)

+ 9
- 3
Marlin/src/module/endstops.cpp 查看文件

@@ -595,9 +595,15 @@ void _O2 Endstops::report_states() {
595 595
 // The following routines are called from an ISR context. It could be the temperature ISR, the
596 596
 // endstop ISR or the Stepper ISR.
597 597
 
598
-#define _ENDSTOP(AXIS, MINMAX) AXIS ##_## MINMAX
599
-#define _ENDSTOP_PIN(AXIS, MINMAX) AXIS ##_## MINMAX ##_PIN
600
-#define _ENDSTOP_INVERTING(AXIS, MINMAX) AXIS ##_## MINMAX ##_ENDSTOP_INVERTING
598
+#if BOTH(DELTA, SENSORLESS_PROBING)
599
+  #define _ENDSTOP(AXIS, MINMAX) AXIS ##_MAX
600
+  #define _ENDSTOP_PIN(AXIS, MINMAX) AXIS ##_MAX_PIN
601
+  #define _ENDSTOP_INVERTING(AXIS, MINMAX) AXIS ##_MAX_ENDSTOP_INVERTING
602
+#else
603
+  #define _ENDSTOP(AXIS, MINMAX) AXIS ##_## MINMAX
604
+  #define _ENDSTOP_PIN(AXIS, MINMAX) AXIS ##_## MINMAX ##_PIN
605
+  #define _ENDSTOP_INVERTING(AXIS, MINMAX) AXIS ##_## MINMAX ##_ENDSTOP_INVERTING
606
+#endif
601 607
 
602 608
 // Check endstops - Could be called from Temperature ISR!
603 609
 void Endstops::update() {

+ 28
- 0
Marlin/src/module/planner.cpp 查看文件

@@ -1527,6 +1527,34 @@ void Planner::check_axes_activity() {
1527 1527
   }
1528 1528
 #endif
1529 1529
 
1530
+#if ENABLED(IMPROVE_HOMING_RELIABILITY)
1531
+
1532
+  void Planner::enable_stall_prevention(const bool onoff) {
1533
+    static motion_state_t saved_motion_state;
1534
+    if (onoff) {
1535
+      saved_motion_state.acceleration.x = settings.max_acceleration_mm_per_s2[X_AXIS];
1536
+      saved_motion_state.acceleration.y = settings.max_acceleration_mm_per_s2[Y_AXIS];
1537
+      settings.max_acceleration_mm_per_s2[X_AXIS] = settings.max_acceleration_mm_per_s2[Y_AXIS] = 100;
1538
+      #if ENABLED(DELTA)
1539
+        saved_motion_state.acceleration.z = settings.max_acceleration_mm_per_s2[Z_AXIS];
1540
+        settings.max_acceleration_mm_per_s2[Z_AXIS] = 100;
1541
+      #endif
1542
+      #if HAS_CLASSIC_JERK
1543
+        saved_motion_state.jerk_state = max_jerk;
1544
+        max_jerk.set(0, 0 OPTARG(DELTA, 0));
1545
+      #endif
1546
+    }
1547
+    else {
1548
+      settings.max_acceleration_mm_per_s2[X_AXIS] = saved_motion_state.acceleration.x;
1549
+      settings.max_acceleration_mm_per_s2[Y_AXIS] = saved_motion_state.acceleration.y;
1550
+      TERN_(DELTA, settings.max_acceleration_mm_per_s2[Z_AXIS] = saved_motion_state.acceleration.z);
1551
+      TERN_(HAS_CLASSIC_JERK, max_jerk = saved_motion_state.jerk_state);
1552
+    }
1553
+    reset_acceleration_rates();
1554
+  }
1555
+
1556
+#endif
1557
+
1530 1558
 #if HAS_LEVELING
1531 1559
 
1532 1560
   constexpr xy_pos_t level_fulcrum = {

+ 13
- 0
Marlin/src/module/planner.h 查看文件

@@ -281,6 +281,15 @@ typedef struct {
281 281
             min_travel_feedrate_mm_s;           // (mm/s) M205 T - Minimum travel feedrate
282 282
 } planner_settings_t;
283 283
 
284
+#if ENABLED(IMPROVE_HOMING_RELIABILITY)
285
+  struct motion_state_t {
286
+    TERN(DELTA, xyz_ulong_t, xy_ulong_t) acceleration;
287
+    #if HAS_CLASSIC_JERK
288
+      TERN(DELTA, xyz_float_t, xy_float_t) jerk_state;
289
+    #endif
290
+  };
291
+#endif
292
+
284 293
 #if DISABLED(SKEW_CORRECTION)
285 294
   #define XY_SKEW_FACTOR 0
286 295
   #define XZ_SKEW_FACTOR 0
@@ -532,6 +541,10 @@ class Planner {
532 541
       }
533 542
     #endif
534 543
 
544
+    #if ENABLED(IMPROVE_HOMING_RELIABILITY)
545
+      void enable_stall_prevention(const bool onoff);
546
+    #endif
547
+
535 548
     #if DISABLED(NO_VOLUMETRICS)
536 549
 
537 550
       // Update multipliers based on new diameter measurements

+ 102
- 7
Marlin/src/module/probe.cpp 查看文件

@@ -68,7 +68,7 @@
68 68
   #include "servo.h"
69 69
 #endif
70 70
 
71
-#if ENABLED(SENSORLESS_PROBING)
71
+#if EITHER(SENSORLESS_PROBING, SENSORLESS_HOMING)
72 72
   #include "stepper.h"
73 73
   #include "../feature/tmc_util.h"
74 74
 #endif
@@ -92,6 +92,10 @@ xyz_pos_t Probe::offset; // Initialized by settings.load()
92 92
   const xy_pos_t &Probe::offset_xy = Probe::offset;
93 93
 #endif
94 94
 
95
+#if ENABLED(SENSORLESS_PROBING)
96
+  Probe::sense_bool_t Probe::test_sensitivity;
97
+#endif
98
+
95 99
 #if ENABLED(Z_PROBE_SLED)
96 100
 
97 101
   #ifndef SLED_DOCKING_OFFSET
@@ -493,11 +497,12 @@ bool Probe::probe_down_to_z(const_float_t z, const_feedRate_t fr_mm_s) {
493 497
   #if ENABLED(SENSORLESS_PROBING)
494 498
     sensorless_t stealth_states { false };
495 499
     #if ENABLED(DELTA)
496
-      stealth_states.x = tmc_enable_stallguard(stepperX);
497
-      stealth_states.y = tmc_enable_stallguard(stepperY);
500
+      if (probe.test_sensitivity.x) stealth_states.x = tmc_enable_stallguard(stepperX);  // Delta watches all DIAG pins for a stall
501
+      if (probe.test_sensitivity.y) stealth_states.y = tmc_enable_stallguard(stepperY);
498 502
     #endif
499
-    stealth_states.z = tmc_enable_stallguard(stepperZ);
503
+    if (probe.test_sensitivity.z) stealth_states.z = tmc_enable_stallguard(stepperZ);    // All machines will check Z-DIAG for stall
500 504
     endstops.enable(true);
505
+    set_homing_current(true);                                 // The "homing" current also applies to probing
501 506
   #endif
502 507
 
503 508
   TERN_(HAS_QUIET_PROBING, set_probing_paused(true));
@@ -520,10 +525,11 @@ bool Probe::probe_down_to_z(const_float_t z, const_feedRate_t fr_mm_s) {
520 525
   #if ENABLED(SENSORLESS_PROBING)
521 526
     endstops.not_homing();
522 527
     #if ENABLED(DELTA)
523
-      tmc_disable_stallguard(stepperX, stealth_states.x);
524
-      tmc_disable_stallguard(stepperY, stealth_states.y);
528
+      if (probe.test_sensitivity.x) tmc_disable_stallguard(stepperX, stealth_states.x);
529
+      if (probe.test_sensitivity.y) tmc_disable_stallguard(stepperY, stealth_states.y);
525 530
     #endif
526
-    tmc_disable_stallguard(stepperZ, stealth_states.z);
531
+    if (probe.test_sensitivity.z) tmc_disable_stallguard(stepperZ, stealth_states.z);
532
+    set_homing_current(false);
527 533
   #endif
528 534
 
529 535
   if (probe_triggered && TERN0(BLTOUCH_SLOW_MODE, bltouch.stow())) // Stow in LOW SPEED MODE on every trigger
@@ -815,4 +821,93 @@ float Probe::probe_at_point(const_float_t rx, const_float_t ry, const ProbePtRai
815 821
 
816 822
 #endif // HAS_Z_SERVO_PROBE
817 823
 
824
+#if EITHER(SENSORLESS_PROBING, SENSORLESS_HOMING)
825
+
826
+  sensorless_t stealth_states { false };
827
+
828
+  /**
829
+   * Disable stealthChop if used. Enable diag1 pin on driver.
830
+   */
831
+  void Probe::enable_stallguard_diag1() {
832
+    #if ENABLED(SENSORLESS_PROBING)
833
+      #if ENABLED(DELTA)
834
+        stealth_states.x = tmc_enable_stallguard(stepperX);
835
+        stealth_states.y = tmc_enable_stallguard(stepperY);
836
+      #endif
837
+      stealth_states.z = tmc_enable_stallguard(stepperZ);
838
+      endstops.enable(true);
839
+    #endif
840
+  }
841
+
842
+  /**
843
+   * Re-enable stealthChop if used. Disable diag1 pin on driver.
844
+   */
845
+  void Probe::disable_stallguard_diag1() {
846
+    #if ENABLED(SENSORLESS_PROBING)
847
+      endstops.not_homing();
848
+      #if ENABLED(DELTA)
849
+        tmc_disable_stallguard(stepperX, stealth_states.x);
850
+        tmc_disable_stallguard(stepperY, stealth_states.y);
851
+      #endif
852
+      tmc_disable_stallguard(stepperZ, stealth_states.z);
853
+    #endif
854
+  }
855
+
856
+  /**
857
+   * Change the current in the TMC drivers to N##_CURRENT_HOME. And we save the current configuration of each TMC driver.
858
+   */
859
+  void Probe::set_homing_current(const bool onoff) {
860
+    #define HAS_CURRENT_HOME(N) (defined(N##_CURRENT_HOME) && N##_CURRENT_HOME != N##_CURRENT)
861
+    #if HAS_CURRENT_HOME(X) || HAS_CURRENT_HOME(Y) || HAS_CURRENT_HOME(Z)
862
+      #if ENABLED(DELTA)
863
+        static int16_t saved_current_X, saved_current_Y;
864
+      #endif
865
+      #if HAS_CURRENT_HOME(Z)
866
+        static int16_t saved_current_Z;
867
+      #endif
868
+      auto debug_current_on = [](PGM_P const s, const int16_t a, const int16_t b) {
869
+        if (DEBUGGING(LEVELING)) { DEBUG_ECHOPGM_P(s); DEBUG_ECHOLNPAIR(" current: ", a, " -> ", b); }
870
+      };
871
+      if (onoff) {
872
+        #if ENABLED(DELTA)
873
+          #if HAS_CURRENT_HOME(X)
874
+            saved_current_X = stepperX.getMilliamps();
875
+            stepperX.rms_current(X_CURRENT_HOME);
876
+            debug_current_on(PSTR("X"), saved_current_X, X_CURRENT_HOME);
877
+          #endif
878
+          #if HAS_CURRENT_HOME(Y)
879
+            saved_current_Y = stepperY.getMilliamps();
880
+            stepperY.rms_current(Y_CURRENT_HOME);
881
+            debug_current_on(PSTR("Y"), saved_current_Y, Y_CURRENT_HOME);
882
+          #endif
883
+        #endif
884
+        #if HAS_CURRENT_HOME(Z)
885
+          saved_current_Z = stepperZ.getMilliamps();
886
+          stepperZ.rms_current(Z_CURRENT_HOME);
887
+          debug_current_on(PSTR("Z"), saved_current_Z, Z_CURRENT_HOME);
888
+        #endif
889
+        TERN_(IMPROVE_HOMING_RELIABILITY, planner.enable_stall_prevention(true));
890
+      }
891
+      else {
892
+        #if ENABLED(DELTA)
893
+          #if HAS_CURRENT_HOME(X)
894
+            stepperX.rms_current(saved_current_X);
895
+            debug_current_on(PSTR("X"), X_CURRENT_HOME, saved_current_X);
896
+          #endif
897
+          #if HAS_CURRENT_HOME(Y)
898
+            stepperY.rms_current(saved_current_Y);
899
+            debug_current_on(PSTR("Y"), Y_CURRENT_HOME, saved_current_Y);
900
+          #endif
901
+        #endif
902
+        #if HAS_CURRENT_HOME(Z)
903
+          stepperZ.rms_current(saved_current_Z);
904
+          debug_current_on(PSTR("Z"), Z_CURRENT_HOME, saved_current_Z);
905
+        #endif
906
+        TERN_(IMPROVE_HOMING_RELIABILITY, planner.enable_stall_prevention(false));
907
+      }
908
+    #endif
909
+  }
910
+
911
+#endif // SENSORLESS_PROBING
912
+
818 913
 #endif // HAS_BED_PROBE

+ 12
- 0
Marlin/src/module/probe.h 查看文件

@@ -56,6 +56,11 @@
56 56
 class Probe {
57 57
 public:
58 58
 
59
+  #if ENABLED(SENSORLESS_PROBING)
60
+    typedef struct { bool x:1, y:1, z:1; } sense_bool_t;
61
+    static sense_bool_t test_sensitivity;
62
+  #endif
63
+
59 64
   #if HAS_BED_PROBE
60 65
 
61 66
     static xyz_pos_t offset;
@@ -256,6 +261,13 @@ public:
256 261
     static bool tare();
257 262
   #endif
258 263
 
264
+  // Basic functions for Sensorless Homing and Probing
265
+  #if EITHER(SENSORLESS_HOMING, SENSORLESS_PROBING)
266
+    static void enable_stallguard_diag1();
267
+    static void disable_stallguard_diag1();
268
+    static void set_homing_current(const bool onoff);
269
+  #endif
270
+
259 271
 private:
260 272
   static bool probe_down_to_z(const_float_t z, const_feedRate_t fr_mm_s);
261 273
   static void do_z_raise(const float z_raise);

正在加载...
取消
保存