Browse Source

Add an option to segment leveled moves

Scott Lahteine 7 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
   /**
890
   /**
891
    * Set granular options based on the specific type of leveling
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
   #define ABL_PLANAR (ENABLED(AUTO_BED_LEVELING_LINEAR) || ENABLED(AUTO_BED_LEVELING_3POINT))
894
   #define ABL_PLANAR (ENABLED(AUTO_BED_LEVELING_LINEAR) || ENABLED(AUTO_BED_LEVELING_3POINT))
895
   #define ABL_GRID   (ENABLED(AUTO_BED_LEVELING_LINEAR) || ENABLED(AUTO_BED_LEVELING_BILINEAR))
895
   #define ABL_GRID   (ENABLED(AUTO_BED_LEVELING_LINEAR) || ENABLED(AUTO_BED_LEVELING_BILINEAR))
896
   #define OLDSCHOOL_ABL         (ABL_PLANAR || ABL_GRID)
896
   #define OLDSCHOOL_ABL         (ABL_PLANAR || ABL_GRID)
905
     #define PROBE_BED_HEIGHT abs(BACK_PROBE_BED_POSITION - (FRONT_PROBE_BED_POSITION))
905
     #define PROBE_BED_HEIGHT abs(BACK_PROBE_BED_POSITION - (FRONT_PROBE_BED_POSITION))
906
   #endif
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
    * Bed Probing rectangular bounds
913
    * Bed Probing rectangular bounds
910
    * These can be further constrained in code for Delta and SCARA
914
    * These can be further constrained in code for Delta and SCARA

+ 5
- 0
Marlin/Configuration.h View File

891
   // The height can be set with M420 Z<height>
891
   // The height can be set with M420 Z<height>
892
   #define ENABLE_LEVELING_FADE_HEIGHT
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
    * Enable the G26 Mesh Validation Pattern tool.
900
    * Enable the G26 Mesh Validation Pattern tool.
896
    */
901
    */

+ 94
- 19
Marlin/Marlin_main.cpp View File

12531
     current_position[axis] = cartes[axis];
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
    * Prepare a mesh-leveled linear move in a Cartesian setup,
12611
    * Prepare a mesh-leveled linear move in a Cartesian setup,
12592
     mesh_line_to_destination(fr_mm_s, x_splits, y_splits);
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
   #define CELL_INDEX(A,V) ((V - bilinear_start[A##_AXIS]) * ABL_BG_FACTOR(A##_AXIS))
12671
   #define CELL_INDEX(A,V) ((V - bilinear_start[A##_AXIS]) * ABL_BG_FACTOR(A##_AXIS))
12598
 
12672
 
12656
   }
12730
   }
12657
 
12731
 
12658
 #endif // AUTO_BED_LEVELING_BILINEAR
12732
 #endif // AUTO_BED_LEVELING_BILINEAR
12733
+#endif // IS_CARTESIAN
12659
 
12734
 
12660
 #if !UBL_DELTA
12735
 #if !UBL_DELTA
12661
 #if IS_KINEMATIC
12736
 #if IS_KINEMATIC
12674
     // Get the top feedrate of the move in the XY plane
12749
     // Get the top feedrate of the move in the XY plane
12675
     const float _feedrate_mm_s = MMS_SCALED(feedrate_mm_s);
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
     // If the move is only in Z/E don't split up the move
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
       planner.buffer_line_kinematic(rtarget, _feedrate_mm_s, active_extruder);
12757
       planner.buffer_line_kinematic(rtarget, _feedrate_mm_s, active_extruder);
12680
       return false;
12758
       return false;
12681
     }
12759
     }
12683
     // Fail if attempting move outside printable radius
12761
     // Fail if attempting move outside printable radius
12684
     if (!position_is_reachable(rtarget[X_AXIS], rtarget[Y_AXIS])) return true;
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
     // Get the linear distance in XYZ
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
     // If the move is very short, check the E move distance
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
     // No E move either? Game over.
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
     if (UNEAR_ZERO(cartesian_mm)) return true;
12773
     if (UNEAR_ZERO(cartesian_mm)) return true;
12702
 
12774
 
12703
     // Minimum number of seconds to move the given distance
12775
     // Minimum number of seconds to move the given distance
12718
     // The approximate length of each segment
12790
     // The approximate length of each segment
12719
     const float inv_segments = 1.0 / float(segments),
12791
     const float inv_segments = 1.0 / float(segments),
12720
                 segment_distance[XYZE] = {
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
     // SERIAL_ECHOPAIR("mm=", cartesian_mm);
12799
     // SERIAL_ECHOPAIR("mm=", cartesian_mm);
12806
    */
12878
    */
12807
   inline bool prepare_move_to_destination_cartesian() {
12879
   inline bool prepare_move_to_destination_cartesian() {
12808
     #if HAS_MESH
12880
     #if HAS_MESH
12809
-      if (planner.leveling_active) {
12881
+      if (planner.leveling_active && planner.leveling_active_at_z(destination[Z_AXIS])) {
12810
         #if ENABLED(AUTO_BED_LEVELING_UBL)
12882
         #if ENABLED(AUTO_BED_LEVELING_UBL)
12811
           ubl.line_to_destination_cartesian(MMS_SCALED(feedrate_mm_s), active_extruder);  // UBL's motion routine needs to know about
12883
           ubl.line_to_destination_cartesian(MMS_SCALED(feedrate_mm_s), active_extruder);  // UBL's motion routine needs to know about
12812
           return true;                                                                    // all moves, including Z-only moves.
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
         #else
12888
         #else
12814
           /**
12889
           /**
12815
            * For MBL and ABL-BILINEAR only segment moves when X or Y are involved.
12890
            * For MBL and ABL-BILINEAR only segment moves when X or Y are involved.

+ 2
- 0
Marlin/SanityCheck.h View File

220
   #error "ENABLE_MESH_EDIT_GFX_OVERLAY is now MESH_EDIT_GFX_OVERLAY. Please update your configuration."
220
   #error "ENABLE_MESH_EDIT_GFX_OVERLAY is now MESH_EDIT_GFX_OVERLAY. Please update your configuration."
221
 #elif defined(BABYSTEP_ZPROBE_GFX_REVERSE)
221
 #elif defined(BABYSTEP_ZPROBE_GFX_REVERSE)
222
   #error "BABYSTEP_ZPROBE_GFX_REVERSE is now set by OVERLAY_GFX_REVERSE. Please update your configurations."
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
 #endif
225
 #endif
224
 
226
 
225
 /**
227
 /**

Loading…
Cancel
Save