Browse Source

🐛 Fix steps-to-mm with backlash (#23814)

Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
tombrazier 2 years ago
parent
commit
87c4cd20e5
No account linked to committer's email address
3 changed files with 54 additions and 13 deletions
  1. 26
    5
      Marlin/src/feature/backlash.cpp
  2. 8
    1
      Marlin/src/feature/backlash.h
  3. 20
    7
      Marlin/src/module/planner.cpp

+ 26
- 5
Marlin/src/feature/backlash.cpp View File

29
 #include "../module/motion.h"
29
 #include "../module/motion.h"
30
 #include "../module/planner.h"
30
 #include "../module/planner.h"
31
 
31
 
32
+axis_bits_t Backlash::last_direction_bits;
33
+#ifdef BACKLASH_SMOOTHING_MM
34
+  xyz_long_t Backlash::residual_error{0};
35
+#endif
36
+
32
 #ifdef BACKLASH_DISTANCE_MM
37
 #ifdef BACKLASH_DISTANCE_MM
33
   #if ENABLED(BACKLASH_GCODE)
38
   #if ENABLED(BACKLASH_GCODE)
34
     xyz_float_t Backlash::distance_mm = BACKLASH_DISTANCE_MM;
39
     xyz_float_t Backlash::distance_mm = BACKLASH_DISTANCE_MM;
61
  */
66
  */
62
 
67
 
63
 void Backlash::add_correction_steps(const int32_t &da, const int32_t &db, const int32_t &dc, const axis_bits_t dm, block_t * const block) {
68
 void Backlash::add_correction_steps(const int32_t &da, const int32_t &db, const int32_t &dc, const axis_bits_t dm, block_t * const block) {
64
-  static axis_bits_t last_direction_bits;
65
   axis_bits_t changed_dir = last_direction_bits ^ dm;
69
   axis_bits_t changed_dir = last_direction_bits ^ dm;
66
   // Ignore direction change unless steps are taken in that direction
70
   // Ignore direction change unless steps are taken in that direction
67
   #if DISABLED(CORE_BACKLASH) || EITHER(MARKFORGED_XY, MARKFORGED_YX)
71
   #if DISABLED(CORE_BACKLASH) || EITHER(MARKFORGED_XY, MARKFORGED_YX)
91
     // smoothing distance. Since the computation of this proportion involves a floating point
95
     // smoothing distance. Since the computation of this proportion involves a floating point
92
     // division, defer computation until needed.
96
     // division, defer computation until needed.
93
     float segment_proportion = 0;
97
     float segment_proportion = 0;
94
-
95
-    // Residual error carried forward across multiple segments, so correction can be applied
96
-    // to segments where there is no direction change.
97
-    static xyz_long_t residual_error{0};
98
   #else
98
   #else
99
     // No direction change, no correction.
99
     // No direction change, no correction.
100
     if (!changed_dir) return;
100
     if (!changed_dir) return;
153
   }
153
   }
154
 }
154
 }
155
 
155
 
156
+int32_t Backlash::applied_steps(const AxisEnum axis) {
157
+  if (axis >= LINEAR_AXES) return 0;
158
+
159
+  const bool reversing = TEST(last_direction_bits, axis);
160
+
161
+  #ifdef BACKLASH_SMOOTHING_MM
162
+    const int32_t residual_error_axis = residual_error[axis];
163
+  #else
164
+    constexpr int32_t residual_error_axis = 0;
165
+  #endif
166
+
167
+  // At startup it is assumed the last move was forwards. So the applied
168
+  // steps will always be a non-positive number.
169
+
170
+  if (!reversing) return -residual_error_axis;
171
+
172
+  const float f_corr = float(correction) / 255.0f;
173
+  const int32_t full_error_axis = -f_corr * distance_mm[axis] * planner.settings.axis_steps_per_mm[axis];
174
+  return full_error_axis - residual_error_axis;
175
+}
176
+
156
 #if ENABLED(MEASURE_BACKLASH_WHEN_PROBING)
177
 #if ENABLED(MEASURE_BACKLASH_WHEN_PROBING)
157
 
178
 
158
   #include "../module/probe.h"
179
   #include "../module/probe.h"

+ 8
- 1
Marlin/src/feature/backlash.h View File

27
 constexpr uint8_t all_on = 0xFF, all_off = 0x00;
27
 constexpr uint8_t all_on = 0xFF, all_off = 0x00;
28
 
28
 
29
 class Backlash {
29
 class Backlash {
30
+private:
31
+  static axis_bits_t last_direction_bits;
32
+  #ifdef BACKLASH_SMOOTHING_MM
33
+    static xyz_long_t residual_error;
34
+  #endif
35
+
30
 public:
36
 public:
31
   #if ENABLED(BACKLASH_GCODE)
37
   #if ENABLED(BACKLASH_GCODE)
32
     static xyz_float_t distance_mm;
38
     static xyz_float_t distance_mm;
71
     return has_measurement(X_AXIS) || has_measurement(Y_AXIS) || has_measurement(Z_AXIS);
77
     return has_measurement(X_AXIS) || has_measurement(Y_AXIS) || has_measurement(Z_AXIS);
72
   }
78
   }
73
 
79
 
74
-  void add_correction_steps(const int32_t &da, const int32_t &db, const int32_t &dc, const axis_bits_t dm, block_t * const block);
80
+  static void add_correction_steps(const int32_t &da, const int32_t &db, const int32_t &dc, const axis_bits_t dm, block_t * const block);
81
+  static int32_t applied_steps(const AxisEnum axis);
75
 };
82
 };
76
 
83
 
