瀏覽代碼

Merge pull request #8730 from thinkyhead/bf2_fixup_ubl

[2.0.x] UBL - Skew and Dual X Carriage
Scott Lahteine 7 年之前
父節點
當前提交
c555a214d2
沒有連結到貢獻者的電子郵件帳戶。

+ 4
- 3
.travis.yml 查看文件

79
   - opt_set TEMP_SENSOR_3 20
79
   - opt_set TEMP_SENSOR_3 20
80
   - opt_set TEMP_SENSOR_4 999
80
   - opt_set TEMP_SENSOR_4 999
81
   - opt_set TEMP_SENSOR_BED 1
81
   - opt_set TEMP_SENSOR_BED 1
82
-  - opt_enable AUTO_BED_LEVELING_UBL DEBUG_LEVELING_FEATURE G26_MESH_EDITING ENABLE_LEVELING_FADE_HEIGHT EEPROM_SETTINGS EEPROM_CHITCHAT G3D_PANEL
82
+  - opt_enable AUTO_BED_LEVELING_UBL DEBUG_LEVELING_FEATURE G26_MESH_EDITING ENABLE_LEVELING_FADE_HEIGHT EEPROM_SETTINGS EEPROM_CHITCHAT G3D_PANEL SKEW_CORRECTION
83
   - opt_enable_adv CUSTOM_USER_MENUS I2C_POSITION_ENCODERS BABYSTEPPING LIN_ADVANCE NANODLP_Z_SYNC
83
   - opt_enable_adv CUSTOM_USER_MENUS I2C_POSITION_ENCODERS BABYSTEPPING LIN_ADVANCE NANODLP_Z_SYNC
84
   - build_marlin_pio ${TRAVIS_BUILD_DIR} ${TEST_PLATFORM}
84
   - build_marlin_pio ${TRAVIS_BUILD_DIR} ${TEST_PLATFORM}
85
   #
85
   #
86
-  # And with a Sled Z Probe
86
+  # Add a Sled Z Probe, do non-segmented moves
87
   #
87
   #
88
   - opt_enable Z_PROBE_SLED
88
   - opt_enable Z_PROBE_SLED
89
+  - opt_disable SEGMENT_LEVELED_MOVES
89
   - opt_enable_adv BABYSTEP_ZPROBE_OFFSET DOUBLECLICK_FOR_Z_BABYSTEPPING
90
   - opt_enable_adv BABYSTEP_ZPROBE_OFFSET DOUBLECLICK_FOR_Z_BABYSTEPPING
90
   - build_marlin_pio ${TRAVIS_BUILD_DIR} ${TEST_PLATFORM}
91
   - build_marlin_pio ${TRAVIS_BUILD_DIR} ${TEST_PLATFORM}
91
   #
92
   #
121
   - opt_enable ULTIMAKERCONTROLLER SDSUPPORT
122
   - opt_enable ULTIMAKERCONTROLLER SDSUPPORT
122
   - opt_enable PRINTCOUNTER NOZZLE_PARK_FEATURE NOZZLE_CLEAN_FEATURE PCA9632 USE_XMAX_PLUG
123
   - opt_enable PRINTCOUNTER NOZZLE_PARK_FEATURE NOZZLE_CLEAN_FEATURE PCA9632 USE_XMAX_PLUG
123
   - opt_enable_adv BEZIER_CURVE_SUPPORT EXPERIMENTAL_I2CBUS
124
   - opt_enable_adv BEZIER_CURVE_SUPPORT EXPERIMENTAL_I2CBUS
124
-  - opt_enable_adv ADVANCED_PAUSE_FEATURE PARK_HEAD_ON_PAUSE LCD_INFO_MENU
125
+  - opt_enable_adv ADVANCED_PAUSE_FEATURE PARK_HEAD_ON_PAUSE LCD_INFO_MENU M114_DETAIL
125
   - opt_set_adv PWM_MOTOR_CURRENT {1300,1300,1250}
126
   - opt_set_adv PWM_MOTOR_CURRENT {1300,1300,1250}
126
   - opt_set_adv I2C_SLAVE_ADDRESS 63
127
   - opt_set_adv I2C_SLAVE_ADDRESS 63
127
   - build_marlin_pio ${TRAVIS_BUILD_DIR} ${TEST_PLATFORM}
128
   - build_marlin_pio ${TRAVIS_BUILD_DIR} ${TEST_PLATFORM}

+ 54
- 1
Marlin/src/feature/bedlevel/ubl/ubl.cpp 查看文件

55
     safe_delay(10);
55
     safe_delay(10);
56
   }
56
   }
57
 
57
 
58
+  #if ENABLED(UBL_DEVEL_DEBUGGING)
59
+
60
+    static void debug_echo_axis(const AxisEnum axis) {
61
+      if (current_position[axis] == destination[axis])
62
+        SERIAL_ECHOPGM("-------------");
63
+      else
64
+        SERIAL_ECHO_F(destination[X_AXIS], 6);
65
+    }
66
+
67
+    void debug_current_and_destination(const char *title) {
68
+
69
+      // if the title message starts with a '!' it is so important, we are going to
70
+      // ignore the status of the g26_debug_flag
71
+      if (*title != '!' && !g26_debug_flag) return;
72
+
73
+      const float de = destination[E_AXIS] - current_position[E_AXIS];
74
+
75
+      if (de == 0.0) return; // Printing moves only
76
+
77
+      const float dx = destination[X_AXIS] - current_position[X_AXIS],
78
+                  dy = destination[Y_AXIS] - current_position[Y_AXIS],
79
+                  xy_dist = HYPOT(dx, dy);
80
+
81
+      if (xy_dist == 0.0) return;
82
+
83
+      SERIAL_ECHOPGM("   fpmm=");
84
+      const float fpmm = de / xy_dist;
85
+      SERIAL_ECHO_F(fpmm, 6);
86
+
87
+      SERIAL_ECHOPGM("    current=( ");
88
+      SERIAL_ECHO_F(current_position[X_AXIS], 6);
89
+      SERIAL_ECHOPGM(", ");
90
+      SERIAL_ECHO_F(current_position[Y_AXIS], 6);
91
+      SERIAL_ECHOPGM(", ");
92
+      SERIAL_ECHO_F(current_position[Z_AXIS], 6);
93
+      SERIAL_ECHOPGM(", ");
94
+      SERIAL_ECHO_F(current_position[E_AXIS], 6);
95
+      SERIAL_ECHOPGM(" )   destination=( ");
96
+      debug_echo_axis(X_AXIS);
97
+      SERIAL_ECHOPGM(", ");
98
+      debug_echo_axis(Y_AXIS);
99
+      SERIAL_ECHOPGM(", ");
100
+      debug_echo_axis(Z_AXIS);
101
+      SERIAL_ECHOPGM(", ");
102
+      debug_echo_axis(E_AXIS);
103
+      SERIAL_ECHOPGM(" )   ");
104
+      SERIAL_ECHO(title);
105
+      SERIAL_EOL();
106
+
107
+    }
108
+
109
+  #endif // UBL_DEVEL_DEBUGGING
110
+
58
   int8_t unified_bed_leveling::storage_slot;
111
   int8_t unified_bed_leveling::storage_slot;
59
 
112
 
60
   float unified_bed_leveling::z_values[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y];
113
   float unified_bed_leveling::z_values[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y];
178
     uint8_t error_flag = 0;
231
     uint8_t error_flag = 0;
179
 
232
 
180
     if (settings.calc_num_meshes() < 1) {
233
     if (settings.calc_num_meshes() < 1) {
181
-      SERIAL_PROTOCOLLNPGM("?Insufficient EEPROM storage for a mesh of this size.");
234
+      SERIAL_PROTOCOLLNPGM("?Mesh too big for EEPROM.");
182
       error_flag++;
235
       error_flag++;
183
     }
236
     }
184
 
237
 

+ 18
- 9
Marlin/src/feature/bedlevel/ubl/ubl.h 查看文件

23
 #ifndef UNIFIED_BED_LEVELING_H
23
 #ifndef UNIFIED_BED_LEVELING_H
24
 #define UNIFIED_BED_LEVELING_H
24
 #define UNIFIED_BED_LEVELING_H
25
 
25
 
26
+//#define UBL_DEVEL_DEBUGGING
27
+
26
 #include "../bedlevel.h"
28
 #include "../bedlevel.h"
27
 #include "../../../module/planner.h"
29
 #include "../../../module/planner.h"
28
 #include "../../../module/motion.h"
30
 #include "../../../module/motion.h"
37
 
39
 
38
 // ubl_motion.cpp
40
 // ubl_motion.cpp
39
 
41
 
40
-void debug_current_and_destination(const char * const title);
42
+#if ENABLED(UBL_DEVEL_DEBUGGING)
43
+  void debug_current_and_destination(const char * const title);
44
+#else
45
+  FORCE_INLINE void debug_current_and_destination(const char * const title) { UNUSED(title); }
46
+#endif
41
 
47
 
42
 // ubl_G29.cpp
48
 // ubl_G29.cpp
43
 
49
 
217
       const float xratio = (rx0 - mesh_index_to_xpos(x1_i)) * (1.0 / (MESH_X_DIST)),
223
       const float xratio = (rx0 - mesh_index_to_xpos(x1_i)) * (1.0 / (MESH_X_DIST)),
218
                   z1 = z_values[x1_i][yi];
224
                   z1 = z_values[x1_i][yi];
219
 
225
 
220
-      return z1 + xratio * (z_values[min(x1_i, GRID_MAX_POINTS_X - 2) + 1][yi] - z1);  // Don't allow x1_i+1 to be past the end of the array
221
-                                                                                       // If it is, it is clamped to the last element of the 
222
-                                                                                       // z_values[][] array and no correction is applied.
226
+      return z1 + xratio * (z_values[min(x1_i, GRID_MAX_POINTS_X - 2) + 1][yi] - z1); // Don't allow x1_i+1 to be past the end of the array
227
+                                                                                      // If it is, it is clamped to the last element of the
228
+                                                                                      // z_values[][] array and no correction is applied.
223
     }
229
     }
224
 
230
 
225
     //
231
     //
243
       const float yratio = (ry0 - mesh_index_to_ypos(y1_i)) * (1.0 / (MESH_Y_DIST)),
249
       const float yratio = (ry0 - mesh_index_to_ypos(y1_i)) * (1.0 / (MESH_Y_DIST)),
244
                   z1 = z_values[xi][y1_i];
250
                   z1 = z_values[xi][y1_i];
245
 
251
 
246
-      return z1 + yratio * (z_values[xi][min(y1_i, GRID_MAX_POINTS_Y - 2) + 1] - z1);  // Don't allow y1_i+1 to be past the end of the array
247
-                                                                                       // If it is, it is clamped to the last element of the 
248
-                                                                                       // z_values[][] array and no correction is applied.
252
+      return z1 + yratio * (z_values[xi][min(y1_i, GRID_MAX_POINTS_Y - 2) + 1] - z1); // Don't allow y1_i+1 to be past the end of the array
253
+                                                                                      // If it is, it is clamped to the last element of the
254
+                                                                                      // z_values[][] array and no correction is applied.
249
     }
255
     }
250
 
256
 
