Browse Source

Add an option to segment leveled moves

Scott Lahteine 6 years ago
parent
commit
d786fb99e2
4 changed files with 106 additions and 20 deletions
  1. 5
    1
      Marlin/Conditionals_post.h
  2. 5
    0
      Marlin/Configuration.h
  3. 94
    19
      Marlin/Marlin_main.cpp
  4. 2
    0
      Marlin/SanityCheck.h

+ 5
- 1
Marlin/Conditionals_post.h View File

@@ -890,7 +890,7 @@
890 890
   /**
891 891
    * Set granular options based on the specific type of leveling
892 892
    */
893
-  #define UBL_DELTA  (ENABLED(AUTO_BED_LEVELING_UBL) && (ENABLED(DELTA) || ENABLED(UBL_GRANULAR_SEGMENTATION_FOR_CARTESIAN)))
893
+  #define UBL_DELTA  (ENABLED(AUTO_BED_LEVELING_UBL) && (ENABLED(DELTA) || ENABLED(SEGMENT_LEVELED_MOVES)))
894 894
   #define ABL_PLANAR (ENABLED(AUTO_BED_LEVELING_LINEAR) || ENABLED(AUTO_BED_LEVELING_3POINT))
895 895
   #define ABL_GRID   (ENABLED(AUTO_BED_LEVELING_LINEAR) || ENABLED(AUTO_BED_LEVELING_BILINEAR))
896 896
   #define OLDSCHOOL_ABL         (ABL_PLANAR || ABL_GRID)
@@ -905,6 +905,10 @@
905 905
     #define PROBE_BED_HEIGHT abs(BACK_PROBE_BED_POSITION - (FRONT_PROBE_BED_POSITION))
906 906
   #endif
907 907
 
908
+  #if ENABLED(SEGMENT_LEVELED_MOVES) && !defined(LEVELED_SEGMENT_LENGTH)
909
+    #define LEVELED_SEGMENT_LENGTH 5
910
+  #endif
911
+
908 912
   /**
909 913
    * Bed Probing rectangular bounds
910 914
    * These can be further constrained in code for Delta and SCARA

+ 5
- 0
Marlin/Configuration.h View File

@@ -891,6 +891,11 @@
891 891
   // The height can be set with M420 Z<height>
892 892
   #define ENABLE_LEVELING_FADE_HEIGHT
893 893
 
894
+  // For Cartesian machines, instead of dividing moves on mesh boundaries,
895
+  // split up moves into short segments like a Delta.
896
+  #define SEGMENT_LEVELED_MOVES
897
+  #define LEVELED_SEGMENT_LENGTH 5.0 // (mm) Length of all segments (except the last one)
898
+
894 899
   /**
895 900
    * Enable the G26 Mesh Validation Pattern tool.
896 901
    */

+ 94
- 19
Marlin/Marlin_main.cpp View File

@@ -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.

+ 2
- 0
Marlin/SanityCheck.h View File

@@ -220,6 +220,8 @@
220 220
   #error "ENABLE_MESH_EDIT_GFX_OVERLAY is now MESH_EDIT_GFX_OVERLAY. Please update your configuration."
221 221
 #elif defined(BABYSTEP_ZPROBE_GFX_REVERSE)
222 222
   #error "BABYSTEP_ZPROBE_GFX_REVERSE is now set by OVERLAY_GFX_REVERSE. Please update your configurations."
223
+#elif defined(UBL_GRANULAR_SEGMENTATION_FOR_CARTESIAN)
224
+  #error "UBL_GRANULAR_SEGMENTATION_FOR_CARTESIAN is now SEGMENT_LEVELED_MOVES. Please update your configuration."
223 225
 #endif
224 226
 
225 227
 /**

Loading…
Cancel
Save