77
 extern Backlash backlash;
84
 extern Backlash backlash;

+ 20
- 7
Marlin/src/module/planner.cpp View File

1706
 }
1706
 }
1707
 
1707
 
1708
 float Planner::triggered_position_mm(const AxisEnum axis) {
1708
 float Planner::triggered_position_mm(const AxisEnum axis) {
1709
-  return stepper.triggered_position(axis) * mm_per_step[axis];
1709
+  const float result = DIFF_TERN(BACKLASH_COMPENSATION, stepper.triggered_position(axis), backlash.applied_steps(axis));
1710
+  return result * mm_per_step[axis];
1710
 }
1711
 }
1711
 
1712
 
1712
 void Planner::finish_and_disable() {
1713
 void Planner::finish_and_disable() {
1728
       // Protect the access to the position.
1729
       // Protect the access to the position.
1729
       const bool was_enabled = stepper.suspend();
1730
       const bool was_enabled = stepper.suspend();
1730
 
1731
 
1731
-      const int32_t p1 = stepper.position(CORE_AXIS_1),
1732
-                    p2 = stepper.position(CORE_AXIS_2);
1732
+      const int32_t p1 = DIFF_TERN(BACKLASH_COMPENSATION, stepper.position(CORE_AXIS_1), backlash.applied_steps(CORE_AXIS_1)),
1733
+                    p2 = DIFF_TERN(BACKLASH_COMPENSATION, stepper.position(CORE_AXIS_2), backlash.applied_steps(CORE_AXIS_2));
1733
 
1734
 
1734
       if (was_enabled) stepper.wake_up();
1735
       if (was_enabled) stepper.wake_up();
1735
 
1736
 
1738
       axis_steps = (axis == CORE_AXIS_2 ? CORESIGN(p1 - p2) : p1 + p2) * 0.5f;
1739
       axis_steps = (axis == CORE_AXIS_2 ? CORESIGN(p1 - p2) : p1 + p2) * 0.5f;
1739
     }
1740
     }
1740
     else
1741
     else
1741
-      axis_steps = stepper.position(axis);
1742
+      axis_steps = DIFF_TERN(BACKLASH_COMPENSATION, stepper.position(axis), backlash.applied_steps(axis));
1742
 
1743
 
1743
   #elif EITHER(MARKFORGED_XY, MARKFORGED_YX)
1744
   #elif EITHER(MARKFORGED_XY, MARKFORGED_YX)
1744
 
1745
 
1755
       axis_steps = ((axis == CORE_AXIS_1) ? p1 - p2 : p2);
1756
       axis_steps = ((axis == CORE_AXIS_1) ? p1 - p2 : p2);
1756
     }
1757
     }
1757
     else
1758
     else
1758
-      axis_steps = stepper.position(axis);
1759
+      axis_steps = DIFF_TERN(BACKLASH_COMPENSATION, stepper.position(axis), backlash.applied_steps(axis));
1759
 
1760
 
1760
   #else
1761
   #else
1761
 
1762
 
1762
     axis_steps = stepper.position(axis);
1763
     axis_steps = stepper.position(axis);
1764
+    TERN_(BACKLASH_COMPENSATION, axis_steps -= backlash.applied_steps(axis));
1763
 
1765
 
1764
   #endif
1766
   #endif
1765
 
1767
 
2841
   block->flag = sync_flag;
2843
   block->flag = sync_flag;
2842
 
2844
 
2843
   block->position = position;
2845
   block->position = position;
2846
+  #if ENABLED(BACKLASH_COMPENSATION)
2847
+    LOOP_LINEAR_AXES(axis) block->position[axis] += backlash.applied_steps((AxisEnum)axis);
2848
+  #endif
2844
 
2849
 
2845
   #if BOTH(HAS_FAN, LASER_SYNCHRONOUS_M106_M107)
2850
   #if BOTH(HAS_FAN, LASER_SYNCHRONOUS_M106_M107)
2846
     FANS_LOOP(i) block->fan_speed[i] = thermalManager.fan_speed[i];
2851
     FANS_LOOP(i) block->fan_speed[i] = thermalManager.fan_speed[i];
3108
       LROUND(abce.k * settings.axis_steps_per_mm[K_AXIS])
3113
       LROUND(abce.k * settings.axis_steps_per_mm[K_AXIS])
3109
     )
3114
     )
3110
   );
3115
   );
3116
+
3111
   if (has_blocks_queued()) {
3117
   if (has_blocks_queued()) {
3112
     //previous_nominal_speed_sqr = 0.0; // Reset planner junction speeds. Assume start from rest.
3118
     //previous_nominal_speed_sqr = 0.0; // Reset planner junction speeds. Assume start from rest.
3113
     //previous_speed.reset();
3119
     //previous_speed.reset();
3114
     buffer_sync_block();
3120
     buffer_sync_block();
3115
   }
3121
   }
3116
-  else
3117
-    stepper.set_position(position);
3122
+  else {
3123
+    #if ENABLED(BACKLASH_COMPENSATION)
3124
+      abce_long_t stepper_pos = position;
3125
+      LOOP_LINEAR_AXES(axis) stepper_pos[axis] += backlash.applied_steps((AxisEnum)axis);
3126
+      stepper.set_position(stepper_pos);
3127
+    #else
3128
+      stepper.set_position(position);
3129
+    #endif
3130
+  }
3118
 }
3131
 }
3119
 
3132
 
3120
 void Planner::set_position_mm(const xyze_pos_t &xyze) {
3133
 void Planner::set_position_mm(const xyze_pos_t &xyze) {

Loading…
Cancel
Save