251
     /**
257
     /**
315
       return i < GRID_MAX_POINTS_Y ? pgm_read_float(&_mesh_index_to_ypos[i]) : MESH_MIN_Y + i * (MESH_Y_DIST);
321
       return i < GRID_MAX_POINTS_Y ? pgm_read_float(&_mesh_index_to_ypos[i]) : MESH_MIN_Y + i * (MESH_Y_DIST);
316
     }
322
     }
317
 
323
 
318
-    static bool prepare_segmented_line_to(const float rtarget[XYZE], const float &feedrate);
319
-    static void line_to_destination_cartesian(const float &fr, uint8_t e);
324
+    #if UBL_SEGMENTED
325
+      static bool prepare_segmented_line_to(const float (&rtarget)[XYZE], const float &feedrate);
326
+    #else
327
+      static void line_to_destination_cartesian(const float &fr, const uint8_t e);
328
+    #endif
320
 
329
 
321
     #define _CMPZ(a,b) (z_values[a][b] == z_values[a][b+1])
330
     #define _CMPZ(a,b) (z_values[a][b] == z_values[a][b+1])
322
     #define CMPZ(a) (_CMPZ(a, 0) && _CMPZ(a, 1))
331
     #define CMPZ(a) (_CMPZ(a, 0) && _CMPZ(a, 1))

+ 213
- 265
Marlin/src/feature/bedlevel/ubl/ubl_motion.cpp 查看文件

23
 
23
 
24
 #if ENABLED(AUTO_BED_LEVELING_UBL)
24
 #if ENABLED(AUTO_BED_LEVELING_UBL)
25
 
25
 
26
-  #include "../bedlevel.h"
27
-  #include "../../../module/planner.h"
28
-  #include "../../../module/stepper.h"
29
-  #include "../../../module/motion.h"
26
+#include "../bedlevel.h"
27
+#include "../../../module/planner.h"
28
+#include "../../../module/stepper.h"
29
+#include "../../../module/motion.h"
30
 
30
 
31
-  #if ENABLED(DELTA)
32
-    #include "../../../module/delta.h"
33
-  #endif
34
-
35
-  #include "../../../Marlin.h"
36
-  #include <math.h>
37
-
38
-  extern float destination[XYZE];
39
-
40
-  #if AVR_AT90USB1286_FAMILY  // Teensyduino & Printrboard IDE extensions have compile errors without this
41
-    inline void set_current_from_destination() { COPY(current_position, destination); }
42
-  #else
43
-    extern void set_current_from_destination();
44
-  #endif
31
+#if ENABLED(DELTA)
32
+  #include "../../../module/delta.h"
33
+#endif
45
 
34
 
46
-  static void debug_echo_axis(const AxisEnum axis) {
47
-    if (current_position[axis] == destination[axis])
48
-      SERIAL_ECHOPGM("-------------");
49
-    else
50
-      SERIAL_ECHO_F(destination[X_AXIS], 6);
51
-  }
35
+#include "../../../Marlin.h"
36
+#include <math.h>
52
 
37
 
53
-  void debug_current_and_destination(const char *title) {
54
-
55
-    // if the title message starts with a '!' it is so important, we are going to
56
-    // ignore the status of the g26_debug_flag
57
-    if (*title != '!' && !g26_debug_flag) return;
58
-
59
-    const float de = destination[E_AXIS] - current_position[E_AXIS];
60
-
61
-    if (de == 0.0) return; // Printing moves only
62
-
63
-    const float dx = destination[X_AXIS] - current_position[X_AXIS],
64
-                dy = destination[Y_AXIS] - current_position[Y_AXIS],
65
-                xy_dist = HYPOT(dx, dy);
66
-
67
-    if (xy_dist == 0.0) return;
68
-
69
-    SERIAL_ECHOPGM("   fpmm=");
70
-    const float fpmm = de / xy_dist;
71
-    SERIAL_ECHO_F(fpmm, 6);
72
-
73
-    SERIAL_ECHOPGM("    current=( ");
74
-    SERIAL_ECHO_F(current_position[X_AXIS], 6);
75
-    SERIAL_ECHOPGM(", ");
76
-    SERIAL_ECHO_F(current_position[Y_AXIS], 6);
77
-    SERIAL_ECHOPGM(", ");
78
-    SERIAL_ECHO_F(current_position[Z_AXIS], 6);
79
-    SERIAL_ECHOPGM(", ");
80
-    SERIAL_ECHO_F(current_position[E_AXIS], 6);
81
-    SERIAL_ECHOPGM(" )   destination=( ");
82
-    debug_echo_axis(X_AXIS);
83
-    SERIAL_ECHOPGM(", ");
84
-    debug_echo_axis(Y_AXIS);
85
-    SERIAL_ECHOPGM(", ");
86
-    debug_echo_axis(Z_AXIS);
87
-    SERIAL_ECHOPGM(", ");
88
-    debug_echo_axis(E_AXIS);
89
-    SERIAL_ECHOPGM(" )   ");
90
-    SERIAL_ECHO(title);
91
-    SERIAL_EOL();
38
+#if AVR_AT90USB1286_FAMILY  // Teensyduino & Printrboard IDE extensions have compile errors without this
39
+  inline void set_current_from_destination() { COPY(current_position, destination); }
40
+#else
41
+  extern void set_current_from_destination();
42
+#endif
92
 
43
 
93
-  }
44
+#if !UBL_SEGMENTED
94
 
45
 
95
-  void unified_bed_leveling::line_to_destination_cartesian(const float &feed_rate, uint8_t extruder) {
46
+  void unified_bed_leveling::line_to_destination_cartesian(const float &feed_rate, const uint8_t extruder) {
96
     /**
47
     /**
97
      * Much of the nozzle movement will be within the same cell. So we will do as little computation
48
      * Much of the nozzle movement will be within the same cell. So we will do as little computation
98
      * as possible to determine if this is the case. If this move is within the same cell, we will
49
      * as possible to determine if this is the case. If this move is within the same cell, we will
99
      * just do the required Z-Height correction, call the Planner's buffer_line() routine, and leave
50
      * just do the required Z-Height correction, call the Planner's buffer_line() routine, and leave
100
      */
51
      */
101
-    const float start[XYZE] = {
102
-                  current_position[X_AXIS],
103
-                  current_position[Y_AXIS],
104
-                  current_position[Z_AXIS],
105
-                  current_position[E_AXIS]
106
-                },
107
-                end[XYZE] = {
108
-                  destination[X_AXIS],
109
-                  destination[Y_AXIS],
110
-                  destination[Z_AXIS],
111
-                  destination[E_AXIS]
112
-                };
52
+    #if ENABLED(SKEW_CORRECTION)
53
+      // For skew correction just adjust the destination point and we're done
54
+      float start[XYZE] = { current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS] },
55
+            end[XYZE] = { destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS] };
56
+      planner.skew(start[X_AXIS], start[Y_AXIS], start[Z_AXIS]);
57
+      planner.skew(end[X_AXIS], end[Y_AXIS], end[Z_AXIS]);
58
+    #else
59
+      const float (&start)[XYZE] = current_position,
60
+                    (&end)[XYZE] = destination;
61
+    #endif
113
 
62
 
114
     const int cell_start_xi = get_cell_index_x(start[X_AXIS]),
63
     const int cell_start_xi = get_cell_index_x(start[X_AXIS]),
115
               cell_start_yi = get_cell_index_y(start[Y_AXIS]),
64
               cell_start_yi = get_cell_index_y(start[Y_AXIS]),
117
               cell_dest_yi  = get_cell_index_y(end[Y_AXIS]);
66
               cell_dest_yi  = get_cell_index_y(end[Y_AXIS]);
118
 
67
 
119
     if (g26_debug_flag) {
68
     if (g26_debug_flag) {
120
-      SERIAL_ECHOPAIR(" ubl.line_to_destination(xe=", end[X_AXIS]);
121
-      SERIAL_ECHOPAIR(", ye=", end[Y_AXIS]);
122
-      SERIAL_ECHOPAIR(", ze=", end[Z_AXIS]);
123
-      SERIAL_ECHOPAIR(", ee=", end[E_AXIS]);
69
+      SERIAL_ECHOPAIR(" ubl.line_to_destination_cartesian(xe=", destination[X_AXIS]);
70
+      SERIAL_ECHOPAIR(", ye=", destination[Y_AXIS]);
71
+      SERIAL_ECHOPAIR(", ze=", destination[Z_AXIS]);
72
+      SERIAL_ECHOPAIR(", ee=", destination[E_AXIS]);
124
       SERIAL_CHAR(')');
73
       SERIAL_CHAR(')');
125
       SERIAL_EOL();
74
       SERIAL_EOL();
126
-      debug_current_and_destination(PSTR("Start of ubl.line_to_destination()"));
75
+      debug_current_and_destination(PSTR("Start of ubl.line_to_destination_cartesian()"));
127
     }
76
     }
128
 
77
 
129
     if (cell_start_xi == cell_dest_xi && cell_start_yi == cell_dest_yi) { // if the whole move is within the same cell,
78
     if (cell_start_xi == cell_dest_xi && cell_start_yi == cell_dest_yi) { // if the whole move is within the same cell,
139
         // Note: There is no Z Correction in this case. We are off the grid and don't know what
88
         // Note: There is no Z Correction in this case. We are off the grid and don't know what
140
         // a reasonable correction would be.
89
         // a reasonable correction would be.
141
 
90
 
142
-        planner._buffer_line(end[X_AXIS], end[Y_AXIS], end[Z_AXIS], end[E_AXIS], feed_rate, extruder);
91
+        planner.buffer_segment(end[X_AXIS], end[Y_AXIS], end[Z_AXIS], end[E_AXIS], feed_rate, extruder);
143
         set_current_from_destination();
92
         set_current_from_destination();
144
 
93
 
145
         if (g26_debug_flag)
94
         if (g26_debug_flag)
146
-          debug_current_and_destination(PSTR("out of bounds in ubl.line_to_destination()"));
95
+          debug_current_and_destination(PSTR("out of bounds in ubl.line_to_destination_cartesian()"));
147
 
96
 
148
         return;
97
         return;
149
       }
98
       }
183
        */
132
        */
184
       if (isnan(z0)) z0 = 0.0;
133
       if (isnan(z0)) z0 = 0.0;
185
 
134
 
186
-      planner._buffer_line(end[X_AXIS], end[Y_AXIS], end[Z_AXIS] + z0, end[E_AXIS], feed_rate, extruder);
135
+      planner.buffer_segment(end[X_AXIS], end[Y_AXIS], end[Z_AXIS] + z0, end[E_AXIS], feed_rate, extruder);
187
 
136
 
188
       if (g26_debug_flag)
137
       if (g26_debug_flag)
189
-        debug_current_and_destination(PSTR("FINAL_MOVE in ubl.line_to_destination()"));
138
+        debug_current_and_destination(PSTR("FINAL_MOVE in ubl.line_to_destination_cartesian()"));
190
 
139
 
191
       set_current_from_destination();
140
       set_current_from_destination();
192
       return;
141
       return;
274
          * Without this check, it is possible for the algorithm to generate a zero length move in the case
223
          * Without this check, it is possible for the algorithm to generate a zero length move in the case
275
          * where the line is heading down and it is starting right on a Mesh Line boundary. For how often that
224
          * where the line is heading down and it is starting right on a Mesh Line boundary. For how often that
276
          * happens, it might be best to remove the check and always 'schedule' the move because
225
          * happens, it might be best to remove the check and always 'schedule' the move because
277
-         * the planner._buffer_line() routine will filter it if that happens.
226
+         * the planner.buffer_segment() routine will filter it if that happens.
278
          */
227
          */
279
         if (ry != start[Y_AXIS]) {
228
         if (ry != start[Y_AXIS]) {
280
           if (!inf_normalized_flag) {
229
           if (!inf_normalized_flag) {
287
             z_position = end[Z_AXIS];
236
             z_position = end[Z_AXIS];
288
           }
237
           }
289
 
238
 
290
-          planner._buffer_line(rx, ry, z_position + z0, e_position, feed_rate, extruder);
239
+          planner.buffer_segment(rx, ry, z_position + z0, e_position, feed_rate, extruder);
291
         } //else printf("FIRST MOVE PRUNED  ");
240
         } //else printf("FIRST MOVE PRUNED  ");
292
       }
241
       }
293
 
242
 
294
       if (g26_debug_flag)
243
       if (g26_debug_flag)
295
-        debug_current_and_destination(PSTR("vertical move done in ubl.line_to_destination()"));
244
+        debug_current_and_destination(PSTR("vertical move done in ubl.line_to_destination_cartesian()"));
296
 
