ソースを参照

Merge pull request #4982 from thinkyhead/rc_abl_bugfix

Fix planner with kinematics, delta ABL
Scott Lahteine 8年前
コミット
f8199b2cc1

+ 4
- 0
Marlin/Conditionals_post.h ファイルの表示

@@ -706,4 +706,8 @@
706 706
   // Stepper pulse duration, in cycles
707 707
   #define STEP_PULSE_CYCLES ((MINIMUM_STEPPER_PULSE) * CYCLES_PER_MICROSECOND)
708 708
 
709
+  #ifndef DELTA_ENDSTOP_ADJ
710
+    #define DELTA_ENDSTOP_ADJ { 0 }
711
+  #endif
712
+
709 713
 #endif // CONDITIONALS_POST_H

+ 52
- 51
Marlin/Marlin_main.cpp ファイルの表示

@@ -456,6 +456,18 @@ static uint8_t target_extruder;
456 456
   #define XY_PROBE_FEEDRATE_MM_S PLANNER_XY_FEEDRATE()
457 457
 #endif
458 458
 
459
+#if ENABLED(AUTO_BED_LEVELING_BILINEAR)
460
+  #define ADJUST_DELTA(V) \
461
+    if (planner.abl_enabled) { \
462
+      const float zadj = bilinear_z_offset(V); \
463
+      delta[A_AXIS] += zadj; \
464
+      delta[B_AXIS] += zadj; \
465
+      delta[C_AXIS] += zadj; \
466
+    }
467
+#elif IS_KINEMATIC
468
+  #define ADJUST_DELTA(V) NOOP
469
+#endif
470
+
459 471
 #if ENABLED(Z_DUAL_ENDSTOPS)
460 472
   float z_endstop_adj = 0;
461 473
 #endif
@@ -711,8 +723,7 @@ inline void sync_plan_position_e() { planner.set_e_position_mm(current_position[
711 723
     #if ENABLED(DEBUG_LEVELING_FEATURE)
712 724
       if (DEBUGGING(LEVELING)) DEBUG_POS("sync_plan_position_kinematic", current_position);
713 725
     #endif
714
-    inverse_kinematics(current_position);
715
-    planner.set_position_mm(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], current_position[E_AXIS]);
726
+    planner.set_position_mm_kinematic(current_position);
716 727
   }
717 728
   #define SYNC_PLAN_POSITION_KINEMATIC() sync_plan_position_kinematic()
718 729
 
@@ -1541,8 +1552,7 @@ inline void set_destination_to_current() { memcpy(destination, current_position,
1541 1552
     ) return;
1542 1553
 
1543 1554
     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);
1555
+    planner.buffer_line_kinematic(destination, MMS_SCALED(fr_mm_s ? fr_mm_s : feedrate_mm_s), active_extruder);
1546 1556
     set_current_to_destination();
1547 1557
   }
1548 1558
 #endif // IS_KINEMATIC
@@ -6778,8 +6788,7 @@ inline void gcode_M503() {
6778 6788
 
6779 6789
     // Define runplan for move axes
6780 6790
     #if IS_KINEMATIC
6781
-      #define RUNPLAN(RATE_MM_S) inverse_kinematics(destination); \
6782
-                                 planner.buffer_line(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], destination[E_AXIS], RATE_MM_S, active_extruder);
6791
+      #define RUNPLAN(RATE_MM_S) planner.buffer_line_kinematic(destination, RATE_MM_S, active_extruder);
6783 6792
     #else
6784 6793
       #define RUNPLAN(RATE_MM_S) line_to_destination(RATE_MM_S);
6785 6794
     #endif
@@ -6894,17 +6903,14 @@ inline void gcode_M503() {
6894 6903
     KEEPALIVE_STATE(IN_HANDLER);
6895 6904
 
6896 6905
     // Set extruder to saved position
6897
-    current_position[E_AXIS] = lastpos[E_AXIS];
6898
-    destination[E_AXIS] = lastpos[E_AXIS];
6906
+    destination[E_AXIS] = current_position[E_AXIS] = lastpos[E_AXIS];
6899 6907
     planner.set_e_position_mm(current_position[E_AXIS]);
6900 6908
 
6901 6909
     #if IS_KINEMATIC
6902
-      // Move XYZ to starting position, then E
6903
-      inverse_kinematics(lastpos);
6904
-      planner.buffer_line(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], destination[E_AXIS], FILAMENT_CHANGE_XY_FEEDRATE, active_extruder);
6905
-      planner.buffer_line(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], lastpos[E_AXIS], FILAMENT_CHANGE_XY_FEEDRATE, active_extruder);
6910
+      // Move XYZ to starting position
6911
+      planner.buffer_line_kinematic(lastpos, FILAMENT_CHANGE_XY_FEEDRATE, active_extruder);
6906 6912
     #else
6907
-      // Move XY to starting position, then Z, then E
6913
+      // Move XY to starting position, then Z
6908 6914
       destination[X_AXIS] = lastpos[X_AXIS];
6909 6915
       destination[Y_AXIS] = lastpos[Y_AXIS];
6910 6916
       RUNPLAN(FILAMENT_CHANGE_XY_FEEDRATE);
