Browse Source

Improve planner kinematics, fix delta ABL

Josef Pavlik 7 years ago
parent
commit
f8c2473a71
6 changed files with 102 additions and 82 deletions
  1. 11
    29
      Marlin/Marlin_main.cpp
  2. 4
    0
      Marlin/SanityCheck.h
  3. 25
    31
      Marlin/planner.cpp
  4. 59
    3
      Marlin/planner.h
  5. 1
    7
      Marlin/planner_bezier.cpp
  6. 2
    12
      Marlin/ultralcd.cpp

+ 11
- 29
Marlin/Marlin_main.cpp View File

711
     #if ENABLED(DEBUG_LEVELING_FEATURE)
711
     #if ENABLED(DEBUG_LEVELING_FEATURE)
712
       if (DEBUGGING(LEVELING)) DEBUG_POS("sync_plan_position_kinematic", current_position);
712
       if (DEBUGGING(LEVELING)) DEBUG_POS("sync_plan_position_kinematic", current_position);
713
     #endif
713
     #endif
714
-    inverse_kinematics(current_position);
715
-    planner.set_position_mm(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], current_position[E_AXIS]);
714
+    planner.set_position_mm_kinematic(current_position);
716
   }
715
   }
717
   #define SYNC_PLAN_POSITION_KINEMATIC() sync_plan_position_kinematic()
716
   #define SYNC_PLAN_POSITION_KINEMATIC() sync_plan_position_kinematic()
718
 
717
 
1541
     ) return;
1540
     ) return;
1542
 
1541
 
1543
     refresh_cmd_timeout();
1542
     refresh_cmd_timeout();
1544
-    inverse_kinematics(destination);
1545
-    planner.buffer_line(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], destination[E_AXIS], MMS_SCALED(fr_mm_s ? fr_mm_s : feedrate_mm_s), active_extruder);
1543
+    planner.buffer_line_kinematic(destination, MMS_SCALED(fr_mm_s ? fr_mm_s : feedrate_mm_s), active_extruder);
1546
     set_current_to_destination();
1544
     set_current_to_destination();
1547
   }
1545
   }
1548
 #endif // IS_KINEMATIC
1546
 #endif // IS_KINEMATIC
6779
 
6777
 
6780
     // Define runplan for move axes
6778
     // Define runplan for move axes
6781
     #if IS_KINEMATIC
6779
     #if IS_KINEMATIC
6782
-      #define RUNPLAN(RATE_MM_S) inverse_kinematics(destination); \
6783
-                                 planner.buffer_line(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], destination[E_AXIS], RATE_MM_S, active_extruder);
6780
+      #define RUNPLAN(RATE_MM_S) planner.buffer_line_kinematic(destination, RATE_MM_S, active_extruder);
6784
     #else
6781
     #else
6785
       #define RUNPLAN(RATE_MM_S) line_to_destination(RATE_MM_S);
6782
       #define RUNPLAN(RATE_MM_S) line_to_destination(RATE_MM_S);
6786
     #endif
6783
     #endif
6900
     planner.set_e_position_mm(current_position[E_AXIS]);
6897
     planner.set_e_position_mm(current_position[E_AXIS]);
6901
 
6898
 
6902
     #if IS_KINEMATIC
6899
     #if IS_KINEMATIC
6903
-      // Move XYZ to starting position, then E
6904
-      inverse_kinematics(lastpos);
6905
-      planner.buffer_line(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], destination[E_AXIS], FILAMENT_CHANGE_XY_FEEDRATE, active_extruder);
6906
-      planner.buffer_line(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], lastpos[E_AXIS], FILAMENT_CHANGE_XY_FEEDRATE, active_extruder);
6900
+      // Move XYZ to starting position
6901
+      planner.buffer_line_kinematic(lastpos, FILAMENT_CHANGE_XY_FEEDRATE, active_extruder);
6907
     #else
6902
     #else
6908
-      // Move XY to starting position, then Z, then E
6903
+      // Move XY to starting position, then Z
6909
       destination[X_AXIS] = lastpos[X_AXIS];
6904
       destination[X_AXIS] = lastpos[X_AXIS];
