|
@@ -12531,7 +12531,81 @@ void set_current_from_steppers_for_axis(const AxisEnum axis) {
|
12531
|
12531
|
current_position[axis] = cartes[axis];
|
12532
|
12532
|
}
|
12533
|
12533
|
|
12534
|
|
-#if ENABLED(MESH_BED_LEVELING)
|
|
12534
|
+#if IS_CARTESIAN
|
|
12535
|
+#if ENABLED(SEGMENT_LEVELED_MOVES)
|
|
12536
|
+
|
|
12537
|
+ /**
|
|
12538
|
+ * Prepare a segmented move on a CARTESIAN setup.
|
|
12539
|
+ *
|
|
12540
|
+ * This calls planner.buffer_line several times, adding
|
|
12541
|
+ * small incremental moves. This allows the planner to
|
|
12542
|
+ * apply more detailed bed leveling to the full move.
|
|
12543
|
+ */
|
|
12544
|
+ inline void segmented_line_to_destination(const float fr_mm_s, const float segment_size=LEVELED_SEGMENT_LENGTH) {
|
|
12545
|
+
|
|
12546
|
+ const float xdiff = destination[X_AXIS] - current_position[X_AXIS],
|
|
12547
|
+ ydiff = destination[Y_AXIS] - current_position[Y_AXIS];
|
|
12548
|
+
|
|
12549
|
+ // If the move is only in Z/E don't split up the move
|
|
12550
|
+ if (!xdiff && !ydiff) {
|
|
12551
|
+ planner.buffer_line_kinematic(destination, fr_mm_s, active_extruder);
|
|
12552
|
+ return;
|
|
12553
|
+ }
|
|
12554
|
+
|
|
12555
|
+ // Remaining cartesian distances
|
|
12556
|
+ const float zdiff = destination[Z_AXIS] - current_position[Z_AXIS],
|
|
12557
|
+ ediff = destination[E_AXIS] - current_position[E_AXIS];
|
|
12558
|
+
|
|
12559
|
+ // Get the linear distance in XYZ
|
|
12560
|
+ // If the move is very short, check the E move distance
|
|
12561
|
+ // No E move either? Game over.
|
|
12562
|
+ float cartesian_mm = SQRT(sq(xdiff) + sq(ydiff) + sq(zdiff));
|
|
12563
|
+ if (UNEAR_ZERO(cartesian_mm)) cartesian_mm = FABS(ediff);
|
|
12564
|
+ if (UNEAR_ZERO(cartesian_mm)) return;
|
|
12565
|
+
|
|
12566
|
+ // The length divided by the segment size
|
|
12567
|
+ // At least one segment is required
|
|
12568
|
+ uint16_t segments = cartesian_mm / segment_size;
|
|
12569
|
+ NOLESS(segments, 1);
|
|
12570
|
+
|
|
12571
|
+ // The approximate length of each segment
|
|
12572
|
+ const float inv_segments = 1.0 / float(segments),
|
|
12573
|
+ segment_distance[XYZE] = {
|
|
12574
|
+ xdiff * inv_segments,
|
|
12575
|
+ ydiff * inv_segments,
|
|
12576
|
+ zdiff * inv_segments,
|
|
12577
|
+ ediff * inv_segments
|
|
12578
|
+ };
|
|
12579
|
+
|
|
12580
|
+ // SERIAL_ECHOPAIR("mm=", cartesian_mm);
|
|
12581
|
+ // SERIAL_ECHOLNPAIR(" segments=", segments);
|
|
12582
|
+
|
|
12583
|
+ // Drop one segment so the last move is to the exact target.
|
|
12584
|
+ // If there's only 1 segment, loops will be skipped entirely.
|
|
12585
|
+ --segments;
|
|
12586
|
+
|
|
12587
|
+ // Get the raw current position as starting point
|
|
12588
|
+ float raw[XYZE];
|
|
12589
|
+ COPY(raw, current_position);
|
|
12590
|
+
|
|
12591
|
+ // Calculate and execute the segments
|
|
12592
|
+ for (uint16_t s = segments + 1; --s;) {
|
|
12593
|
+ static millis_t next_idle_ms = millis() + 200UL;
|
|
12594
|
+ thermalManager.manage_heater(); // This returns immediately if not really needed.
|
|
12595
|
+ if (ELAPSED(millis(), next_idle_ms)) {
|
|
12596
|
+ next_idle_ms = millis() + 200UL;
|
|
12597
|
+ idle();
|
|
12598
|
+ }
|
|
12599
|
+ LOOP_XYZE(i) raw[i] += segment_distance[i];
|
|
12600
|
+ planner.buffer_line_kinematic(raw, fr_mm_s, active_extruder);
|
|
12601
|
+ }
|
|
12602
|
+
|
|
12603
|
+ // Since segment_distance is only approximate,
|
|
12604
|
+ // the final move must be to the exact destination.
|
|
12605
|
+ planner.buffer_line_kinematic(destination, fr_mm_s, active_extruder);
|
|
12606
|
+ }
|
|
12607
|
+
|
|
12608
|
+#elif ENABLED(MESH_BED_LEVELING)
|
12535
|
12609
|
|
12536
|
12610
|
/**
|
12537
|
12611
|
* Prepare a mesh-leveled linear move in a Cartesian setup,
|
|
@@ -12592,7 +12666,7 @@ void set_current_from_steppers_for_axis(const AxisEnum axis) {
|
12592
|
12666
|
mesh_line_to_destination(fr_mm_s, x_splits, y_splits);
|
12593
|
12667
|
}
|
12594
|
12668
|
|
12595
|
|
-#elif ENABLED(AUTO_BED_LEVELING_BILINEAR) && !IS_KINEMATIC
|
|
12669
|
+#elif ENABLED(AUTO_BED_LEVELING_BILINEAR)
|
12596
|
12670
|
|
12597
|
12671
|
#define CELL_INDEX(A,V) ((V - bilinear_start[A##_AXIS]) * ABL_BG_FACTOR(A##_AXIS))
|
12598
|
12672
|
|
|
@@ -12656,6 +12730,7 @@ void set_current_from_steppers_for_axis(const AxisEnum axis) {
|
12656
|
12730
|
}
|
12657
|
12731
|
|
12658
|
12732
|
#endif // AUTO_BED_LEVELING_BILINEAR
|
|
12733
|
+#endif // IS_CARTESIAN
|
12659
|
12734
|
|
12660
|
12735
|
#if !UBL_DELTA
|
12661
|
12736
|
#if IS_KINEMATIC
|
|
@@ -12674,8 +12749,11 @@ void set_current_from_steppers_for_axis(const AxisEnum axis) {
|
12674
|
12749
|
// Get the top feedrate of the move in the XY plane
|
12675
|
12750
|
const float _feedrate_mm_s = MMS_SCALED(feedrate_mm_s);
|
12676
|
12751
|
|
|
12752
|
+ const float xdiff = rtarget[X_AXIS] - current_position[X_AXIS],
|
|
12753
|
+ ydiff = rtarget[Y_AXIS] - current_position[Y_AXIS];
|
|
12754
|
+
|
12677
|
12755
|
// If the move is only in Z/E don't split up the move
|
12678
|
|
- if (rtarget[X_AXIS] == current_position[X_AXIS] && rtarget[Y_AXIS] == current_position[Y_AXIS]) {
|
|
12756
|
+ if (!xdiff && !ydiff) {
|
12679
|
12757
|
planner.buffer_line_kinematic(rtarget, _feedrate_mm_s, active_extruder);
|
12680
|
12758
|
return false;
|
12681
|
12759
|
}
|
|
@@ -12683,21 +12761,15 @@ void set_current_from_steppers_for_axis(const AxisEnum axis) {
|
12683
|
12761
|
// Fail if attempting move outside printable radius
|
12684
|
12762
|
if (!position_is_reachable(rtarget[X_AXIS], rtarget[Y_AXIS])) return true;
|
12685
|
12763
|
|
12686
|
|
- // Get the cartesian distances moved in XYZE
|
12687
|
|
- const float difference[XYZE] = {
|
12688
|
|
- rtarget[X_AXIS] - current_position[X_AXIS],
|
12689
|
|
- rtarget[Y_AXIS] - current_position[Y_AXIS],
|
12690
|
|
- rtarget[Z_AXIS] - current_position[Z_AXIS],
|
12691
|
|
- rtarget[E_AXIS] - current_position[E_AXIS]
|
12692
|
|
- };
|
|
12764
|
+ // Remaining cartesian distances
|
|
12765
|
+ const float zdiff = rtarget[Z_AXIS] - current_position[Z_AXIS],
|
|
12766
|
+ ediff = rtarget[E_AXIS] - current_position[E_AXIS];
|
12693
|
12767
|
|
12694
|
12768
|
// Get the linear distance in XYZ
|
12695
|
|
- float cartesian_mm = SQRT(sq(difference[X_AXIS]) + sq(difference[Y_AXIS]) + sq(difference[Z_AXIS]));
|
12696
|
|
-
|
12697
|
12769
|
// If the move is very short, check the E move distance
|
12698
|
|
- if (UNEAR_ZERO(cartesian_mm)) cartesian_mm = FABS(difference[E_AXIS]);
|
12699
|
|
-
|
12700
|
12770
|
// No E move either? Game over.
|
|
12771
|
+ float cartesian_mm = SQRT(sq(xdiff) + sq(ydiff) + sq(zdiff));
|
|
12772
|
+ if (UNEAR_ZERO(cartesian_mm)) cartesian_mm = FABS(ediff);
|
12701
|
12773
|
if (UNEAR_ZERO(cartesian_mm)) return true;
|
12702
|
12774
|
|
12703
|
12775
|
// Minimum number of seconds to move the given distance
|
|
@@ -12718,10 +12790,10 @@ void set_current_from_steppers_for_axis(const AxisEnum axis) {
|
12718
|
12790
|
// The approximate length of each segment
|
12719
|
12791
|
const float inv_segments = 1.0 / float(segments),
|
12720
|
12792
|
segment_distance[XYZE] = {
|
12721
|
|
- difference[X_AXIS] * inv_segments,
|
12722
|
|
- difference[Y_AXIS] * inv_segments,
|
12723
|
|
- difference[Z_AXIS] * inv_segments,
|
12724
|
|
- difference[E_AXIS] * inv_segments
|
|
12793
|
+ xdiff * inv_segments,
|
|
12794
|
+ ydiff * inv_segments,
|
|
12795
|
+ zdiff * inv_segments,
|
|
12796
|
+ ediff * inv_segments
|
12725
|
12797
|
};
|
12726
|
12798
|
|
12727
|
12799
|
// SERIAL_ECHOPAIR("mm=", cartesian_mm);
|
|
@@ -12806,10 +12878,13 @@ void set_current_from_steppers_for_axis(const AxisEnum axis) {
|
12806
|
12878
|
*/
|
12807
|
12879
|
inline bool prepare_move_to_destination_cartesian() {
|
12808
|
12880
|
#if HAS_MESH
|
12809
|
|
- if (planner.leveling_active) {
|
|
12881
|
+ if (planner.leveling_active && planner.leveling_active_at_z(destination[Z_AXIS])) {
|
12810
|
12882
|
#if ENABLED(AUTO_BED_LEVELING_UBL)
|
12811
|
12883
|
ubl.line_to_destination_cartesian(MMS_SCALED(feedrate_mm_s), active_extruder); // UBL's motion routine needs to know about
|
12812
|
12884
|
return true; // all moves, including Z-only moves.
|
|
12885
|
+ #elif ENABLED(SEGMENT_LEVELED_MOVES)
|
|
12886
|
+ segmented_line_to_destination(MMS_SCALED(feedrate_mm_s));
|
|
12887
|
+ return false;
|
12813
|
12888
|
#else
|
12814
|
12889
|
/**
|
12815
|
12890
|
* For MBL and ABL-BILINEAR only segment moves when X or Y are involved.
|