ソースを参照

G34 Z stepper locking (#20091)

Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
InsanityAutomation 3年前
コミット
1b0a5abd73
コミッターのメールアドレスに関連付けられたアカウントが存在しません

+ 5
- 0
Marlin/src/gcode/calibrate/G28.cpp ファイルの表示

@@ -375,6 +375,11 @@ void GcodeSuite::G28() {
375 375
     // Home Z last if homing towards the bed
376 376
     #if DISABLED(HOME_Z_FIRST)
377 377
       if (doZ) {
378
+        #if EITHER(Z_MULTI_ENDSTOPS, Z_STEPPER_AUTO_ALIGN)
379
+          stepper.set_all_z_lock(false);
380
+          stepper.set_separate_multi_axis(false);
381
+        #endif
382
+
378 383
         TERN_(BLTOUCH, bltouch.init());
379 384
         TERN(Z_SAFE_HOMING, home_z_safely(), homeaxis(Z_AXIS));
380 385
         probe.move_z_after_homing();

+ 328
- 294
Marlin/src/gcode/calibrate/G34_M422.cpp ファイルの表示

@@ -22,7 +22,7 @@
22 22
 
23 23
 #include "../../inc/MarlinConfigPre.h"
24 24
 
25
-#if ENABLED(Z_STEPPER_AUTO_ALIGN)
25
+#if EITHER(Z_MULTI_ENDSTOPS, Z_STEPPER_AUTO_ALIGN)
26 26
 
27 27
 #include "../../feature/z_stepper_align.h"
28 28
 
@@ -51,364 +51,398 @@
51 51
 /**
52 52
  * G34: Z-Stepper automatic alignment
53 53
  *
54
- *   I<iterations>
55
- *   T<accuracy>
56
- *   A<amplification>
57
- *   R<recalculate> points based on current probe offsets
54
+ * Manual stepper lock controls (reset by G28):
55
+ *   L                 Unlock all steppers
56
+ *   Z<1-4>            Z stepper to lock / unlock
57
+ *   S<state>          0=UNLOCKED 1=LOCKED. If omitted, assume LOCKED.
58
+ *
59
+ *   Examples:
60
+ *     G34 Z1     ; Lock Z1
61
+ *     G34 L Z2   ; Unlock all, then lock Z2
62
+ *     G34 Z2 S0  ; Unlock Z2
63
+ *
64
+ * With Z_STEPPER_AUTO_ALIGN:
65
+ *   I<iterations>     Number of tests. If omitted, Z_STEPPER_ALIGN_ITERATIONS.
66
+ *   T<accuracy>       Target Accuracy factor. If omitted, Z_STEPPER_ALIGN_ACC.
67
+ *   A<amplification>  Provide an Amplification value. If omitted, Z_STEPPER_ALIGN_AMP.
68
+ *   R                 Flag to recalculate points based on current probe offsets
58 69
  */
59 70
 void GcodeSuite::G34() {
60 71
   DEBUG_SECTION(log_G34, "G34", DEBUGGING(LEVELING));
61 72
   if (DEBUGGING(LEVELING)) log_machine_info();
62 73
 
63
-  do { // break out on error
64
-
65
-    #if NUM_Z_STEPPER_DRIVERS == 4
66
-      SERIAL_ECHOLNPGM("Alignment for 4 steppers is Experimental!");
67
-    #elif NUM_Z_STEPPER_DRIVERS > 4
68
-      SERIAL_ECHOLNPGM("Alignment not supported for over 4 steppers");
69
-      break;
70
-    #endif
71
-
72
-    const int8_t z_auto_align_iterations = parser.intval('I', Z_STEPPER_ALIGN_ITERATIONS);
73
-    if (!WITHIN(z_auto_align_iterations, 1, 30)) {
74
-      SERIAL_ECHOLNPGM("?(I)teration out of bounds (1-30).");
75
-      break;
74
+  planner.synchronize();  // Prevent damage
75
+
76
+  const bool seenL = parser.seen('L');
77
+  if (seenL) stepper.set_all_z_lock(false);
78
+
79
+  const bool seenZ = parser.seenval('Z');
80
+  if (seenZ) {
81
+    const bool state = parser.boolval('S', true);
82
+    switch (parser.intval('Z')) {
83
+      case 1: stepper.set_z1_lock(state); break;
84
+      case 2: stepper.set_z2_lock(state); break;
85
+      #if NUM_Z_STEPPER_DRIVERS >= 3
86
+        case 3: stepper.set_z3_lock(state); break;
87
+        #if NUM_Z_STEPPER_DRIVERS >= 4
88
+          case 4: stepper.set_z4_lock(state); break;
89
+        #endif
90
+      #endif
76 91
     }
92
+  }
77 93
 
78
-    const float z_auto_align_accuracy = parser.floatval('T', Z_STEPPER_ALIGN_ACC);
79
-    if (!WITHIN(z_auto_align_accuracy, 0.01f, 1.0f)) {
80
-      SERIAL_ECHOLNPGM("?(T)arget accuracy out of bounds (0.01-1.0).");
81
-      break;
82
-    }
94
+  if (seenL || seenZ) {
95
+    stepper.set_separate_multi_axis(seenZ);
96
+    return;
97
+  }
83 98
 
84
-    const float z_auto_align_amplification =
85
-      #if ENABLED(Z_STEPPER_ALIGN_KNOWN_STEPPER_POSITIONS)
86
-        Z_STEPPER_ALIGN_AMP;
87
-      #else
88
-        parser.floatval('A', Z_STEPPER_ALIGN_AMP);
89
-        if (!WITHIN(ABS(z_auto_align_amplification), 0.5f, 2.0f)) {
90
-          SERIAL_ECHOLNPGM("?(A)mplification out of bounds (0.5-2.0).");
91
-          break;
92
-        }
99
+  #if ENABLED(Z_STEPPER_AUTO_ALIGN)
100
+    do { // break out on error
101
+
102
+      #if NUM_Z_STEPPER_DRIVERS == 4
103
+        SERIAL_ECHOLNPGM("Alignment for 4 steppers is Experimental!");
104
+      #elif NUM_Z_STEPPER_DRIVERS > 4
105
+        SERIAL_ECHOLNPGM("Alignment not supported for over 4 steppers");
106
+        break;
93 107
       #endif
94 108
 
95
-    if (parser.seen('R')) z_stepper_align.reset_to_default();
109
+      const int8_t z_auto_align_iterations = parser.intval('I', Z_STEPPER_ALIGN_ITERATIONS);
110
+      if (!WITHIN(z_auto_align_iterations, 1, 30)) {
111
+        SERIAL_ECHOLNPGM("?(I)teration out of bounds (1-30).");
112
+        break;
113
+      }
96 114
 
97
-    const ProbePtRaise raise_after = parser.boolval('E') ? PROBE_PT_STOW : PROBE_PT_RAISE;
115
+      const float z_auto_align_accuracy = parser.floatval('T', Z_STEPPER_ALIGN_ACC);
116
+      if (!WITHIN(z_auto_align_accuracy, 0.01f, 1.0f)) {
117
+        SERIAL_ECHOLNPGM("?(T)arget accuracy out of bounds (0.01-1.0).");
118
+        break;
119
+      }
98 120
 
99
-    // Wait for planner moves to finish!
100
-    planner.synchronize();
121
+      const float z_auto_align_amplification = TERN(Z_STEPPER_ALIGN_KNOWN_STEPPER_POSITIONS, Z_STEPPER_ALIGN_AMP, parser.floatval('A', Z_STEPPER_ALIGN_AMP));
122
+      if (!WITHIN(ABS(z_auto_align_amplification), 0.5f, 2.0f)) {
123
+        SERIAL_ECHOLNPGM("?(A)mplification out of bounds (0.5-2.0).");
124
+        break;
125
+      }
101 126
 
102
-    // Disable the leveling matrix before auto-aligning
103
-    #if HAS_LEVELING
104
-      TERN_(RESTORE_LEVELING_AFTER_G34, const bool leveling_was_active = planner.leveling_active);
105
-      set_bed_leveling_enabled(false);
106
-    #endif
127
+      if (parser.seen('R')) z_stepper_align.reset_to_default();
107 128
 
108
-    TERN_(CNC_WORKSPACE_PLANES, workspace_plane = PLANE_XY);
129
+      const ProbePtRaise raise_after = parser.boolval('E') ? PROBE_PT_STOW : PROBE_PT_RAISE;
109 130
 
110
-    // Always home with tool 0 active
111
-    #if HAS_MULTI_HOTEND
112
-      const uint8_t old_tool_index = active_extruder;
113
-      tool_change(0, true);
114
-    #endif
131
+      // Disable the leveling matrix before auto-aligning
132
+      #if HAS_LEVELING
133
+        TERN_(RESTORE_LEVELING_AFTER_G34, const bool leveling_was_active = planner.leveling_active);
134
+        set_bed_leveling_enabled(false);
135
+      #endif
115 136
 
116
-    TERN_(HAS_DUPLICATION_MODE, set_duplication_enabled(false));
117
-
118
-    // In BLTOUCH HS mode, the probe travels in a deployed state.
119
-    // Users of G34 might have a badly misaligned bed, so raise Z by the
120
-    // length of the deployed pin (BLTOUCH stroke < 7mm)
121
-    #define Z_BASIC_CLEARANCE (Z_CLEARANCE_BETWEEN_PROBES + 7.0f * BOTH(BLTOUCH, BLTOUCH_HS_MODE))
122
-
123
-    // Compute a worst-case clearance height to probe from. After the first
124
-    // iteration this will be re-calculated based on the actual bed position
125
-    auto magnitude2 = [&](const uint8_t i, const uint8_t j) {
126
-      const xy_pos_t diff = z_stepper_align.xy[i] - z_stepper_align.xy[j];
127
-      return HYPOT2(diff.x, diff.y);
128
-    };
129
-    float z_probe = Z_BASIC_CLEARANCE + (G34_MAX_GRADE) * 0.01f * SQRT(
130
-      #if NUM_Z_STEPPER_DRIVERS == 3
131
-         _MAX(magnitude2(0, 1), magnitude2(1, 2), magnitude2(2, 0))
132
-      #elif NUM_Z_STEPPER_DRIVERS == 4
133
-         _MAX(magnitude2(0, 1), magnitude2(1, 2), magnitude2(2, 3),
134
-              magnitude2(3, 0), magnitude2(0, 2), magnitude2(1, 3))
135
-      #else
136
-         magnitude2(0, 1)
137
+      TERN_(CNC_WORKSPACE_PLANES, workspace_plane = PLANE_XY);
138
+
139
+      // Always home with tool 0 active
140
+      #if HAS_MULTI_HOTEND
141
+        const uint8_t old_tool_index = active_extruder;
142
+        tool_change(0, true);
137 143
       #endif
138
-    );
139 144
 
140
-    // Home before the alignment procedure
141
-    if (!all_axes_known()) home_all_axes();
145
+      TERN_(HAS_DUPLICATION_MODE, set_duplication_enabled(false));
142 146
 
143
-    // Move the Z coordinate realm towards the positive - dirty trick
144
-    current_position.z += z_probe * 0.5f;
145
-    sync_plan_position();
146
-    // Now, the Z origin lies below the build plate. That allows to probe deeper, before run_z_probe throws an error.
147
-    // This hack is un-done at the end of G34 - either by re-homing, or by using the probed heights of the last iteration.
147
+      // In BLTOUCH HS mode, the probe travels in a deployed state.
148
+      // Users of G34 might have a badly misaligned bed, so raise Z by the
149
+      // length of the deployed pin (BLTOUCH stroke < 7mm)
150
+      #define Z_BASIC_CLEARANCE (Z_CLEARANCE_BETWEEN_PROBES + 7.0f * BOTH(BLTOUCH, BLTOUCH_HS_MODE))
148 151
 
149
-    #if DISABLED(Z_STEPPER_ALIGN_KNOWN_STEPPER_POSITIONS)
150
-      float last_z_align_move[NUM_Z_STEPPER_DRIVERS] = ARRAY_N(NUM_Z_STEPPER_DRIVERS, 10000.0f, 10000.0f, 10000.0f, 10000.0f);
151
-    #else
152
-      float last_z_align_level_indicator = 10000.0f;
153
-    #endif
154
-    float z_measured[NUM_Z_STEPPER_DRIVERS] = { 0 },
155
-          z_maxdiff = 0.0f,
156
-          amplification = z_auto_align_amplification;
152
+      // Compute a worst-case clearance height to probe from. After the first
153
+      // iteration this will be re-calculated based on the actual bed position
154
+      auto magnitude2 = [&](const uint8_t i, const uint8_t j) {
155
+        const xy_pos_t diff = z_stepper_align.xy[i] - z_stepper_align.xy[j];
156
+        return HYPOT2(diff.x, diff.y);
157
+      };
158
+      float z_probe = Z_BASIC_CLEARANCE + (G34_MAX_GRADE) * 0.01f * SQRT(
159
+        #if NUM_Z_STEPPER_DRIVERS == 3
160
+          _MAX(magnitude2(0, 1), magnitude2(1, 2), magnitude2(2, 0))
161
+        #elif NUM_Z_STEPPER_DRIVERS == 4
162
+          _MAX(magnitude2(0, 1), magnitude2(1, 2), magnitude2(2, 3),
163
+                magnitude2(3, 0), magnitude2(0, 2), magnitude2(1, 3))
164
+        #else
165
+          magnitude2(0, 1)
166
+        #endif
167
+      );
157 168
 
158
-    #if DISABLED(Z_STEPPER_ALIGN_KNOWN_STEPPER_POSITIONS)
159
-      bool adjustment_reverse = false;
160
-    #endif
169
+      // Home before the alignment procedure
170
+      if (!all_axes_known()) home_all_axes();
161 171
 
162
-    #if HAS_DISPLAY
163
-      PGM_P const msg_iteration = GET_TEXT(MSG_ITERATION);
164
-      const uint8_t iter_str_len = strlen_P(msg_iteration);
165
-    #endif
172
+      // Move the Z coordinate realm towards the positive - dirty trick
173
+      current_position.z += z_probe * 0.5f;
174
+      sync_plan_position();
175
+      // Now, the Z origin lies below the build plate. That allows to probe deeper, before run_z_probe throws an error.
176
+      // This hack is un-done at the end of G34 - either by re-homing, or by using the probed heights of the last iteration.
177
+
178
+      #if DISABLED(Z_STEPPER_ALIGN_KNOWN_STEPPER_POSITIONS)
179
+        float last_z_align_move[NUM_Z_STEPPER_DRIVERS] = ARRAY_N(NUM_Z_STEPPER_DRIVERS, 10000.0f, 10000.0f, 10000.0f, 10000.0f);
180
+      #else
181
+        float last_z_align_level_indicator = 10000.0f;
182
+      #endif
183
+      float z_measured[NUM_Z_STEPPER_DRIVERS] = { 0 },
184
+            z_maxdiff = 0.0f,
185
+            amplification = z_auto_align_amplification;
166 186
 
167
-    // Final z and iteration values will be used after breaking the loop
168
-    float z_measured_min;
169
-    uint8_t iteration = 0;
170
-    bool err_break = false; // To break out of nested loops
171
-    while (iteration < z_auto_align_iterations) {
172
-      if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("> probing all positions.");
187
+      #if DISABLED(Z_STEPPER_ALIGN_KNOWN_STEPPER_POSITIONS)
188
+        bool adjustment_reverse = false;
189
+      #endif
173 190
 
174
-      const int iter = iteration + 1;
175
-      SERIAL_ECHOLNPAIR("\nG34 Iteration: ", iter);
176 191
       #if HAS_DISPLAY
177
-        char str[iter_str_len + 2 + 1];
178
-        sprintf_P(str, msg_iteration, iter);
179
-        ui.set_status(str);
192
+        PGM_P const msg_iteration = GET_TEXT(MSG_ITERATION);
193
+        const uint8_t iter_str_len = strlen_P(msg_iteration);
180 194
       #endif
181 195
 
182
-      // Initialize minimum value
183
-      z_measured_min =  100000.0f;
184
-      float z_measured_max = -100000.0f;
185
-
186
-      // Probe all positions (one per Z-Stepper)
187
-      LOOP_L_N(i, NUM_Z_STEPPER_DRIVERS) {
188
-        // iteration odd/even --> downward / upward stepper sequence
189
-        const uint8_t iprobe = (iteration & 1) ? NUM_Z_STEPPER_DRIVERS - 1 - i : i;
190
-
191
-        // Safe clearance even on an incline
192
-        if ((iteration == 0 || i > 0) && z_probe > current_position.z) do_blocking_move_to_z(z_probe);
193
-
194
-        if (DEBUGGING(LEVELING))
195
-          DEBUG_ECHOLNPAIR_P(PSTR("Probing X"), z_stepper_align.xy[iprobe].x, SP_Y_STR, z_stepper_align.xy[iprobe].y);
196
-
197
-        // Probe a Z height for each stepper.
198
-        // Probing sanity check is disabled, as it would trigger even in normal cases because
199
-        // current_position.z has been manually altered in the "dirty trick" above.
200
-        const float z_probed_height = probe.probe_at_point(z_stepper_align.xy[iprobe], raise_after, 0, true, false);
201
-        if (isnan(z_probed_height)) {
202
-          SERIAL_ECHOLNPGM("Probing failed");
203
-          LCD_MESSAGEPGM(MSG_LCD_PROBING_FAILED);
204
-          err_break = true;
205
-          break;
206
-        }
196
+      // Final z and iteration values will be used after breaking the loop
197
+      float z_measured_min;
198
+      uint8_t iteration = 0;
199
+      bool err_break = false; // To break out of nested loops
200
+      while (iteration < z_auto_align_iterations) {
201
+        if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("> probing all positions.");
202
+
203
+        const int iter = iteration + 1;
204
+        SERIAL_ECHOLNPAIR("\nG34 Iteration: ", iter);
205
+        #if HAS_DISPLAY
206
+          char str[iter_str_len + 2 + 1];
207
+          sprintf_P(str, msg_iteration, iter);
208
+          ui.set_status(str);
209
+        #endif
207 210
 
208
-        // Add height to each value, to provide a more useful target height for
209
-        // the next iteration of probing. This allows adjustments to be made away from the bed.
210
-        z_measured[iprobe] = z_probed_height + Z_CLEARANCE_BETWEEN_PROBES;
211
+        // Initialize minimum value
212
+        z_measured_min =  100000.0f;
213
+        float z_measured_max = -100000.0f;
211 214
 
212
-        if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR("> Z", int(iprobe + 1), " measured position is ", z_measured[iprobe]);
215
+        // Probe all positions (one per Z-Stepper)
216
+        LOOP_L_N(i, NUM_Z_STEPPER_DRIVERS) {
217
+          // iteration odd/even --> downward / upward stepper sequence
218
+          const uint8_t iprobe = (iteration & 1) ? NUM_Z_STEPPER_DRIVERS - 1 - i : i;
219
+
220
+          // Safe clearance even on an incline
221
+          if ((iteration == 0 || i > 0) && z_probe > current_position.z) do_blocking_move_to_z(z_probe);
222
+
223
+          if (DEBUGGING(LEVELING))
224
+            DEBUG_ECHOLNPAIR_P(PSTR("Probing X"), z_stepper_align.xy[iprobe].x, SP_Y_STR, z_stepper_align.xy[iprobe].y);
225
+
226
+          // Probe a Z height for each stepper.
227
+          // Probing sanity check is disabled, as it would trigger even in normal cases because
228
+          // current_position.z has been manually altered in the "dirty trick" above.
229
+          const float z_probed_height = probe.probe_at_point(z_stepper_align.xy[iprobe], raise_after, 0, true, false);
230
+          if (isnan(z_probed_height)) {
231
+            SERIAL_ECHOLNPGM("Probing failed");
232
+            LCD_MESSAGEPGM(MSG_LCD_PROBING_FAILED);
233
+            err_break = true;
234
+            break;
235
+          }
213 236
 
214
-        // Remember the minimum measurement to calculate the correction later on
215
-        z_measured_min = _MIN(z_measured_min, z_measured[iprobe]);
216
-        z_measured_max = _MAX(z_measured_max, z_measured[iprobe]);
217
-      } // for (i)
237
+          // Add height to each value, to provide a more useful target height for
238
+          // the next iteration of probing. This allows adjustments to be made away from the bed.
239
+          z_measured[iprobe] = z_probed_height + Z_CLEARANCE_BETWEEN_PROBES;
218 240
 
219
-      if (err_break) break;
241
+          if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR("> Z", int(iprobe + 1), " measured position is ", z_measured[iprobe]);
220 242
 
221
-      // Adapt the next probe clearance height based on the new measurements.
222
-      // Safe_height = lowest distance to bed (= highest measurement) plus highest measured misalignment.
223
-      z_maxdiff = z_measured_max - z_measured_min;
224
-      z_probe = Z_BASIC_CLEARANCE + z_measured_max + z_maxdiff;
243
+          // Remember the minimum measurement to calculate the correction later on
244
+          z_measured_min = _MIN(z_measured_min, z_measured[iprobe]);
245
+          z_measured_max = _MAX(z_measured_max, z_measured[iprobe]);
246
+        } // for (i)
225 247
 
226
-      #if ENABLED(Z_STEPPER_ALIGN_KNOWN_STEPPER_POSITIONS)
227
-        // Replace the initial values in z_measured with calculated heights at
228
-        // each stepper position. This allows the adjustment algorithm to be
229
-        // shared between both possible probing mechanisms.
230
-
231
-        // This must be done after the next z_probe height is calculated, so that
232
-        // the height is calculated from actual print area positions, and not
233
-        // extrapolated motor movements.
234
-
235
-        // Compute the least-squares fit for all probed points.
236
-        // Calculate the Z position of each stepper and store it in z_measured.
237
-        // This allows the actual adjustment logic to be shared by both algorithms.
238
-        linear_fit_data lfd;
239
-        incremental_LSF_reset(&lfd);
240
-        LOOP_L_N(i, NUM_Z_STEPPER_DRIVERS) {
241
-          SERIAL_ECHOLNPAIR("PROBEPT_", int(i), ": ", z_measured[i]);
242
-          incremental_LSF(&lfd, z_stepper_align.xy[i], z_measured[i]);
243
-        }
244
-        finish_incremental_LSF(&lfd);
248
+        if (err_break) break;
245 249
 
246
-        z_measured_min = 100000.0f;
247
-        LOOP_L_N(i, NUM_Z_STEPPER_DRIVERS) {
248
-          z_measured[i] = -(lfd.A * z_stepper_align.stepper_xy[i].x + lfd.B * z_stepper_align.stepper_xy[i].y + lfd.D);
249
-          z_measured_min = _MIN(z_measured_min, z_measured[i]);
250
-        }
250
+        // Adapt the next probe clearance height based on the new measurements.
251
+        // Safe_height = lowest distance to bed (= highest measurement) plus highest measured misalignment.
252
+        z_maxdiff = z_measured_max - z_measured_min;
253
+        z_probe = Z_BASIC_CLEARANCE + z_measured_max + z_maxdiff;
254
+
255
+        #if ENABLED(Z_STEPPER_ALIGN_KNOWN_STEPPER_POSITIONS)
256
+          // Replace the initial values in z_measured with calculated heights at
257
+          // each stepper position. This allows the adjustment algorithm to be
258
+          // shared between both possible probing mechanisms.
259
+
260
+          // This must be done after the next z_probe height is calculated, so that
261
+          // the height is calculated from actual print area positions, and not
262
+          // extrapolated motor movements.
263
+
264
+          // Compute the least-squares fit for all probed points.
265
+          // Calculate the Z position of each stepper and store it in z_measured.
266
+          // This allows the actual adjustment logic to be shared by both algorithms.
267
+          linear_fit_data lfd;
268
+          incremental_LSF_reset(&lfd);
269
+          LOOP_L_N(i, NUM_Z_STEPPER_DRIVERS) {
270
+            SERIAL_ECHOLNPAIR("PROBEPT_", int(i), ": ", z_measured[i]);
271
+            incremental_LSF(&lfd, z_stepper_align.xy[i], z_measured[i]);
272
+          }
273
+          finish_incremental_LSF(&lfd);
251 274
 
252
-        SERIAL_ECHOLNPAIR("CALCULATED STEPPER POSITIONS: Z1=", z_measured[0], " Z2=", z_measured[1], " Z3=", z_measured[2]);
253
-      #endif
275
+          z_measured_min = 100000.0f;
276
+          LOOP_L_N(i, NUM_Z_STEPPER_DRIVERS) {
277
+            z_measured[i] = -(lfd.A * z_stepper_align.stepper_xy[i].x + lfd.B * z_stepper_align.stepper_xy[i].y + lfd.D);
278
+            z_measured_min = _MIN(z_measured_min, z_measured[i]);
279
+          }
254 280
 
255
-      SERIAL_ECHOLNPAIR("\n"
256
-        "DIFFERENCE Z1-Z2=", ABS(z_measured[0] - z_measured[1])
257
-        #if NUM_Z_STEPPER_DRIVERS == 3
258
-          , " Z2-Z3=", ABS(z_measured[1] - z_measured[2])
259
-          , " Z3-Z1=", ABS(z_measured[2] - z_measured[0])
260
-        #endif
261
-      );
262
-      #if HAS_DISPLAY
263
-        char fstr1[10];
264
-        #if NUM_Z_STEPPER_DRIVERS == 2
265
-          char msg[6 + (6 + 5) * 1 + 1];
266
-        #else
267
-          char msg[6 + (6 + 5) * 3 + 1], fstr2[10], fstr3[10];
281
+          SERIAL_ECHOLNPAIR("CALCULATED STEPPER POSITIONS: Z1=", z_measured[0], " Z2=", z_measured[1], " Z3=", z_measured[2]);
268 282
         #endif
269
-        sprintf_P(msg,
270
-          PSTR("Diffs Z1-Z2=%s"
271
-            #if NUM_Z_STEPPER_DRIVERS == 3
272
-              " Z2-Z3=%s"
273
-              " Z3-Z1=%s"
274
-            #endif
275
-          ), dtostrf(ABS(z_measured[0] - z_measured[1]), 1, 3, fstr1)
283
+
284
+        SERIAL_ECHOLNPAIR("\n"
285
+          "DIFFERENCE Z1-Z2=", ABS(z_measured[0] - z_measured[1])
276 286
           #if NUM_Z_STEPPER_DRIVERS == 3
277
-            , dtostrf(ABS(z_measured[1] - z_measured[2]), 1, 3, fstr2)
278
-            , dtostrf(ABS(z_measured[2] - z_measured[0]), 1, 3, fstr3)
287
+            , " Z2-Z3=", ABS(z_measured[1] - z_measured[2])
288
+            , " Z3-Z1=", ABS(z_measured[2] - z_measured[0])
279 289
           #endif
280 290
         );
281
-        ui.set_status(msg);
282
-      #endif
291
+        #if HAS_DISPLAY
292
+          char fstr1[10];
293
+          #if NUM_Z_STEPPER_DRIVERS == 2
294
+            char msg[6 + (6 + 5) * 1 + 1];
295
+          #else
296
+            char msg[6 + (6 + 5) * 3 + 1], fstr2[10], fstr3[10];
297
+          #endif
298
+          sprintf_P(msg,
299
+            PSTR("Diffs Z1-Z2=%s"
300
+              #if NUM_Z_STEPPER_DRIVERS == 3
301
+                " Z2-Z3=%s"
302
+                " Z3-Z1=%s"
303
+              #endif
304
+            ), dtostrf(ABS(z_measured[0] - z_measured[1]), 1, 3, fstr1)
305
+            #if NUM_Z_STEPPER_DRIVERS == 3
306
+              , dtostrf(ABS(z_measured[1] - z_measured[2]), 1, 3, fstr2)
307
+              , dtostrf(ABS(z_measured[2] - z_measured[0]), 1, 3, fstr3)
308
+            #endif
309
+          );
310
+          ui.set_status(msg);
311
+        #endif
283 312
 
284
-      auto decreasing_accuracy = [](const float &v1, const float &v2){
285
-        if (v1 < v2 * 0.7f) {
286
-          SERIAL_ECHOLNPGM("Decreasing Accuracy Detected.");
287
-          LCD_MESSAGEPGM(MSG_DECREASING_ACCURACY);
288
-          return true;
289
-        }
290
-        return false;
291
-      };
313
+        auto decreasing_accuracy = [](const float &v1, const float &v2){
314
+          if (v1 < v2 * 0.7f) {
315
+            SERIAL_ECHOLNPGM("Decreasing Accuracy Detected.");
316
+            LCD_MESSAGEPGM(MSG_DECREASING_ACCURACY);
317
+            return true;
318
+          }
319
+          return false;
320
+        };
292 321
 
293
-      #if ENABLED(Z_STEPPER_ALIGN_KNOWN_STEPPER_POSITIONS)
322
+        #if ENABLED(Z_STEPPER_ALIGN_KNOWN_STEPPER_POSITIONS)
294 323
 
295
-        // Check if the applied corrections go in the correct direction.
296
-        // Calculate the sum of the absolute deviations from the mean of the probe measurements.
297
-        // Compare to the last iteration to ensure it's getting better.
324
+          // Check if the applied corrections go in the correct direction.
325
+          // Calculate the sum of the absolute deviations from the mean of the probe measurements.
326
+          // Compare to the last iteration to ensure it's getting better.
298 327
 
299
-        // Calculate mean value as a reference
300
-        float z_measured_mean = 0.0f;
301
-        LOOP_L_N(zstepper, NUM_Z_STEPPER_DRIVERS) z_measured_mean += z_measured[zstepper];
302
-        z_measured_mean /= NUM_Z_STEPPER_DRIVERS;
328
+          // Calculate mean value as a reference
329
+          float z_measured_mean = 0.0f;
330
+          LOOP_L_N(zstepper, NUM_Z_STEPPER_DRIVERS) z_measured_mean += z_measured[zstepper];
331
+          z_measured_mean /= NUM_Z_STEPPER_DRIVERS;
303 332
 
304
-        // Calculate the sum of the absolute deviations from the mean value
305
-        float z_align_level_indicator = 0.0f;
306
-        LOOP_L_N(zstepper, NUM_Z_STEPPER_DRIVERS)
307
-          z_align_level_indicator += ABS(z_measured[zstepper] - z_measured_mean);
333
+          // Calculate the sum of the absolute deviations from the mean value
334
+          float z_align_level_indicator = 0.0f;
335
+          LOOP_L_N(zstepper, NUM_Z_STEPPER_DRIVERS)
336
+            z_align_level_indicator += ABS(z_measured[zstepper] - z_measured_mean);
308 337
 
309
-        // If it's getting worse, stop and throw an error
310
-        err_break = decreasing_accuracy(last_z_align_level_indicator, z_align_level_indicator);
311
-        if (err_break) break;
338
+          // If it's getting worse, stop and throw an error
339
+          err_break = decreasing_accuracy(last_z_align_level_indicator, z_align_level_indicator);
340
+          if (err_break) break;
312 341
 
313
-        last_z_align_level_indicator = z_align_level_indicator;
314
-      #endif
342
+          last_z_align_level_indicator = z_align_level_indicator;
343
+        #endif
315 344
 
316
-      // The following correction actions are to be enabled for select Z-steppers only
317
-      stepper.set_separate_multi_axis(true);
318
-
319
-      bool success_break = true;
320
-      // Correct the individual stepper offsets
321
-      LOOP_L_N(zstepper, NUM_Z_STEPPER_DRIVERS) {
322
-        // Calculate current stepper move
323
-        float z_align_move = z_measured[zstepper] - z_measured_min;
324
-        const float z_align_abs = ABS(z_align_move);
325
-
326
-        #if DISABLED(Z_STEPPER_ALIGN_KNOWN_STEPPER_POSITIONS)
327
-          // Optimize one iteration's correction based on the first measurements
328
-          if (z_align_abs) amplification = (iteration == 1) ? _MIN(last_z_align_move[zstepper] / z_align_abs, 2.0f) : z_auto_align_amplification;
329
-
330
-          // Check for less accuracy compared to last move
331
-          if (decreasing_accuracy(last_z_align_move[zstepper], z_align_abs)) {
332
-            if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR("> Z", int(zstepper + 1), " last_z_align_move = ", last_z_align_move[zstepper]);
333
-            if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR("> Z", int(zstepper + 1), " z_align_abs = ", z_align_abs);
334
-            adjustment_reverse = !adjustment_reverse;
335
-          }
345
+        // The following correction actions are to be enabled for select Z-steppers only
346
+        stepper.set_separate_multi_axis(true);
347
+
348
+        bool success_break = true;
349
+        // Correct the individual stepper offsets
350
+        LOOP_L_N(zstepper, NUM_Z_STEPPER_DRIVERS) {
351
+          // Calculate current stepper move
352
+          float z_align_move = z_measured[zstepper] - z_measured_min;
353
+          const float z_align_abs = ABS(z_align_move);
354
+
355
+          #if DISABLED(Z_STEPPER_ALIGN_KNOWN_STEPPER_POSITIONS)
356
+            // Optimize one iteration's correction based on the first measurements
357
+            if (z_align_abs) amplification = (iteration == 1) ? _MIN(last_z_align_move[zstepper] / z_align_abs, 2.0f) : z_auto_align_amplification;
358
+
359
+            // Check for less accuracy compared to last move
360
+            if (decreasing_accuracy(last_z_align_move[zstepper], z_align_abs)) {
361
+              if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR("> Z", int(zstepper + 1), " last_z_align_move = ", last_z_align_move[zstepper]);
362
+              if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR("> Z", int(zstepper + 1), " z_align_abs = ", z_align_abs);
363
+              adjustment_reverse = !adjustment_reverse;
364
+            }
365
+
366
+            // Remember the alignment for the next iteration, but only if steppers move,
367
+            // otherwise it would be just zero (in case this stepper was at z_measured_min already)
368
+            if (z_align_abs > 0) last_z_align_move[zstepper] = z_align_abs;
369
+          #endif
336 370
 
337
-          // Remember the alignment for the next iteration, but only if steppers move,
338
-          // otherwise it would be just zero (in case this stepper was at z_measured_min already)
339
-          if (z_align_abs > 0) last_z_align_move[zstepper] = z_align_abs;
340
-        #endif
371
+          // Stop early if all measured points achieve accuracy target
372
+          if (z_align_abs > z_auto_align_accuracy) success_break = false;
341 373
 
342
-        // Stop early if all measured points achieve accuracy target
343
-        if (z_align_abs > z_auto_align_accuracy) success_break = false;
374
+          if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR("> Z", int(zstepper + 1), " corrected by ", z_align_move);
344 375
 
345
-        if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR("> Z", int(zstepper + 1), " corrected by ", z_align_move);
376
+          // Lock all steppers except one
377
+          stepper.set_all_z_lock(true, zstepper);
346 378
 
347
-        // Lock all steppers except one
348
-        stepper.set_all_z_lock(true, zstepper);
379
+          #if DISABLED(Z_STEPPER_ALIGN_KNOWN_STEPPER_POSITIONS)
380
+            // Decreasing accuracy was detected so move was inverted.
381
+            // Will match reversed Z steppers on dual steppers. Triple will need more work to map.
382
+            if (adjustment_reverse) {
383
+              z_align_move = -z_align_move;
384
+              if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR("> Z", int(zstepper + 1), " correction reversed to ", z_align_move);
385
+            }
386
+          #endif
349 387
 
350
-        #if DISABLED(Z_STEPPER_ALIGN_KNOWN_STEPPER_POSITIONS)
351
-          // Decreasing accuracy was detected so move was inverted.
352
-          // Will match reversed Z steppers on dual steppers. Triple will need more work to map.
353
-          if (adjustment_reverse) {
354
-            z_align_move = -z_align_move;
355
-            if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR("> Z", int(zstepper + 1), " correction reversed to ", z_align_move);
356
-          }
357
-        #endif
388
+          // Do a move to correct part of the misalignment for the current stepper
389
+          do_blocking_move_to_z(amplification * z_align_move + current_position.z);
390
+        } // for (zstepper)
358 391
 
359
-        // Do a move to correct part of the misalignment for the current stepper
360
-        do_blocking_move_to_z(amplification * z_align_move + current_position.z);
361
-      } // for (zstepper)
392
+        // Back to normal stepper operations
393
+        stepper.set_all_z_lock(false);
394
+        stepper.set_separate_multi_axis(false);
362 395
 
363
-      // Back to normal stepper operations
364
-      stepper.set_all_z_lock(false);
365
-      stepper.set_separate_multi_axis(false);
396
+        if (err_break) break;
366 397
 
367
-      if (err_break) break;
398
+        if (success_break) {
399
+          SERIAL_ECHOLNPGM("Target accuracy achieved.");
400
+          LCD_MESSAGEPGM(MSG_ACCURACY_ACHIEVED);
401
+          break;
402
+        }
368 403
 
369
-      if (success_break) {
370
-        SERIAL_ECHOLNPGM("Target accuracy achieved.");
371
-        LCD_MESSAGEPGM(MSG_ACCURACY_ACHIEVED);
372
-        break;
373
-      }
404
+        iteration++;
405
+      } // while (iteration < z_auto_align_iterations)
374 406
 
375
-      iteration++;
376
-    } // while (iteration < z_auto_align_iterations)
407
+      if (err_break)
408
+        SERIAL_ECHOLNPGM("G34 aborted.");
409
+      else {
410
+        SERIAL_ECHOLNPAIR("Did ", int(iteration + (iteration != z_auto_align_iterations)), " of ", int(z_auto_align_iterations));
411
+        SERIAL_ECHOLNPAIR_F("Accuracy: ", z_maxdiff);
412
+      }
377 413
 
378
-    if (err_break)
379
-      SERIAL_ECHOLNPGM("G34 aborted.");
380
-    else {
381
-      SERIAL_ECHOLNPAIR("Did ", int(iteration + (iteration != z_auto_align_iterations)), " of ", int(z_auto_align_iterations));
382
-      SERIAL_ECHOLNPAIR_F("Accuracy: ", z_maxdiff);
383
-    }
414
+      // Stow the probe, as the last call to probe.probe_at_point(...) left
415
+      // the probe deployed if it was successful.
416
+      probe.stow();
384 417
 
385
-    // Stow the probe, as the last call to probe.probe_at_point(...) left
386
-    // the probe deployed if it was successful.
387
-    probe.stow();
388
-
389
-    #if ENABLED(HOME_AFTER_G34)
390
-      // After this operation the z position needs correction
391
-      set_axis_never_homed(Z_AXIS);
392
-      // Home Z after the alignment procedure
393
-      process_subcommands_now_P(PSTR("G28Z"));
394
-    #else
395
-      // Use the probed height from the last iteration to determine the Z height.
396
-      // z_measured_min is used, because all steppers are aligned to z_measured_min.
397
-      // Ideally, this would be equal to the 'z_probe * 0.5f' which was added earlier.
398
-      current_position.z -= z_measured_min - (float)Z_CLEARANCE_BETWEEN_PROBES;
399
-      sync_plan_position();
400
-    #endif
418
+      #if ENABLED(HOME_AFTER_G34)
419
+        // After this operation the z position needs correction
420
+        set_axis_never_homed(Z_AXIS);
421
+        // Home Z after the alignment procedure
422
+        process_subcommands_now_P(PSTR("G28Z"));
423
+      #else
424
+        // Use the probed height from the last iteration to determine the Z height.
425
+        // z_measured_min is used, because all steppers are aligned to z_measured_min.
426
+        // Ideally, this would be equal to the 'z_probe * 0.5f' which was added earlier.
427
+        current_position.z -= z_measured_min - (float)Z_CLEARANCE_BETWEEN_PROBES;
428
+        sync_plan_position();
429
+      #endif
401 430
 
402
-    // Restore the active tool after homing
403
-    TERN_(HAS_MULTI_HOTEND, tool_change(old_tool_index, DISABLED(PARKING_EXTRUDER))); // Fetch previous tool for parking extruder
431
+      // Restore the active tool after homing
432
+      TERN_(HAS_MULTI_HOTEND, tool_change(old_tool_index, DISABLED(PARKING_EXTRUDER))); // Fetch previous tool for parking extruder
404 433
 
405
-    #if BOTH(HAS_LEVELING, RESTORE_LEVELING_AFTER_G34)
406
-      set_bed_leveling_enabled(leveling_was_active);
407
-    #endif
434
+      #if BOTH(HAS_LEVELING, RESTORE_LEVELING_AFTER_G34)
435
+        set_bed_leveling_enabled(leveling_was_active);
436
+      #endif
408 437
 
409
-  }while(0);
438
+    }while(0);
439
+  #endif
410 440
 }
411 441
 
442
+#endif // Z_MULTI_ENDSTOPS || Z_STEPPER_AUTO_ALIGN
443
+
444
+#if ENABLED(Z_STEPPER_AUTO_ALIGN)
445
+
412 446
 /**
413 447
  * M422: Set a Z-Stepper automatic alignment XY point.
414 448
  *       Use repeatedly to set multiple points.

+ 1
- 1
Marlin/src/gcode/gcode.cpp ファイルの表示

@@ -327,7 +327,7 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
327 327
         case 33: G33(); break;                                    // G33: Delta Auto-Calibration
328 328
       #endif
329 329
 
330
-      #if EITHER(Z_STEPPER_AUTO_ALIGN, MECHANICAL_GANTRY_CALIBRATION)
330
+      #if ANY(Z_MULTI_ENDSTOPS, Z_STEPPER_AUTO_ALIGN, MECHANICAL_GANTRY_CALIBRATION)
331 331
         case 34: G34(); break;                                    // G34: Z Stepper automatic alignment using probe
332 332
       #endif
333 333
 

+ 1
- 1
Marlin/src/gcode/gcode.h ファイルの表示

@@ -468,7 +468,7 @@ private:
468 468
 
469 469
   TERN_(DELTA_AUTO_CALIBRATION, static void G33());
470 470
 
471
-  #if EITHER(Z_STEPPER_AUTO_ALIGN, MECHANICAL_GANTRY_CALIBRATION)
471
+  #if ANY(Z_MULTI_ENDSTOPS, Z_STEPPER_AUTO_ALIGN, MECHANICAL_GANTRY_CALIBRATION)
472 472
     static void G34();
473 473
   #endif
474 474
 

+ 5
- 2
Marlin/src/inc/SanityCheck.h ファイルの表示

@@ -2792,8 +2792,11 @@ static_assert(   _ARR_TEST(3,0) && _ARR_TEST(3,1) && _ARR_TEST(3,2)
2792 2792
     #error "Z_STEPPER_AUTO_ALIGN requires NUM_Z_STEPPER_DRIVERS greater than 1."
2793 2793
   #elif !HAS_BED_PROBE
2794 2794
     #error "Z_STEPPER_AUTO_ALIGN requires a Z-bed probe."
2795
-  #elif ENABLED(Z_STEPPER_ALIGN_KNOWN_STEPPER_POSITIONS) && NUM_Z_STEPPER_DRIVERS < 3
2796
-    #error "Z_STEPPER_ALIGN_KNOWN_STEPPER_POSITIONS requires NUM_Z_STEPPER_DRIVERS to be 3 or 4."
2795
+  #elif ENABLED(Z_STEPPER_ALIGN_KNOWN_STEPPER_POSITIONS)
2796
+    static_assert(WITHIN(Z_STEPPER_ALIGN_AMP, 0.5, 2.0), "Z_STEPPER_ALIGN_AMP must be between 0.5 and 2.0.");
2797
+    #if NUM_Z_STEPPER_DRIVERS < 3
2798
+      #error "Z_STEPPER_ALIGN_KNOWN_STEPPER_POSITIONS requires NUM_Z_STEPPER_DRIVERS to be 3 or 4."
2799
+    #endif
2797 2800
   #endif
2798 2801
 #endif
2799 2802
 

+ 1
- 0
platformio.ini ファイルの表示

@@ -316,6 +316,7 @@ EXT_SOLENOID|MANUAL_SOLENOID_CONTROL = src_filter=+<src/feature/solenoid.cpp> +<
316 316
 HAS_CUTTER              = src_filter=+<src/feature/spindle_laser.cpp> +<src/gcode/control/M3-M5.cpp>
317 317
 EXPERIMENTAL_I2CBUS     = src_filter=+<src/feature/twibus.cpp> +<src/gcode/feature/i2c>
318 318
 MECHANICAL_GANTRY_CAL.+ = src_filter=+<src/gcode/calibrate/G34.cpp>
319
+Z_MULTI_ENDSTOPS        = src_filter=+<src/gcode/calibrate/G34_M422.cpp>
319 320
 Z_STEPPER_AUTO_ALIGN    = src_filter=+<src/feature/z_stepper_align.cpp> +<src/gcode/calibrate/G34_M422.cpp>
320 321
 G26_MESH_VALIDATION     = src_filter=+<src/gcode/bedlevel/G26.cpp>
321 322
 ASSISTED_TRAMMING       = src_filter=+<src/gcode/bedlevel/G35.cpp>

読み込み中…
キャンセル
保存