6910
       destination[Y_AXIS] = lastpos[Y_AXIS];
6905
       destination[Y_AXIS] = lastpos[Y_AXIS];
6911
       RUNPLAN(FILAMENT_CHANGE_XY_FEEDRATE);
6906
       RUNPLAN(FILAMENT_CHANGE_XY_FEEDRATE);
8671
 
8666
 
8672
     // If the move is only in Z/E don't split up the move
8667
     // If the move is only in Z/E don't split up the move
8673
     if (ltarget[X_AXIS] == current_position[X_AXIS] && ltarget[Y_AXIS] == current_position[Y_AXIS]) {
8668
     if (ltarget[X_AXIS] == current_position[X_AXIS] && ltarget[Y_AXIS] == current_position[Y_AXIS]) {
8674
-      inverse_kinematics(ltarget);
8675
-      planner.buffer_line(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], ltarget[E_AXIS], _feedrate_mm_s, active_extruder);
8669
+      planner.buffer_line_kinematic(ltarget, _feedrate_mm_s, active_extruder);
8676
       return true;
8670
       return true;
8677
     }
8671
     }
8678
 
8672
 
8815
       // For non-interpolated delta calculate every segment
8809
       // For non-interpolated delta calculate every segment
8816
       for (uint16_t s = segments + 1; --s;) {
8810
       for (uint16_t s = segments + 1; --s;) {
8817
         DELTA_NEXT(segment_distance[i]);
8811
         DELTA_NEXT(segment_distance[i]);
8818
-        DELTA_IK();
8819
-        planner.buffer_line(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], DELTA_VAR[E_AXIS], _feedrate_mm_s, active_extruder);
8812
+        planner.buffer_line_kinematic(DELTA_VAR, _feedrate_mm_s, active_extruder);
8820
       }
8813
       }
8821
 
8814
 
8822
     #endif
8815
     #endif
8823
 
8816
 
8824
     // Since segment_distance is only approximate,
8817
     // Since segment_distance is only approximate,
8825
     // the final move must be to the exact destination.
8818
     // the final move must be to the exact destination.
8826
-    inverse_kinematics(ltarget);
8827
-    planner.buffer_line(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], ltarget[E_AXIS], _feedrate_mm_s, active_extruder);
8819
+    planner.buffer_line_kinematic(ltarget, _feedrate_mm_s, active_extruder);
8828
     return true;
8820
     return true;
8829
   }
8821
   }
8830
 
8822
 
9064
 
9056
 
9065
       clamp_to_software_endstops(arc_target);
9057
       clamp_to_software_endstops(arc_target);
9066
 
9058
 
9067
-      #if IS_KINEMATIC
9068
-        inverse_kinematics(arc_target);
9069
-        planner.buffer_line(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], arc_target[E_AXIS], fr_mm_s, active_extruder);
9070
-      #else
9071
-        planner.buffer_line(arc_target[X_AXIS], arc_target[Y_AXIS], arc_target[Z_AXIS], arc_target[E_AXIS], fr_mm_s, active_extruder);
9072
-      #endif
9059
+      planner.buffer_line_kinematic(arc_target, fr_mm_s, active_extruder);
9073
     }
9060
     }
9074
 
9061
 
9075
     // Ensure last segment arrives at target location.
9062
     // Ensure last segment arrives at target location.
9076
-    #if IS_KINEMATIC
9077
-      inverse_kinematics(logical);
9078
-      planner.buffer_line(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], logical[E_AXIS], fr_mm_s, active_extruder);
9079
-    #else
9080
-      planner.buffer_line(logical[X_AXIS], logical[Y_AXIS], logical[Z_AXIS], logical[E_AXIS], fr_mm_s, active_extruder);
9081
-    #endif
9063
+    planner.buffer_line_kinematic(logical, fr_mm_s, active_extruder);
9082
 
9064
 
9083
     // As far as the parser is concerned, the position is now == target. In reality the
9065
     // As far as the parser is concerned, the position is now == target. In reality the
9084
     // motion control system might still be processing the action and the real tool position
9066
     // motion control system might still be processing the action and the real tool position

