diff --git a/Marlin/Marlin_main.cpp b/Marlin/Marlin_main.cpp index e717aa25f0..ca8f9a94c3 100644 --- a/Marlin/Marlin_main.cpp +++ b/Marlin/Marlin_main.cpp @@ -2136,7 +2136,9 @@ static void clean_up_after_endstop_or_probe_move() { #if ABL_PLANAR planner.bed_level_matrix.set_to_identity(); #elif ENABLED(AUTO_BED_LEVELING_BILINEAR) - memset(bed_level_grid, 0, sizeof(bed_level_grid)); + for (uint8_t x = 0; x < ABL_GRID_POINTS_X; x++) + for (uint8_t y = 0; y < ABL_GRID_POINTS_Y; y++) + bed_level_grid[x][y] = 1000.0; #endif } @@ -2148,44 +2150,125 @@ static void clean_up_after_endstop_or_probe_move() { * Extrapolate a single point from its neighbors */ static void extrapolate_one_point(uint8_t x, uint8_t y, int8_t xdir, int8_t ydir) { - if (bed_level_grid[x][y]) return; // Don't overwrite good values. - float a = 2 * bed_level_grid[x + xdir][y] - bed_level_grid[x + xdir * 2][y], // Left to right. - b = 2 * bed_level_grid[x][y + ydir] - bed_level_grid[x][y + ydir * 2], // Front to back. - c = 2 * bed_level_grid[x + xdir][y + ydir] - bed_level_grid[x + xdir * 2][y + ydir * 2]; // Diagonal. + #if ENABLED(DEBUG_LEVELING_FEATURE) + if (DEBUGGING(LEVELING)) { + SERIAL_ECHOPGM("Extrapolate ["); + if (x < 10) SERIAL_CHAR(' '); + SERIAL_ECHO((int)x); + SERIAL_CHAR(xdir ? (xdir > 0 ? '+' : '-') : ' '); + SERIAL_CHAR(' '); + if (y < 10) SERIAL_CHAR(' '); + SERIAL_ECHO((int)y); + SERIAL_CHAR(ydir ? (ydir > 0 ? '+' : '-') : ' '); + SERIAL_CHAR(']'); + } + #endif + if (bed_level_grid[x][y] < 999.0) { + #if ENABLED(DEBUG_LEVELING_FEATURE) + if (DEBUGGING(LEVELING)) SERIAL_ECHOLNPGM(" (done)"); + #endif + return; // Don't overwrite good values. + } + + // Get X neighbors, Y neighbors, and XY neighbors + float a1 = bed_level_grid[x + xdir][y], a2 = bed_level_grid[x + xdir * 2][y], + b1 = bed_level_grid[x][y + ydir], b2 = bed_level_grid[x][y + ydir * 2], + c1 = bed_level_grid[x + xdir][y + ydir], c2 = bed_level_grid[x + xdir * 2][y + ydir * 2]; + + // Treat far unprobed points as zero, near as equal to far + if (a2 > 999.0) a2 = 0.0; if (a1 > 999.0) a1 = a2; + if (b2 > 999.0) b2 = 0.0; if (b1 > 999.0) b1 = b2; + if (c2 > 999.0) c2 = 0.0; if (c1 > 999.0) c1 = c2; + + float a = 2 * a1 - a2, b = 2 * b1 - b2, c = 2 * c1 - c2; + + // Take the average intstead of the median + bed_level_grid[x][y] = (a + b + c) / 3.0; + // Median is robust (ignores outliers). - bed_level_grid[x][y] = (a < b) ? ((b < c) ? b : (c < a) ? a : c) - : ((c < b) ? b : (a < c) ? a : c); + // bed_level_grid[x][y] = (a < b) ? ((b < c) ? b : (c < a) ? a : c) + // : ((c < b) ? b : (a < c) ? a : c); } + #define EXTRAPOLATE_FROM_EDGE + + #if ENABLED(EXTRAPOLATE_FROM_EDGE) + #if ABL_GRID_POINTS_X < ABL_GRID_POINTS_Y + #define HALF_IN_X + #elif ABL_GRID_POINTS_Y < ABL_GRID_POINTS_X + #define HALF_IN_Y + #endif + #endif + /** * Fill in the unprobed points (corners of circular print surface) * using linear extrapolation, away from the center. */ static void extrapolate_unprobed_bed_level() { - int half_x = (ABL_GRID_POINTS_X - 1) / 2, - half_y = (ABL_GRID_POINTS_Y - 1) / 2; - for (uint8_t y = 0; y <= half_y; y++) { - for (uint8_t x = 0; x <= half_x; x++) { - if (x + y < 3) continue; - extrapolate_one_point(half_x - x, half_y - y, x > 1 ? +1 : 0, y > 1 ? +1 : 0); - extrapolate_one_point(half_x + x, half_y - y, x > 1 ? -1 : 0, y > 1 ? +1 : 0); - extrapolate_one_point(half_x - x, half_y + y, x > 1 ? +1 : 0, y > 1 ? -1 : 0); - extrapolate_one_point(half_x + x, half_y + y, x > 1 ? -1 : 0, y > 1 ? -1 : 0); + #ifdef HALF_IN_X + const uint8_t ctrx2 = 0, xlen = ABL_GRID_POINTS_X - 1; + #else + const uint8_t ctrx1 = (ABL_GRID_POINTS_X - 1) / 2, // left-of-center + ctrx2 = ABL_GRID_POINTS_X / 2, // right-of-center + xlen = ctrx1; + #endif + + #ifdef HALF_IN_Y + const uint8_t ctry2 = 0, ylen = ABL_GRID_POINTS_Y - 1; + #else + const uint8_t ctry1 = (ABL_GRID_POINTS_Y - 1) / 2, // top-of-center + ctry2 = ABL_GRID_POINTS_Y / 2, // bottom-of-center + ylen = ctry1; + #endif + + for (uint8_t xo = 0; xo <= xlen; xo++) + for (uint8_t yo = 0; yo <= ylen; yo++) { + uint8_t x2 = ctrx2 + xo, y2 = ctry2 + yo; + #ifndef HALF_IN_X + uint8_t x1 = ctrx1 - xo; + #endif + #ifndef HALF_IN_Y + uint8_t y1 = ctry1 - yo; + #ifndef HALF_IN_X + extrapolate_one_point(x1, y1, +1, +1); // left-below + + + #endif + extrapolate_one_point(x2, y1, -1, +1); // right-below - + + #endif + #ifndef HALF_IN_X + extrapolate_one_point(x1, y2, +1, -1); // left-above + - + #endif + extrapolate_one_point(x2, y2, -1, -1); // right-above - - } - } + } /** * Print calibration results for plotting or manual frame adjustment. */ static void print_bed_level() { + SERIAL_ECHOPGM("Bilinear Leveling Grid:\n "); + for (uint8_t x = 1; x < ABL_GRID_POINTS_X + 1; x++) { + SERIAL_PROTOCOLPGM(" "); + if (x < 10) SERIAL_PROTOCOLCHAR(' '); + SERIAL_PROTOCOL((int)x); + } + SERIAL_EOL; for (uint8_t y = 0; y < ABL_GRID_POINTS_Y; y++) { + if (y < 9) SERIAL_PROTOCOLCHAR(' '); + SERIAL_PROTOCOL(y + 1); for (uint8_t x = 0; x < ABL_GRID_POINTS_X; x++) { - SERIAL_PROTOCOL_F(bed_level_grid[x][y], 2); SERIAL_PROTOCOLCHAR(' '); + float offset = bed_level_grid[x][y]; + if (offset < 999.0) { + if (offset > 0) SERIAL_CHAR('+'); + SERIAL_PROTOCOL_F(offset, 2); + } + else + SERIAL_PROTOCOLPGM(" ===="); } SERIAL_EOL; } + SERIAL_EOL; } #endif // AUTO_BED_LEVELING_BILINEAR