diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index a7953a53d..a6e26eb75 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -805,8 +805,8 @@ #if ENABLED(AUTO_BED_LEVELING_LINEAR) || ENABLED(AUTO_BED_LEVELING_BILINEAR) // Set the number of grid points per dimension. - #define ABL_GRID_POINTS_X 3 - #define ABL_GRID_POINTS_Y ABL_GRID_POINTS_X + #define ABL_GRID_MAX_POINTS_X 3 + #define ABL_GRID_MAX_POINTS_Y ABL_GRID_MAX_POINTS_X // Set the boundaries for probing (where the probe can reach). #define LEFT_PROBE_BED_POSITION 15 diff --git a/Marlin/Marlin.h b/Marlin/Marlin.h index 749655132..97af92c58 100644 --- a/Marlin/Marlin.h +++ b/Marlin/Marlin.h @@ -330,8 +330,14 @@ float code_value_temp_diff(); #endif #if ENABLED(AUTO_BED_LEVELING_BILINEAR) - extern int bilinear_grid_spacing[2]; + extern int bilinear_grid_spacing[2], bilinear_start[2]; + extern float bed_level_grid[ABL_GRID_MAX_POINTS_X][ABL_GRID_MAX_POINTS_Y]; float bilinear_z_offset(float logical[XYZ]); + void set_bed_leveling_enabled(bool enable=true); +#endif + +#if PLANNER_LEVELING + void reset_bed_level(); #endif #if ENABLED(Z_DUAL_ENDSTOPS) diff --git a/Marlin/Marlin_main.cpp b/Marlin/Marlin_main.cpp index 3205d1207..847ce7af7 100755 --- a/Marlin/Marlin_main.cpp +++ b/Marlin/Marlin_main.cpp @@ -575,8 +575,9 @@ static uint8_t target_extruder; #endif #if ENABLED(AUTO_BED_LEVELING_BILINEAR) - int bilinear_grid_spacing[2] = { 0 }, bilinear_start[2] = { 0 }; - float bed_level_grid[ABL_GRID_POINTS_X][ABL_GRID_POINTS_Y]; + #define UNPROBED 9999.0f + int bilinear_grid_spacing[2], bilinear_start[2]; + float bed_level_grid[ABL_GRID_MAX_POINTS_X][ABL_GRID_MAX_POINTS_Y]; #endif #if IS_SCARA @@ -2228,7 +2229,7 @@ static void clean_up_after_endstop_or_probe_move() { * Disable: Current position = physical position * Enable: Current position = "unleveled" physical position */ - void set_bed_leveling_enabled(bool enable=true) { + void set_bed_leveling_enabled(bool enable/*=true*/) { #if ENABLED(MESH_BED_LEVELING) if (enable != mbl.active()) { @@ -2243,7 +2244,13 @@ static void clean_up_after_endstop_or_probe_move() { #elif HAS_ABL - if (enable != planner.abl_enabled) { + #if ENABLED(AUTO_BED_LEVELING_BILINEAR) + const bool can_change = (!enable || (bilinear_grid_spacing[0] && bilinear_grid_spacing[1])); + #else + constexpr bool can_change = true; + #endif + + if (can_change && enable != planner.abl_enabled) { planner.abl_enabled = enable; if (!enable) set_current_from_steppers_for_axis( @@ -2289,23 +2296,24 @@ static void clean_up_after_endstop_or_probe_move() { * Reset calibration results to zero. */ void reset_bed_level() { + set_bed_leveling_enabled(false); #if ENABLED(MESH_BED_LEVELING) if (mbl.has_mesh()) { - set_bed_leveling_enabled(false); mbl.reset(); mbl.set_has_mesh(false); } #else - planner.abl_enabled = false; #if ENABLED(DEBUG_LEVELING_FEATURE) if (DEBUGGING(LEVELING)) SERIAL_ECHOLNPGM("reset_bed_level"); #endif #if ABL_PLANAR planner.bed_level_matrix.set_to_identity(); #elif ENABLED(AUTO_BED_LEVELING_BILINEAR) - 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; + bilinear_start[X_AXIS] = bilinear_start[Y_AXIS] = + bilinear_grid_spacing[X_AXIS] = bilinear_grid_spacing[Y_AXIS] = 0; + for (uint8_t x = 0; x < ABL_GRID_MAX_POINTS_X; x++) + for (uint8_t y = 0; y < ABL_GRID_MAX_POINTS_Y; y++) + bed_level_grid[x][y] = UNPROBED; #endif #endif } @@ -2331,7 +2339,7 @@ static void clean_up_after_endstop_or_probe_move() { SERIAL_CHAR(']'); } #endif - if (bed_level_grid[x][y] < 999.0) { + if (bed_level_grid[x][y] != UNPROBED) { #if ENABLED(DEBUG_LEVELING_FEATURE) if (DEBUGGING(LEVELING)) SERIAL_ECHOLNPGM(" (done)"); #endif @@ -2345,13 +2353,13 @@ static void clean_up_after_endstop_or_probe_move() { 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; + if (a2 == UNPROBED) a2 = 0.0; if (a1 == UNPROBED) a1 = a2; + if (b2 == UNPROBED) b2 = 0.0; if (b1 == UNPROBED) b1 = b2; + if (c2 == UNPROBED) c2 = 0.0; if (c1 == UNPROBED) c1 = c2; float a = 2 * a1 - a2, b = 2 * b1 - b2, c = 2 * c1 - c2; - // Take the average intstead of the median + // Take the average instead of the median bed_level_grid[x][y] = (a + b + c) / 3.0; // Median is robust (ignores outliers). @@ -2363,9 +2371,9 @@ static void clean_up_after_endstop_or_probe_move() { //#define EXTRAPOLATE_FROM_EDGE #if ENABLED(EXTRAPOLATE_FROM_EDGE) - #if ABL_GRID_POINTS_X < ABL_GRID_POINTS_Y + #if ABL_GRID_MAX_POINTS_X < ABL_GRID_MAX_POINTS_Y #define HALF_IN_X - #elif ABL_GRID_POINTS_Y < ABL_GRID_POINTS_X + #elif ABL_GRID_MAX_POINTS_Y < ABL_GRID_MAX_POINTS_X #define HALF_IN_Y #endif #endif @@ -2376,18 +2384,18 @@ static void clean_up_after_endstop_or_probe_move() { */ static void extrapolate_unprobed_bed_level() { #ifdef HALF_IN_X - const uint8_t ctrx2 = 0, xlen = ABL_GRID_POINTS_X - 1; + const uint8_t ctrx2 = 0, xlen = ABL_GRID_MAX_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 + const uint8_t ctrx1 = (ABL_GRID_MAX_POINTS_X - 1) / 2, // left-of-center + ctrx2 = ABL_GRID_MAX_POINTS_X / 2, // right-of-center xlen = ctrx1; #endif #ifdef HALF_IN_Y - const uint8_t ctry2 = 0, ylen = ABL_GRID_POINTS_Y - 1; + const uint8_t ctry2 = 0, ylen = ABL_GRID_MAX_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 + const uint8_t ctry1 = (ABL_GRID_MAX_POINTS_Y - 1) / 2, // top-of-center + ctry2 = ABL_GRID_MAX_POINTS_Y / 2, // bottom-of-center ylen = ctry1; #endif @@ -2415,21 +2423,21 @@ static void clean_up_after_endstop_or_probe_move() { /** * Print calibration results for plotting or manual frame adjustment. */ - static void print_bed_level() { + static void print_bilinear_leveling_grid() { SERIAL_ECHOPGM("Bilinear Leveling Grid:\n "); - for (uint8_t x = 0; x < ABL_GRID_POINTS_X; x++) { + for (uint8_t x = 0; x < ABL_GRID_MAX_POINTS_X; 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++) { + for (uint8_t y = 0; y < ABL_GRID_MAX_POINTS_Y; y++) { if (y < 10) SERIAL_PROTOCOLCHAR(' '); SERIAL_PROTOCOL((int)y); - for (uint8_t x = 0; x < ABL_GRID_POINTS_X; x++) { + for (uint8_t x = 0; x < ABL_GRID_MAX_POINTS_X; x++) { SERIAL_PROTOCOLCHAR(' '); float offset = bed_level_grid[x][y]; - if (offset < 999.0) { + if (offset != UNPROBED) { if (offset > 0) SERIAL_CHAR('+'); SERIAL_PROTOCOL_F(offset, 2); } @@ -2442,10 +2450,10 @@ static void clean_up_after_endstop_or_probe_move() { } #if ENABLED(ABL_BILINEAR_SUBDIVISION) - #define ABL_GRID_POINTS_VIRT_X (ABL_GRID_POINTS_X - 1) * (BILINEAR_SUBDIVISIONS) + 1 - #define ABL_GRID_POINTS_VIRT_Y (ABL_GRID_POINTS_Y - 1) * (BILINEAR_SUBDIVISIONS) + 1 + #define ABL_GRID_POINTS_VIRT_X (ABL_GRID_MAX_POINTS_X - 1) * (BILINEAR_SUBDIVISIONS) + 1 + #define ABL_GRID_POINTS_VIRT_Y (ABL_GRID_MAX_POINTS_Y - 1) * (BILINEAR_SUBDIVISIONS) + 1 float bed_level_grid_virt[ABL_GRID_POINTS_VIRT_X][ABL_GRID_POINTS_VIRT_Y]; - float bed_level_grid_virt_temp[ABL_GRID_POINTS_X + 2][ABL_GRID_POINTS_Y + 2]; //temporary for calculation (maybe dynamical?) + float bed_level_grid_virt_temp[ABL_GRID_MAX_POINTS_X + 2][ABL_GRID_MAX_POINTS_Y + 2]; //temporary for calculation (maybe dynamical?) int bilinear_grid_spacing_virt[2] = { 0 }; static void bed_level_virt_print() { @@ -2462,7 +2470,7 @@ static void clean_up_after_endstop_or_probe_move() { for (uint8_t x = 0; x < ABL_GRID_POINTS_VIRT_X; x++) { SERIAL_PROTOCOLCHAR(' '); float offset = bed_level_grid_virt[x][y]; - if (offset < 999.0) { + if (offset != UNPROBED) { if (offset > 0) SERIAL_CHAR('+'); SERIAL_PROTOCOL_F(offset, 5); } @@ -2474,10 +2482,10 @@ static void clean_up_after_endstop_or_probe_move() { SERIAL_EOL; } #define LINEAR_EXTRAPOLATION(E, I) (E * 2 - I) - static void bed_level_virt_prepare() { - for (uint8_t y = 1; y <= ABL_GRID_POINTS_Y; y++) { + void bed_level_virt_prepare() { + for (uint8_t y = 1; y <= ABL_GRID_MAX_POINTS_Y; y++) { - for (uint8_t x = 1; x <= ABL_GRID_POINTS_X; x++) + for (uint8_t x = 1; x <= ABL_GRID_MAX_POINTS_X; x++) bed_level_grid_virt_temp[x][y] = bed_level_grid[x - 1][y - 1]; bed_level_grid_virt_temp[0][y] = LINEAR_EXTRAPOLATION( @@ -2485,21 +2493,21 @@ static void clean_up_after_endstop_or_probe_move() { bed_level_grid_virt_temp[2][y] ); - bed_level_grid_virt_temp[(ABL_GRID_POINTS_X + 2) - 1][y] = + bed_level_grid_virt_temp[(ABL_GRID_MAX_POINTS_X + 2) - 1][y] = LINEAR_EXTRAPOLATION( - bed_level_grid_virt_temp[(ABL_GRID_POINTS_X + 2) - 2][y], - bed_level_grid_virt_temp[(ABL_GRID_POINTS_X + 2) - 3][y] + bed_level_grid_virt_temp[(ABL_GRID_MAX_POINTS_X + 2) - 2][y], + bed_level_grid_virt_temp[(ABL_GRID_MAX_POINTS_X + 2) - 3][y] ); } - for (uint8_t x = 0; x < ABL_GRID_POINTS_X + 2; x++) { + for (uint8_t x = 0; x < ABL_GRID_MAX_POINTS_X + 2; x++) { bed_level_grid_virt_temp[x][0] = LINEAR_EXTRAPOLATION( bed_level_grid_virt_temp[x][1], bed_level_grid_virt_temp[x][2] ); - bed_level_grid_virt_temp[x][(ABL_GRID_POINTS_Y + 2) - 1] = + bed_level_grid_virt_temp[x][(ABL_GRID_MAX_POINTS_Y + 2) - 1] = LINEAR_EXTRAPOLATION( - bed_level_grid_virt_temp[x][(ABL_GRID_POINTS_Y + 2) - 2], - bed_level_grid_virt_temp[x][(ABL_GRID_POINTS_Y + 2) - 3] + bed_level_grid_virt_temp[x][(ABL_GRID_MAX_POINTS_Y + 2) - 2], + bed_level_grid_virt_temp[x][(ABL_GRID_MAX_POINTS_Y + 2) - 3] ); } } @@ -2520,12 +2528,12 @@ static void clean_up_after_endstop_or_probe_move() { } return bed_level_virt_cmr(row, 1, tx); } - static void bed_level_virt_interpolate() { - for (uint8_t y = 0; y < ABL_GRID_POINTS_Y; y++) - for (uint8_t x = 0; x < ABL_GRID_POINTS_X; x++) + void bed_level_virt_interpolate() { + for (uint8_t y = 0; y < ABL_GRID_MAX_POINTS_Y; y++) + for (uint8_t x = 0; x < ABL_GRID_MAX_POINTS_X; x++) for (uint8_t ty = 0; ty < BILINEAR_SUBDIVISIONS; ty++) for (uint8_t tx = 0; tx < BILINEAR_SUBDIVISIONS; tx++) { - if ((ty && y == ABL_GRID_POINTS_Y - 1) || (tx && x == ABL_GRID_POINTS_X - 1)) + if ((ty && y == ABL_GRID_MAX_POINTS_Y - 1) || (tx && x == ABL_GRID_MAX_POINTS_X - 1)) continue; bed_level_grid_virt[x * (BILINEAR_SUBDIVISIONS) + tx][y * (BILINEAR_SUBDIVISIONS) + ty] = bed_level_virt_2cmr( @@ -3422,9 +3430,9 @@ inline void gcode_G28() { // Wait for planner moves to finish! stepper.synchronize(); - // For auto bed leveling, clear the level matrix - #if HAS_ABL - reset_bed_level(); + // Disable the leveling matrix before homing + #if PLANNER_LEVELING + set_bed_leveling_enabled(false); #endif // Always home with tool 0 active @@ -3693,6 +3701,20 @@ inline void gcode_G28() { // Save 130 bytes with non-duplication of PSTR void say_not_entered() { SERIAL_PROTOCOLLNPGM(" not entered."); } + void mbl_mesh_report() { + SERIAL_PROTOCOLLNPGM("Num X,Y: " STRINGIFY(MESH_NUM_X_POINTS) "," STRINGIFY(MESH_NUM_Y_POINTS)); + SERIAL_PROTOCOLLNPGM("Z search height: " STRINGIFY(MESH_HOME_SEARCH_Z)); + SERIAL_PROTOCOLPGM("Z offset: "); SERIAL_PROTOCOL_F(mbl.z_offset, 5); + SERIAL_PROTOCOLLNPGM("\nMeasured points:"); + for (uint8_t py = 0; py < MESH_NUM_Y_POINTS; py++) { + for (uint8_t px = 0; px < MESH_NUM_X_POINTS; px++) { + SERIAL_PROTOCOLPGM(" "); + SERIAL_PROTOCOL_F(mbl.z_values[py][px], 5); + } + SERIAL_EOL; + } + } + /** * G29: Mesh-based Z probe, probes a grid and produces a * mesh to compensate for variable bed height @@ -3728,21 +3750,11 @@ inline void gcode_G28() { switch (state) { case MeshReport: if (mbl.has_mesh()) { - SERIAL_PROTOCOLPAIR("State: ", mbl.active() ? MSG_ON : MSG_OFF); - SERIAL_PROTOCOLLNPGM("\nNum X,Y: " STRINGIFY(MESH_NUM_X_POINTS) "," STRINGIFY(MESH_NUM_Y_POINTS)); - SERIAL_PROTOCOLLNPGM("Z search height: " STRINGIFY(MESH_HOME_SEARCH_Z)); - SERIAL_PROTOCOLPGM("Z offset: "); SERIAL_PROTOCOL_F(mbl.z_offset, 5); - SERIAL_PROTOCOLLNPGM("\nMeasured points:"); - for (py = 0; py < MESH_NUM_Y_POINTS; py++) { - for (px = 0; px < MESH_NUM_X_POINTS; px++) { - SERIAL_PROTOCOLPGM(" "); - SERIAL_PROTOCOL_F(mbl.z_values[py][px], 5); - } - SERIAL_EOL; - } + SERIAL_PROTOCOLLNPAIR("State: ", mbl.active() ? MSG_ON : MSG_OFF); + mbl_mesh_report(); } else - SERIAL_PROTOCOLLNPGM("Mesh bed leveling not active."); + SERIAL_PROTOCOLLNPGM("Mesh bed leveling has no data."); break; case MeshStart: @@ -3863,7 +3875,7 @@ inline void gcode_G28() { * * Enhanced G29 Auto Bed Leveling Probe Routine * - * Parameters With ABL_GRID: + * Parameters With LINEAR and BILINEAR: * * P Set the size of the grid that will be probed (P x P points). * Not supported by non-linear delta printer bed leveling. @@ -3887,6 +3899,10 @@ inline void gcode_G28() { * L Set the Left limit of the probing grid * R Set the Right limit of the probing grid * + * Parameters with BILINEAR only: + * + * Z Supply an additional Z probe offset + * * Global Parameters: * * E/e By default G29 will engage the Z probe, test the bed, then disengage. @@ -3934,8 +3950,8 @@ inline void gcode_G28() { // X and Y specify points in each direction, overriding the default // These values may be saved with the completed mesh - int abl_grid_points_x = code_seen('X') ? code_value_int() : ABL_GRID_POINTS_X, - abl_grid_points_y = code_seen('Y') ? code_value_int() : ABL_GRID_POINTS_Y; + int abl_grid_points_x = code_seen('X') ? code_value_int() : ABL_GRID_MAX_POINTS_X, + abl_grid_points_y = code_seen('Y') ? code_value_int() : ABL_GRID_MAX_POINTS_Y; if (code_seen('P')) abl_grid_points_x = abl_grid_points_y = code_value_int(); @@ -3946,7 +3962,7 @@ inline void gcode_G28() { #else - const int abl_grid_points_x = ABL_GRID_POINTS_X, abl_grid_points_y = ABL_GRID_POINTS_Y; + const uint8_t abl_grid_points_x = ABL_GRID_MAX_POINTS_X, abl_grid_points_y = ABL_GRID_MAX_POINTS_Y; #endif @@ -4030,7 +4046,11 @@ inline void gcode_G28() { || left_probe_bed_position != bilinear_start[X_AXIS] || front_probe_bed_position != bilinear_start[Y_AXIS] ) { + // Before reset bed level, re-enable to correct the position + planner.abl_enabled = abl_should_enable; + // Reset grid to 0.0 or "not probed". (Also disables ABL) reset_bed_level(); + #if ENABLED(ABL_BILINEAR_SUBDIVISION) bilinear_grid_spacing_virt[X_AXIS] = xGridSpacing / (BILINEAR_SUBDIVISIONS); bilinear_grid_spacing_virt[Y_AXIS] = yGridSpacing / (BILINEAR_SUBDIVISIONS); @@ -4039,6 +4059,7 @@ inline void gcode_G28() { bilinear_grid_spacing[Y_AXIS] = yGridSpacing; bilinear_start[X_AXIS] = RAW_X_POSITION(left_probe_bed_position); bilinear_start[Y_AXIS] = RAW_Y_POSITION(front_probe_bed_position); + // Can't re-enable (on error) until the new grid is written abl_should_enable = false; } @@ -4203,7 +4224,7 @@ inline void gcode_G28() { #if ENABLED(AUTO_BED_LEVELING_BILINEAR) if (!dryrun) extrapolate_unprobed_bed_level(); - print_bed_level(); + print_bilinear_leveling_grid(); #if ENABLED(ABL_BILINEAR_SUBDIVISION) bed_level_virt_prepare(); @@ -4322,45 +4343,34 @@ inline void gcode_G28() { // Correct the current XYZ position based on the tilted plane. // - // 1. Get the distance from the current position to the reference point. - float x_dist = RAW_CURRENT_POSITION(X_AXIS) - X_TILT_FULCRUM, - y_dist = RAW_CURRENT_POSITION(Y_AXIS) - Y_TILT_FULCRUM, - z_real = current_position[Z_AXIS], - z_zero = 0; - #if ENABLED(DEBUG_LEVELING_FEATURE) if (DEBUGGING(LEVELING)) DEBUG_POS("G29 uncorrected XYZ", current_position); #endif - matrix_3x3 inverse = matrix_3x3::transpose(planner.bed_level_matrix); - - // 2. Apply the inverse matrix to the distance - // from the reference point to X, Y, and zero. - apply_rotation_xyz(inverse, x_dist, y_dist, z_zero); + float converted[XYZ]; + memcpy(converted, current_position, sizeof(converted)); - // 3. Get the matrix-based corrected Z. - // (Even if not used, get it for comparison.) - float new_z = z_real + z_zero; + planner.abl_enabled = true; + planner.unapply_leveling(converted); // use conversion machinery + planner.abl_enabled = false; - // 4. Use the last measured distance to the bed, if possible + // Use the last measured distance to the bed, if possible if ( NEAR(current_position[X_AXIS], xProbe - (X_PROBE_OFFSET_FROM_EXTRUDER)) && NEAR(current_position[Y_AXIS], yProbe - (Y_PROBE_OFFSET_FROM_EXTRUDER)) ) { - float simple_z = z_real - (measured_z - (-zprobe_zoffset)); + float simple_z = current_position[Z_AXIS] - (measured_z - (-zprobe_zoffset)); #if ENABLED(DEBUG_LEVELING_FEATURE) if (DEBUGGING(LEVELING)) { SERIAL_ECHOPAIR("Z from Probe:", simple_z); - SERIAL_ECHOPAIR(" Matrix:", new_z); - SERIAL_ECHOLNPAIR(" Discrepancy:", simple_z - new_z); + SERIAL_ECHOPAIR(" Matrix:", converted[Z_AXIS]); + SERIAL_ECHOLNPAIR(" Discrepancy:", simple_z - converted[Z_AXIS]); } #endif - new_z = simple_z; + converted[Z_AXIS] = simple_z; } - // 5. The rotated XY and corrected Z are now current_position - current_position[X_AXIS] = LOGICAL_X_POSITION(x_dist) + X_TILT_FULCRUM; - current_position[Y_AXIS] = LOGICAL_Y_POSITION(y_dist) + Y_TILT_FULCRUM; - current_position[Z_AXIS] = new_z; + // The rotated XY and corrected Z are now current_position + memcpy(current_position, converted, sizeof(converted)); #if ENABLED(DEBUG_LEVELING_FEATURE) if (DEBUGGING(LEVELING)) DEBUG_POS("G29 corrected XYZ", current_position); @@ -5041,7 +5051,8 @@ inline void gcode_M42() { // Disable bed level correction in M48 because we want the raw data when we probe #if HAS_ABL - reset_bed_level(); + const bool abl_was_enabled = planner.abl_enabled; + set_bed_leveling_enabled(false); #endif setup_for_endstop_or_probe_move(); @@ -5192,6 +5203,11 @@ inline void gcode_M42() { clean_up_after_endstop_or_probe_move(); + // Re-enable bed level correction if it has been on + #if HAS_ABL + set_bed_leveling_enabled(abl_was_enabled); + #endif + report_current_position(); } @@ -7000,12 +7016,54 @@ void quickstop_stepper() { * * S[bool] Turns leveling on or off * Z[height] Sets the Z fade height (0 or none to disable) + * V[bool] Verbose - Print the levelng grid */ inline void gcode_M420() { - if (code_seen('S')) set_bed_leveling_enabled(code_value_bool()); + bool to_enable = false; + + if (code_seen('S')) { + to_enable = code_value_bool(); + set_bed_leveling_enabled(to_enable); + } + #if ENABLED(ENABLE_LEVELING_FADE_HEIGHT) if (code_seen('Z')) set_z_fade_height(code_value_linear_units()); #endif + + if (to_enable && !( + #if ENABLED(MESH_BED_LEVELING) + mbl.active() + #else + planner.abl_enabled + #endif + ) ) { + to_enable = false; + SERIAL_ERROR_START; + SERIAL_ERRORLNPGM(MSG_ERR_M420_FAILED); + } + + SERIAL_ECHO_START; + SERIAL_ECHOLNPAIR("Bed Leveling ", to_enable ? MSG_ON : MSG_OFF); + + // V to print the matrix or mesh + if (code_seen('V')) { + #if ABL_PLANAR + planner.bed_level_matrix.debug("Bed Level Correction Matrix:"); + #elif ENABLED(AUTO_BED_LEVELING_BILINEAR) + if (bilinear_grid_spacing[X_AXIS]) { + print_bilinear_leveling_grid(); + #if ENABLED(ABL_BILINEAR_SUBDIVISION) + bed_level_virt_print(); + #endif + } + #elif ENABLED(MESH_BED_LEVELING) + if (mbl.has_mesh()) { + SERIAL_ECHOLNPGM("Mesh Bed Level data:"); + mbl_mesh_report(); + } + #endif + } + } #endif @@ -7048,6 +7106,40 @@ void quickstop_stepper() { } } +#elif ENABLED(AUTO_BED_LEVELING_BILINEAR) + + /** + * M421: Set a single Mesh Bed Leveling Z coordinate + * + * M421 I J Z + */ + inline void gcode_M421() { + int8_t px = 0, py = 0; + float z = 0; + bool hasI, hasJ, hasZ; + if ((hasI = code_seen('I'))) px = code_value_axis_units(X_AXIS); + if ((hasJ = code_seen('J'))) py = code_value_axis_units(Y_AXIS); + if ((hasZ = code_seen('Z'))) z = code_value_axis_units(Z_AXIS); + + if (hasI && hasJ && hasZ) { + if (px >= 0 && px < ABL_GRID_MAX_POINTS_X && py >= 0 && py < ABL_GRID_MAX_POINTS_X) { + bed_level_grid[px][py] = z; + #if ENABLED(ABL_BILINEAR_SUBDIVISION) + bed_level_virt_prepare(); + bed_level_virt_interpolate(); + #endif + } + else { + SERIAL_ERROR_START; + SERIAL_ERRORLNPGM(MSG_ERR_MESH_XY); + } + } + else { + SERIAL_ERROR_START; + SERIAL_ERRORLNPGM(MSG_ERR_M421_PARAMETERS); + } + } + #endif /** @@ -8757,8 +8849,8 @@ void ok_to_send() { #define ABL_BG_GRID(X,Y) bed_level_grid_virt[X][Y] #else #define ABL_BG_SPACING(A) bilinear_grid_spacing[A] - #define ABL_BG_POINTS_X ABL_GRID_POINTS_X - #define ABL_BG_POINTS_Y ABL_GRID_POINTS_Y + #define ABL_BG_POINTS_X ABL_GRID_MAX_POINTS_X + #define ABL_BG_POINTS_Y ABL_GRID_MAX_POINTS_Y #define ABL_BG_GRID(X,Y) bed_level_grid[X][Y] #endif diff --git a/Marlin/SanityCheck.h b/Marlin/SanityCheck.h index 56032fc40..0890f581b 100644 --- a/Marlin/SanityCheck.h +++ b/Marlin/SanityCheck.h @@ -142,7 +142,9 @@ #elif defined(AUTO_BED_LEVELING_FEATURE) #error "AUTO_BED_LEVELING_FEATURE is deprecated. Specify AUTO_BED_LEVELING_LINEAR, AUTO_BED_LEVELING_BILINEAR, or AUTO_BED_LEVELING_3POINT." #elif defined(ABL_GRID_POINTS) - #error "ABL_GRID_POINTS is now ABL_GRID_POINTS_X and ABL_GRID_POINTS_Y. Please update your configuration." + #error "ABL_GRID_POINTS is now ABL_GRID_MAX_POINTS_X and ABL_GRID_MAX_POINTS_Y. Please update your configuration." +#elif defined(ABL_GRID_POINTS_X) || defined(ABL_GRID_POINTS_Y) + #error "ABL_GRID_POINTS_[XY] is now ABL_GRID_MAX_POINTS_[XY]. Please update your configuration." #elif defined(BEEPER) #error "BEEPER is now BEEPER_PIN. Please update your pins definitions." #elif defined(SDCARDDETECT) @@ -212,10 +214,10 @@ #error "You probably want to use Max Endstops for DELTA!" #endif #if ABL_GRID - #if (ABL_GRID_POINTS_X & 1) == 0 || (ABL_GRID_POINTS_Y & 1) == 0 - #error "DELTA requires ABL_GRID_POINTS_X and ABL_GRID_POINTS_Y to be odd numbers." - #elif ABL_GRID_POINTS_X < 3 - #error "DELTA requires ABL_GRID_POINTS_X and ABL_GRID_POINTS_Y to be 3 or higher." + #if (ABL_GRID_MAX_POINTS_X & 1) == 0 || (ABL_GRID_MAX_POINTS_Y & 1) == 0 + #error "DELTA requires ABL_GRID_MAX_POINTS_X and ABL_GRID_MAX_POINTS_Y to be odd numbers." + #elif ABL_GRID_MAX_POINTS_X < 3 + #error "DELTA requires ABL_GRID_MAX_POINTS_X and ABL_GRID_MAX_POINTS_Y to be 3 or higher." #endif #endif #endif diff --git a/Marlin/configuration_store.cpp b/Marlin/configuration_store.cpp index bbd286844..934aac1c3 100644 --- a/Marlin/configuration_store.cpp +++ b/Marlin/configuration_store.cpp @@ -36,18 +36,18 @@ * */ -#define EEPROM_VERSION "V28" +#define EEPROM_VERSION "V29" // Change EEPROM version if these are changed: #define EEPROM_OFFSET 100 /** - * V28 EEPROM Layout: + * V29 EEPROM Layout: * - * 100 Version (char x4) - * 104 EEPROM Checksum (uint16_t) + * 100 Version (char x4) + * 104 EEPROM Checksum (uint16_t) * - * 106 E_STEPPERS (uint8_t) + * 106 E_STEPPERS (uint8_t) * 107 M92 XYZE planner.axis_steps_per_mm (float x4 ... x7) * 123 M203 XYZE planner.max_feedrate_mm_s (float x4 ... x7) * 139 M201 XYZE planner.max_acceleration_mm_per_s2 (uint32_t x4 ... x7) @@ -65,60 +65,71 @@ * 207 M218 XYZ hotend_offset (float x3 per additional hotend) * * Mesh bed leveling: - * 219 M420 S status (uint8) - * 220 z_offset (float) - * 224 mesh_num_x (uint8 as set in firmware) - * 225 mesh_num_y (uint8 as set in firmware) - * 226 G29 S3 XYZ z_values[][] (float x9, by default, up to float x 81) + * 219 M420 S from mbl.status (bool) + * 220 mbl.z_offset (float) + * 224 MESH_NUM_X_POINTS (uint8 as set in firmware) + * 225 MESH_NUM_Y_POINTS (uint8 as set in firmware) + * 226 G29 S3 XYZ z_values[][] (float x9, by default, up to float x 81) +288 * * AUTO BED LEVELING * 262 M851 zprobe_zoffset (float) * - * DELTA: - * 266 M666 XYZ endstop_adj (float x3) - * 278 M665 R delta_radius (float) - * 282 M665 L delta_diagonal_rod (float) - * 286 M665 S delta_segments_per_second (float) - * 290 M665 A delta_diagonal_rod_trim_tower_1 (float) - * 294 M665 B delta_diagonal_rod_trim_tower_2 (float) - * 298 M665 C delta_diagonal_rod_trim_tower_3 (float) + * ABL_PLANAR (or placeholder): 36 bytes + * 266 planner.bed_level_matrix (matrix_3x3 = float x9) * - * Z_DUAL_ENDSTOPS: - * 302 M666 Z z_endstop_adj (float) + * AUTO_BED_LEVELING_BILINEAR (or placeholder): 47 bytes + * 302 ABL_GRID_MAX_POINTS_X (uint8_t) + * 303 ABL_GRID_MAX_POINTS_Y (uint8_t) + * 304 bilinear_grid_spacing (int x2) from G29: (B-F)/X, (R-L)/Y + * 308 G29 L F bilinear_start (int x2) + * 312 bed_level_grid[][] (float x9, up to float x256) +988 * - * ULTIPANEL: - * 306 M145 S0 H lcd_preheat_hotend_temp (int x2) - * 310 M145 S0 B lcd_preheat_bed_temp (int x2) - * 314 M145 S0 F lcd_preheat_fan_speed (int x2) + * DELTA (if deltabot): 36 bytes + * 348 M666 XYZ endstop_adj (float x3) + * 360 M665 R delta_radius (float) + * 364 M665 L delta_diagonal_rod (float) + * 368 M665 S delta_segments_per_second (float) + * 372 M665 A delta_diagonal_rod_trim_tower_1 (float) + * 376 M665 B delta_diagonal_rod_trim_tower_2 (float) + * 380 M665 C delta_diagonal_rod_trim_tower_3 (float) * - * PIDTEMP: - * 318 M301 E0 PIDC Kp[0], Ki[0], Kd[0], Kc[0] (float x4) - * 334 M301 E1 PIDC Kp[1], Ki[1], Kd[1], Kc[1] (float x4) - * 350 M301 E2 PIDC Kp[2], Ki[2], Kd[2], Kc[2] (float x4) - * 366 M301 E3 PIDC Kp[3], Ki[3], Kd[3], Kc[3] (float x4) - * 382 M301 L lpq_len (int) + * Z_DUAL_ENDSTOPS: 4 bytes + * 384 M666 Z z_endstop_adj (float) + * + * ULTIPANEL: 6 bytes + * 388 M145 S0 H lcd_preheat_hotend_temp (int x2) + * 392 M145 S0 B lcd_preheat_bed_temp (int x2) + * 396 M145 S0 F lcd_preheat_fan_speed (int x2) + * + * PIDTEMP: 66 bytes + * 400 M301 E0 PIDC Kp[0], Ki[0], Kd[0], Kc[0] (float x4) + * 416 M301 E1 PIDC Kp[1], Ki[1], Kd[1], Kc[1] (float x4) + * 432 M301 E2 PIDC Kp[2], Ki[2], Kd[2], Kc[2] (float x4) + * 448 M301 E3 PIDC Kp[3], Ki[3], Kd[3], Kc[3] (float x4) + * 464 M301 L lpq_len (int) * * PIDTEMPBED: - * 384 M304 PID thermalManager.bedKp, thermalManager.bedKi, thermalManager.bedKd (float x3) + * 466 M304 PID thermalManager.bedKp, thermalManager.bedKi, thermalManager.bedKd (float x3) * - * DOGLCD: - * 396 M250 C lcd_contrast (int) + * DOGLCD: 2 bytes + * 478 M250 C lcd_contrast (int) * - * FWRETRACT: - * 398 M209 S autoretract_enabled (bool) - * 399 M207 S retract_length (float) - * 403 M207 W retract_length_swap (float) - * 407 M207 F retract_feedrate_mm_s (float) - * 411 M207 Z retract_zlift (float) - * 415 M208 S retract_recover_length (float) - * 419 M208 W retract_recover_length_swap (float) - * 423 M208 F retract_recover_feedrate_mm_s (float) + * FWRETRACT: 29 bytes + * 480 M209 S autoretract_enabled (bool) + * 481 M207 S retract_length (float) + * 485 M207 W retract_length_swap (float) + * 489 M207 F retract_feedrate_mm_s (float) + * 493 M207 Z retract_zlift (float) + * 497 M208 S retract_recover_length (float) + * 501 M208 W retract_recover_length_swap (float) + * 505 M208 F retract_recover_feedrate_mm_s (float) * - * Volumetric Extrusion: - * 427 M200 D volumetric_enabled (bool) - * 428 M200 T D filament_size (float x4) (T0..3) + * Volumetric Extrusion: 17 bytes + * 509 M200 D volumetric_enabled (bool) + * 510 M200 T D filament_size (float x4) (T0..3) * - * 444 This Slot is Available! + * 526 Minimum end-point + * 1847 (526 + 36 + 9 + 288 + 988) Maximum end-point * */ #include "Marlin.h" @@ -133,6 +144,11 @@ #include "mesh_bed_leveling.h" #endif +#if ENABLED(ABL_BILINEAR_SUBDIVISION) + extern void bed_level_virt_prepare(); + extern void bed_level_virt_interpolate(); +#endif + /** * Post-process after Retrieve or Reset */ @@ -188,10 +204,11 @@ void Config_Postprocess() { value++; }; } + bool eeprom_read_error; void _EEPROM_readData(int &pos, uint8_t* value, uint8_t size) { do { uint8_t c = eeprom_read_byte((unsigned char*)pos); - *value = c; + if (!eeprom_read_error) *value = c; eeprom_checksum += c; pos++; value++; @@ -203,6 +220,7 @@ void Config_Postprocess() { #define EEPROM_SKIP(VAR) eeprom_index += sizeof(VAR) #define EEPROM_WRITE(VAR) _EEPROM_writeData(eeprom_index, (uint8_t*)&VAR, sizeof(VAR)) #define EEPROM_READ(VAR) _EEPROM_readData(eeprom_index, (uint8_t*)&VAR, sizeof(VAR)) + #define EEPROM_ASSERT(TST,ERR) if () do{ SERIAL_ERROR_START; SERIAL_ERRORLNPGM(ERR); eeprom_read_error |= true; }while(0) /** * M500 - Store Configuration @@ -241,28 +259,30 @@ void Config_Postprocess() { LOOP_XYZ(i) EEPROM_WRITE(hotend_offset[i][e]); #endif + // + // Mesh Bed Leveling + // + #if ENABLED(MESH_BED_LEVELING) // Compile time test that sizeof(mbl.z_values) is as expected typedef char c_assert[(sizeof(mbl.z_values) == (MESH_NUM_X_POINTS) * (MESH_NUM_Y_POINTS) * sizeof(dummy)) ? 1 : -1]; - uint8_t mesh_num_x = MESH_NUM_X_POINTS, - mesh_num_y = MESH_NUM_Y_POINTS, - dummy_uint8 = mbl.status & _BV(MBL_STATUS_HAS_MESH_BIT); - EEPROM_WRITE(dummy_uint8); + const bool leveling_is_on = TEST(mbl.status, MBL_STATUS_HAS_MESH_BIT); + const uint8_t mesh_num_x = MESH_NUM_X_POINTS, mesh_num_y = MESH_NUM_Y_POINTS; + EEPROM_WRITE(leveling_is_on); EEPROM_WRITE(mbl.z_offset); EEPROM_WRITE(mesh_num_x); EEPROM_WRITE(mesh_num_y); EEPROM_WRITE(mbl.z_values); #else // For disabled MBL write a default mesh - uint8_t mesh_num_x = 3, - mesh_num_y = 3, - dummy_uint8 = 0; + const bool leveling_is_on = false; dummy = 0.0f; - EEPROM_WRITE(dummy_uint8); - EEPROM_WRITE(dummy); + const uint8_t mesh_num_x = 3, mesh_num_y = 3; + EEPROM_WRITE(leveling_is_on); + EEPROM_WRITE(dummy); // z_offset EEPROM_WRITE(mesh_num_x); EEPROM_WRITE(mesh_num_y); - for (uint8_t q = 0; q < mesh_num_x * mesh_num_y; q++) EEPROM_WRITE(dummy); + for (uint8_t q = mesh_num_x * mesh_num_y; q--;) EEPROM_WRITE(dummy); #endif // MESH_BED_LEVELING #if !HAS_BED_PROBE @@ -270,6 +290,42 @@ void Config_Postprocess() { #endif EEPROM_WRITE(zprobe_zoffset); + // + // Planar Bed Leveling matrix + // + + #if ABL_PLANAR + EEPROM_WRITE(planner.bed_level_matrix); + #else + dummy = 0.0; + for (uint8_t q = 9; q--;) EEPROM_WRITE(dummy); + #endif + + // + // Bilinear Auto Bed Leveling + // + + #if ENABLED(AUTO_BED_LEVELING_BILINEAR) + // Compile time test that sizeof(bed_level_grid) is as expected + typedef char c_assert[(sizeof(bed_level_grid) == (ABL_GRID_MAX_POINTS_X) * (ABL_GRID_MAX_POINTS_Y) * sizeof(dummy)) ? 1 : -1]; + const uint8_t grid_max_x = ABL_GRID_MAX_POINTS_X, grid_max_y = ABL_GRID_MAX_POINTS_Y; + EEPROM_WRITE(grid_max_x); // 1 byte + EEPROM_WRITE(grid_max_y); // 1 byte + EEPROM_WRITE(bilinear_grid_spacing); // 2 ints + EEPROM_WRITE(bilinear_start); // 2 ints + EEPROM_WRITE(bed_level_grid); // 9-256 floats + #else + // For disabled Bilinear Grid write an empty 3x3 grid + const uint8_t grid_max_x = 3, grid_max_y = 3; + const int bilinear_start[2] = { 0 }, bilinear_grid_spacing[2] = { 0 }; + dummy = 0.0f; + EEPROM_WRITE(grid_max_x); + EEPROM_WRITE(grid_max_y); + EEPROM_WRITE(bilinear_grid_spacing); + EEPROM_WRITE(bilinear_start); + for (uint16_t q = grid_max_x * grid_max_y; q--;) EEPROM_WRITE(dummy); + #endif // AUTO_BED_LEVELING_BILINEAR + // 9 floats for DELTA / Z_DUAL_ENDSTOPS #if ENABLED(DELTA) EEPROM_WRITE(endstop_adj); // 3 floats @@ -371,17 +427,21 @@ void Config_Postprocess() { EEPROM_WRITE(dummy); } - uint16_t final_checksum = eeprom_checksum, - eeprom_size = eeprom_index; + if (!eeprom_write_error) { + + uint16_t final_checksum = eeprom_checksum, + eeprom_size = eeprom_index; - eeprom_index = EEPROM_OFFSET; - EEPROM_WRITE(version); - EEPROM_WRITE(final_checksum); + // Write the EEPROM header + eeprom_index = EEPROM_OFFSET; + EEPROM_WRITE(version); + EEPROM_WRITE(final_checksum); - // Report storage size - SERIAL_ECHO_START; - SERIAL_ECHOPAIR("Settings Stored (", eeprom_size); - SERIAL_ECHOLNPGM(" bytes)"); + // Report storage size + SERIAL_ECHO_START; + SERIAL_ECHOPAIR("Settings Stored (", eeprom_size); + SERIAL_ECHOLNPGM(" bytes)"); + } } /** @@ -390,6 +450,7 @@ void Config_Postprocess() { void Config_RetrieveSettings() { EEPROM_START(); + eeprom_read_error = false; // If set EEPROM_READ won't write into RAM char stored_ver[4]; EEPROM_READ(stored_ver); @@ -418,9 +479,9 @@ void Config_Postprocess() { // Get only the number of E stepper parameters previously stored // Any steppers added later are set to their defaults const float def1[] = DEFAULT_AXIS_STEPS_PER_UNIT, def2[] = DEFAULT_MAX_FEEDRATE; - const long def3[] = DEFAULT_MAX_ACCELERATION; + const uint32_t def3[] = DEFAULT_MAX_ACCELERATION; float tmp1[XYZ + esteppers], tmp2[XYZ + esteppers]; - long tmp3[XYZ + esteppers]; + uint32_t tmp3[XYZ + esteppers]; EEPROM_READ(tmp1); EEPROM_READ(tmp2); EEPROM_READ(tmp3); @@ -445,13 +506,19 @@ void Config_Postprocess() { LOOP_XYZ(i) EEPROM_READ(hotend_offset[i][e]); #endif - uint8_t dummy_uint8 = 0, mesh_num_x = 0, mesh_num_y = 0; - EEPROM_READ(dummy_uint8); + // + // Mesh (Manual) Bed Leveling + // + + bool leveling_is_on; + uint8_t mesh_num_x, mesh_num_y; + EEPROM_READ(leveling_is_on); EEPROM_READ(dummy); EEPROM_READ(mesh_num_x); EEPROM_READ(mesh_num_y); + #if ENABLED(MESH_BED_LEVELING) - mbl.status = dummy_uint8; + mbl.status = leveling_is_on ? _BV(MBL_STATUS_HAS_MESH_BIT) : 0; mbl.z_offset = dummy; if (mesh_num_x == MESH_NUM_X_POINTS && mesh_num_y == MESH_NUM_Y_POINTS) { // EEPROM data fits the current mesh @@ -460,11 +527,11 @@ void Config_Postprocess() { else { // EEPROM data is stale mbl.reset(); - for (uint8_t q = 0; q < mesh_num_x * mesh_num_y; q++) EEPROM_READ(dummy); + for (uint16_t q = mesh_num_x * mesh_num_y; q--;) EEPROM_READ(dummy); } #else // MBL is disabled - skip the stored data - for (uint8_t q = 0; q < mesh_num_x * mesh_num_y; q++) EEPROM_READ(dummy); + for (uint16_t q = mesh_num_x * mesh_num_y; q--;) EEPROM_READ(dummy); #endif // MESH_BED_LEVELING #if !HAS_BED_PROBE @@ -472,6 +539,45 @@ void Config_Postprocess() { #endif EEPROM_READ(zprobe_zoffset); + // + // Planar Bed Leveling matrix + // + + #if ABL_PLANAR + EEPROM_READ(planner.bed_level_matrix); + #else + for (uint8_t q = 9; q--;) EEPROM_READ(dummy); + #endif + + // + // Bilinear Auto Bed Leveling + // + + uint8_t grid_max_x, grid_max_y; + EEPROM_READ(grid_max_x); // 1 byte + EEPROM_READ(grid_max_y); // 1 byte + #if ENABLED(AUTO_BED_LEVELING_BILINEAR) + if (grid_max_x == ABL_GRID_MAX_POINTS_X && grid_max_y == ABL_GRID_MAX_POINTS_Y) { + set_bed_leveling_enabled(false); + EEPROM_READ(bilinear_grid_spacing); // 2 ints + EEPROM_READ(bilinear_start); // 2 ints + EEPROM_READ(bed_level_grid); // 9 to 256 floats + #if ENABLED(ABL_BILINEAR_SUBDIVISION) + bed_level_virt_prepare(); + bed_level_virt_interpolate(); + #endif + //set_bed_leveling_enabled(leveling_is_on); + } + else // EEPROM data is stale + #endif // AUTO_BED_LEVELING_BILINEAR + { + // Skip past disabled (or stale) Bilinear Grid data + int bgs[2], bs[2]; + EEPROM_READ(bgs); + EEPROM_READ(bs); + for (uint16_t q = grid_max_x * grid_max_y; q--;) EEPROM_READ(dummy); + } + #if ENABLED(DELTA) EEPROM_READ(endstop_adj); // 3 floats EEPROM_READ(delta_radius); // 1 float @@ -568,11 +674,15 @@ void Config_Postprocess() { } if (eeprom_checksum == stored_checksum) { - Config_Postprocess(); - SERIAL_ECHO_START; - SERIAL_ECHO(version); - SERIAL_ECHOPAIR(" stored settings retrieved (", eeprom_index); - SERIAL_ECHOLNPGM(" bytes)"); + if (eeprom_read_error) + Config_ResetDefault(); + else { + Config_Postprocess(); + SERIAL_ECHO_START; + SERIAL_ECHO(version); + SERIAL_ECHOPAIR(" stored settings retrieved (", eeprom_index); + SERIAL_ECHOLNPGM(" bytes)"); + } } else { SERIAL_ERROR_START; @@ -600,7 +710,7 @@ void Config_Postprocess() { */ void Config_ResetDefault() { const float tmp1[] = DEFAULT_AXIS_STEPS_PER_UNIT, tmp2[] = DEFAULT_MAX_FEEDRATE; - const long tmp3[] = DEFAULT_MAX_ACCELERATION; + const uint32_t tmp3[] = DEFAULT_MAX_ACCELERATION; LOOP_XYZE_N(i) { planner.axis_steps_per_mm[i] = tmp1[i < COUNT(tmp1) ? i : COUNT(tmp1) - 1]; planner.max_feedrate_mm_s[i] = tmp2[i < COUNT(tmp2) ? i : COUNT(tmp2) - 1]; @@ -636,8 +746,9 @@ void Config_ResetDefault() { LOOP_XYZ(i) HOTEND_LOOP() hotend_offset[i][e] = tmp4[i][e]; #endif - #if ENABLED(MESH_BED_LEVELING) - mbl.reset(); + // Applies to all MBL and ABL + #if PLANNER_LEVELING + reset_bed_level(); #endif #if HAS_BED_PROBE @@ -649,9 +760,9 @@ void Config_ResetDefault() { endstop_adj[A_AXIS] = adj[A_AXIS]; endstop_adj[B_AXIS] = adj[B_AXIS]; endstop_adj[C_AXIS] = adj[C_AXIS]; - delta_radius = DELTA_RADIUS; - delta_diagonal_rod = DELTA_DIAGONAL_ROD; - delta_segments_per_second = DELTA_SEGMENTS_PER_SECOND; + delta_radius = DELTA_RADIUS; + delta_diagonal_rod = DELTA_DIAGONAL_ROD; + delta_segments_per_second = DELTA_SEGMENTS_PER_SECOND; delta_diagonal_rod_trim_tower_1 = DELTA_DIAGONAL_ROD_TRIM_TOWER_1; delta_diagonal_rod_trim_tower_2 = DELTA_DIAGONAL_ROD_TRIM_TOWER_2; delta_diagonal_rod_trim_tower_3 = DELTA_DIAGONAL_ROD_TRIM_TOWER_3; @@ -852,13 +963,10 @@ void Config_ResetDefault() { #if ENABLED(MESH_BED_LEVELING) if (!forReplay) { - SERIAL_ECHOLNPGM("Mesh bed leveling:"); + SERIAL_ECHOLNPGM("Mesh Bed Leveling:"); CONFIG_ECHO_START; } - SERIAL_ECHOPAIR(" M420 S", mbl.has_mesh() ? 1 : 0); - SERIAL_ECHOPAIR(" X", MESH_NUM_X_POINTS); - SERIAL_ECHOPAIR(" Y", MESH_NUM_Y_POINTS); - SERIAL_EOL; + SERIAL_ECHOLNPAIR(" M420 S", mbl.has_mesh() ? 1 : 0); for (uint8_t py = 1; py <= MESH_NUM_Y_POINTS; py++) { for (uint8_t px = 1; px <= MESH_NUM_X_POINTS; px++) { CONFIG_ECHO_START; @@ -869,6 +977,12 @@ void Config_ResetDefault() { SERIAL_EOL; } } + #elif HAS_ABL + if (!forReplay) { + SERIAL_ECHOLNPGM("Auto Bed Leveling:"); + CONFIG_ECHO_START; + } + SERIAL_ECHOLNPAIR(" M420 S", planner.abl_enabled ? 1 : 0); #endif #if ENABLED(DELTA) diff --git a/Marlin/example_configurations/Cartesio/Configuration.h b/Marlin/example_configurations/Cartesio/Configuration.h index f25f13230..e7efeb545 100644 --- a/Marlin/example_configurations/Cartesio/Configuration.h +++ b/Marlin/example_configurations/Cartesio/Configuration.h @@ -805,8 +805,8 @@ #if ENABLED(AUTO_BED_LEVELING_LINEAR) || ENABLED(AUTO_BED_LEVELING_BILINEAR) // Set the number of grid points per dimension. - #define ABL_GRID_POINTS_X 3 - #define ABL_GRID_POINTS_Y ABL_GRID_POINTS_X + #define ABL_GRID_MAX_POINTS_X 3 + #define ABL_GRID_MAX_POINTS_Y ABL_GRID_MAX_POINTS_X // Set the boundaries for probing (where the probe can reach). #define LEFT_PROBE_BED_POSITION 15 diff --git a/Marlin/example_configurations/Felix/Configuration.h b/Marlin/example_configurations/Felix/Configuration.h index 87cc01323..22dc72c61 100644 --- a/Marlin/example_configurations/Felix/Configuration.h +++ b/Marlin/example_configurations/Felix/Configuration.h @@ -788,8 +788,8 @@ #if ENABLED(AUTO_BED_LEVELING_LINEAR) || ENABLED(AUTO_BED_LEVELING_BILINEAR) // Set the number of grid points per dimension. - #define ABL_GRID_POINTS_X 3 - #define ABL_GRID_POINTS_Y ABL_GRID_POINTS_X + #define ABL_GRID_MAX_POINTS_X 3 + #define ABL_GRID_MAX_POINTS_Y ABL_GRID_MAX_POINTS_X // Set the boundaries for probing (where the probe can reach). #define LEFT_PROBE_BED_POSITION 15 diff --git a/Marlin/example_configurations/Felix/DUAL/Configuration.h b/Marlin/example_configurations/Felix/DUAL/Configuration.h index 4178d7fc1..8b31c6ef4 100644 --- a/Marlin/example_configurations/Felix/DUAL/Configuration.h +++ b/Marlin/example_configurations/Felix/DUAL/Configuration.h @@ -788,8 +788,8 @@ #if ENABLED(AUTO_BED_LEVELING_LINEAR) || ENABLED(AUTO_BED_LEVELING_BILINEAR) // Set the number of grid points per dimension. - #define ABL_GRID_POINTS_X 3 - #define ABL_GRID_POINTS_Y ABL_GRID_POINTS_X + #define ABL_GRID_MAX_POINTS_X 3 + #define ABL_GRID_MAX_POINTS_Y ABL_GRID_MAX_POINTS_X // Set the boundaries for probing (where the probe can reach). #define LEFT_PROBE_BED_POSITION 15 diff --git a/Marlin/example_configurations/Hephestos/Configuration.h b/Marlin/example_configurations/Hephestos/Configuration.h index bb19408c2..051427cd4 100644 --- a/Marlin/example_configurations/Hephestos/Configuration.h +++ b/Marlin/example_configurations/Hephestos/Configuration.h @@ -797,8 +797,8 @@ #if ENABLED(AUTO_BED_LEVELING_LINEAR) || ENABLED(AUTO_BED_LEVELING_BILINEAR) // Set the number of grid points per dimension. - #define ABL_GRID_POINTS_X 3 - #define ABL_GRID_POINTS_Y ABL_GRID_POINTS_X + #define ABL_GRID_MAX_POINTS_X 3 + #define ABL_GRID_MAX_POINTS_Y ABL_GRID_MAX_POINTS_X // Set the boundaries for probing (where the probe can reach). #define LEFT_PROBE_BED_POSITION 15 diff --git a/Marlin/example_configurations/Hephestos_2/Configuration.h b/Marlin/example_configurations/Hephestos_2/Configuration.h index 2f971ee70..497cb3c37 100644 --- a/Marlin/example_configurations/Hephestos_2/Configuration.h +++ b/Marlin/example_configurations/Hephestos_2/Configuration.h @@ -799,8 +799,8 @@ #if ENABLED(AUTO_BED_LEVELING_LINEAR) || ENABLED(AUTO_BED_LEVELING_BILINEAR) // Set the number of grid points per dimension. - #define ABL_GRID_POINTS_X 3 - #define ABL_GRID_POINTS_Y ABL_GRID_POINTS_X + #define ABL_GRID_MAX_POINTS_X 3 + #define ABL_GRID_MAX_POINTS_Y ABL_GRID_MAX_POINTS_X // Set the boundaries for probing (where the probe can reach). #define LEFT_PROBE_BED_POSITION X_MIN_POS + X_PROBE_OFFSET_FROM_EXTRUDER diff --git a/Marlin/example_configurations/K8200/Configuration.h b/Marlin/example_configurations/K8200/Configuration.h index f5320ac07..bc85e0c1e 100644 --- a/Marlin/example_configurations/K8200/Configuration.h +++ b/Marlin/example_configurations/K8200/Configuration.h @@ -834,8 +834,8 @@ #if ENABLED(AUTO_BED_LEVELING_LINEAR) || ENABLED(AUTO_BED_LEVELING_BILINEAR) // Set the number of grid points per dimension. - #define ABL_GRID_POINTS_X 3 - #define ABL_GRID_POINTS_Y ABL_GRID_POINTS_X + #define ABL_GRID_MAX_POINTS_X 3 + #define ABL_GRID_MAX_POINTS_Y ABL_GRID_MAX_POINTS_X // Set the boundaries for probing (where the probe can reach). #define LEFT_PROBE_BED_POSITION 15 diff --git a/Marlin/example_configurations/K8400/Configuration.h b/Marlin/example_configurations/K8400/Configuration.h index 31fae7bc7..b4dd9838c 100644 --- a/Marlin/example_configurations/K8400/Configuration.h +++ b/Marlin/example_configurations/K8400/Configuration.h @@ -805,8 +805,8 @@ #if ENABLED(AUTO_BED_LEVELING_LINEAR) || ENABLED(AUTO_BED_LEVELING_BILINEAR) // Set the number of grid points per dimension. - #define ABL_GRID_POINTS_X 3 - #define ABL_GRID_POINTS_Y ABL_GRID_POINTS_X + #define ABL_GRID_MAX_POINTS_X 3 + #define ABL_GRID_MAX_POINTS_Y ABL_GRID_MAX_POINTS_X // Set the boundaries for probing (where the probe can reach). #define LEFT_PROBE_BED_POSITION 15 diff --git a/Marlin/example_configurations/K8400/Dual-head/Configuration.h b/Marlin/example_configurations/K8400/Dual-head/Configuration.h index 5d90bb888..a4f9e267b 100644 --- a/Marlin/example_configurations/K8400/Dual-head/Configuration.h +++ b/Marlin/example_configurations/K8400/Dual-head/Configuration.h @@ -805,8 +805,8 @@ #if ENABLED(AUTO_BED_LEVELING_LINEAR) || ENABLED(AUTO_BED_LEVELING_BILINEAR) // Set the number of grid points per dimension. - #define ABL_GRID_POINTS_X 3 - #define ABL_GRID_POINTS_Y ABL_GRID_POINTS_X + #define ABL_GRID_MAX_POINTS_X 3 + #define ABL_GRID_MAX_POINTS_Y ABL_GRID_MAX_POINTS_X // Set the boundaries for probing (where the probe can reach). #define LEFT_PROBE_BED_POSITION 15 diff --git a/Marlin/example_configurations/RepRapWorld/Megatronics/Configuration.h b/Marlin/example_configurations/RepRapWorld/Megatronics/Configuration.h index cc746f782..3368bea44 100644 --- a/Marlin/example_configurations/RepRapWorld/Megatronics/Configuration.h +++ b/Marlin/example_configurations/RepRapWorld/Megatronics/Configuration.h @@ -805,8 +805,8 @@ #if ENABLED(AUTO_BED_LEVELING_LINEAR) || ENABLED(AUTO_BED_LEVELING_BILINEAR) // Set the number of grid points per dimension. - #define ABL_GRID_POINTS_X 3 - #define ABL_GRID_POINTS_Y ABL_GRID_POINTS_X + #define ABL_GRID_MAX_POINTS_X 3 + #define ABL_GRID_MAX_POINTS_Y ABL_GRID_MAX_POINTS_X // Set the boundaries for probing (where the probe can reach). #define LEFT_PROBE_BED_POSITION 15 diff --git a/Marlin/example_configurations/RigidBot/Configuration.h b/Marlin/example_configurations/RigidBot/Configuration.h index 426f74bd1..6a77fca66 100644 --- a/Marlin/example_configurations/RigidBot/Configuration.h +++ b/Marlin/example_configurations/RigidBot/Configuration.h @@ -804,8 +804,8 @@ #if ENABLED(AUTO_BED_LEVELING_LINEAR) || ENABLED(AUTO_BED_LEVELING_BILINEAR) // Set the number of grid points per dimension. - #define ABL_GRID_POINTS_X 3 - #define ABL_GRID_POINTS_Y ABL_GRID_POINTS_X + #define ABL_GRID_MAX_POINTS_X 3 + #define ABL_GRID_MAX_POINTS_Y ABL_GRID_MAX_POINTS_X // Set the boundaries for probing (where the probe can reach). #define LEFT_PROBE_BED_POSITION 15 diff --git a/Marlin/example_configurations/SCARA/Configuration.h b/Marlin/example_configurations/SCARA/Configuration.h index a80ac2923..59587ffac 100644 --- a/Marlin/example_configurations/SCARA/Configuration.h +++ b/Marlin/example_configurations/SCARA/Configuration.h @@ -820,8 +820,8 @@ #if ENABLED(AUTO_BED_LEVELING_LINEAR) || ENABLED(AUTO_BED_LEVELING_BILINEAR) // Set the number of grid points per dimension. - #define ABL_GRID_POINTS_X 3 - #define ABL_GRID_POINTS_Y ABL_GRID_POINTS_X + #define ABL_GRID_MAX_POINTS_X 3 + #define ABL_GRID_MAX_POINTS_Y ABL_GRID_MAX_POINTS_X // Set the boundaries for probing (where the probe can reach). #define LEFT_PROBE_BED_POSITION 15 diff --git a/Marlin/example_configurations/TAZ4/Configuration.h b/Marlin/example_configurations/TAZ4/Configuration.h index ee76668e8..6bdce5e2e 100644 --- a/Marlin/example_configurations/TAZ4/Configuration.h +++ b/Marlin/example_configurations/TAZ4/Configuration.h @@ -826,8 +826,8 @@ #if ENABLED(AUTO_BED_LEVELING_LINEAR) || ENABLED(AUTO_BED_LEVELING_BILINEAR) // Set the number of grid points per dimension. - #define ABL_GRID_POINTS_X 3 - #define ABL_GRID_POINTS_Y ABL_GRID_POINTS_X + #define ABL_GRID_MAX_POINTS_X 3 + #define ABL_GRID_MAX_POINTS_Y ABL_GRID_MAX_POINTS_X // Set the boundaries for probing (where the probe can reach). #define LEFT_PROBE_BED_POSITION 15 diff --git a/Marlin/example_configurations/WITBOX/Configuration.h b/Marlin/example_configurations/WITBOX/Configuration.h index 11dca14e6..13047faf6 100644 --- a/Marlin/example_configurations/WITBOX/Configuration.h +++ b/Marlin/example_configurations/WITBOX/Configuration.h @@ -797,8 +797,8 @@ #if ENABLED(AUTO_BED_LEVELING_LINEAR) || ENABLED(AUTO_BED_LEVELING_BILINEAR) // Set the number of grid points per dimension. - #define ABL_GRID_POINTS_X 3 - #define ABL_GRID_POINTS_Y ABL_GRID_POINTS_X + #define ABL_GRID_MAX_POINTS_X 3 + #define ABL_GRID_MAX_POINTS_Y ABL_GRID_MAX_POINTS_X // Set the boundaries for probing (where the probe can reach). #define LEFT_PROBE_BED_POSITION 15 diff --git a/Marlin/example_configurations/adafruit/ST7565/Configuration.h b/Marlin/example_configurations/adafruit/ST7565/Configuration.h index 30930fd71..694965a72 100644 --- a/Marlin/example_configurations/adafruit/ST7565/Configuration.h +++ b/Marlin/example_configurations/adafruit/ST7565/Configuration.h @@ -805,8 +805,8 @@ #if ENABLED(AUTO_BED_LEVELING_LINEAR) || ENABLED(AUTO_BED_LEVELING_BILINEAR) // Set the number of grid points per dimension. - #define ABL_GRID_POINTS_X 3 - #define ABL_GRID_POINTS_Y ABL_GRID_POINTS_X + #define ABL_GRID_MAX_POINTS_X 3 + #define ABL_GRID_MAX_POINTS_Y ABL_GRID_MAX_POINTS_X // Set the boundaries for probing (where the probe can reach). #define LEFT_PROBE_BED_POSITION 15 diff --git a/Marlin/example_configurations/delta/biv2.5/Configuration.h b/Marlin/example_configurations/delta/biv2.5/Configuration.h index c1966cbaf..1db02eb65 100644 --- a/Marlin/example_configurations/delta/biv2.5/Configuration.h +++ b/Marlin/example_configurations/delta/biv2.5/Configuration.h @@ -898,8 +898,8 @@ // Set the number of grid points per dimension. // Works best with 5 or more points in each dimension. - #define ABL_GRID_POINTS_X 9 - #define ABL_GRID_POINTS_Y ABL_GRID_POINTS_X + #define ABL_GRID_MAX_POINTS_X 9 + #define ABL_GRID_MAX_POINTS_Y ABL_GRID_MAX_POINTS_X // Set the boundaries for probing (where the probe can reach). #define DELTA_PROBEABLE_RADIUS (DELTA_PRINTABLE_RADIUS - 10) diff --git a/Marlin/example_configurations/delta/generic/Configuration.h b/Marlin/example_configurations/delta/generic/Configuration.h index c3bea40d9..dbb80a25b 100644 --- a/Marlin/example_configurations/delta/generic/Configuration.h +++ b/Marlin/example_configurations/delta/generic/Configuration.h @@ -892,8 +892,8 @@ // Set the number of grid points per dimension. // Works best with 5 or more points in each dimension. - #define ABL_GRID_POINTS_X 9 - #define ABL_GRID_POINTS_Y ABL_GRID_POINTS_X + #define ABL_GRID_MAX_POINTS_X 9 + #define ABL_GRID_MAX_POINTS_Y ABL_GRID_MAX_POINTS_X // Set the boundaries for probing (where the probe can reach). #define DELTA_PROBEABLE_RADIUS (DELTA_PRINTABLE_RADIUS - 10) diff --git a/Marlin/example_configurations/delta/kossel_mini/Configuration.h b/Marlin/example_configurations/delta/kossel_mini/Configuration.h index c317f7dd0..943cbb0d1 100644 --- a/Marlin/example_configurations/delta/kossel_mini/Configuration.h +++ b/Marlin/example_configurations/delta/kossel_mini/Configuration.h @@ -895,8 +895,8 @@ // Set the number of grid points per dimension. // Works best with 5 or more points in each dimension. - #define ABL_GRID_POINTS_X 9 - #define ABL_GRID_POINTS_Y ABL_GRID_POINTS_X + #define ABL_GRID_MAX_POINTS_X 9 + #define ABL_GRID_MAX_POINTS_Y ABL_GRID_MAX_POINTS_X // Set the boundaries for probing (where the probe can reach). #define DELTA_PROBEABLE_RADIUS (DELTA_PRINTABLE_RADIUS - 10) diff --git a/Marlin/example_configurations/delta/kossel_pro/Configuration.h b/Marlin/example_configurations/delta/kossel_pro/Configuration.h index 7bdaf265b..8b415f794 100644 --- a/Marlin/example_configurations/delta/kossel_pro/Configuration.h +++ b/Marlin/example_configurations/delta/kossel_pro/Configuration.h @@ -894,8 +894,8 @@ // Set the number of grid points per dimension. // Works best with 5 or more points in each dimension. - #define ABL_GRID_POINTS_X 7 - #define ABL_GRID_POINTS_Y ABL_GRID_POINTS_X + #define ABL_GRID_MAX_POINTS_X 7 + #define ABL_GRID_MAX_POINTS_Y ABL_GRID_MAX_POINTS_X // Set the boundaries for probing (where the probe can reach). #define DELTA_PROBEABLE_RADIUS (DELTA_PRINTABLE_RADIUS-25) diff --git a/Marlin/example_configurations/delta/kossel_xl/Configuration.h b/Marlin/example_configurations/delta/kossel_xl/Configuration.h index 3fdd41239..428daa9a8 100644 --- a/Marlin/example_configurations/delta/kossel_xl/Configuration.h +++ b/Marlin/example_configurations/delta/kossel_xl/Configuration.h @@ -898,8 +898,8 @@ // Set the number of grid points per dimension. // Works best with 5 or more points in each dimension. - #define ABL_GRID_POINTS_X 5 - #define ABL_GRID_POINTS_Y ABL_GRID_POINTS_X + #define ABL_GRID_MAX_POINTS_X 5 + #define ABL_GRID_MAX_POINTS_Y ABL_GRID_MAX_POINTS_X // Set the boundaries for probing (where the probe can reach). #define DELTA_PROBEABLE_RADIUS (DELTA_PRINTABLE_RADIUS - 10) diff --git a/Marlin/example_configurations/makibox/Configuration.h b/Marlin/example_configurations/makibox/Configuration.h index 492081c43..b6c555e6b 100644 --- a/Marlin/example_configurations/makibox/Configuration.h +++ b/Marlin/example_configurations/makibox/Configuration.h @@ -808,8 +808,8 @@ #if ENABLED(AUTO_BED_LEVELING_LINEAR) || ENABLED(AUTO_BED_LEVELING_BILINEAR) // Set the number of grid points per dimension. - #define ABL_GRID_POINTS_X 3 - #define ABL_GRID_POINTS_Y ABL_GRID_POINTS_X + #define ABL_GRID_MAX_POINTS_X 3 + #define ABL_GRID_MAX_POINTS_Y ABL_GRID_MAX_POINTS_X // Set the boundaries for probing (where the probe can reach). #define LEFT_PROBE_BED_POSITION 15 diff --git a/Marlin/example_configurations/tvrrug/Round2/Configuration.h b/Marlin/example_configurations/tvrrug/Round2/Configuration.h index eb87304a0..8cf3ba5d8 100644 --- a/Marlin/example_configurations/tvrrug/Round2/Configuration.h +++ b/Marlin/example_configurations/tvrrug/Round2/Configuration.h @@ -801,8 +801,8 @@ #if ENABLED(AUTO_BED_LEVELING_LINEAR) || ENABLED(AUTO_BED_LEVELING_BILINEAR) // Set the number of grid points per dimension. - #define ABL_GRID_POINTS_X 3 - #define ABL_GRID_POINTS_Y ABL_GRID_POINTS_X + #define ABL_GRID_MAX_POINTS_X 3 + #define ABL_GRID_MAX_POINTS_Y ABL_GRID_MAX_POINTS_X // Set the boundaries for probing (where the probe can reach). #define LEFT_PROBE_BED_POSITION 15 diff --git a/Marlin/language.h b/Marlin/language.h index 2ab41cc9b..27bfaed64 100644 --- a/Marlin/language.h +++ b/Marlin/language.h @@ -153,10 +153,11 @@ #define MSG_Z2_MAX "z2_max: " #define MSG_Z_PROBE "z_probe: " #define MSG_ERR_MATERIAL_INDEX "M145 S out of range (0-1)" -#define MSG_ERR_M421_PARAMETERS "M421 requires XYZ or IJZ parameters" -#define MSG_ERR_MESH_XY "Mesh XY or IJ cannot be resolved" +#define MSG_ERR_M421_PARAMETERS "M421 required parameters missing" +#define MSG_ERR_MESH_XY "Mesh point cannot be resolved" #define MSG_ERR_ARC_ARGS "G2/G3 bad parameters" #define MSG_ERR_PROTECTED_PIN "Protected Pin" +#define MSG_ERR_M420_FAILED "Failed to enable Bed Leveling" #define MSG_ERR_M428_TOO_FAR "Too far from reference point" #define MSG_ERR_M303_DISABLED "PIDTEMP disabled" #define MSG_M119_REPORT "Reporting endstop status" diff --git a/Marlin/planner.h b/Marlin/planner.h index 407ca7de3..50595708f 100644 --- a/Marlin/planner.h +++ b/Marlin/planner.h @@ -148,8 +148,8 @@ class Planner { static float max_feedrate_mm_s[XYZE_N], // Max speeds in mm per second axis_steps_per_mm[XYZE_N], steps_to_mm[XYZE_N]; - static unsigned long max_acceleration_steps_per_s2[XYZE_N], - max_acceleration_mm_per_s2[XYZE_N]; // Use M201 to override by software + static uint32_t max_acceleration_steps_per_s2[XYZE_N], + max_acceleration_mm_per_s2[XYZE_N]; // Use M201 to override by software static millis_t min_segment_time; static float min_feedrate_mm_s,