+ 4
- 0
Marlin/SanityCheck.h View File

518
  */
518
  */
519
 #if HAS_ABL
519
 #if HAS_ABL
520
 
520
 
521
+  #if ENABLED(USE_RAW_KINEMATICS) || ENABLED(USE_DELTA_IK_INTERPOLATION)
522
+    #error "USE_RAW_KINEMATICS and USE_DELTA_IK_INTERPOLATION are not compatible with AUTO_BED_LEVELING"
523
+  #endif
524
+
521
   /**
525
   /**
522
    * Delta and SCARA have limited bed leveling options
526
    * Delta and SCARA have limited bed leveling options
523
    */
527
    */

+ 25
- 31
Marlin/planner.cpp View File

522
 }
522
 }
523
 
523
 
524
 #if PLANNER_LEVELING
524
 #if PLANNER_LEVELING
525
-
525
+  /**
526
+   * lx, ly, lz - logical (cartesian, not delta) positions in mm
527
+   */
526
   void Planner::apply_leveling(float &lx, float &ly, float &lz) {
528
   void Planner::apply_leveling(float &lx, float &ly, float &lz) {
527
 
529
 
528
     #if HAS_ABL
530
     #if HAS_ABL
549
     #elif ENABLED(AUTO_BED_LEVELING_BILINEAR)
551
     #elif ENABLED(AUTO_BED_LEVELING_BILINEAR)
550
 
552
 
551
       float tmp[XYZ] = { lx, ly, 0 };
553
       float tmp[XYZ] = { lx, ly, 0 };
552
-
553
-      #if ENABLED(DELTA)
554
-
555
-        float offset = bilinear_z_offset(tmp);
556
-        lx += offset;
557
-        ly += offset;
558
-        lz += offset;
559
-
560
-      #else
561
-
562
-        lz += bilinear_z_offset(tmp);
563
-
564
-      #endif
554
+      lz += bilinear_z_offset(tmp);
565
 
555
 
566
     #endif
556
     #endif
567
   }
557
   }
601
 #endif // PLANNER_LEVELING
591
 #endif // PLANNER_LEVELING
602
 
592
 
603
 /**
593
 /**
604
- * Planner::buffer_line
594
+ * Planner::_buffer_line
605
  *
595
  *
606
  * Add a new linear movement to the buffer.
596
  * Add a new linear movement to the buffer.
597
+ * Not apply the leveling.
607
  *
598
  *
608
  *  x,y,z,e   - target position in mm
599
  *  x,y,z,e   - target position in mm
609
  *  fr_mm_s   - (target) speed of the move
600
  *  fr_mm_s   - (target) speed of the move
610
  *  extruder  - target extruder
601
  *  extruder  - target extruder
611
  */
602
  */