245
 
297
       //
246
       //
298
       // Check if we are at the final destination. Usually, we won't be, but if it is on a Y Mesh Line, we are done.
247
       // Check if we are at the final destination. Usually, we won't be, but if it is on a Y Mesh Line, we are done.
338
          * Without this check, it is possible for the algorithm to generate a zero length move in the case
287
          * Without this check, it is possible for the algorithm to generate a zero length move in the case
339
          * where the line is heading left and it is starting right on a Mesh Line boundary. For how often
288
          * where the line is heading left and it is starting right on a Mesh Line boundary. For how often
340
          * that happens, it might be best to remove the check and always 'schedule' the move because
289
          * that happens, it might be best to remove the check and always 'schedule' the move because
341
-         * the planner._buffer_line() routine will filter it if that happens.
290
+         * the planner.buffer_segment() routine will filter it if that happens.
342
          */
291
          */
343
         if (rx != start[X_AXIS]) {
292
         if (rx != start[X_AXIS]) {
344
           if (!inf_normalized_flag) {
293
           if (!inf_normalized_flag) {
351
             z_position = end[Z_AXIS];
300
             z_position = end[Z_AXIS];
352
           }
301
           }
353
 
302
 
354
-          planner._buffer_line(rx, ry, z_position + z0, e_position, feed_rate, extruder);
303
+          planner.buffer_segment(rx, ry, z_position + z0, e_position, feed_rate, extruder);
355
         } //else printf("FIRST MOVE PRUNED  ");
304
         } //else printf("FIRST MOVE PRUNED  ");
356
       }
305
       }
357
 
306
 
358
       if (g26_debug_flag)
307
       if (g26_debug_flag)
359
-        debug_current_and_destination(PSTR("horizontal move done in ubl.line_to_destination()"));
308
+        debug_current_and_destination(PSTR("horizontal move done in ubl.line_to_destination_cartesian()"));
360
 
309
 
361
       if (current_position[X_AXIS] != end[X_AXIS] || current_position[Y_AXIS] != end[Y_AXIS])
310
       if (current_position[X_AXIS] != end[X_AXIS] || current_position[Y_AXIS] != end[Y_AXIS])
362
         goto FINAL_MOVE;
311
         goto FINAL_MOVE;
413
           e_position = end[E_AXIS];
362
           e_position = end[E_AXIS];
414
           z_position = end[Z_AXIS];
363
           z_position = end[Z_AXIS];
415
         }
364
         }
416
-        planner._buffer_line(rx, next_mesh_line_y, z_position + z0, e_position, feed_rate, extruder);
365
+        planner.buffer_segment(rx, next_mesh_line_y, z_position + z0, e_position, feed_rate, extruder);
417
         current_yi += dyi;
366
         current_yi += dyi;
418
         yi_cnt--;
367
         yi_cnt--;
419
       }
368
       }
441
           z_position = end[Z_AXIS];
390
           z_position = end[Z_AXIS];
442
         }
391
         }
443
 
392
 
444
-        planner._buffer_line(next_mesh_line_x, ry, z_position + z0, e_position, feed_rate, extruder);
393
+        planner.buffer_segment(next_mesh_line_x, ry, z_position + z0, e_position, feed_rate, extruder);
445
         current_xi += dxi;
394
         current_xi += dxi;
446
         xi_cnt--;
395
         xi_cnt--;
447
       }
396
       }
450
     }
399
     }
451
 
400
 
452
     if (g26_debug_flag)
401
     if (g26_debug_flag)
453
-      debug_current_and_destination(PSTR("generic move done in ubl.line_to_destination()"));
402
+      debug_current_and_destination(PSTR("generic move done in ubl.line_to_destination_cartesian()"));
454
 
403
 
455
     if (current_position[X_AXIS] != end[X_AXIS] || current_position[Y_AXIS] != end[Y_AXIS])
404
     if (current_position[X_AXIS] != end[X_AXIS] || current_position[Y_AXIS] != end[Y_AXIS])
456
       goto FINAL_MOVE;
405
       goto FINAL_MOVE;
458
     set_current_from_destination();
407
     set_current_from_destination();
459
   }
408
   }
460
 
409
 
461
-  #if UBL_DELTA
410
+#else // UBL_SEGMENTED
462
 
411
 
463
-    // macro to inline copy exactly 4 floats, don't rely on sizeof operator
464
-    #define COPY_XYZE( target, source ) { \
465
-                target[X_AXIS] = source[X_AXIS]; \
466
-                target[Y_AXIS] = source[Y_AXIS]; \
467
-                target[Z_AXIS] = source[Z_AXIS]; \
468
-                target[E_AXIS] = source[E_AXIS]; \
469
-            }
412
+  #if IS_SCARA // scale the feed rate from mm/s to degrees/s
413
+    static float scara_feed_factor, scara_oldA, scara_oldB;
414
+  #endif
470
 
415
 
471
-    #if IS_SCARA // scale the feed rate from mm/s to degrees/s
472
-      static float scara_feed_factor, scara_oldA, scara_oldB;
473
-    #endif
416
+  // We don't want additional apply_leveling() performed by regular buffer_line or buffer_line_kinematic,
417
+  // so we call buffer_segment directly here.  Per-segmented leveling and kinematics performed first.
474
 
418
 
475
-    // We don't want additional apply_leveling() performed by regular buffer_line or buffer_line_kinematic,
476
-    // so we call _buffer_line directly here.  Per-segmented leveling and kinematics performed first.
419
+  inline void _O2 ubl_buffer_segment_raw(const float (&in_raw)[XYZE], const float &fr) {
477
 
420
 
478
-    inline void _O2 ubl_buffer_segment_raw(const float raw[XYZE], const float &fr) {
421
+    #if ENABLED(SKEW_CORRECTION)
422
+      float raw[XYZE] = { in_raw[X_AXIS], in_raw[Y_AXIS], in_raw[Z_AXIS] };
423
+      planner.skew(raw[X_AXIS], raw[Y_AXIS], raw[Z_AXIS]);
424
+    #else
425
+      const float (&raw)[XYZE] = in_raw;
426
+    #endif
479
 
427
 
480
-      #if ENABLED(DELTA)  // apply delta inverse_kinematics
428
+    #if ENABLED(DELTA)  // apply delta inverse_kinematics
481
 
429
 
482
-        DELTA_RAW_IK();
483
-        planner._buffer_line(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], raw[E_AXIS], fr, active_extruder);
430
+      DELTA_RAW_IK();
431
+      planner.buffer_segment(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], in_raw[E_AXIS], fr, active_extruder);
484
 
432
 
485
-      #elif IS_SCARA  // apply scara inverse_kinematics (should be changed to save raw->logical->raw)
433
+    #elif IS_SCARA  // apply scara inverse_kinematics (should be changed to save raw->logical->raw)
486
 
434
 
487
-        inverse_kinematics(raw);  // this writes delta[ABC] from raw[XYZE]
488
-                                  // should move the feedrate scaling to scara inverse_kinematics
435
+      inverse_kinematics(raw);  // this writes delta[ABC] from raw[XYZE]
436
+                                // should move the feedrate scaling to scara inverse_kinematics
489
 
437
 
490
-        const float adiff = FABS(delta[A_AXIS] - scara_oldA),
491
-                    bdiff = FABS(delta[B_AXIS] - scara_oldB);
492
-        scara_oldA = delta[A_AXIS];
493
-        scara_oldB = delta[B_AXIS];
494
-        float s_feedrate = max(adiff, bdiff) * scara_feed_factor;
438
+      const float adiff = FABS(delta[A_AXIS] - scara_oldA),
439
+                  bdiff = FABS(delta[B_AXIS] - scara_oldB);
440
+      scara_oldA = delta[A_AXIS];
441
+      scara_oldB = delta[B_AXIS];
442
+      float s_feedrate = max(adiff, bdiff) * scara_feed_factor;
495
 
443
 
496
-        planner._buffer_line(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], raw[E_AXIS], s_feedrate, active_extruder);
444
+      planner.buffer_segment(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], in_raw[E_AXIS], s_feedrate, active_extruder);
497
 
445
 
498
-      #else // CARTESIAN
446
+    #else // CARTESIAN
499
 
447
 
500
-        planner._buffer_line(raw[X_AXIS], raw[Y_AXIS], raw[Z_AXIS], raw[E_AXIS], fr, active_extruder);
448
+      planner.buffer_segment(raw[X_AXIS], raw[Y_AXIS], raw[Z_AXIS], in_raw[E_AXIS], fr, active_extruder);
501
 
449
 
502
-      #endif
503
-    }
450
+    #endif
451
+  }
504
 
452
 
505
-    #if IS_SCARA
506
-      #define DELTA_SEGMENT_MIN_LENGTH 0.25 // SCARA minimum segment size is 0.25mm
507
-    #elif ENABLED(DELTA)
508
-      #define DELTA_SEGMENT_MIN_LENGTH 0.10 // mm (still subject to DELTA_SEGMENTS_PER_SECOND)
509
-    #else // CARTESIAN
510
-      #ifdef LEVELED_SEGMENT_LENGTH
511
-        #define DELTA_SEGMENT_MIN_LENGTH LEVELED_SEGMENT_LENGTH
512
-      #else
513
-        #define DELTA_SEGMENT_MIN_LENGTH 1.00 // mm (similar to G2/G3 arc segmentation)
514
-      #endif
453
+  #if IS_SCARA
454
+    #define DELTA_SEGMENT_MIN_LENGTH 0.25 // SCARA minimum segment size is 0.25mm
455
+  #elif ENABLED(DELTA)
456
+    #define DELTA_SEGMENT_MIN_LENGTH 0.10 // mm (still subject to DELTA_SEGMENTS_PER_SECOND)
457
+  #else // CARTESIAN
458
+    #ifdef LEVELED_SEGMENT_LENGTH
459
+      #define DELTA_SEGMENT_MIN_LENGTH LEVELED_SEGMENT_LENGTH
460
+    #else
461
+      #define DELTA_SEGMENT_MIN_LENGTH 1.00 // mm (similar to G2/G3 arc segmentation)
515
     #endif
462
     #endif
463
+  #endif
516
 
464
 
