|
@@ -2136,7 +2136,9 @@ static void clean_up_after_endstop_or_probe_move() {
|
2136
|
2136
|
#if ABL_PLANAR
|
2137
|
2137
|
planner.bed_level_matrix.set_to_identity();
|
2138
|
2138
|
#elif ENABLED(AUTO_BED_LEVELING_BILINEAR)
|
2139
|
|
- memset(bed_level_grid, 0, sizeof(bed_level_grid));
|
|
2139
|
+ for (uint8_t x = 0; x < ABL_GRID_POINTS_X; x++)
|
|
2140
|
+ for (uint8_t y = 0; y < ABL_GRID_POINTS_Y; y++)
|
|
2141
|
+ bed_level_grid[x][y] = 1000.0;
|
2140
|
2142
|
#endif
|
2141
|
2143
|
}
|
2142
|
2144
|
|
|
@@ -2148,44 +2150,125 @@ static void clean_up_after_endstop_or_probe_move() {
|
2148
|
2150
|
* Extrapolate a single point from its neighbors
|
2149
|
2151
|
*/
|
2150
|
2152
|
static void extrapolate_one_point(uint8_t x, uint8_t y, int8_t xdir, int8_t ydir) {
|
2151
|
|
- if (bed_level_grid[x][y]) return; // Don't overwrite good values.
|
2152
|
|
- float a = 2 * bed_level_grid[x + xdir][y] - bed_level_grid[x + xdir * 2][y], // Left to right.
|
2153
|
|
- b = 2 * bed_level_grid[x][y + ydir] - bed_level_grid[x][y + ydir * 2], // Front to back.
|
2154
|
|
- c = 2 * bed_level_grid[x + xdir][y + ydir] - bed_level_grid[x + xdir * 2][y + ydir * 2]; // Diagonal.
|
|
2153
|
+ #if ENABLED(DEBUG_LEVELING_FEATURE)
|
|
2154
|
+ if (DEBUGGING(LEVELING)) {
|
|
2155
|
+ SERIAL_ECHOPGM("Extrapolate [");
|
|
2156
|
+ if (x < 10) SERIAL_CHAR(' ');
|
|
2157
|
+ SERIAL_ECHO((int)x);
|
|
2158
|
+ SERIAL_CHAR(xdir ? (xdir > 0 ? '+' : '-') : ' ');
|
|
2159
|
+ SERIAL_CHAR(' ');
|
|
2160
|
+ if (y < 10) SERIAL_CHAR(' ');
|
|
2161
|
+ SERIAL_ECHO((int)y);
|
|
2162
|
+ SERIAL_CHAR(ydir ? (ydir > 0 ? '+' : '-') : ' ');
|
|
2163
|
+ SERIAL_CHAR(']');
|
|
2164
|
+ }
|
|
2165
|
+ #endif
|
|
2166
|
+ if (bed_level_grid[x][y] < 999.0) {
|
|
2167
|
+ #if ENABLED(DEBUG_LEVELING_FEATURE)
|
|
2168
|
+ if (DEBUGGING(LEVELING)) SERIAL_ECHOLNPGM(" (done)");
|
|
2169
|
+ #endif
|
|
2170
|
+ return; // Don't overwrite good values.
|
|
2171
|
+ }
|
|
2172
|
+
|
|
2173
|
+ // Get X neighbors, Y neighbors, and XY neighbors
|
|
2174
|
+ float a1 = bed_level_grid[x + xdir][y], a2 = bed_level_grid[x + xdir * 2][y],
|
|
2175
|
+ b1 = bed_level_grid[x][y + ydir], b2 = bed_level_grid[x][y + ydir * 2],
|
|
2176
|
+ c1 = bed_level_grid[x + xdir][y + ydir], c2 = bed_level_grid[x + xdir * 2][y + ydir * 2];
|
|
2177
|
+
|
|
2178
|
+ // Treat far unprobed points as zero, near as equal to far
|
|
2179
|
+ if (a2 > 999.0) a2 = 0.0; if (a1 > 999.0) a1 = a2;
|
|
2180
|
+ if (b2 > 999.0) b2 = 0.0; if (b1 > 999.0) b1 = b2;
|
|
2181
|
+ if (c2 > 999.0) c2 = 0.0; if (c1 > 999.0) c1 = c2;
|
|
2182
|
+
|
|
2183
|
+ float a = 2 * a1 - a2, b = 2 * b1 - b2, c = 2 * c1 - c2;
|
|
2184
|
+
|
|
2185
|
+ // Take the average intstead of the median
|
|
2186
|
+ bed_level_grid[x][y] = (a + b + c) / 3.0;
|
|
2187
|
+
|
2155
|
2188
|
// Median is robust (ignores outliers).
|
2156
|
|
- bed_level_grid[x][y] = (a < b) ? ((b < c) ? b : (c < a) ? a : c)
|
2157
|
|
- : ((c < b) ? b : (a < c) ? a : c);
|
|
2189
|
+ // bed_level_grid[x][y] = (a < b) ? ((b < c) ? b : (c < a) ? a : c)
|
|
2190
|
+ // : ((c < b) ? b : (a < c) ? a : c);
|
2158
|
2191
|
}
|
2159
|
2192
|
|
|
2193
|
+ #define EXTRAPOLATE_FROM_EDGE
|
|
2194
|
+
|
|
2195
|
+ #if ENABLED(EXTRAPOLATE_FROM_EDGE)
|
|
2196
|
+ #if ABL_GRID_POINTS_X < ABL_GRID_POINTS_Y
|
|
2197
|
+ #define HALF_IN_X
|
|
2198
|
+ #elif ABL_GRID_POINTS_Y < ABL_GRID_POINTS_X
|
|
2199
|
+ #define HALF_IN_Y
|
|
2200
|
+ #endif
|
|
2201
|
+ #endif
|
|
2202
|
+
|
2160
|
2203
|
/**
|
2161
|
2204
|
* Fill in the unprobed points (corners of circular print surface)
|
2162
|
2205
|
* using linear extrapolation, away from the center.
|
2163
|
2206
|
*/
|
2164
|
2207
|
static void extrapolate_unprobed_bed_level() {
|
2165
|
|
- int half_x = (ABL_GRID_POINTS_X - 1) / 2,
|
2166
|
|
- half_y = (ABL_GRID_POINTS_Y - 1) / 2;
|
2167
|
|
- for (uint8_t y = 0; y <= half_y; y++) {
|
2168
|
|
- for (uint8_t x = 0; x <= half_x; x++) {
|
2169
|
|
- if (x + y < 3) continue;
|
2170
|
|
- extrapolate_one_point(half_x - x, half_y - y, x > 1 ? +1 : 0, y > 1 ? +1 : 0);
|
2171
|
|
- extrapolate_one_point(half_x + x, half_y - y, x > 1 ? -1 : 0, y > 1 ? +1 : 0);
|
2172
|
|
- extrapolate_one_point(half_x - x, half_y + y, x > 1 ? +1 : 0, y > 1 ? -1 : 0);
|
2173
|
|
- extrapolate_one_point(half_x + x, half_y + y, x > 1 ? -1 : 0, y > 1 ? -1 : 0);
|
|
2208
|
+ #ifdef HALF_IN_X
|
|
2209
|
+ const uint8_t ctrx2 = 0, xlen = ABL_GRID_POINTS_X - 1;
|
|
2210
|
+ #else
|
|
2211
|
+ const uint8_t ctrx1 = (ABL_GRID_POINTS_X - 1) / 2, // left-of-center
|
|
2212
|
+ ctrx2 = ABL_GRID_POINTS_X / 2, // right-of-center
|
|
2213
|
+ xlen = ctrx1;
|
|
2214
|
+ #endif
|
|
2215
|
+
|
|
2216
|
+ #ifdef HALF_IN_Y
|
|
2217
|
+ const uint8_t ctry2 = 0, ylen = ABL_GRID_POINTS_Y - 1;
|
|
2218
|
+ #else
|
|
2219
|
+ const uint8_t ctry1 = (ABL_GRID_POINTS_Y - 1) / 2, // top-of-center
|
|
2220
|
+ ctry2 = ABL_GRID_POINTS_Y / 2, // bottom-of-center
|
|
2221
|
+ ylen = ctry1;
|
|
2222
|
+ #endif
|
|
2223
|
+
|
|
2224
|
+ for (uint8_t xo = 0; xo <= xlen; xo++)
|
|
2225
|
+ for (uint8_t yo = 0; yo <= ylen; yo++) {
|
|
2226
|
+ uint8_t x2 = ctrx2 + xo, y2 = ctry2 + yo;
|
|
2227
|
+ #ifndef HALF_IN_X
|
|
2228
|
+ uint8_t x1 = ctrx1 - xo;
|
|
2229
|
+ #endif
|
|
2230
|
+ #ifndef HALF_IN_Y
|
|
2231
|
+ uint8_t y1 = ctry1 - yo;
|
|
2232
|
+ #ifndef HALF_IN_X
|
|
2233
|
+ extrapolate_one_point(x1, y1, +1, +1); // left-below + +
|
|
2234
|
+ #endif
|
|
2235
|
+ extrapolate_one_point(x2, y1, -1, +1); // right-below - +
|
|
2236
|
+ #endif
|
|
2237
|
+ #ifndef HALF_IN_X
|
|
2238
|
+ extrapolate_one_point(x1, y2, +1, -1); // left-above + -
|
|
2239
|
+ #endif
|
|
2240
|
+ extrapolate_one_point(x2, y2, -1, -1); // right-above - -
|
2174
|
2241
|
}
|
2175
|
|
- }
|
|
2242
|
+
|
2176
|
2243
|
}
|
2177
|
2244
|
|
2178
|
2245
|
/**
|
2179
|
2246
|
* Print calibration results for plotting or manual frame adjustment.
|
2180
|
2247
|
*/
|
2181
|
2248
|
static void print_bed_level() {
|
|
2249
|
+ SERIAL_ECHOPGM("Bilinear Leveling Grid:\n ");
|
|
2250
|
+ for (uint8_t x = 1; x < ABL_GRID_POINTS_X + 1; x++) {
|
|
2251
|
+ SERIAL_PROTOCOLPGM(" ");
|
|
2252
|
+ if (x < 10) SERIAL_PROTOCOLCHAR(' ');
|
|
2253
|
+ SERIAL_PROTOCOL((int)x);
|
|
2254
|
+ }
|
|
2255
|
+ SERIAL_EOL;
|
2182
|
2256
|
for (uint8_t y = 0; y < ABL_GRID_POINTS_Y; y++) {
|
|
2257
|
+ if (y < 9) SERIAL_PROTOCOLCHAR(' ');
|
|
2258
|
+ SERIAL_PROTOCOL(y + 1);
|
2183
|
2259
|
for (uint8_t x = 0; x < ABL_GRID_POINTS_X; x++) {
|
2184
|
|
- SERIAL_PROTOCOL_F(bed_level_grid[x][y], 2);
|
2185
|
2260
|
SERIAL_PROTOCOLCHAR(' ');
|
|
2261
|
+ float offset = bed_level_grid[x][y];
|
|
2262
|
+ if (offset < 999.0) {
|
|
2263
|
+ if (offset > 0) SERIAL_CHAR('+');
|
|
2264
|
+ SERIAL_PROTOCOL_F(offset, 2);
|
|
2265
|
+ }
|
|
2266
|
+ else
|
|
2267
|
+ SERIAL_PROTOCOLPGM(" ====");
|
2186
|
2268
|
}
|
2187
|
2269
|
SERIAL_EOL;
|
2188
|
2270
|
}
|
|
2271
|
+ SERIAL_EOL;
|
2189
|
2272
|
}
|
2190
|
2273
|
|
2191
|
2274
|
#endif // AUTO_BED_LEVELING_BILINEAR
|