612
-void Planner::buffer_line(ARG_X, ARG_Y, ARG_Z, const float &e, float fr_mm_s, const uint8_t extruder) {
603
+void Planner::_buffer_line(const float &lx, const float &ly, const float &lz, const float &e, float fr_mm_s, const uint8_t extruder) {
613
   // Calculate the buffer head after we push this byte
604
   // Calculate the buffer head after we push this byte
614
   int next_buffer_head = next_block_index(block_buffer_head);
605
   int next_buffer_head = next_block_index(block_buffer_head);
615
 
606
 
617
   // Rest here until there is room in the buffer.
608
   // Rest here until there is room in the buffer.
618
   while (block_buffer_tail == next_buffer_head) idle();
609
   while (block_buffer_tail == next_buffer_head) idle();
619
 
610
 
620
-  #if PLANNER_LEVELING
621
-    apply_leveling(lx, ly, lz);
622
-  #endif
623
-
624
   // The target position of the tool in absolute steps
611
   // The target position of the tool in absolute steps
625
   // Calculate target position in absolute steps
612
   // Calculate target position in absolute steps
626
   //this should be done after the wait, because otherwise a M92 code within the gcode disrupts this calculation somehow
613
   //this should be done after the wait, because otherwise a M92 code within the gcode disrupts this calculation somehow
1196
  *
1183
  *
1197
  * On CORE machines stepper ABC will be translated from the given XYZ.
1184
  * On CORE machines stepper ABC will be translated from the given XYZ.
1198
  */
1185
  */
1199
-void Planner::set_position_mm(ARG_X, ARG_Y, ARG_Z, const float &e) {
1200
-
1201
-  #if PLANNER_LEVELING
1202
-    apply_leveling(lx, ly, lz);
1203
-  #endif
1204
 
1186
 
1187
+void Planner::_set_position_mm(const float &lx, const float &ly, const float &lz, const float &e) {
1205
   long nx = position[X_AXIS] = lround(lx * axis_steps_per_mm[X_AXIS]),
1188
   long nx = position[X_AXIS] = lround(lx * axis_steps_per_mm[X_AXIS]),
1206
        ny = position[Y_AXIS] = lround(ly * axis_steps_per_mm[Y_AXIS]),
1189
        ny = position[Y_AXIS] = lround(ly * axis_steps_per_mm[Y_AXIS]),
1207
        nz = position[Z_AXIS] = lround(lz * axis_steps_per_mm[Z_AXIS]),
1190
        nz = position[Z_AXIS] = lround(lz * axis_steps_per_mm[Z_AXIS]),
1212
   memset(previous_speed, 0, sizeof(previous_speed));
1195
   memset(previous_speed, 0, sizeof(previous_speed));
1213
 }
1196
 }
1214
 
1197
 
1198
+void Planner::set_position_mm_kinematic(const float position[NUM_AXIS]) {
1199
+  #if PLANNER_LEVELING
1200
+    float pos[XYZ] = { position[X_AXIS], position[Y_AXIS], position[Z_AXIS] };
1201
+    apply_leveling(pos);
1202
+  #else
1203
+    const float * const pos = position;
1204
+  #endif
1205
+  #if IS_KINEMATIC
1206
+    inverse_kinematics(pos);
1207
+    _set_position_mm(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], position[E_AXIS]);
1208
+  #else
1209
+    _set_position_mm(pos[X_AXIS], pos[Y_AXIS], pos[Z_AXIS], position[E_AXIS]);
1210
+  #endif
1211
+}
1212
+
1213
+
1215
 /**
1214
 /**
1216
  * Sync from the stepper positions. (e.g., after an interrupted move)
1215
  * Sync from the stepper positions. (e.g., after an interrupted move)
1217
  */
1216
  */
1237
 // Recalculate position, steps_to_mm if axis_steps_per_mm changes!
1236
 // Recalculate position, steps_to_mm if axis_steps_per_mm changes!
1238
 void Planner::refresh_positioning() {
1237
 void Planner::refresh_positioning() {
1239
   LOOP_XYZE(i) steps_to_mm[i] = 1.0 / axis_steps_per_mm[i];
1238
   LOOP_XYZE(i) steps_to_mm[i] = 1.0 / axis_steps_per_mm[i];
1240
-  #if IS_KINEMATIC
1241
-    inverse_kinematics(current_position);
1242
-    set_position_mm(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], current_position[E_AXIS]);
1243
-  #else
1244
-    set_position_mm(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
1245
-  #endif
1239
+  set_position_mm_kinematic(current_position);
1246
   reset_acceleration_rates();
1240
   reset_acceleration_rates();
1247
 }
1241
 }
1248
 
1242
 

+ 59
- 3
Marlin/planner.h View File

43
 class Planner;
43
 class Planner;
44
 extern Planner planner;
44
 extern Planner planner;
45
 
45
 
46
+#if IS_KINEMATIC
47
+  // for inline buffer_line_kinematic
48
+  extern float delta[ABC];
49
+  void inverse_kinematics(const float logical[XYZ]);
50
+#endif
51
+
46
 /**
52
 /**
47
  * struct block_t
53
  * struct block_t
48
  *
54
  *
218
        * as it will be given to the planner and steppers.
224
        * as it will be given to the planner and steppers.
219
        */
225
        */
220
       static void apply_leveling(float &lx, float &ly, float &lz);
226
       static void apply_leveling(float &lx, float &ly, float &lz);
227
+      static void apply_leveling(float logical[XYZ]) { apply_leveling(logical[X_AXIS], logical[Y_AXIS], logical[Z_AXIS]); }
221
       static void unapply_leveling(float logical[XYZ]);
228
       static void unapply_leveling(float logical[XYZ]);
222
 
229
 
223
     #endif
230
     #endif
224
 
231
 
225
     /**
232
     /**
233
+     * Planner::_buffer_line
234
+     *
235
+     * Add a new linear movement to the buffer.
236
+     * Doesn't apply the leveling.
237
+     *
238
+     *  x,y,z,e   - target position in mm
239
+     *  fr_mm_s   - (target) speed of the move
240
+     *  extruder  - target extruder
241
+     */
242
+    static void _buffer_line(const float &lx, const float &ly, const float &lz, const float &e, float fr_mm_s, const uint8_t extruder);
243
+
244
+    static void _set_position_mm(const float &lx, const float &ly, const float &lz, const float &e);
245
+
246
+    /**
226
      * Add a new linear movement to the buffer.
247
      * Add a new linear movement to the buffer.
248
+     * The target is NOT translated to delta/scara
227
      *
249
      *
228
      *  x,y,z,e   - target position in mm
250
      *  x,y,z,e   - target position in mm
229
      *  fr_mm_s   - (target) speed of the move (mm/s)
251
      *  fr_mm_s   - (target) speed of the move (mm/s)
230
      *  extruder  - target extruder
252
      *  extruder  - target extruder
231
      */
253
      */
232
-    static void buffer_line(ARG_X, ARG_Y, ARG_Z, const float& e, float fr_mm_s, const uint8_t extruder);
254
+    static FORCE_INLINE void buffer_line(ARG_X, ARG_Y, ARG_Z, const float &e, float fr_mm_s, const uint8_t extruder) {
255
+      #if PLANNER_LEVELING && ! IS_KINEMATIC
256
+        apply_leveling(lx, ly, lz);
257
+      #endif
258
+      _buffer_line(lx, ly, lz, e, fr_mm_s, extruder);
259
+    }
260
+
261
+    /**
262
+     * Add a new linear movement to the buffer.
263
+     * The target is cartesian, it's translated to delta/scara if
264
+     * needed.
265
+     *
266
+     *  target   - x,y,z,e CARTESIAN target in mm
267
+     *  fr_mm_s  - (target) speed of the move (mm/s)
268
+     *  extruder - target extruder
269
+     */
270
+     static FORCE_INLINE void buffer_line_kinematic(const float target[NUM_AXIS], float fr_mm_s, const uint8_t extruder) {
271
+      #if PLANNER_LEVELING
272
+        float pos[XYZ] = { target[X_AXIS], target[Y_AXIS], target[Z_AXIS] };
273
+        apply_leveling(pos);
274
+      #else
275
+        const float * const pos = target;
276
+      #endif
277
+      #if IS_KINEMATIC
278
+        inverse_kinematics(pos);
279
+        _buffer_line(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], target[E_AXIS], fr_mm_s, extruder);
280
+      #else
281
+        _buffer_line(pos[X_AXIS], pos[Y_AXIS], pos[Z_AXIS], target[E_AXIS], fr_mm_s, extruder);
282
+      #endif
283
+    }
233
 