517
-    /**
518
-     * Prepare a segmented linear move for DELTA/SCARA/CARTESIAN with UBL and FADE semantics.
519
-     * This calls planner._buffer_line multiple times for small incremental moves.
520
-     * Returns true if did NOT move, false if moved (requires current_position update).
521
-     */
465
+  /**
466
+   * Prepare a segmented linear move for DELTA/SCARA/CARTESIAN with UBL and FADE semantics.
467
+   * This calls planner.buffer_segment multiple times for small incremental moves.
468
+   * Returns true if did NOT move, false if moved (requires current_position update).
469
+   */
470
+
471
+  bool _O2 unified_bed_leveling::prepare_segmented_line_to(const float (&rtarget)[XYZE], const float &feedrate) {
472
+
473
+    if (!position_is_reachable(rtarget[X_AXIS], rtarget[Y_AXIS]))  // fail if moving outside reachable boundary
474
+      return true; // did not move, so current_position still accurate
475
+
476
+    const float total[XYZE] = {
477
+      rtarget[X_AXIS] - current_position[X_AXIS],
478
+      rtarget[Y_AXIS] - current_position[Y_AXIS],
479
+      rtarget[Z_AXIS] - current_position[Z_AXIS],
480
+      rtarget[E_AXIS] - current_position[E_AXIS]
481
+    };
482
+
483
+    const float cartesian_xy_mm = HYPOT(total[X_AXIS], total[Y_AXIS]);  // total horizontal xy distance
484
+
485
+    #if IS_KINEMATIC
486
+      const float seconds = cartesian_xy_mm / feedrate;                                  // seconds to move xy distance at requested rate
487
+      uint16_t segments = lroundf(delta_segments_per_second * seconds),                  // preferred number of segments for distance @ feedrate
488
+               seglimit = lroundf(cartesian_xy_mm * (1.0 / (DELTA_SEGMENT_MIN_LENGTH))); // number of segments at minimum segment length
489
+      NOMORE(segments, seglimit);                                                        // limit to minimum segment length (fewer segments)
490
+    #else
491
+      uint16_t segments = lroundf(cartesian_xy_mm * (1.0 / (DELTA_SEGMENT_MIN_LENGTH))); // cartesian fixed segment length
492
+    #endif
522
 
493
 
523
-    bool _O2 unified_bed_leveling::prepare_segmented_line_to(const float rtarget[XYZE], const float &feedrate) {
524
-
525
-      if (!position_is_reachable(rtarget[X_AXIS], rtarget[Y_AXIS]))  // fail if moving outside reachable boundary
526
-        return true; // did not move, so current_position still accurate
527
-
528
-      const float total[XYZE] = {
529
-        rtarget[X_AXIS] - current_position[X_AXIS],
530
-        rtarget[Y_AXIS] - current_position[Y_AXIS],
531
-        rtarget[Z_AXIS] - current_position[Z_AXIS],
532
-        rtarget[E_AXIS] - current_position[E_AXIS]
533
-      };
534
-
535
-      const float cartesian_xy_mm = HYPOT(total[X_AXIS], total[Y_AXIS]);  // total horizontal xy distance
536
-
537
-      #if IS_KINEMATIC
538
-        const float seconds = cartesian_xy_mm / feedrate;                                  // seconds to move xy distance at requested rate
539
-        uint16_t segments = lroundf(delta_segments_per_second * seconds),                  // preferred number of segments for distance @ feedrate
540
-                 seglimit = lroundf(cartesian_xy_mm * (1.0 / (DELTA_SEGMENT_MIN_LENGTH))); // number of segments at minimum segment length
541
-        NOMORE(segments, seglimit);                                                        // limit to minimum segment length (fewer segments)
542
-      #else
543
-        uint16_t segments = lroundf(cartesian_xy_mm * (1.0 / (DELTA_SEGMENT_MIN_LENGTH))); // cartesian fixed segment length
544
-      #endif
545
-
546
-      NOLESS(segments, 1);                        // must have at least one segment
547
-      const float inv_segments = 1.0 / segments;  // divide once, multiply thereafter
548
-
549
-      #if IS_SCARA // scale the feed rate from mm/s to degrees/s
550
-        scara_feed_factor = cartesian_xy_mm * inv_segments * feedrate;
551
-        scara_oldA = stepper.get_axis_position_degrees(A_AXIS);
552
-        scara_oldB = stepper.get_axis_position_degrees(B_AXIS);
553
-      #endif
554
-
555
-      const float diff[XYZE] = {
556
-        total[X_AXIS] * inv_segments,
557
-        total[Y_AXIS] * inv_segments,
558
-        total[Z_AXIS] * inv_segments,
559
-        total[E_AXIS] * inv_segments
560
-      };
561
-
562
-      // Note that E segment distance could vary slightly as z mesh height
563
-      // changes for each segment, but small enough to ignore.
564
-
565
-      float raw[XYZE] = {
566
-        current_position[X_AXIS],
567
-        current_position[Y_AXIS],
568
-        current_position[Z_AXIS],
569
-        current_position[E_AXIS]
570
-      };
571
-
572
-      // Only compute leveling per segment if ubl active and target below z_fade_height.
573
-      if (!planner.leveling_active || !planner.leveling_active_at_z(rtarget[Z_AXIS])) {   // no mesh leveling
574
-        while (--segments) {
575
-          LOOP_XYZE(i) raw[i] += diff[i];
576
-          ubl_buffer_segment_raw(raw, feedrate);
577
-        }
578
-        ubl_buffer_segment_raw(rtarget, feedrate);
579
-        return false; // moved but did not set_current_from_destination();
494
+    NOLESS(segments, 1);                        // must have at least one segment
495
+    const float inv_segments = 1.0 / segments;  // divide once, multiply thereafter
496
+
497
+    #if IS_SCARA // scale the feed rate from mm/s to degrees/s
498
+      scara_feed_factor = cartesian_xy_mm * inv_segments * feedrate;
499
+      scara_oldA = stepper.get_axis_position_degrees(A_AXIS);
500
+      scara_oldB = stepper.get_axis_position_degrees(B_AXIS);
501
+    #endif
502
+
503
+    const float diff[XYZE] = {
504
+      total[X_AXIS] * inv_segments,
505
+      total[Y_AXIS] * inv_segments,
506
+      total[Z_AXIS] * inv_segments,
507
+      total[E_AXIS] * inv_segments
508
+    };
509
+
510
+    // Note that E segment distance could vary slightly as z mesh height
511
+    // changes for each segment, but small enough to ignore.
512
+
513
+    float raw[XYZE] = {
514
+      current_position[X_AXIS],
515
+      current_position[Y_AXIS],
516
+      current_position[Z_AXIS],
517
+      current_position[E_AXIS]
518
+    };
519
+
520
+    // Only compute leveling per segment if ubl active and target below z_fade_height.
521
+    if (!planner.leveling_active || !planner.leveling_active_at_z(rtarget[Z_AXIS])) {   // no mesh leveling
522
+      while (--segments) {
523
+        LOOP_XYZE(i) raw[i] += diff[i];
524
+        ubl_buffer_segment_raw(raw, feedrate);
580
       }
525
       }
526
+      ubl_buffer_segment_raw(rtarget, feedrate);
527
+      return false; // moved but did not set_current_from_destination();
528
+    }
581
 
529
 
582
-      // Otherwise perform per-segment leveling
530
+    // Otherwise perform per-segment leveling
583
 
531
 
584
-      #if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
585
-        const float fade_scaling_factor = planner.fade_scaling_factor_for_z(rtarget[Z_AXIS]);
586
-      #endif
532
+    #if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
533
+      const float fade_scaling_factor = planner.fade_scaling_factor_for_z(rtarget[Z_AXIS]);
534
+    #endif
587
 
535
 
588
-      // increment to first segment destination
589
-      LOOP_XYZE(i) raw[i] += diff[i];
536
+    // increment to first segment destination
537
+    LOOP_XYZE(i) raw[i] += diff[i];
590
 
538
 
591
-      for(;;) {  // for each mesh cell encountered during the move
539
+    for(;;) {  // for each mesh cell encountered during the move
592
 
540
 
593
-        // Compute mesh cell invariants that remain constant for all segments within cell.
594
-        // Note for cell index, if point is outside the mesh grid (in MESH_INSET perimeter)
595
-        // the bilinear interpolation from the adjacent cell within the mesh will still work.
596
-        // Inner loop will exit each time (because out of cell bounds) but will come back
597
-        // in top of loop and again re-find same adjacent cell and use it, just less efficient
598
-        // for mesh inset area.
541
+      // Compute mesh cell invariants that remain constant for all segments within cell.
542
+      // Note for cell index, if point is outside the mesh grid (in MESH_INSET perimeter)
543
+      // the bilinear interpolation from the adjacent cell within the mesh will still work.
544
+      // Inner loop will exit each time (because out of cell bounds) but will come back
545
+      // in top of loop and again re-find same adjacent cell and use it, just less efficient
546
+      // for mesh inset area.
599
 
547
 
600
-        int8_t cell_xi = (raw[X_AXIS] - (MESH_MIN_X)) * (1.0 / (MESH_X_DIST)),
601
-               cell_yi = (raw[Y_AXIS] - (MESH_MIN_Y)) * (1.0 / (MESH_X_DIST));
548
+      int8_t cell_xi = (raw[X_AXIS] - (MESH_MIN_X)) * (1.0 / (MESH_X_DIST)),
549
+             cell_yi = (raw[Y_AXIS] - (MESH_MIN_Y)) * (1.0 / (MESH_X_DIST));
602
 
550
 
603
-        cell_xi = constrain(cell_xi, 0, (GRID_MAX_POINTS_X) - 1);
604
-        cell_yi = constrain(cell_yi, 0, (GRID_MAX_POINTS_Y) - 1);
551
+      cell_xi = constrain(cell_xi, 0, (GRID_MAX_POINTS_X) - 1);
552
+      cell_yi = constrain(cell_yi, 0, (GRID_MAX_POINTS_Y) - 1);
605
 
553
 
606
-        const float x0 = mesh_index_to_xpos(cell_xi),   // 64 byte table lookup avoids mul+add
607
-                    y0 = mesh_index_to_ypos(cell_yi);
554
+      const float x0 = mesh_index_to_xpos(cell_xi),   // 64 byte table lookup avoids mul+add
555
+                  y0 = mesh_index_to_ypos(cell_yi);
608
 
556
 
609
-        float z_x0y0 = z_values[cell_xi  ][cell_yi  ],  // z at lower left corner
610
-              z_x1y0 = z_values[cell_xi+1][cell_yi  ],  // z at upper left corner
611
-              z_x0y1 = z_values[cell_xi  ][cell_yi+1],  // z at lower right corner
612
-              z_x1y1 = z_values[cell_xi+1][cell_yi+1];  // z at upper right corner
557
+      float z_x0y0 = z_values[cell_xi  ][cell_yi  ],  // z at lower left corner
558
+            z_x1y0 = z_values[cell_xi+1][cell_yi  ],  // z at upper left corner
559
+            z_x0y1 = z_values[cell_xi  ][cell_yi+1],  // z at lower right corner
560
+            z_x1y1 = z_values[cell_xi+1][cell_yi+1];  // z at upper right corner
613
 
561
 
614
-        if (isnan(z_x0y0)) z_x0y0 = 0;              // ideally activating planner.leveling_active (G29 A)
615
-        if (isnan(z_x1y0)) z_x1y0 = 0;              //   should refuse if any invalid mesh points
616
-        if (isnan(z_x0y1)) z_x0y1 = 0;              //   in order to avoid isnan tests per cell,
617
-        if (isnan(z_x1y1)) z_x1y1 = 0;              //   thus guessing zero for undefined points
562
+      if (isnan(z_x0y0)) z_x0y0 = 0;              // ideally activating planner.leveling_active (G29 A)
563
+      if (isnan(z_x1y0)) z_x1y0 = 0;              //   should refuse if any invalid mesh points
564
+      if (isnan(z_x0y1)) z_x0y1 = 0;              //   in order to avoid isnan tests per cell,
565
+      if (isnan(z_x1y1)) z_x1y1 = 0;              //   thus guessing zero for undefined points
618
 
566
 
619
-        float cx = raw[X_AXIS] - x0,   // cell-relative x and y
620
-              cy = raw[Y_AXIS] - y0;
567
+      float cx = raw[X_AXIS] - x0,   // cell-relative x and y
568
+            cy = raw[Y_AXIS] - y0;
621
 
569
 
622
-        const float z_xmy0 = (z_x1y0 - z_x0y0) * (1.0 / (MESH_X_DIST)),   // z slope per x along y0 (lower left to lower right)
623
-                    z_xmy1 = (z_x1y1 - z_x0y1) * (1.0 / (MESH_X_DIST));   // z slope per x along y1 (upper left to upper right)
570
+      const float z_xmy0 = (z_x1y0 - z_x0y0) * (1.0 / (MESH_X_DIST)),   // z slope per x along y0 (lower left to lower right)
571
+                  z_xmy1 = (z_x1y1 - z_x0y1) * (1.0 / (MESH_X_DIST));   // z slope per x along y1 (upper left to upper right)
624
 
572
 
625
-              float z_cxy0 = z_x0y0 + z_xmy0 * cx;            // z height along y0 at cx (changes for each cx in cell)
573
+            float z_cxy0 = z_x0y0 + z_xmy0 * cx;            // z height along y0 at cx (changes for each cx in cell)
626
 
574
 
627
-        const float z_cxy1 = z_x0y1 + z_xmy1 * cx,            // z height along y1 at cx
628
-                    z_cxyd = z_cxy1 - z_cxy0;                 // z height difference along cx from y0 to y1
575
+      const float z_cxy1 = z_x0y1 + z_xmy1 * cx,            // z height along y1 at cx
576
+                  z_cxyd = z_cxy1 - z_cxy0;                 // z height difference along cx from y0 to y1
629
 
577
 
630
-              float z_cxym = z_cxyd * (1.0 / (MESH_Y_DIST));  // z slope per y along cx from y0 to y1 (changes for each cx in cell)
578
+            float z_cxym = z_cxyd * (1.0 / (MESH_Y_DIST));  // z slope per y along cx from y0 to y1 (changes for each cx in cell)
631
 
579
 
632
-        //    float z_cxcy = z_cxy0 + z_cxym * cy;            // interpolated mesh z height along cx at cy (do inside the segment loop)
580
+      //    float z_cxcy = z_cxy0 + z_cxym * cy;            // interpolated mesh z height along cx at cy (do inside the segment loop)
633
 
581
 
634
-        // As subsequent segments step through this cell, the z_cxy0 intercept will change
635
-        // and the z_cxym slope will change, both as a function of cx within the cell, and
636
-        // each change by a constant for fixed segment lengths.
582
+      // As subsequent segments step through this cell, the z_cxy0 intercept will change
583
+      // and the z_cxym slope will change, both as a function of cx within the cell, and
584
+      // each change by a constant for fixed segment lengths.
637
 
585
 
638
-        const float z_sxy0 = z_xmy0 * diff[X_AXIS],                                     // per-segment adjustment to z_cxy0
639
-                    z_sxym = (z_xmy1 - z_xmy0) * (1.0 / (MESH_Y_DIST)) * diff[X_AXIS];  // per-segment adjustment to z_cxym
586
+      const float z_sxy0 = z_xmy0 * diff[X_AXIS],                                     // per-segment adjustment to z_cxy0
587
+                  z_sxym = (z_xmy1 - z_xmy0) * (1.0 / (MESH_Y_DIST)) * diff[X_AXIS];  // per-segment adjustment to z_cxym
640
 
588
 
641
-        for(;;) {  // for all segments within this mesh cell
589
+      for(;;) {  // for all segments within this mesh cell
642
 
590
 
643
-          if (--segments == 0)                      // if this is last segment, use rtarget for exact
644
-            COPY(raw, rtarget);
591
+        if (--segments == 0)                      // if this is last segment, use rtarget for exact
592
+          COPY(raw, rtarget);
645
 
593
 
646
-          const float z_cxcy = (z_cxy0 + z_cxym * cy) // interpolated mesh z height along cx at cy
647
-            #if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
648
-              * fade_scaling_factor                   // apply fade factor to interpolated mesh height
649
-            #endif
650
-          ;
594
+        const float z_cxcy = (z_cxy0 + z_cxym * cy) // interpolated mesh z height along cx at cy
595
+          #if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
596
+            * fade_scaling_factor                   // apply fade factor to interpolated mesh height
597
+          #endif
598
+        ;
651
 
599
 
652
-          const float z = raw[Z_AXIS];
653
-          raw[Z_AXIS] += z_cxcy;
654
-          ubl_buffer_segment_raw(raw, feedrate);
655
-          raw[Z_AXIS] = z;
600
+        const float z = raw[Z_AXIS];
601
+        raw[Z_AXIS] += z_cxcy;
602
+        ubl_buffer_segment_raw(raw, feedrate);
603
+        raw[Z_AXIS] = z;
656
 
604
 
657
-          if (segments == 0)                        // done with last segment
658
-            return false;                           // did not set_current_from_destination()
605
+        if (segments == 0)                        // done with last segment
606
+          return false;                           // did not set_current_from_destination()
659
 
607
 
660
-          LOOP_XYZE(i) raw[i] += diff[i];
608
+        LOOP_XYZE(i) raw[i] += diff[i];
661
 
609
 
662
-          cx += diff[X_AXIS];
663
-          cy += diff[Y_AXIS];
610
+        cx += diff[X_AXIS];
611
+        cy += diff[Y_AXIS];
664
 
612
 
665
-          if (!WITHIN(cx, 0, MESH_X_DIST) || !WITHIN(cy, 0, MESH_Y_DIST))    // done within this cell, break to next
666
-            break;
613
+        if (!WITHIN(cx, 0, MESH_X_DIST) || !WITHIN(cy, 0, MESH_Y_DIST))    // done within this cell, break to next
614
+          break;
667
 
615
 
668
-          // Next segment still within same mesh cell, adjust the per-segment
669
-          // slope and intercept to compute next z height.
616
+        // Next segment still within same mesh cell, adjust the per-segment
617
+        // slope and intercept to compute next z height.
670
 
618
 
671
-          z_cxy0 += z_sxy0;   // adjust z_cxy0 by per-segment z_sxy0
672
-          z_cxym += z_sxym;   // adjust z_cxym by per-segment z_sxym
619
+        z_cxy0 += z_sxy0;   // adjust z_cxy0 by per-segment z_sxy0
620
+        z_cxym += z_sxym;   // adjust z_cxym by per-segment z_sxym
673
 
621
 
674
-        } // segment loop
675
-      } // cell loop
676
-    }
622
+      } // segment loop
623
+    } // cell loop
624
+  }
677
 
