Browse Source

🐛 Fix probe temp compensation maths (#23004)

tombrazier 3 years ago
parent
commit
9c055621a0
No account linked to committer's email address

+ 36
- 27
Marlin/src/feature/probe_temp_comp.cpp View File

24
 
24
 
25
 #if ENABLED(PROBE_TEMP_COMPENSATION)
25
 #if ENABLED(PROBE_TEMP_COMPENSATION)
26
 
26
 
27
+//#define DEBUG_PTC   // Print extra debug output with 'M871'
28
+
27
 #include "probe_temp_comp.h"
29
 #include "probe_temp_comp.h"
28
 #include <math.h>
30
 #include <math.h>
29
 
31
 
79
         " temp: ", temp,
81
         " temp: ", temp,
80
         "C; Offset: ", i < 0 ? 0.0f : sensor_z_offsets[s][i], " um"
82
         "C; Offset: ", i < 0 ? 0.0f : sensor_z_offsets[s][i], " um"
81
       );
83
       );
82
-      temp += cali_info[s].temp_res;
84
+      temp += cali_info[s].temp_resolution;
83
     }
85
     }
84
   }
86
   }
87
+  #if ENABLED(DEBUG_PTC)
88
+    float meas[4] = { 0, 0, 0, 0 };
89
+    compensate_measurement(TSI_PROBE, 27.5, meas[0]);
90
+    compensate_measurement(TSI_PROBE, 32.5, meas[1]);
91
+    compensate_measurement(TSI_PROBE, 77.5, meas[2]);
92
+    compensate_measurement(TSI_PROBE, 82.5, meas[3]);
93
+    SERIAL_ECHOLNPGM("DEBUG_PTC 27.5:", meas[0], " 32.5:", meas[1], " 77.5:", meas[2], " 82.5:", meas[3]);
94
+  #endif
85
 }
95
 }
86
 
96
 
87
 void ProbeTempComp::prepare_new_calibration(const_float_t init_meas_z) {
97
 void ProbeTempComp::prepare_new_calibration(const_float_t init_meas_z) {
111
 
121
 
112
   const uint8_t measurements = cali_info[tsi].measurements;
122
   const uint8_t measurements = cali_info[tsi].measurements;
113
   const celsius_t start_temp = cali_info[tsi].start_temp,
123
   const celsius_t start_temp = cali_info[tsi].start_temp,
114
-                    res_temp = cali_info[tsi].temp_res;
124
+                    res_temp = cali_info[tsi].temp_resolution;
115
   int16_t * const data = sensor_z_offsets[tsi];
125
   int16_t * const data = sensor_z_offsets[tsi];
116
 
126
 
117
   // Extrapolate
127
   // Extrapolate
156
 }
166
 }
157
 
167
 
158
 void ProbeTempComp::compensate_measurement(const TempSensorID tsi, const celsius_t temp, float &meas_z) {
168
 void ProbeTempComp::compensate_measurement(const TempSensorID tsi, const celsius_t temp, float &meas_z) {
159
-  if (WITHIN(temp, cali_info[tsi].start_temp, cali_info[tsi].end_temp))
160
-    meas_z -= get_offset_for_temperature(tsi, temp);
161
-}
162
-
163
-float ProbeTempComp::get_offset_for_temperature(const TempSensorID tsi, const celsius_t temp) {
164
   const uint8_t measurements = cali_info[tsi].measurements;
169
   const uint8_t measurements = cali_info[tsi].measurements;
165
   const celsius_t start_temp = cali_info[tsi].start_temp,
170
   const celsius_t start_temp = cali_info[tsi].start_temp,
166
-                    res_temp = cali_info[tsi].temp_res;
171
+                    end_temp = cali_info[tsi].end_temp,
172
+                    res_temp = cali_info[tsi].temp_resolution;
167
   const int16_t * const data = sensor_z_offsets[tsi];
173
   const int16_t * const data = sensor_z_offsets[tsi];
168
 
174
 
169
-  auto point = [&](uint8_t i) -> xy_float_t {
170
-    return xy_float_t({ static_cast<float>(start_temp) + i * res_temp, static_cast<float>(data[i]) });
175
+  // Given a data index, return { celsius, zoffset } in the form { x, y }
176
+  auto tpoint = [&](uint8_t i) -> xy_float_t {
177
+    return xy_float_t({ static_cast<float>(start_temp) + i * res_temp, i ? static_cast<float>(data[i - 1]) : 0.0f });
171
   };
178
   };
172
 
179
 
180
+  // Interpolate Z based on a temperature being within a given range
173
   auto linear_interp = [](const_float_t x, xy_float_t p1, xy_float_t p2) {
181
   auto linear_interp = [](const_float_t x, xy_float_t p1, xy_float_t p2) {
174
-    return (p2.y - p1.y) / (p2.x - p2.y) * (x - p1.x) + p1.y;
182
+    //   zoffs1 +      zoffset_per_toffset      *  toffset
183
+    return p1.y + (p2.y - p1.y) / (p2.x - p1.x) * (x - p1.x);
175
   };
184
   };
176
 
185
 
177
-  // Linear interpolation
178
-  uint8_t idx = static_cast<uint8_t>((temp - start_temp) / res_temp);
179
-
180
   // offset in µm
186
   // offset in µm
181
   float offset = 0.0f;
187
   float offset = 0.0f;
182
 
188
 
183
-  #if !defined(PTC_LINEAR_EXTRAPOLATION) || PTC_LINEAR_EXTRAPOLATION <= 0
184
-    if (idx < 0)
189
+  #if PTC_LINEAR_EXTRAPOLATION
190
+    if (temp < start_temp)
191
+      offset = linear_interp(temp, tpoint(0), tpoint(PTC_LINEAR_EXTRAPOLATION));
192
+    else if (temp >= end_temp)
193
+      offset = linear_interp(temp, tpoint(measurements - PTC_LINEAR_EXTRAPOLATION), tpoint(measurements));
194
+  #else
195
+    if (temp < start_temp)
185
       offset = 0.0f;
196
       offset = 0.0f;
186
-    else if (idx > measurements - 2)
197
+    else if (temp >= end_temp)
187
       offset = static_cast<float>(data[measurements - 1]);
198
       offset = static_cast<float>(data[measurements - 1]);
188
-  #else
189
-    if (idx < 0)
190
-      offset = linear_interp(temp, point(0), point(PTC_LINEAR_EXTRAPOLATION));
191
-    else if (idx > measurements - 2)
192
-      offset = linear_interp(temp, point(measurements - PTC_LINEAR_EXTRAPOLATION - 1), point(measurements - 1));
193
   #endif
199
   #endif
194
-    else
195
-      offset = linear_interp(temp, point(idx), point(idx + 1));
200
+    else {
201
+      // Linear interpolation
202
+      const int8_t idx = static_cast<int8_t>((temp - start_temp) / res_temp);
203
+      offset = linear_interp(temp, tpoint(idx), tpoint(idx + 1));
204
+    }
196
 
205
 
197
-  // return offset in mm
198
-  return offset / 1000.0f;
206
+  // convert offset to mm and apply it
207
+  meas_z -= offset / 1000.0f;
199
 }
208
 }