284
 
234
     /**
285
     /**
235
      * Set the planner.position and individual stepper positions.
286
      * Set the planner.position and individual stepper positions.
240
      *
291
      *
241
      * Clears previous speed values.
292
      * Clears previous speed values.
242
      */
293
      */
243
-    static void set_position_mm(ARG_X, ARG_Y, ARG_Z, const float& e);
294
+    static FORCE_INLINE void set_position_mm(ARG_X, ARG_Y, ARG_Z, const float &e) {
295
+      #if PLANNER_LEVELING && ! IS_KINEMATIC
296
+        apply_leveling(lx, ly, lz);
297
+      #endif
298
+      _set_position_mm(lx, ly, lz, e);
299
+    }
300
+    static void set_position_mm_kinematic(const float position[NUM_AXIS]);
244
     static void set_position_mm(const AxisEnum axis, const float& v);
301
     static void set_position_mm(const AxisEnum axis, const float& v);
245
-
246
     static FORCE_INLINE void set_z_position_mm(const float& z) { set_position_mm(Z_AXIS, z); }
302
     static FORCE_INLINE void set_z_position_mm(const float& z) { set_position_mm(Z_AXIS, z); }
247
     static FORCE_INLINE void set_e_position_mm(const float& e) { set_position_mm(E_AXIS, e); }