625
 
678
-  #endif // UBL_DELTA
626
+#endif // UBL_SEGMENTED
679
 
627
 
680
 #endif // AUTO_BED_LEVELING_UBL
628
 #endif // AUTO_BED_LEVELING_UBL

+ 4
- 4
Marlin/src/gcode/bedlevel/G26.cpp 查看文件

220
 void G26_line_to_destination(const float &feed_rate) {
220
 void G26_line_to_destination(const float &feed_rate) {
221
   const float save_feedrate = feedrate_mm_s;
221
   const float save_feedrate = feedrate_mm_s;
222
   feedrate_mm_s = feed_rate;      // use specified feed rate
222
   feedrate_mm_s = feed_rate;      // use specified feed rate
223
-  prepare_move_to_destination();  // will ultimately call ubl.line_to_destination_cartesian or ubl.prepare_linear_move_to for UBL_DELTA
223
+  prepare_move_to_destination();  // will ultimately call ubl.line_to_destination_cartesian or ubl.prepare_linear_move_to for UBL_SEGMENTED
224
   feedrate_mm_s = save_feedrate;  // restore global feed rate
224
   feedrate_mm_s = save_feedrate;  // restore global feed rate
225
 }
225
 }
226
 
226
 
261
   set_destination_from_current();
261
   set_destination_from_current();
262
 }
262
 }
263
 
263
 
264
-FORCE_INLINE void move_to(const float where[XYZE], const float &de) { move_to(where[X_AXIS], where[Y_AXIS], where[Z_AXIS], de); }
264
+FORCE_INLINE void move_to(const float (&where)[XYZE], const float &de) { move_to(where[X_AXIS], where[Y_AXIS], where[Z_AXIS], de); }
265
 
265
 
266
-void retract_filament(const float where[XYZE]) {
266
+void retract_filament(const float (&where)[XYZE]) {
267
   if (!g26_retracted) { // Only retract if we are not already retracted!
267
   if (!g26_retracted) { // Only retract if we are not already retracted!
268
     g26_retracted = true;
268
     g26_retracted = true;
269
     move_to(where, -1.0 * g26_retraction_multiplier);
269
     move_to(where, -1.0 * g26_retraction_multiplier);
270
   }
270
   }
271
 }
271
 }
272
 
272
 