@@ -7295,15 +7301,11 @@ void tool_change(const uint8_t tmp_extruder, const float fr_mm_s/*=0.0*/, bool n
7295 7301
             float z_diff = hotend_offset[Z_AXIS][active_extruder] - hotend_offset[Z_AXIS][tmp_extruder],
7296 7302
                   z_raise = 0.3 + (z_diff > 0.0 ? z_diff : 0.0);
7297 7303
 
7304
+            set_destination_to_current();
7305
+
7298 7306
             // Always raise by some amount
7299
-            planner.buffer_line(
7300
-              current_position[X_AXIS],
7301
-              current_position[Y_AXIS],
7302
-              current_position[Z_AXIS] + z_raise,
7303
-              current_position[E_AXIS],
7304
-              planner.max_feedrate_mm_s[Z_AXIS],
7305
-              active_extruder
7306
-            );
7307
+            destination[Z_AXIS] += z_raise;
7308
+            planner.buffer_line_kinematic(destination, planner.max_feedrate_mm_s[Z_AXIS], active_extruder);
7307 7309
             stepper.synchronize();
7308 7310
 
7309 7311
             move_extruder_servo(active_extruder);
@@ -7311,14 +7313,8 @@ void tool_change(const uint8_t tmp_extruder, const float fr_mm_s/*=0.0*/, bool n
7311 7313
 
7312 7314
             // Move back down, if needed
7313 7315
             if (z_raise != z_diff) {
7314
-              planner.buffer_line(
7315
-                current_position[X_AXIS],
7316
-                current_position[Y_AXIS],
7317
-                current_position[Z_AXIS] + z_diff,
7318
-                current_position[E_AXIS],
7319
-                planner.max_feedrate_mm_s[Z_AXIS],
7320
-                active_extruder
7321
-              );
7316
+              destination[Z_AXIS] = current_position[Z_AXIS] + z_diff;
7317
+              planner.buffer_line_kinematic(destination, planner.max_feedrate_mm_s[Z_AXIS], active_extruder);
7322 7318
               stepper.synchronize();
7323 7319
             }
7324 7320
           #endif
@@ -8670,8 +8666,7 @@ void set_current_from_steppers_for_axis(const AxisEnum axis) {
8670 8666
 
8671 8667
     // If the move is only in Z/E don't split up the move
8672 8668
     if (ltarget[X_AXIS] == current_position[X_AXIS] && ltarget[Y_AXIS] == current_position[Y_AXIS]) {
8673
-      inverse_kinematics(ltarget);
8674
-      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);
8675 8670
       return true;
8676 8671
     }
8677 8672
 
@@ -8764,7 +8759,10 @@ void set_current_from_steppers_for_axis(const AxisEnum axis) {
8764 8759
       #define DELTA_NEXT(ADDEND) LOOP_XYZ(i) DELTA_VAR[i] += ADDEND;
8765 8760
 
8766 8761
       // Get the starting delta if interpolation is possible
8767
-      if (segments >= 2) DELTA_IK();
8762
+      if (segments >= 2) {
8763
+        DELTA_IK();
8764
+        ADJUST_DELTA(DELTA_VAR); // Adjust Z if bed leveling is enabled
8765
+      }
8768 8766
 
8769 8767
       // Loop using decrement
8770 8768
       for (uint16_t s = segments + 1; --s;) {
@@ -8781,6 +8779,7 @@ void set_current_from_steppers_for_axis(const AxisEnum axis) {
8781 8779
 
8782 8780
           // Get the exact delta for the move after this
8783 8781
           DELTA_IK();
8782
+          ADJUST_DELTA(DELTA_VAR); // Adjust Z if bed leveling is enabled
8784 8783
 
8785 8784
           // Move to the interpolated delta position first
8786 8785
           planner.buffer_line(
@@ -8801,6 +8800,7 @@ void set_current_from_steppers_for_axis(const AxisEnum axis) {
8801 8800
           DELTA_NEXT(segment_distance[i]);
8802 8801
           DELTA_VAR[E_AXIS] += segment_distance[E_AXIS];
8803 8802
           DELTA_IK();
8803
+          ADJUST_DELTA(DELTA_VAR); // Adjust Z if bed leveling is enabled
8804 8804
         }
8805 8805
 
8806 8806
         // Move to the non-interpolated position
@@ -8815,6 +8815,7 @@ void set_current_from_steppers_for_axis(const AxisEnum axis) {
8815 8815
       for (uint16_t s = segments + 1; --s;) {
8816 8816
         DELTA_NEXT(segment_distance[i]);
8817 8817
         DELTA_IK();
8818
+        ADJUST_DELTA(DELTA_VAR);
8818 8819
         planner.buffer_line(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], DELTA_VAR[E_AXIS], _feedrate_mm_s, active_extruder);
8819 8820
       }
8820 8821
 
@@ -8822,8 +8823,7 @@ void set_current_from_steppers_for_axis(const AxisEnum axis) {
8822 8823
 
8823 8824
     // Since segment_distance is only approximate,
8824 8825
     // the final move must be to the exact destination.
8825
-    inverse_kinematics(ltarget);
8826
-    planner.buffer_line(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], ltarget[E_AXIS], _feedrate_mm_s, active_extruder);
8826
+    planner.buffer_line_kinematic(ltarget, _feedrate_mm_s, active_extruder);
8827 8827
     return true;
8828 8828
   }
8829 8829
 
@@ -9063,21 +9063,11 @@ void prepare_move_to_destination() {
9063 9063
 
9064 9064
       clamp_to_software_endstops(arc_target);
9065 9065
 
9066
-      #if IS_KINEMATIC
9067
-        inverse_kinematics(arc_target);
9068
-        planner.buffer_line(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], arc_target[E_AXIS], fr_mm_s, active_extruder);
9069
-      #else
9070
-        planner.buffer_line(arc_target[X_AXIS], arc_target[Y_AXIS], arc_target[Z_AXIS], arc_target[E_AXIS], fr_mm_s, active_extruder);
9071
-      #endif
9066
+      planner.buffer_line_kinematic(arc_target, fr_mm_s, active_extruder);
9072 9067
     }
9073 9068
 
9074 9069
     // Ensure last segment arrives at target location.
9075
-    #if IS_KINEMATIC
9076
-      inverse_kinematics(logical);
9077
-      planner.buffer_line(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], logical[E_AXIS], fr_mm_s, active_extruder);
9078
-    #else
9079
-      planner.buffer_line(logical[X_AXIS], logical[Y_AXIS], logical[Z_AXIS], logical[E_AXIS], fr_mm_s, active_extruder);
9080
-    #endif
9070
+    planner.buffer_line_kinematic(logical, fr_mm_s, active_extruder);
9081 9071
 
9082 9072
     // As far as the parser is concerned, the position is now == target. In reality the
9083 9073
     // motion control system might still be processing the action and the real tool position
@@ -9472,11 +9462,22 @@ void manage_inactivity(bool ignore_stepper_queue/*=false*/) {
9472 9462
       #endif // !SWITCHING_EXTRUDER
9473 9463
 
9474 9464
       previous_cmd_ms = ms; // refresh_cmd_timeout()
9475
-      planner.buffer_line(
9476
-        current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS],
9477
-        current_position[E_AXIS] + EXTRUDER_RUNOUT_EXTRUDE,
9478
-        MMM_TO_MMS(EXTRUDER_RUNOUT_SPEED), active_extruder
9479
-      );
9465
+
9466
+      #if IS_KINEMATIC
9467
+        inverse_kinematics(current_position);
9468
+        ADJUST_DELTA(current_position);
9469
+        planner.buffer_line(
9470
+          delta[A_AXIS], delta[B_AXIS], delta[C_AXIS],
9471
+          current_position[E_AXIS] + EXTRUDER_RUNOUT_EXTRUDE,
9472
+          MMM_TO_MMS(EXTRUDER_RUNOUT_SPEED), active_extruder
9473
+        );
9474
+      #else
9475
+        planner.buffer_line(
9476
+          current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS],
9477
+          current_position[E_AXIS] + EXTRUDER_RUNOUT_EXTRUDE,
9478
+          MMM_TO_MMS(EXTRUDER_RUNOUT_SPEED), active_extruder
9479
+        );
9480
+      #endif
9480 9481
       stepper.synchronize();
9481 9482
       planner.set_e_position_mm(current_position[E_AXIS]);
9482 9483
       #if ENABLED(SWITCHING_EXTRUDER)

+ 4
- 0
Marlin/SanityCheck.h ファイルの表示

@@ -518,6 +518,10 @@
518 518
  */
519 519
 #if HAS_ABL
520 520
 
521
+  #if ENABLED(USE_RAW_KINEMATICS)
522
+    #error "USE_RAW_KINEMATICS is not compatible with AUTO_BED_LEVELING"
523
+  #endif
524
+
521 525
   /**
522 526
    * Delta and SCARA have limited bed leveling options
523 527
    */

+ 4
- 1
Marlin/configuration_store.cpp ファイルの表示

@@ -589,7 +589,10 @@ void Config_ResetDefault() {
589 589
   #endif
590 590
 
591 591
   #if ENABLED(DELTA)
592
-    endstop_adj[X_AXIS] = endstop_adj[Y_AXIS] = endstop_adj[Z_AXIS] = 0;
592
+    const float adj[ABC] = DELTA_ENDSTOP_ADJ;
593
+    endstop_adj[A_AXIS] = adj[A_AXIS];
594
+    endstop_adj[B_AXIS] = adj[B_AXIS];
595
+    endstop_adj[C_AXIS] = adj[C_AXIS];
593 596
     delta_radius =  DELTA_RADIUS;
594 597
     delta_diagonal_rod =  DELTA_DIAGONAL_ROD;
595 598
     delta_segments_per_second =  DELTA_SEGMENTS_PER_SECOND;

+ 2
- 0
Marlin/example_configurations/delta/biv2.5/Configuration.h ファイルの表示

@@ -441,6 +441,8 @@
441 441
   // in ultralcd.cpp@lcd_delta_calibrate_menu()
442 442
   //#define DELTA_CALIBRATION_MENU
443 443
 
444
+  //#define DELTA_ENDSTOP_ADJ { 0, 0, 0 }
445
+
444 446
 #endif
445 447
 
446 448
 // Enable this option for Toshiba steppers

+ 2
- 0
Marlin/example_configurations/delta/generic/Configuration.h ファイルの表示

@@ -441,6 +441,8 @@
441 441
   // in ultralcd.cpp@lcd_delta_calibrate_menu()
442 442
   //#define DELTA_CALIBRATION_MENU
443 443
 
444
+  //#define DELTA_ENDSTOP_ADJ { 0, 0, 0 }
445
+
444 446
 #endif
445 447
 
446 448
 // Enable this option for Toshiba steppers

+ 2
- 0
Marlin/example_configurations/delta/kossel_mini/Configuration.h ファイルの表示

@@ -441,6 +441,8 @@
441 441
   // in ultralcd.cpp@lcd_delta_calibrate_menu()
442 442
   //#define DELTA_CALIBRATION_MENU
443 443
 
444
+  //#define DELTA_ENDSTOP_ADJ { 0, 0, 0 }
445
+
444 446
 #endif
445 447
 
446 448
 // Enable this option for Toshiba steppers

+ 2
- 0
Marlin/example_configurations/delta/kossel_pro/Configuration.h ファイルの表示

@@ -430,6 +430,8 @@
430 430
   // in ultralcd.cpp@lcd_delta_calibrate_menu()
431 431
   //#define DELTA_CALIBRATION_MENU
432 432
 
433
+  //#define DELTA_ENDSTOP_ADJ { 0, 0, 0 }
434
+
433 435
 #endif
434 436
 
435 437
 // Enable this option for Toshiba steppers

+ 2
- 0
Marlin/example_configurations/delta/kossel_xl/Configuration.h ファイルの表示

@@ -439,6 +439,8 @@
439 439
   // in ultralcd.cpp@lcd_delta_calibrate_menu()
440 440
   //#define DELTA_CALIBRATION_MENU
441 441
 
442
+  //#define DELTA_ENDSTOP_ADJ { 0, 0, 0 }
443
+
442 444
 #endif
443 445
 
444 446
 // Enable this option for Toshiba steppers

+ 102
- 107
Marlin/planner.cpp ファイルの表示

@@ -522,7 +522,9 @@ void Planner::check_axes_activity() {
522 522
 }
523 523
 
524 524
 #if PLANNER_LEVELING
525
-
525
+  /**
526
+   * lx, ly, lz - logical (cartesian, not delta) positions in mm
527
+   */
526 528
   void Planner::apply_leveling(float &lx, float &ly, float &lz) {
527 529
 
528 530
     #if HAS_ABL
@@ -549,19 +551,7 @@ void Planner::check_axes_activity() {
549 551
     #elif ENABLED(AUTO_BED_LEVELING_BILINEAR)
550 552
 
551 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 556
     #endif
567 557
   }
@@ -601,15 +591,17 @@ void Planner::check_axes_activity() {
601 591
 #endif // PLANNER_LEVELING
602 592
 
603 593
 /**
604
- * Planner::buffer_line
594
+ * Planner::_buffer_line
605 595
  *
606 596
  * Add a new linear movement to the buffer.
607 597
  *
608
- *  x,y,z,e   - target position in mm
609
- *  fr_mm_s   - (target) speed of the move
610
- *  extruder  - target extruder
598
+ * Leveling and kinematics should be applied ahead of calling this.
599
+ *
600
+ *  a,b,c,e     - target positions in mm or degrees
601
+ *  fr_mm_s     - (target) speed of the move
602
+ *  extruder    - target extruder
611 603
  */
612
-void Planner::buffer_line(ARG_X, ARG_Y, ARG_Z, const float &e, float fr_mm_s, const uint8_t extruder) {
604
+void Planner::_buffer_line(const float &a, const float &b, const float &c, const float &e, float fr_mm_s, const uint8_t extruder) {
613 605
   // Calculate the buffer head after we push this byte
614 606
   int next_buffer_head = next_block_index(block_buffer_head);
615 607
 
@@ -617,43 +609,39 @@ void Planner::buffer_line(ARG_X, ARG_Y, ARG_Z, const float &e, float fr_mm_s, co
617 609
   // Rest here until there is room in the buffer.
618 610
   while (block_buffer_tail == next_buffer_head) idle();
619 611
 
620
-  #if PLANNER_LEVELING
621
-    apply_leveling(lx, ly, lz);
622
-  #endif
623
-
624 612
   // The target position of the tool in absolute steps
625 613
   // Calculate target position in absolute steps
626 614
   //this should be done after the wait, because otherwise a M92 code within the gcode disrupts this calculation somehow
627
-  long target[NUM_AXIS] = {
628
-    lround(lx * axis_steps_per_mm[X_AXIS]),
629
-    lround(ly * axis_steps_per_mm[Y_AXIS]),
630
-    lround(lz * axis_steps_per_mm[Z_AXIS]),
615
+  long target[XYZE] = {
616
+    lround(a * axis_steps_per_mm[X_AXIS]),
617
+    lround(b * axis_steps_per_mm[Y_AXIS]),
618
+    lround(c * axis_steps_per_mm[Z_AXIS]),
631 619
     lround(e * axis_steps_per_mm[E_AXIS])
632 620
   };
633 621
 
634
-  long dx = target[X_AXIS] - position[X_AXIS],
635
-       dy = target[Y_AXIS] - position[Y_AXIS],
636
-       dz = target[Z_AXIS] - position[Z_AXIS];
622
+  long da = target[X_AXIS] - position[X_AXIS],
623
+       db = target[Y_AXIS] - position[Y_AXIS],
624
+       dc = target[Z_AXIS] - position[Z_AXIS];
637 625
 
638 626
   /*
639 627
   SERIAL_ECHOPAIR("  Planner FR:", fr_mm_s);
640 628
   SERIAL_CHAR(' ');
641 629
   #if IS_KINEMATIC
642
-    SERIAL_ECHOPAIR("A:", lx);
643
-    SERIAL_ECHOPAIR(" (", dx);
644
-    SERIAL_ECHOPAIR(") B:", ly);
630
+    SERIAL_ECHOPAIR("A:", a);
631
+    SERIAL_ECHOPAIR(" (", da);
632
+    SERIAL_ECHOPAIR(") B:", b);
645 633
   #else
646
-    SERIAL_ECHOPAIR("X:", lx);
647
-    SERIAL_ECHOPAIR(" (", dx);
648
-    SERIAL_ECHOPAIR(") Y:", ly);
634
+    SERIAL_ECHOPAIR("X:", a);
635
+    SERIAL_ECHOPAIR(" (", da);
636
+    SERIAL_ECHOPAIR(") Y:", b);
649 637
   #endif
650
-  SERIAL_ECHOPAIR(" (", dy);
638
+  SERIAL_ECHOPAIR(" (", db);
651 639
   #if ENABLED(DELTA)
652
-    SERIAL_ECHOPAIR(") C:", lz);
640
+    SERIAL_ECHOPAIR(") C:", c);
653 641
   #else
654
-    SERIAL_ECHOPAIR(") Z:", lz);
642
+    SERIAL_ECHOPAIR(") Z:", c);
655 643
   #endif
656
-  SERIAL_ECHOPAIR(" (", dz);
644
+  SERIAL_ECHOPAIR(" (", dc);
657 645
   SERIAL_CHAR(')');
658 646
   SERIAL_EOL;
659 647
   //*/
@@ -692,24 +680,24 @@ void Planner::buffer_line(ARG_X, ARG_Y, ARG_Z, const float &e, float fr_mm_s, co
692 680
   #if ENABLED(COREXY)
693 681
     // corexy planning
694 682
     // these equations follow the form of the dA and dB equations on http://www.corexy.com/theory.html
695
-    block->steps[A_AXIS] = labs(dx + dy);
696
-    block->steps[B_AXIS] = labs(dx - dy);
697
-    block->steps[Z_AXIS] = labs(dz);
683
+    block->steps[A_AXIS] = labs(da + db);
684
+    block->steps[B_AXIS] = labs(da - db);
685
+    block->steps[Z_AXIS] = labs(dc);
698 686
   #elif ENABLED(COREXZ)
699 687
     // corexz planning
700
-    block->steps[A_AXIS] = labs(dx + dz);
701
-    block->steps[Y_AXIS] = labs(dy);
702
-    block->steps[C_AXIS] = labs(dx - dz);
688
+    block->steps[A_AXIS] = labs(da + dc);
689
+    block->steps[Y_AXIS] = labs(db);
690
+    block->steps[C_AXIS] = labs(da - dc);
703 691
   #elif ENABLED(COREYZ)
704 692
     // coreyz planning
705
-    block->steps[X_AXIS] = labs(dx);
706
-    block->steps[B_AXIS] = labs(dy + dz);
707
-    block->steps[C_AXIS] = labs(dy - dz);
693
+    block->steps[X_AXIS] = labs(da);
694
+    block->steps[B_AXIS] = labs(db + dc);
695
+    block->steps[C_AXIS] = labs(db - dc);
708 696
   #else
709 697
     // default non-h-bot planning
710
-    block->steps[X_AXIS] = labs(dx);
711
-    block->steps[Y_AXIS] = labs(dy);
712
-    block->steps[Z_AXIS] = labs(dz);
698
+    block->steps[X_AXIS] = labs(da);
699
+    block->steps[Y_AXIS] = labs(db);
700
+    block->steps[Z_AXIS] = labs(dc);
713 701
   #endif
714 702
 
715 703
   block->steps[E_AXIS] = labs(de) * volumetric_multiplier[extruder] * flow_percentage[extruder] * 0.01 + 0.5;
@@ -733,33 +721,33 @@ void Planner::buffer_line(ARG_X, ARG_Y, ARG_Z, const float &e, float fr_mm_s, co
733 721
     block->e_to_p_pressure = baricuda_e_to_p_pressure;
734 722
   #endif
735 723
 
736
-  // Compute direction bits for this block
737
-  uint8_t db = 0;
724
+  // Compute direction bit-mask for this block
725
+  uint8_t dm = 0;
738 726
   #if ENABLED(COREXY)
739
-    if (dx < 0) SBI(db, X_HEAD); // Save the real Extruder (head) direction in X Axis
740
-    if (dy < 0) SBI(db, Y_HEAD); // ...and Y
741
-    if (dz < 0) SBI(db, Z_AXIS);
742
-    if (dx + dy < 0) SBI(db, A_AXIS); // Motor A direction
743
-    if (dx - dy < 0) SBI(db, B_AXIS); // Motor B direction
727
+    if (da < 0) SBI(dm, X_HEAD); // Save the real Extruder (head) direction in X Axis
728
+    if (db < 0) SBI(dm, Y_HEAD); // ...and Y
729
+    if (dc < 0) SBI(dm, Z_AXIS);
730
+    if (da + db < 0) SBI(dm, A_AXIS); // Motor A direction
731
+    if (da - db < 0) SBI(dm, B_AXIS); // Motor B direction
744 732
   #elif ENABLED(COREXZ)
745
-    if (dx < 0) SBI(db, X_HEAD); // Save the real Extruder (head) direction in X Axis
746
-    if (dy < 0) SBI(db, Y_AXIS);
747
-    if (dz < 0) SBI(db, Z_HEAD); // ...and Z
748
-    if (dx + dz < 0) SBI(db, A_AXIS); // Motor A direction
749
-    if (dx - dz < 0) SBI(db, C_AXIS); // Motor C direction
733
+    if (da < 0) SBI(dm, X_HEAD); // Save the real Extruder (head) direction in X Axis
734
+    if (db < 0) SBI(dm, Y_AXIS);
735
+    if (dc < 0) SBI(dm, Z_HEAD); // ...and Z
736
+    if (da + dc < 0) SBI(dm, A_AXIS); // Motor A direction
737
+    if (da - dc < 0) SBI(dm, C_AXIS); // Motor C direction
750 738
   #elif ENABLED(COREYZ)
751
-    if (dx < 0) SBI(db, X_AXIS);
752
-    if (dy < 0) SBI(db, Y_HEAD); // Save the real Extruder (head) direction in Y Axis
753
-    if (dz < 0) SBI(db, Z_HEAD); // ...and Z
754
-    if (dy + dz < 0) SBI(db, B_AXIS); // Motor B direction
755
-    if (dy - dz < 0) SBI(db, C_AXIS); // Motor C direction
739
+    if (da < 0) SBI(dm, X_AXIS);
740
+    if (db < 0) SBI(dm, Y_HEAD); // Save the real Extruder (head) direction in Y Axis
741
+    if (dc < 0) SBI(dm, Z_HEAD); // ...and Z
742
+    if (db + dc < 0) SBI(dm, B_AXIS); // Motor B direction
743
+    if (db - dc < 0) SBI(dm, C_AXIS); // Motor C direction
756 744
   #else
757
-    if (dx < 0) SBI(db, X_AXIS);
758
-    if (dy < 0) SBI(db, Y_AXIS);
759
-    if (dz < 0) SBI(db, Z_AXIS);
745
+    if (da < 0) SBI(dm, X_AXIS);
746
+    if (db < 0) SBI(dm, Y_AXIS);
747
+    if (dc < 0) SBI(dm, Z_AXIS);
760 748
   #endif
761
-  if (de < 0) SBI(db, E_AXIS);
762
-  block->direction_bits = db;
749
+  if (de < 0) SBI(dm, E_AXIS);
750
+  block->direction_bits = dm;
763 751
 
764 752
   block->active_extruder = extruder;
765 753
 
@@ -872,29 +860,29 @@ void Planner::buffer_line(ARG_X, ARG_Y, ARG_Z, const float &e, float fr_mm_s, co
872 860
   #if ENABLED(COREXY) || ENABLED(COREXZ) || ENABLED(COREYZ)
873 861
     float delta_mm[7];
874 862
     #if ENABLED(COREXY)
875
-      delta_mm[X_HEAD] = dx * steps_to_mm[A_AXIS];
876
-      delta_mm[Y_HEAD] = dy * steps_to_mm[B_AXIS];
877
-      delta_mm[Z_AXIS] = dz * steps_to_mm[Z_AXIS];
878
-      delta_mm[A_AXIS] = (dx + dy) * steps_to_mm[A_AXIS];
879
-      delta_mm[B_AXIS] = (dx - dy) * steps_to_mm[B_AXIS];
863
+      delta_mm[X_HEAD] = da * steps_to_mm[A_AXIS];
864
+      delta_mm[Y_HEAD] = db * steps_to_mm[B_AXIS];
865
+      delta_mm[Z_AXIS] = dc * steps_to_mm[Z_AXIS];
866
+      delta_mm[A_AXIS] = (da + db) * steps_to_mm[A_AXIS];
867
+      delta_mm[B_AXIS] = (da - db) * steps_to_mm[B_AXIS];
880 868
     #elif ENABLED(COREXZ)
881
-      delta_mm[X_HEAD] = dx * steps_to_mm[A_AXIS];
882
-      delta_mm[Y_AXIS] = dy * steps_to_mm[Y_AXIS];
883
-      delta_mm[Z_HEAD] = dz * steps_to_mm[C_AXIS];
884
-      delta_mm[A_AXIS] = (dx + dz) * steps_to_mm[A_AXIS];
885
-      delta_mm[C_AXIS] = (dx - dz) * steps_to_mm[C_AXIS];
869
+      delta_mm[X_HEAD] = da * steps_to_mm[A_AXIS];
870
+      delta_mm[Y_AXIS] = db * steps_to_mm[Y_AXIS];
871
+      delta_mm[Z_HEAD] = dc * steps_to_mm[C_AXIS];
872
+      delta_mm[A_AXIS] = (da + dc) * steps_to_mm[A_AXIS];
873
+      delta_mm[C_AXIS] = (da - dc) * steps_to_mm[C_AXIS];
886 874
     #elif ENABLED(COREYZ)
887
-      delta_mm[X_AXIS] = dx * steps_to_mm[X_AXIS];
888
-      delta_mm[Y_HEAD] = dy * steps_to_mm[B_AXIS];
889
-      delta_mm[Z_HEAD] = dz * steps_to_mm[C_AXIS];
890
-      delta_mm[B_AXIS] = (dy + dz) * steps_to_mm[B_AXIS];
891
-      delta_mm[C_AXIS] = (dy - dz) * steps_to_mm[C_AXIS];
875
+      delta_mm[X_AXIS] = da * steps_to_mm[X_AXIS];
876
+      delta_mm[Y_HEAD] = db * steps_to_mm[B_AXIS];
877
+      delta_mm[Z_HEAD] = dc * steps_to_mm[C_AXIS];
878
+      delta_mm[B_AXIS] = (db + dc) * steps_to_mm[B_AXIS];
879
+      delta_mm[C_AXIS] = (db - dc) * steps_to_mm[C_AXIS];
892 880
     #endif
893 881
   #else
894 882
     float delta_mm[4];
895
-    delta_mm[X_AXIS] = dx * steps_to_mm[X_AXIS];
896
-    delta_mm[Y_AXIS] = dy * steps_to_mm[Y_AXIS];
897
-    delta_mm[Z_AXIS] = dz * steps_to_mm[Z_AXIS];
883
+    delta_mm[X_AXIS] = da * steps_to_mm[X_AXIS];
884
+    delta_mm[Y_AXIS] = db * steps_to_mm[Y_AXIS];
885
+    delta_mm[Z_AXIS] = dc * steps_to_mm[Z_AXIS];
898 886
   #endif
899 887
   delta_mm[E_AXIS] = 0.01 * (de * steps_to_mm[E_AXIS]) * volumetric_multiplier[extruder] * flow_percentage[extruder];
900 888
 
@@ -1196,22 +1184,34 @@ void Planner::buffer_line(ARG_X, ARG_Y, ARG_Z, const float &e, float fr_mm_s, co
1196 1184
  *
1197 1185
  * On CORE machines stepper ABC will be translated from the given XYZ.
1198 1186
  */
1199
-void Planner::set_position_mm(ARG_X, ARG_Y, ARG_Z, const float &e) {
1200 1187
 
1201
-  #if PLANNER_LEVELING
1202
-    apply_leveling(lx, ly, lz);
1203
-  #endif
1204
-
1205
-  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]),
1207
-       nz = position[Z_AXIS] = lround(lz * axis_steps_per_mm[Z_AXIS]),
1188
+void Planner::_set_position_mm(const float &a, const float &b, const float &c, const float &e) {
1189
+  long na = position[X_AXIS] = lround(a * axis_steps_per_mm[X_AXIS]),
1190
+       nb = position[Y_AXIS] = lround(b * axis_steps_per_mm[Y_AXIS]),
1191
+       nc = position[Z_AXIS] = lround(c * axis_steps_per_mm[Z_AXIS]),
1208 1192
        ne = position[E_AXIS] = lround(e * axis_steps_per_mm[E_AXIS]);
1209
-  stepper.set_position(nx, ny, nz, ne);
1193
+  stepper.set_position(na, nb, nc, ne);
1210 1194
   previous_nominal_speed = 0.0; // Resets planner junction speeds. Assumes start from rest.
1211 1195
 
1212 1196
   memset(previous_speed, 0, sizeof(previous_speed));
1213 1197
 }
1214 1198
 
1199
+void Planner::set_position_mm_kinematic(const float position[NUM_AXIS]) {
1200
+  #if PLANNER_LEVELING
1201
+    float pos[XYZ] = { position[X_AXIS], position[Y_AXIS], position[Z_AXIS] };
1202
+    apply_leveling(pos);
1203
+  #else
1204
+    const float * const pos = position;
1205
+  #endif
1206
+  #if IS_KINEMATIC
1207
+    inverse_kinematics(pos);
1208
+    _set_position_mm(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], position[E_AXIS]);
1209
+  #else
1210
+    _set_position_mm(pos[X_AXIS], pos[Y_AXIS], pos[Z_AXIS], position[E_AXIS]);
1211
+  #endif
1212
+}
1213
+
1214
+
1215 1215
 /**
1216 1216
  * Sync from the stepper positions. (e.g., after an interrupted move)
1217 1217
  */
@@ -1237,12 +1237,7 @@ void Planner::reset_acceleration_rates() {
1237 1237
 // Recalculate position, steps_to_mm if axis_steps_per_mm changes!
1238 1238
 void Planner::refresh_positioning() {
1239 1239
   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
1240
+  set_position_mm_kinematic(current_position);
1246 1241
   reset_acceleration_rates();
1247 1242
 }
1248 1243
 

+ 66
- 5
Marlin/planner.h ファイルの表示

@@ -43,6 +43,12 @@
43 43
 class Planner;
44 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 53
  * struct block_t
48 54
  *
@@ -218,18 +224,68 @@ class Planner {
218 224
        * as it will be given to the planner and steppers.
219 225
        */
220 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 228
       static void unapply_leveling(float logical[XYZ]);
222 229
 
223 230
     #endif
224 231
 
225 232
     /**
226
-     * Add a new linear movement to the buffer.
233
+     * Planner::_buffer_line
227 234
      *
228
-     *  x,y,z,e   - target position in mm
235
+     * Add a new direct linear movement to the buffer.
236
+     *
237
+     * Leveling and kinematics should be applied ahead of this.
238
+     *
239
+     *  a,b,c,e   - target position in mm or degrees
229 240
      *  fr_mm_s   - (target) speed of the move (mm/s)
230 241
      *  extruder  - target extruder
231 242
      */
232
-    static void buffer_line(ARG_X, ARG_Y, ARG_Z, const float& e, float fr_mm_s, const uint8_t extruder);
243
+    static void _buffer_line(const float &a, const float &b, const float &c, const float &e, float fr_mm_s, const uint8_t extruder);
244
+
245
+    static void _set_position_mm(const float &a, const float &b, const float &c, const float &e);
246
+
247
+    /**
248
+     * Add a new linear movement to the buffer.
249
+     * The target is NOT translated to delta/scara
250
+     *
251
+     * Leveling will be applied to input on cartesians.
252
+     * Kinematic machines should call buffer_line_kinematic (for leveled moves).
253
+     * (Cartesians may also call buffer_line_kinematic.)
254
+     *
255
+     *  lx,ly,lz,e   - target position in mm or degrees
256
+     *  fr_mm_s      - (target) speed of the move (mm/s)
257
+     *  extruder     - target extruder
258
+     */
259
+    static FORCE_INLINE void buffer_line(ARG_X, ARG_Y, ARG_Z, const float &e, float fr_mm_s, const uint8_t extruder) {
260
+      #if PLANNER_LEVELING && IS_CARTESIAN
261
+        apply_leveling(lx, ly, lz);
262
+      #endif
263
+      _buffer_line(lx, ly, lz, e, fr_mm_s, extruder);
264
+    }
265
+
266
+    /**
267
+     * Add a new linear movement to the buffer.
268
+     * The target is cartesian, it's translated to delta/scara if
269
+     * needed.
270
+     *
271
+     *  target   - x,y,z,e CARTESIAN target in mm
272
+     *  fr_mm_s  - (target) speed of the move (mm/s)
273
+     *  extruder - target extruder
274
+     */
275
+    static FORCE_INLINE void buffer_line_kinematic(const float target[XYZE], float fr_mm_s, const uint8_t extruder) {
276
+      #if PLANNER_LEVELING
277
+        float pos[XYZ] = { target[X_AXIS], target[Y_AXIS], target[Z_AXIS] };
278
+        apply_leveling(pos);
279
+      #else
280
+        const float * const pos = target;
281
+      #endif
282
+      #if IS_KINEMATIC
283
+        inverse_kinematics(pos);
284
+        _buffer_line(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], target[E_AXIS], fr_mm_s, extruder);
285
+      #else
286
+        _buffer_line(pos[X_AXIS], pos[Y_AXIS], pos[Z_AXIS], target[E_AXIS], fr_mm_s, extruder);
287
+      #endif
288
+    }
233 289
 
234 290
     /**
235 291
      * Set the planner.position and individual stepper positions.
@@ -240,9 +296,14 @@ class Planner {
240 296
      *
241 297
      * Clears previous speed values.
242 298
      */
243
-    static void set_position_mm(ARG_X, ARG_Y, ARG_Z, const float& e);
299
+    static FORCE_INLINE void set_position_mm(ARG_X, ARG_Y, ARG_Z, const float &e) {
300
+      #if PLANNER_LEVELING && IS_CARTESIAN
301
+        apply_leveling(lx, ly, lz);
302
+      #endif
303
+      _set_position_mm(lx, ly, lz, e);
304
+    }
305
+    static void set_position_mm_kinematic(const float position[NUM_AXIS]);
244 306
     static void set_position_mm(const AxisEnum axis, const float& v);
245
-
246 307
     static FORCE_INLINE void set_z_position_mm(const float& z) { set_position_mm(Z_AXIS, z); }
247 308
     static FORCE_INLINE void set_e_position_mm(const float& e) { set_position_mm(E_AXIS, e); }
248 309
 

+ 1
- 7
Marlin/planner_bezier.cpp ファイルの表示

@@ -187,13 +187,7 @@ void cubic_b_spline(const float position[NUM_AXIS], const float target[NUM_AXIS]
187 187
     bez_target[Z_AXIS] = interp(position[Z_AXIS], target[Z_AXIS], t);
188 188
     bez_target[E_AXIS] = interp(position[E_AXIS], target[E_AXIS], t);
189 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
 

+ 15
- 15
Marlin/stepper.cpp ファイルの表示

@@ -966,7 +966,7 @@ void Stepper::synchronize() { while (planner.blocks_queued()) idle(); }
966 966
  * This allows get_axis_position_mm to correctly
967 967
  * derive the current XYZ position later on.
968 968
  */
969
-void Stepper::set_position(const long& x, const long& y, const long& z, const long& e) {
969
+void Stepper::set_position(const long &a, const long &b, const long &c, const long &e) {
970 970
 
971 971
   synchronize(); // Bad to set stepper counts in the middle of a move
972 972
 
@@ -975,37 +975,37 @@ void Stepper::set_position(const long& x, const long& y, const long& z, const lo
975 975
   #if ENABLED(COREXY)
976 976
     // corexy positioning
977 977
     // these equations follow the form of the dA and dB equations on http://www.corexy.com/theory.html
978
-    count_position[A_AXIS] = x + y;
979
-    count_position[B_AXIS] = x - y;
980
-    count_position[Z_AXIS] = z;
978
+    count_position[A_AXIS] = a + b;
979
+    count_position[B_AXIS] = a - b;
980
+    count_position[Z_AXIS] = c;
981 981
   #elif ENABLED(COREXZ)
982 982
     // corexz planning
983
-    count_position[A_AXIS] = x + z;
984
-    count_position[Y_AXIS] = y;
985
-    count_position[C_AXIS] = x - z;
983
+    count_position[A_AXIS] = a + c;
984
+    count_position[Y_AXIS] = b;
985
+    count_position[C_AXIS] = a - c;
986 986
   #elif ENABLED(COREYZ)
987 987
     // coreyz planning
988
-    count_position[X_AXIS] = x;
989
-    count_position[B_AXIS] = y + z;
990
-    count_position[C_AXIS] = y - z;
988
+    count_position[X_AXIS] = a;
989
+    count_position[B_AXIS] = y + c;
990
+    count_position[C_AXIS] = y - c;
991 991
   #else
992 992
     // default non-h-bot planning
993
-    count_position[X_AXIS] = x;
994
-    count_position[Y_AXIS] = y;
995
-    count_position[Z_AXIS] = z;
993
+    count_position[X_AXIS] = a;
994
+    count_position[Y_AXIS] = b;
995
+    count_position[Z_AXIS] = c;
996 996
   #endif
997 997
 
998 998
   count_position[E_AXIS] = e;
999 999
   CRITICAL_SECTION_END;
1000 1000
 }
1001 1001
 
1002
-void Stepper::set_position(const AxisEnum &axis, const long& v) {
1002
+void Stepper::set_position(const AxisEnum &axis, const long &v) {
1003 1003
   CRITICAL_SECTION_START;
1004 1004
   count_position[axis] = v;
1005 1005
   CRITICAL_SECTION_END;
1006 1006
 }
1007 1007
 
1008
-void Stepper::set_e_position(const long& e) {
1008
+void Stepper::set_e_position(const long &e) {
1009 1009
   CRITICAL_SECTION_START;
1010 1010
   count_position[E_AXIS] = e;
1011 1011
   CRITICAL_SECTION_END;

+ 3
- 3
Marlin/stepper.h ファイルの表示

@@ -188,9 +188,9 @@ class Stepper {
188 188
     //
189 189
     // Set the current position in steps
190 190
     //
191
-    static void set_position(const long& x, const long& y, const long& z, const long& e);
192
-    static void set_position(const AxisEnum& a, const long& v);
193
-    static void set_e_position(const long& e);
191
+    static void set_position(const long &a, const long &b, const long &c, const long &e);
192
+    static void set_position(const AxisEnum &a, const long &v);
193
+    static void set_e_position(const long &e);
194 194
 
195 195
     //
196 196
     // Set direction bits for all steppers

+ 2
- 12
Marlin/ultralcd.cpp ファイルの表示

@@ -561,12 +561,7 @@ void kill_screen(const char* lcd_msg) {
561 561
 #if ENABLED(ULTIPANEL)
562 562
 
563 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 567
   #if ENABLED(SDSUPPORT)
@@ -1351,12 +1346,7 @@ void kill_screen(const char* lcd_msg) {
1351 1346
    */
1352 1347
   inline void manage_manual_move() {
1353 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 1350
       manual_move_axis = (int8_t)NO_AXIS;
1361 1351
     }
1362 1352
   }

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