303
     static FORCE_INLINE void set_e_position_mm(const float& e) { set_position_mm(E_AXIS, e); }
248
 
304
 

+ 1
- 7
Marlin/planner_bezier.cpp View File

187
     bez_target[Z_AXIS] = interp(position[Z_AXIS], target[Z_AXIS], t);
187
     bez_target[Z_AXIS] = interp(position[Z_AXIS], target[Z_AXIS], t);
188
     bez_target[E_AXIS] = interp(position[E_AXIS], target[E_AXIS], t);
188
     bez_target[E_AXIS] = interp(position[E_AXIS], target[E_AXIS], t);
189
     clamp_to_software_endstops(bez_target);
189
     clamp_to_software_endstops(bez_target);
190
-
191
-    #if IS_KINEMATIC
192
-      inverse_kinematics(bez_target);
193
-      planner.buffer_line(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], bez_target[E_AXIS], fr_mm_s, extruder);
194
-    #else
195
-      planner.buffer_line(bez_target[X_AXIS], bez_target[Y_AXIS], bez_target[Z_AXIS], bez_target[E_AXIS], fr_mm_s, extruder);
196
-    #endif
190
+    planner.buffer_line_kinematic(bez_target, fr_mm_s, extruder);
197
   }
191
   }
198
 }
192
 }
199
 
193
 

+ 2
- 12
Marlin/ultralcd.cpp View File

561
 #if ENABLED(ULTIPANEL)
561
 #if ENABLED(ULTIPANEL)
562
 
562
 
563
   inline void line_to_current(AxisEnum axis) {
563
   inline void line_to_current(AxisEnum axis) {
564
-    #if ENABLED(DELTA)
565
-      inverse_kinematics(current_position);
566
-      planner.buffer_line(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], current_position[E_AXIS], MMM_TO_MMS(manual_feedrate_mm_m[axis]), active_extruder);
567
-    #else // !DELTA
568
-      planner.buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], MMM_TO_MMS(manual_feedrate_mm_m[axis]), active_extruder);
569
-    #endif // !DELTA
564
+    planner.buffer_line_kinematic(current_position, MMM_TO_MMS(manual_feedrate_mm_m[axis]), active_extruder);
570
   }
565
   }
571
 
566
 
572
   #if ENABLED(SDSUPPORT)
567
   #if ENABLED(SDSUPPORT)
1351
    */
1346
    */
1352
   inline void manage_manual_move() {
1347
   inline void manage_manual_move() {
1353
     if (manual_move_axis != (int8_t)NO_AXIS && ELAPSED(millis(), manual_move_start_time) && !planner.is_full()) {
1348
     if (manual_move_axis != (int8_t)NO_AXIS && ELAPSED(millis(), manual_move_start_time) && !planner.is_full()) {
1354
-      #if ENABLED(DELTA)
1355
-        inverse_kinematics(current_position);
1356
-        planner.buffer_line(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], current_position[E_AXIS], MMM_TO_MMS(manual_feedrate_mm_m[manual_move_axis]), manual_move_e_index);
1357
-      #else
1358
-        planner.buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], MMM_TO_MMS(manual_feedrate_mm_m[manual_move_axis]), manual_move_e_index);
1359
-      #endif
1349
+      planner.buffer_line_kinematic(current_position, MMM_TO_MMS(manual_feedrate_mm_m[manual_move_axis]), manual_move_e_index);
1360
       manual_move_axis = (int8_t)NO_AXIS;
1350
       manual_move_axis = (int8_t)NO_AXIS;
1361
     }
1351
     }
1362
   }
1352
   }

Loading…
Cancel
Save