200
 
209
 
201
 bool ProbeTempComp::linear_regression(const TempSensorID tsi, float &k, float &d) {
210
 bool ProbeTempComp::linear_regression(const TempSensorID tsi, float &k, float &d) {
204
   if (!WITHIN(calib_idx, 2, cali_info[tsi].measurements)) return false;
213
   if (!WITHIN(calib_idx, 2, cali_info[tsi].measurements)) return false;
205
 
214
 
206
   const celsius_t start_temp = cali_info[tsi].start_temp,
215
   const celsius_t start_temp = cali_info[tsi].start_temp,
207
-                    res_temp = cali_info[tsi].temp_res;
216
+                    res_temp = cali_info[tsi].temp_resolution;
208
   const int16_t * const data = sensor_z_offsets[tsi];
217
   const int16_t * const data = sensor_z_offsets[tsi];
209
 
218
 
210
   float sum_x = start_temp,
219
   float sum_x = start_temp,

+ 3
- 5
Marlin/src/feature/probe_temp_comp.h View File

33
 };
33
 };
34
 
34
 
35
 typedef struct {
35
 typedef struct {
36
-  uint8_t measurements; // Max. number of measurements to be stored (35 - 80°C)
37
-  celsius_t temp_res,   // Resolution in °C between measurements
38
-            start_temp, // Base measurement; z-offset == 0
36
+  uint8_t measurements;       // Max. number of measurements to be stored (35 - 80°C)
37
+  celsius_t temp_resolution,  // Resolution in °C between measurements
38
+            start_temp,       // Base measurement; z-offset == 0
39
             end_temp;
39
             end_temp;
40
 } temp_calib_t;
40
 } temp_calib_t;
41
 
41
 
135
      */
135
      */
136
     static float init_measurement;
136
     static float init_measurement;
137
 
137
 
138
-    static float get_offset_for_temperature(const TempSensorID tsi, const celsius_t temp);
139
-
140
     /**
138
     /**
141
      * Fit a linear function in measured temperature offsets
139
      * Fit a linear function in measured temperature offsets
142
      * to allow generating values of higher temperatures.
140
      * to allow generating values of higher temperatures.

+ 1
- 1
Marlin/src/gcode/calibrate/G76_M192_M871.cpp View File

121
         temp_comp.prepare_new_calibration(measured_z);
121
         temp_comp.prepare_new_calibration(measured_z);
122
       else
122
       else
123
         temp_comp.push_back_new_measurement(sid, measured_z);
123
         temp_comp.push_back_new_measurement(sid, measured_z);
124
-      targ += cali_info_init[sid].temp_res;
124
+      targ += cali_info_init[sid].temp_resolution;
125
     }
125
     }
126
     return measured_z;
126
     return measured_z;
127
   };
127
   };

Loading…
Cancel
Save