273
-void recover_filament(const float where[XYZE]) {
273
+void recover_filament(const float (&where)[XYZE]) {
274
   if (g26_retracted) { // Only un-retract if we are retracted.
274
   if (g26_retracted) { // Only un-retract if we are retracted.
275
     move_to(where, 1.2 * g26_retraction_multiplier);
275
     move_to(where, 1.2 * g26_retraction_multiplier);
276
     g26_retracted = false;
276
     g26_retracted = false;

+ 9
- 4
Marlin/src/gcode/host/M114.cpp 查看文件

28
 
28
 
29
 #if ENABLED(M114_DETAIL)
29
 #if ENABLED(M114_DETAIL)
30
 
30
 
31
-  void report_xyze(const float pos[XYZE], const uint8_t n = 4, const uint8_t precision = 3) {
31
+  void report_xyze(const float pos[], const uint8_t n = 4, const uint8_t precision = 3) {
32
     char str[12];
32
     char str[12];
33
     for (uint8_t i = 0; i < n; i++) {
33
     for (uint8_t i = 0; i < n; i++) {
34
       SERIAL_CHAR(' ');
34
       SERIAL_CHAR(' ');
39
     SERIAL_EOL();
39
     SERIAL_EOL();
40
   }
40
   }
41
 
41
 
42
-  inline void report_xyz(const float pos[XYZ]) { report_xyze(pos, 3); }
42
+  inline void report_xyz(const float pos[]) { report_xyze(pos, 3); }
43
 
43
 
44
   void report_current_position_detail() {
44
   void report_current_position_detail() {
45
 
45
 
80
     #endif
80
     #endif
81
 
81
 
82
     SERIAL_PROTOCOLPGM("Stepper:");
82
     SERIAL_PROTOCOLPGM("Stepper:");
83
-    const float step_count[XYZE] = { stepper.position(X_AXIS), stepper.position(Y_AXIS), stepper.position(Z_AXIS), stepper.position(E_AXIS) };
84
-    report_xyze(step_count, 4, 0);
83
+    LOOP_XYZE(i) {
84
+      SERIAL_CHAR(' ');
85
+      SERIAL_CHAR(axis_codes[i]);
86
+      SERIAL_CHAR(':');
87
+      SERIAL_PROTOCOL(stepper.position((AxisEnum)i));
88
+    }
89
+    SERIAL_EOL();
85
 
90
 
86
     #if IS_SCARA
91
     #if IS_SCARA
87
       const float deg[XYZ] = {
92
       const float deg[XYZ] = {

+ 9
- 9
Marlin/src/gcode/motion/G2_G3.cpp 查看文件

44
  * options for G2/G3 arc generation. In future these options may be GCode tunable.
44
  * options for G2/G3 arc generation. In future these options may be GCode tunable.
45
  */
45
  */
46
 void plan_arc(
46
 void plan_arc(
47
-  float rtarget[XYZE], // Destination position
48
-  float *offset,       // Center of rotation relative to current_position
49
-  uint8_t clockwise    // Clockwise?
47
+  const float (&cart)[XYZE],  // Destination position
48
+  const float (&offset)[2],   // Center of rotation relative to current_position
49
+  const uint8_t clockwise     // Clockwise?
50
 ) {
50
 ) {
51
   #if ENABLED(CNC_WORKSPACE_PLANES)
51
   #if ENABLED(CNC_WORKSPACE_PLANES)
52
     AxisEnum p_axis, q_axis, l_axis;
52
     AxisEnum p_axis, q_axis, l_axis;
66
   const float radius = HYPOT(r_P, r_Q),
66
   const float radius = HYPOT(r_P, r_Q),
67
               center_P = current_position[p_axis] - r_P,
67
               center_P = current_position[p_axis] - r_P,
68
               center_Q = current_position[q_axis] - r_Q,
68
               center_Q = current_position[q_axis] - r_Q,
69
-              rt_X = rtarget[p_axis] - center_P,
70
-              rt_Y = rtarget[q_axis] - center_Q,
71
-              linear_travel = rtarget[l_axis] - current_position[l_axis],
72
-              extruder_travel = rtarget[E_AXIS] - current_position[E_AXIS];
69
+              rt_X = cart[p_axis] - center_P,
70
+              rt_Y = cart[q_axis] - center_Q,
71
+              linear_travel = cart[l_axis] - current_position[l_axis],
72
+              extruder_travel = cart[E_AXIS] - current_position[E_AXIS];
73
 
73
 
74
   // CCW angle of rotation between position and target from the circle center. Only one atan2() trig computation required.
74
   // CCW angle of rotation between position and target from the circle center. Only one atan2() trig computation required.
75
   float angular_travel = ATAN2(r_P * rt_Y - r_Q * rt_X, r_P * rt_X + r_Q * rt_Y);
75
   float angular_travel = ATAN2(r_P * rt_Y - r_Q * rt_X, r_P * rt_X + r_Q * rt_Y);
77
   if (clockwise) angular_travel -= RADIANS(360);
77
   if (clockwise) angular_travel -= RADIANS(360);
78
 
78
 
79
   // Make a circle if the angular rotation is 0 and the target is current position
79
   // Make a circle if the angular rotation is 0 and the target is current position
80
-  if (angular_travel == 0 && current_position[p_axis] == rtarget[p_axis] && current_position[q_axis] == rtarget[q_axis])
80
+  if (angular_travel == 0 && current_position[p_axis] == cart[p_axis] && current_position[q_axis] == cart[q_axis])
81
     angular_travel = RADIANS(360);
81
     angular_travel = RADIANS(360);
82
 
82
 
83
   const float mm_of_travel = HYPOT(angular_travel * radius, FABS(linear_travel));
83
   const float mm_of_travel = HYPOT(angular_travel * radius, FABS(linear_travel));
177
   }
177
   }
178
 
178
 
179
   // Ensure last segment arrives at target location.
179
   // Ensure last segment arrives at target location.
180
-  planner.buffer_line_kinematic(rtarget, fr_mm_s, active_extruder);
180
+  planner.buffer_line_kinematic(cart, fr_mm_s, active_extruder);
181
 
181
 
182
   // As far as the parser is concerned, the position is now == target. In reality the
182
   // As far as the parser is concerned, the position is now == target. In reality the
183
   // motion control system might still be processing the action and the real tool position
183
   // motion control system might still be processing the action and the real tool position

+ 2
- 2
Marlin/src/gcode/motion/G5.cpp 查看文件

27
 #include "../../module/motion.h"
27
 #include "../../module/motion.h"
28
 #include "../../module/planner_bezier.h"
28
 #include "../../module/planner_bezier.h"
29
 
29
 
30
-void plan_cubic_move(const float offset[4]) {
30
+void plan_cubic_move(const float (&offset)[4]) {
31
   cubic_b_spline(current_position, destination, offset, MMS_SCALED(feedrate_mm_s), active_extruder);
31
   cubic_b_spline(current_position, destination, offset, MMS_SCALED(feedrate_mm_s), active_extruder);
32
 
32
 
33
   // As far as the parser is concerned, the position is now == destination. In reality the
33
   // As far as the parser is concerned, the position is now == destination. In reality the
62
 
62
 
63
     get_destination_from_command();
63
     get_destination_from_command();
64
 
64
 
65
-    const float offset[] = {
65
+    const float offset[4] = {
66
       parser.linearval('I'),
66
       parser.linearval('I'),
67
       parser.linearval('J'),
67
       parser.linearval('J'),
68
       parser.linearval('P'),
68
       parser.linearval('P'),

+ 9
- 9
Marlin/src/inc/Conditionals_post.h 查看文件

977
 /**
977
 /**
978
  * Set granular options based on the specific type of leveling
978
  * Set granular options based on the specific type of leveling
979
  */
979
  */
980
-#define UBL_DELTA  (ENABLED(AUTO_BED_LEVELING_UBL) && (ENABLED(DELTA) || ENABLED(SEGMENT_LEVELED_MOVES)))
981
-#define ABL_PLANAR (ENABLED(AUTO_BED_LEVELING_LINEAR) || ENABLED(AUTO_BED_LEVELING_3POINT))
982
-#define ABL_GRID   (ENABLED(AUTO_BED_LEVELING_LINEAR) || ENABLED(AUTO_BED_LEVELING_BILINEAR))
983
-#define OLDSCHOOL_ABL         (ABL_PLANAR || ABL_GRID)
984
-#define HAS_ABL               (OLDSCHOOL_ABL || ENABLED(AUTO_BED_LEVELING_UBL))
985
-#define HAS_LEVELING          (HAS_ABL || ENABLED(MESH_BED_LEVELING))
986
-#define HAS_AUTOLEVEL         (HAS_ABL && DISABLED(PROBE_MANUALLY))
987
-#define HAS_MESH              (ENABLED(AUTO_BED_LEVELING_BILINEAR) || ENABLED(AUTO_BED_LEVELING_UBL) || ENABLED(MESH_BED_LEVELING))
988
-#define PLANNER_LEVELING      (OLDSCHOOL_ABL || ENABLED(MESH_BED_LEVELING) || UBL_DELTA)
980
+#define UBL_SEGMENTED  (ENABLED(AUTO_BED_LEVELING_UBL) && (ENABLED(DELTA) || ENABLED(SEGMENT_LEVELED_MOVES)))
981
+#define ABL_PLANAR     (ENABLED(AUTO_BED_LEVELING_LINEAR) || ENABLED(AUTO_BED_LEVELING_3POINT))
982
+#define ABL_GRID       (ENABLED(AUTO_BED_LEVELING_LINEAR) || ENABLED(AUTO_BED_LEVELING_BILINEAR))
983
+#define OLDSCHOOL_ABL  (ABL_PLANAR || ABL_GRID)
984
+#define HAS_ABL        (OLDSCHOOL_ABL || ENABLED(AUTO_BED_LEVELING_UBL))
985
+#define HAS_LEVELING   (HAS_ABL || ENABLED(MESH_BED_LEVELING))
986
+#define HAS_AUTOLEVEL  (HAS_ABL && DISABLED(PROBE_MANUALLY))
987
+#define HAS_MESH       (ENABLED(AUTO_BED_LEVELING_BILINEAR) || ENABLED(AUTO_BED_LEVELING_UBL) || ENABLED(MESH_BED_LEVELING))
988
+#define PLANNER_LEVELING      (OLDSCHOOL_ABL || ENABLED(MESH_BED_LEVELING))
989
 #define HAS_PROBING_PROCEDURE (HAS_ABL || ENABLED(Z_MIN_PROBE_REPEATABILITY_TEST))
989
 #define HAS_PROBING_PROCEDURE (HAS_ABL || ENABLED(Z_MIN_PROBE_REPEATABILITY_TEST))
990
 #if HAS_PROBING_PROCEDURE
990
 #if HAS_PROBING_PROCEDURE
991
   #define PROBE_BED_WIDTH abs(RIGHT_PROBE_BED_POSITION - (LEFT_PROBE_BED_POSITION))
991
   #define PROBE_BED_WIDTH abs(RIGHT_PROBE_BED_POSITION - (LEFT_PROBE_BED_POSITION))

+ 1
- 4
Marlin/src/inc/SanityCheck.h 查看文件

603
     #error "Delta probably shouldn't use Z_MIN_PROBE_ENDSTOP. Comment out this line to continue."
603
     #error "Delta probably shouldn't use Z_MIN_PROBE_ENDSTOP. Comment out this line to continue."
604
   #elif DISABLED(USE_XMAX_PLUG) && DISABLED(USE_YMAX_PLUG) && DISABLED(USE_ZMAX_PLUG)
604
   #elif DISABLED(USE_XMAX_PLUG) && DISABLED(USE_YMAX_PLUG) && DISABLED(USE_ZMAX_PLUG)
605
     #error "You probably want to use Max Endstops for DELTA!"
605
     #error "You probably want to use Max Endstops for DELTA!"
606
-  #elif ENABLED(ENABLE_LEVELING_FADE_HEIGHT) && DISABLED(AUTO_BED_LEVELING_BILINEAR) && !UBL_DELTA
606
+  #elif ENABLED(ENABLE_LEVELING_FADE_HEIGHT) && DISABLED(AUTO_BED_LEVELING_BILINEAR) && !UBL_SEGMENTED
607
     #error "ENABLE_LEVELING_FADE_HEIGHT on DELTA requires AUTO_BED_LEVELING_BILINEAR or AUTO_BED_LEVELING_UBL."
607
     #error "ENABLE_LEVELING_FADE_HEIGHT on DELTA requires AUTO_BED_LEVELING_BILINEAR or AUTO_BED_LEVELING_UBL."
608
   #elif ENABLED(DELTA_AUTO_CALIBRATION) && !(HAS_BED_PROBE || ENABLED(ULTIPANEL))
608
   #elif ENABLED(DELTA_AUTO_CALIBRATION) && !(HAS_BED_PROBE || ENABLED(ULTIPANEL))
609
     #error "DELTA_AUTO_CALIBRATION requires a probe or LCD Controller."
609
     #error "DELTA_AUTO_CALIBRATION requires a probe or LCD Controller."
1497
 #endif
1497
 #endif
1498
 
1498
 
1499
 #if ENABLED(SKEW_CORRECTION)
1499
 #if ENABLED(SKEW_CORRECTION)
1500
-  #if ENABLED(AUTO_BED_LEVELING_UBL) && !ENABLED(SEGMENT_LEVELED_MOVES)
1501
-    #error "SKEW_CORRECTION with AUTO_BED_LEVELING_UBL requires SEGMENT_LEVELED_MOVES."
1502
-  #endif
1503
   #if !defined(XY_SKEW_FACTOR) && !(defined(XY_DIAG_AC) && defined(XY_DIAG_BD) && defined(XY_SIDE_AD))
1500
   #if !defined(XY_SKEW_FACTOR) && !(defined(XY_DIAG_AC) && defined(XY_DIAG_BD) && defined(XY_SIDE_AD))
1504
     #error "SKEW_CORRECTION requires XY_SKEW_FACTOR or XY_DIAG_AC, XY_DIAG_BD, XY_SIDE_AD."
1501
     #error "SKEW_CORRECTION requires XY_SKEW_FACTOR or XY_DIAG_AC, XY_DIAG_BD, XY_SIDE_AD."
1505
   #endif
1502
   #endif

+ 17
- 9
Marlin/src/module/motion.cpp 查看文件

264
 
264
 
265
     gcode.refresh_cmd_timeout();
265
     gcode.refresh_cmd_timeout();
266
 
266
 
267
-    #if UBL_DELTA
267
+    #if UBL_SEGMENTED
268
       // ubl segmented line will do z-only moves in single segment
268
       // ubl segmented line will do z-only moves in single segment
269
       ubl.prepare_segmented_line_to(destination, MMS_SCALED(fr_mm_s ? fr_mm_s : feedrate_mm_s));
269
       ubl.prepare_segmented_line_to(destination, MMS_SCALED(fr_mm_s ? fr_mm_s : feedrate_mm_s));
270
     #else
270
     #else
495
 
495
 
496
 #endif
496
 #endif
497
 
497
 
498
-#if !UBL_DELTA
498
+#if !UBL_SEGMENTED
499
 #if IS_KINEMATIC
499
 #if IS_KINEMATIC
500
 
500
 
501
   #if ENABLED(AUTO_BED_LEVELING_BILINEAR)
501
   #if ENABLED(AUTO_BED_LEVELING_BILINEAR)
517
   /**
517
   /**
518
    * Prepare a linear move in a DELTA or SCARA setup.
518
    * Prepare a linear move in a DELTA or SCARA setup.
519
    *
519
    *
520
+   * Called from prepare_move_to_destination as the
521
+   * default Delta/SCARA segmenter.
522
+   *
520
    * This calls planner.buffer_line several times, adding
523
    * This calls planner.buffer_line several times, adding
521
    * small incremental moves for DELTA or SCARA.
524
    * small incremental moves for DELTA or SCARA.
522
    *
525
    *
523
    * For Unified Bed Leveling (Delta or Segmented Cartesian)
526
    * For Unified Bed Leveling (Delta or Segmented Cartesian)
524
    * the ubl.prepare_segmented_line_to method replaces this.
527
    * the ubl.prepare_segmented_line_to method replaces this.
528
+   *
529
+   * For Auto Bed Leveling (Bilinear) with SEGMENT_LEVELED_MOVES
530
+   * this is replaced by segmented_line_to_destination below.
525
    */
531
    */
526
-  inline bool prepare_kinematic_move_to(float rtarget[XYZE]) {
532
+  inline bool prepare_kinematic_move_to(const float (&rtarget)[XYZE]) {
527
 
533
 
528
     // Get the top feedrate of the move in the XY plane
534
     // Get the top feedrate of the move in the XY plane
529
     const float _feedrate_mm_s = MMS_SCALED(feedrate_mm_s);
535
     const float _feedrate_mm_s = MMS_SCALED(feedrate_mm_s);
756
   }
762
   }
757
 
763
 
758
 #endif // !IS_KINEMATIC
764
 #endif // !IS_KINEMATIC
759
-#endif // !UBL_DELTA
765
+#endif // !UBL_SEGMENTED
760
 
766
 
761
 #if ENABLED(DUAL_X_CARRIAGE) || ENABLED(DUAL_NOZZLE_DUPLICATION_MODE)
767
 #if ENABLED(DUAL_X_CARRIAGE) || ENABLED(DUAL_NOZZLE_DUPLICATION_MODE)
762
   bool extruder_duplication_enabled = false;                              // Used in Dual X mode 2
768
   bool extruder_duplication_enabled = false;                              // Used in Dual X mode 2
790
    *
796
    *
791
    * Return true if current_position[] was set to destination[]
797
    * Return true if current_position[] was set to destination[]
792
    */
798
    */
793
-  inline bool prepare_move_to_destination_dualx() {
799
+  inline bool dual_x_carriage_unpark() {
794
     if (active_extruder_parked) {
800
     if (active_extruder_parked) {
795
       switch (dual_x_carriage_mode) {
801
       switch (dual_x_carriage_mode) {
796
         case DXC_FULL_CONTROL_MODE:
802
         case DXC_FULL_CONTROL_MODE:
859
           break;
865
           break;
860
       }
866
       }
861
     }
867
     }
862
-    return prepare_move_to_destination_cartesian();
868
+    return false;
863
   }
869
   }
864
 
870
 
865
 #endif // DUAL_X_CARRIAGE
871
 #endif // DUAL_X_CARRIAGE
900
 
906
 
901
   #endif // PREVENT_COLD_EXTRUSION || PREVENT_LENGTHY_EXTRUDE
907
   #endif // PREVENT_COLD_EXTRUSION || PREVENT_LENGTHY_EXTRUDE
902
 
908
 
909
+  #if ENABLED(DUAL_X_CARRIAGE)
910
+    if (dual_x_carriage_unpark()) return;
911
+  #endif
912
+
903
   if (
913
   if (
904
-    #if UBL_DELTA // Also works for CARTESIAN (smaller segments follow mesh more closely)
914
+    #if UBL_SEGMENTED
905
       ubl.prepare_segmented_line_to(destination, MMS_SCALED(feedrate_mm_s))
915
       ubl.prepare_segmented_line_to(destination, MMS_SCALED(feedrate_mm_s))
906
     #elif IS_KINEMATIC
916
     #elif IS_KINEMATIC
907
       prepare_kinematic_move_to(destination)
917
       prepare_kinematic_move_to(destination)
908
-    #elif ENABLED(DUAL_X_CARRIAGE)
909
-      prepare_move_to_destination_dualx()
910
     #else
918
     #else
911
       prepare_move_to_destination_cartesian()
919
       prepare_move_to_destination_cartesian()
912
     #endif
920
     #endif

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

580
   void Planner::apply_leveling(float &rx, float &ry, float &rz) {
580
   void Planner::apply_leveling(float &rx, float &ry, float &rz) {
581
 
581
 
582
     #if ENABLED(SKEW_CORRECTION)
582
     #if ENABLED(SKEW_CORRECTION)
583
-      if (WITHIN(rx, X_MIN_POS + 1, X_MAX_POS) && WITHIN(ry, Y_MIN_POS + 1, Y_MAX_POS)) {
584
-        const float tempry = ry - (rz * planner.yz_skew_factor),
585
-                    temprx = rx - (ry * planner.xy_skew_factor) - (rz * (planner.xz_skew_factor - (planner.xy_skew_factor * planner.yz_skew_factor)));
586
-        if (WITHIN(temprx, X_MIN_POS, X_MAX_POS) && WITHIN(tempry, Y_MIN_POS, Y_MAX_POS)) {
587
-          rx = temprx;
588
-          ry = tempry;
589
-        }
590
-      }
583
+      skew(rx, ry, rz);
591
     #endif
584
     #endif
592
 
585
 
593
     if (!leveling_active) return;
586
     if (!leveling_active) return;
616
       #endif
609
       #endif
617
 
610
 
618
       rz += (
611
       rz += (
619
-        #if ENABLED(AUTO_BED_LEVELING_UBL) // UBL_DELTA
612
+        #if ENABLED(AUTO_BED_LEVELING_UBL)
620
           ubl.get_z_correction(rx, ry) * fade_scaling_factor
613
           ubl.get_z_correction(rx, ry) * fade_scaling_factor
621
         #elif ENABLED(MESH_BED_LEVELING)
614
         #elif ENABLED(MESH_BED_LEVELING)
622
           mbl.get_z(rx, ry
615
           mbl.get_z(rx, ry
678
     }
671
     }
679
 
672
 
680
     #if ENABLED(SKEW_CORRECTION)
673
     #if ENABLED(SKEW_CORRECTION)
681
-      if (WITHIN(raw[X_AXIS], X_MIN_POS, X_MAX_POS) && WITHIN(raw[Y_AXIS], Y_MIN_POS, Y_MAX_POS)) {
682
-        const float temprx = raw[X_AXIS] + raw[Y_AXIS] * planner.xy_skew_factor + raw[Z_AXIS] * planner.xz_skew_factor,
683
-                    tempry = raw[Y_AXIS] + raw[Z_AXIS] * planner.yz_skew_factor;
684
-        if (WITHIN(temprx, X_MIN_POS, X_MAX_POS) && WITHIN(tempry, Y_MIN_POS, Y_MAX_POS)) {
685
-          raw[X_AXIS] = temprx;
686
-          raw[Y_AXIS] = tempry;
687
-        }
688
-      }
674
+      unskew(raw[X_AXIS], raw[Y_AXIS], raw[Z_AXIS]);
689
     #endif
675
     #endif
690
   }
676
   }
691
 
677
 
1365
 } // _buffer_steps()
1351
 } // _buffer_steps()
1366
 
1352
 
1367
 /**
1353
 /**
1368
- * Planner::_buffer_line
1354
+ * Planner::buffer_segment
1369
  *
1355
  *
1370
  * Add a new linear movement to the buffer in axis units.
1356
  * Add a new linear movement to the buffer in axis units.
1371
  *
1357
  *
1375
  *  fr_mm_s   - (target) speed of the move
1361
  *  fr_mm_s   - (target) speed of the move
1376
  *  extruder  - target extruder
1362
  *  extruder  - target extruder
1377
  */
1363
  */
1378
-void Planner::_buffer_line(const float &a, const float &b, const float &c, const float &e, const float &fr_mm_s, const uint8_t extruder) {
1364
+void Planner::buffer_segment(const float &a, const float &b, const float &c, const float &e, const float &fr_mm_s, const uint8_t extruder) {
1379
   // When changing extruders recalculate steps corresponding to the E position
1365
   // When changing extruders recalculate steps corresponding to the E position
1380
   #if ENABLED(DISTINCT_E_FACTORS)
1366
   #if ENABLED(DISTINCT_E_FACTORS)
1381
     if (last_extruder != extruder && axis_steps_per_mm[E_AXIS_N] != axis_steps_per_mm[E_AXIS + last_extruder]) {
1367
     if (last_extruder != extruder && axis_steps_per_mm[E_AXIS_N] != axis_steps_per_mm[E_AXIS + last_extruder]) {
1394
   };
1380
   };
1395
 
1381
 
1396
   /* <-- add a slash to enable
1382
   /* <-- add a slash to enable
1397
-    SERIAL_ECHOPAIR("  _buffer_line FR:", fr_mm_s);
1383
+    SERIAL_ECHOPAIR("  buffer_segment FR:", fr_mm_s);
1398
     #if IS_KINEMATIC
1384
     #if IS_KINEMATIC
1399
       SERIAL_ECHOPAIR(" A:", a);
1385
       SERIAL_ECHOPAIR(" A:", a);
1400
       SERIAL_ECHOPAIR(" (", position[A_AXIS]);
1386
       SERIAL_ECHOPAIR(" (", position[A_AXIS]);
1441
 
1427
 
1442
   stepper.wake_up();
1428
   stepper.wake_up();
1443
 
1429
 
1444
-} // _buffer_line()
1430
+} // buffer_segment()
1445
 
1431
 
1446
 /**
1432
 /**
1447
  * Directly set the planner XYZ position (and stepper positions)
1433
  * Directly set the planner XYZ position (and stepper positions)
1466
   ZERO(previous_speed);
1452
   ZERO(previous_speed);
1467
 }
1453
 }
1468
 
1454
 
1469
-void Planner::set_position_mm_kinematic(const float position[NUM_AXIS]) {
1455
+void Planner::set_position_mm_kinematic(const float (&cart)[XYZE]) {
1470
   #if PLANNER_LEVELING
1456
   #if PLANNER_LEVELING
1471
-    float lpos[XYZ] = { position[X_AXIS], position[Y_AXIS], position[Z_AXIS] };
1472
-    apply_leveling(lpos);
1457
+    float raw[XYZ] = { cart[X_AXIS], cart[Y_AXIS], cart[Z_AXIS] };
1458
+    apply_leveling(raw);
1473
   #else
1459
   #else
1474
-    const float * const lpos = position;
1460
+    const float (&raw)[XYZE] = cart;
1475
   #endif
1461
   #endif
1476
   #if IS_KINEMATIC
1462
   #if IS_KINEMATIC
1477
-    inverse_kinematics(lpos);
1478
-    _set_position_mm(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], position[E_AXIS]);
1463
+    inverse_kinematics(raw);
1464
+    _set_position_mm(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], cart[E_AXIS]);
1479
   #else
1465
   #else
1480
-    _set_position_mm(lpos[X_AXIS], lpos[Y_AXIS], lpos[Z_AXIS], position[E_AXIS]);
1466
+    _set_position_mm(raw[X_AXIS], raw[Y_AXIS], raw[Z_AXIS], cart[E_AXIS]);
1481
   #endif
1467
   #endif
1482
 }
1468
 }
1483
 
1469
 

+ 34
- 10
Marlin/src/module/planner.h 查看文件

146
      *            head!=tail : blocks are in the buffer
146
      *            head!=tail : blocks are in the buffer
147
      *   head==(tail-1)%size : the buffer is full
147
      *   head==(tail-1)%size : the buffer is full
148
      *
148
      *
149
-     *  Writer of head is Planner::_buffer_line().
149
+     *  Writer of head is Planner::buffer_segment().
150
      *  Reader of tail is Stepper::isr(). Always consider tail busy / read-only
150
      *  Reader of tail is Stepper::isr(). Always consider tail busy / read-only
151
      */
151
      */
152
     static block_t block_buffer[BLOCK_BUFFER_SIZE];
152
     static block_t block_buffer[BLOCK_BUFFER_SIZE];
345
 
345
 
346
     #endif
346
     #endif
347
 
347
 
348
+    #if ENABLED(SKEW_CORRECTION)
349
+
350
+      FORCE_INLINE static void skew(float &cx, float &cy, const float &cz) {
351
+        if (WITHIN(cx, X_MIN_POS + 1, X_MAX_POS) && WITHIN(cy, Y_MIN_POS + 1, Y_MAX_POS)) {
352
+          const float sx = cx - (cy * xy_skew_factor) - (cz * (xz_skew_factor - (xy_skew_factor * yz_skew_factor))),
353
+                      sy = cy - (cz * yz_skew_factor);
354
+          if (WITHIN(sx, X_MIN_POS, X_MAX_POS) && WITHIN(sy, Y_MIN_POS, Y_MAX_POS)) {
355
+            cx = sx; cy = sy;
356
+          }
357
+        }
358
+      }
359
+
360
+      FORCE_INLINE static void unskew(float &cx, float &cy, const float &cz) {
361
+        if (WITHIN(cx, X_MIN_POS, X_MAX_POS) && WITHIN(cy, Y_MIN_POS, Y_MAX_POS)) {
362
+          const float sx = cx + cy * xy_skew_factor + cz * xz_skew_factor,
363
+                      sy = cy + cz * yz_skew_factor;
364
+          if (WITHIN(sx, X_MIN_POS, X_MAX_POS) && WITHIN(sy, Y_MIN_POS, Y_MAX_POS)) {
365
+            cx = sx; cy = sy;
366
+          }
367
+        }
368
+      }
369
+
370
+    #endif // SKEW_CORRECTION
371
+
348
     #if PLANNER_LEVELING
372
     #if PLANNER_LEVELING
349
 
373
 
350
       #define ARG_X float rx
374
       #define ARG_X float rx
356
        * as it will be given to the planner and steppers.
380
        * as it will be given to the planner and steppers.
357
        */
381
        */
358
       static void apply_leveling(float &rx, float &ry, float &rz);
382
       static void apply_leveling(float &rx, float &ry, float &rz);
359
-      static void apply_leveling(float raw[XYZ]) { apply_leveling(raw[X_AXIS], raw[Y_AXIS], raw[Z_AXIS]); }
383
+      static void apply_leveling(float (&raw)[XYZ]) { apply_leveling(raw[X_AXIS], raw[Y_AXIS], raw[Z_AXIS]); }
360
       static void unapply_leveling(float raw[XYZ]);
384
       static void unapply_leveling(float raw[XYZ]);
361
 
385
 
362
     #else
386
     #else
379
     static void _buffer_steps(const int32_t (&target)[XYZE], float fr_mm_s, const uint8_t extruder);
403
     static void _buffer_steps(const int32_t (&target)[XYZE], float fr_mm_s, const uint8_t extruder);
380
 
404
 
381
     /**
405
     /**
382
-     * Planner::_buffer_line
406
+     * Planner::buffer_segment
383
      *
407
      *
384
      * Add a new linear movement to the buffer in axis units.
408
      * Add a new linear movement to the buffer in axis units.
385
      *
409
      *
389
      *  fr_mm_s   - (target) speed of the move
413
      *  fr_mm_s   - (target) speed of the move
390
      *  extruder  - target extruder
414
      *  extruder  - target extruder
391
      */
415
      */
392
-    static void _buffer_line(const float &a, const float &b, const float &c, const float &e, const float &fr_mm_s, const uint8_t extruder);
416
+    static void buffer_segment(const float &a, const float &b, const float &c, const float &e, const float &fr_mm_s, const uint8_t extruder);
393
 
417
 
394
     static void _set_position_mm(const float &a, const float &b, const float &c, const float &e);
418
     static void _set_position_mm(const float &a, const float &b, const float &c, const float &e);
395
 
419
 
409
       #if PLANNER_LEVELING && IS_CARTESIAN
433
       #if PLANNER_LEVELING && IS_CARTESIAN
410
         apply_leveling(rx, ry, rz);
434
         apply_leveling(rx, ry, rz);
411
       #endif
435
       #endif
412
-      _buffer_line(rx, ry, rz, e, fr_mm_s, extruder);
436
+      buffer_segment(rx, ry, rz, e, fr_mm_s, extruder);
413
     }
437
     }
414
 
438
 
415
     /**
439
     /**
421
      *  fr_mm_s  - (target) speed of the move (mm/s)
445
      *  fr_mm_s  - (target) speed of the move (mm/s)
422
      *  extruder - target extruder
446
      *  extruder - target extruder
423
      */
447
      */
424
-    FORCE_INLINE static void buffer_line_kinematic(const float cart[XYZE], const float &fr_mm_s, const uint8_t extruder) {
448
+    FORCE_INLINE static void buffer_line_kinematic(const float (&cart)[XYZE], const float &fr_mm_s, const uint8_t extruder) {
425
       #if PLANNER_LEVELING
449
       #if PLANNER_LEVELING
426
         float raw[XYZ] = { cart[X_AXIS], cart[Y_AXIS], cart[Z_AXIS] };
450
         float raw[XYZ] = { cart[X_AXIS], cart[Y_AXIS], cart[Z_AXIS] };
427
         apply_leveling(raw);
451
         apply_leveling(raw);
428
       #else
452
       #else
429
-        const float * const raw = cart;
453
+        const float (&raw)[XYZE] = cart;
430
       #endif
454
       #endif
431
       #if IS_KINEMATIC
455
       #if IS_KINEMATIC
432
         inverse_kinematics(raw);
456
         inverse_kinematics(raw);
433
-        _buffer_line(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], cart[E_AXIS], fr_mm_s, extruder);
457
+        buffer_segment(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], cart[E_AXIS], fr_mm_s, extruder);
434
       #else
458
       #else
435
-        _buffer_line(raw[X_AXIS], raw[Y_AXIS], raw[Z_AXIS], cart[E_AXIS], fr_mm_s, extruder);
459
+        buffer_segment(raw[X_AXIS], raw[Y_AXIS], raw[Z_AXIS], cart[E_AXIS], fr_mm_s, extruder);
436
       #endif
460
       #endif
437
     }
461
     }
438
 
462
 
451
       #endif
475
       #endif
452
       _set_position_mm(rx, ry, rz, e);
476
       _set_position_mm(rx, ry, rz, e);
453
     }
477
     }
454
-    static void set_position_mm_kinematic(const float position[NUM_AXIS]);
478
+    static void set_position_mm_kinematic(const float (&cart)[XYZE]);
455
     static void set_position_mm(const AxisEnum axis, const float &v);
479
     static void set_position_mm(const AxisEnum axis, const float &v);
456
     FORCE_INLINE static void set_z_position_mm(const float &z) { set_position_mm(Z_AXIS, z); }
480
     FORCE_INLINE static void set_z_position_mm(const float &z) { set_position_mm(Z_AXIS, z); }
457
     FORCE_INLINE static void set_e_position_mm(const float &e) { set_position_mm(AxisEnum(E_AXIS), e); }
481
     FORCE_INLINE static void set_e_position_mm(const float &e) { set_position_mm(AxisEnum(E_AXIS), e); }

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

107
 
107
 
108
 #elif ENABLED(Z_PROBE_ALLEN_KEY)
108
 #elif ENABLED(Z_PROBE_ALLEN_KEY)
109
 
109
 
110
-  FORCE_INLINE void do_blocking_move_to(const float raw[XYZ], const float &fr_mm_s) {
110
+  FORCE_INLINE void do_blocking_move_to(const float (&raw)[XYZ], const float &fr_mm_s) {
111
     do_blocking_move_to(raw[X_AXIS], raw[Y_AXIS], raw[Z_AXIS], fr_mm_s);
111
     do_blocking_move_to(raw[X_AXIS], raw[Y_AXIS], raw[Z_AXIS], fr_mm_s);
112
   }
112
   }
113
 
113
 

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

1193
 /**
1193
 /**
1194
  * Get a stepper's position in steps.
1194
  * Get a stepper's position in steps.
1195
  */
1195
  */
1196
-long Stepper::position(AxisEnum axis) {
1196
+long Stepper::position(const AxisEnum axis) {
1197
   CRITICAL_SECTION_START;
1197
   CRITICAL_SECTION_START;
1198
   const long count_pos = count_position[axis];
1198
   const long count_pos = count_position[axis];
1199
   CRITICAL_SECTION_END;
1199
   CRITICAL_SECTION_END;
1204
  * Get an axis position according to stepper position(s)
1204
  * Get an axis position according to stepper position(s)
1205
  * For CORE machines apply translation from ABC to XYZ.
1205
  * For CORE machines apply translation from ABC to XYZ.
1206
  */
1206
  */
1207
-float Stepper::get_axis_position_mm(AxisEnum axis) {
1207
+float Stepper::get_axis_position_mm(const AxisEnum axis) {
1208
   float axis_steps;
1208
   float axis_steps;
1209
   #if IS_CORE
1209
   #if IS_CORE
1210
     // Requesting one of the "core" axes?
1210
     // Requesting one of the "core" axes?
1242
   #endif
1242
   #endif
1243
 }
1243
 }
1244
 
1244
 
1245
-void Stepper::endstop_triggered(AxisEnum axis) {
1245
+void Stepper::endstop_triggered(const AxisEnum axis) {
1246
 
1246
 
1247
   #if IS_CORE
1247
   #if IS_CORE
1248
 
1248
 

+ 6
- 6
Marlin/src/module/stepper.h 查看文件

183
     //
183
     //
184
     // Get the position of a stepper, in steps
184
     // Get the position of a stepper, in steps
185
     //
185
     //
186
-    static long position(AxisEnum axis);
186
+    static long position(const AxisEnum axis);
187
 
187
 
188
     //
188
     //
189
     // Report the positions of the steppers, in steps
189
     // Report the positions of the steppers, in steps
193
     //
193
     //
194
     // Get the position (mm) of an axis based on stepper position(s)
194
     // Get the position (mm) of an axis based on stepper position(s)
195
     //
195
     //
196
-    static float get_axis_position_mm(AxisEnum axis);
196
+    static float get_axis_position_mm(const AxisEnum axis);
197
 
197
 
198
     //
198
     //
199
     // SCARA AB axes are in degrees, not mm
199
     // SCARA AB axes are in degrees, not mm
200
     //
200
     //
201
     #if IS_SCARA
201
     #if IS_SCARA
202
-      FORCE_INLINE static float get_axis_position_degrees(AxisEnum axis) { return get_axis_position_mm(axis); }
202
+      FORCE_INLINE static float get_axis_position_degrees(const AxisEnum axis) { return get_axis_position_mm(axis); }
203
     #endif
203
     #endif
204
 
204
 
205
     //
205
     //
221
     //
221
     //
222
     // The direction of a single motor
222
     // The direction of a single motor
223
     //
223
     //
224
-    FORCE_INLINE static bool motor_direction(AxisEnum axis) { return TEST(last_direction_bits, axis); }
224
+    FORCE_INLINE static bool motor_direction(const AxisEnum axis) { return TEST(last_direction_bits, axis); }
225
 
225
 
226
     #if HAS_DIGIPOTSS || HAS_MOTOR_CURRENT_PWM
226
     #if HAS_DIGIPOTSS || HAS_MOTOR_CURRENT_PWM
227
       static void digitalPotWrite(const int16_t address, const int16_t value);
227
       static void digitalPotWrite(const int16_t address, const int16_t value);
263
     //
263
     //
264
     // Handle a triggered endstop
264
     // Handle a triggered endstop
265
     //
265
     //
266
-    static void endstop_triggered(AxisEnum axis);
266
+    static void endstop_triggered(const AxisEnum axis);
267
 
267
 
268
     //
268
     //
269
     // Triggered position of an axis in mm (not core-savvy)
269
     // Triggered position of an axis in mm (not core-savvy)
270
     //
270
     //
271
-    FORCE_INLINE static float triggered_position_mm(AxisEnum axis) {
271
+    FORCE_INLINE static float triggered_position_mm(const AxisEnum axis) {
272
       return endstops_trigsteps[axis] * planner.steps_to_mm[axis];
272
       return endstops_trigsteps[axis] * planner.steps_to_mm[axis];
273
     }
273
     }
274
 
274
 

Loading…
取消
儲存