From 11e1806e0cf90968606ff9839369b209de5d3cd3 Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Mon, 1 May 2023 02:46:19 +0200 Subject: [PATCH 01/34] Gcode documentation --- Firmware/Marlin_main.cpp | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index d8d022ff9..cf7f01f9b 100644 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -4957,7 +4957,7 @@ void process_commands() Default 3x3 grid can be changed on MK2.5/s and MK3/s to 7x7 grid. #### Usage - G80 [ N | R | V | L | R | F | B ] + G80 [ N | R | V | L | R | F | B | X | Y | W | H ] #### Parameters - `N` - Number of mesh points on x axis. Default is 3. Valid values are 3 and 7. @@ -4970,16 +4970,13 @@ void process_commands() - `R` - Right Bed Level correct value in um. - `F` - Front Bed Level correct value in um. - `B` - Back Bed Level correct value in um. + + The following parameters are used to define the area used by the print: + - `X` - area lower left point X coordinate + - `Y` - area lower left point Y coordinate + - `W` - area width (on X axis) + - `H` - area height (on Y axis) */ - - /* - * Probes a grid and produces a mesh to compensate for variable bed height - * The S0 report the points as below - * +----> X-axis - * | - * | - * v Y-axis - */ case 80: { gcode_G80(); From 7b9f2086f4c19f07a5f3e49d8cfac4b7020a2c5a Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Mon, 1 May 2023 03:46:43 +0200 Subject: [PATCH 02/34] MBL print area initial implementation --- Firmware/Marlin_main.cpp | 79 +++++++++++++++++-------------- Firmware/mesh_bed_calibration.cpp | 3 +- Firmware/mesh_bed_leveling.cpp | 26 +++++----- 3 files changed, 56 insertions(+), 52 deletions(-) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index cf7f01f9b..954aec2a2 100644 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -2841,6 +2841,11 @@ static void gcode_G80() } bool magnet_elimination = (eeprom_read_byte((uint8_t*)EEPROM_MBL_MAGNET_ELIMINATION) > 0); + float area_min_x = code_seen('X') ? code_value() - MESH_X_DIST - X_PROBE_OFFSET_FROM_EXTRUDER : -INFINITY; + float area_min_y = code_seen('Y') ? code_value() - MESH_Y_DIST - Y_PROBE_OFFSET_FROM_EXTRUDER : -INFINITY; + float area_max_x = code_seen('W') ? area_min_x + code_value() + 2 * MESH_X_DIST : INFINITY; + float area_max_y = code_seen('H') ? area_min_y + code_value() + 2 * MESH_Y_DIST : INFINITY; + #ifndef PINDA_THERMISTOR if (run == false && eeprom_read_byte((uint8_t *)EEPROM_TEMP_CAL_ACTIVE) && calibration_status_pinda() == true && target_temperature_bed >= 50) { @@ -2902,30 +2907,36 @@ static void gcode_G80() } #endif // SUPPORT_VERBOSITY int l_feedmultiply = setup_for_endstop_move(false); //save feedrate and feedmultiply, sets feedmultiply to 100 - while (mesh_point != nMeasPoints * nMeasPoints) { + while (mesh_point != MESH_NUM_X_POINTS * MESH_NUM_Y_POINTS) { // Get coords of a measuring point. - uint8_t ix = mesh_point % nMeasPoints; // from 0 to MESH_NUM_X_POINTS - 1 - uint8_t iy = mesh_point / nMeasPoints; + uint8_t ix = mesh_point % MESH_NUM_X_POINTS; // from 0 to MESH_NUM_X_POINTS - 1 + uint8_t iy = mesh_point / MESH_NUM_X_POINTS; + if (iy & 1) ix = (MESH_NUM_X_POINTS - 1) - ix; // Zig zag + bool isOn3x3Mesh = ((ix % 3 == 0) && (iy % 3 == 0)); + float x_pos = BED_X(ix, MESH_NUM_X_POINTS); + float y_pos = BED_Y(iy, MESH_NUM_X_POINTS); + + if ((nMeasPoints == 3) && !isOn3x3Mesh) { + mesh_point++; + continue; //skip + } + + if ((nMeasPoints == 7) && !isOn3x3Mesh && (x_pos < area_min_x || x_pos > area_max_x || y_pos < area_min_y || y_pos > area_max_y)) { + mesh_point++; + custom_message_state--; + continue; //skip + } + /*if (!mbl_point_measurement_valid(ix, iy, nMeasPoints, true)) { printf_P(PSTR("Skipping point [%d;%d] \n"), ix, iy); custom_message_state--; mesh_point++; continue; //skip }*/ - if (iy & 1) ix = (nMeasPoints - 1) - ix; // Zig zag - if (nMeasPoints == 7) //if we have 7x7 mesh, compare with Z-calibration for points which are in 3x3 mesh - { - has_z = ((ix % 3 == 0) && (iy % 3 == 0)) && is_bed_z_jitter_data_valid(); - } + float z0 = 0.f; - if (has_z && (mesh_point > 0)) { - uint16_t z_offset_u = 0; - if (nMeasPoints == 7) { - z_offset_u = eeprom_read_word((uint16_t*)(EEPROM_BED_CALIBRATION_Z_JITTER + 2 * ((ix/3) + iy - 1))); - } - else { - z_offset_u = eeprom_read_word((uint16_t*)(EEPROM_BED_CALIBRATION_Z_JITTER + 2 * (ix + iy * 3 - 1))); - } + if (has_z && isOn3x3Mesh && (mesh_point > 0)) { + uint16_t z_offset_u = eeprom_read_word((uint16_t*)(EEPROM_BED_CALIBRATION_Z_JITTER + 2 * ((ix/3) + iy - 1))); z0 = mbl.z_values[0][0] + *reinterpret_cast(&z_offset_u) * 0.01; #ifdef SUPPORT_VERBOSITY if (verbosity_level >= 1) { @@ -2942,8 +2953,8 @@ static void gcode_G80() st_synchronize(); // Move to XY position of the sensor point. - current_position[X_AXIS] = BED_X(ix, nMeasPoints); - current_position[Y_AXIS] = BED_Y(iy, nMeasPoints); + current_position[X_AXIS] = x_pos; + current_position[Y_AXIS] = y_pos; //printf_P(PSTR("[%f;%f]\n"), current_position[X_AXIS], current_position[Y_AXIS]); @@ -3034,7 +3045,7 @@ static void gcode_G80() #endif // SUPPORT_VERBOSITY plan_buffer_line_curposXYZE(Z_LIFT_FEEDRATE); st_synchronize(); - if (mesh_point != nMeasPoints * nMeasPoints) { + if (mesh_point != MESH_NUM_X_POINTS * MESH_NUM_Y_POINTS) { Sound_MakeSound(e_SOUND_TYPE_StandardAlert); bool bState; do { // repeat until Z-leveling o.k. @@ -3112,19 +3123,17 @@ static void gcode_G80() if (correction[i] == 0) continue; } - for (uint8_t row = 0; row < nMeasPoints; ++row) { - for (uint8_t col = 0; col < nMeasPoints; ++col) { + for (uint8_t row = 0; row < MESH_NUM_Y_POINTS; ++row) { + for (uint8_t col = 0; col < MESH_NUM_X_POINTS; ++col) { mbl.z_values[row][col] +=0.001f * ( - + correction[0] * (nMeasPoints - 1 - col) + + correction[0] * (MESH_NUM_X_POINTS - 1 - col) + correction[1] * col - + correction[2] * (nMeasPoints - 1 - row) + + correction[2] * (MESH_NUM_Y_POINTS - 1 - row) + correction[3] * row) / (float)(nMeasPoints - 1); } } // SERIAL_ECHOLNPGM("Bed leveling correction finished"); - if (nMeasPoints == 3) { - mbl.upsample_3x3(); //interpolation from 3x3 to 7x7 points using largrangian polynomials while using the same array z_values[iy][ix] for storing (just coppying measured data to new destination and interpolating between them) - } + mbl.upsample_3x3(); //interpolation from 3x3 to 7x7 points using largrangian polynomials while using the same array z_values[iy][ix] for storing (just coppying measured data to new destination and interpolating between them) /* SERIAL_PROTOCOLPGM("Num X,Y: "); SERIAL_PROTOCOL(MESH_NUM_X_POINTS); @@ -3134,11 +3143,10 @@ static void gcode_G80() SERIAL_PROTOCOL(MESH_HOME_Z_SEARCH); SERIAL_PROTOCOLLNPGM("\nMeasured points:"); for (int y = MESH_NUM_Y_POINTS-1; y >= 0; y--) { - for (int x = 0; x < MESH_NUM_X_POINTS; x++) { - SERIAL_PROTOCOLPGM(" "); - SERIAL_PROTOCOL_F(mbl.z_values[y][x], 5); - } - SERIAL_PROTOCOLPGM("\n"); + for (int x = 0; x < MESH_NUM_X_POINTS; x++) { + printf_P(PSTR(" %.5f"), mbl.z_values[y][x]); + } + SERIAL_PROTOCOLPGM("\n"); } */ if (nMeasPoints == 7 && magnet_elimination) { @@ -3153,11 +3161,10 @@ static void gcode_G80() SERIAL_PROTOCOL(MESH_HOME_Z_SEARCH); SERIAL_PROTOCOLLNPGM("\nMeasured points:"); for (int y = MESH_NUM_Y_POINTS-1; y >= 0; y--) { - for (int x = 0; x < MESH_NUM_X_POINTS; x++) { - SERIAL_PROTOCOLPGM(" "); - SERIAL_PROTOCOL_F(mbl.z_values[y][x], 5); - } - SERIAL_PROTOCOLPGM("\n"); + for (int x = 0; x < MESH_NUM_X_POINTS; x++) { + printf_P(PSTR(" %.5f"), mbl.z_values[y][x]); + } + SERIAL_PROTOCOLPGM("\n"); } */ // SERIAL_ECHOLNPGM("Upsample finished"); diff --git a/Firmware/mesh_bed_calibration.cpp b/Firmware/mesh_bed_calibration.cpp index 4d1c4aee7..d7fd2b4db 100644 --- a/Firmware/mesh_bed_calibration.cpp +++ b/Firmware/mesh_bed_calibration.cpp @@ -2951,8 +2951,7 @@ bool sample_mesh_and_store_reference() } } - mbl.upsample_3x3(); - mbl.active = true; + mbl.reset(); go_home_with_z_lift(); diff --git a/Firmware/mesh_bed_leveling.cpp b/Firmware/mesh_bed_leveling.cpp index aa969340c..70c9816e5 100644 --- a/Firmware/mesh_bed_leveling.cpp +++ b/Firmware/mesh_bed_leveling.cpp @@ -10,13 +10,17 @@ mesh_bed_leveling::mesh_bed_leveling() { reset(); } void mesh_bed_leveling::reset() { active = 0; - memset(z_values, 0, sizeof(float) * MESH_NUM_X_POINTS * MESH_NUM_Y_POINTS); + for (uint8_t row = 0; row < MESH_NUM_Y_POINTS; ++row) { + for (uint8_t col = 0; col < MESH_NUM_X_POINTS; ++col) { + mbl.z_values[row][col] = NAN; + } + } } static inline bool vec_undef(const float v[2]) { const uint32_t *vx = (const uint32_t*)v; - return vx[0] == 0x0FFFFFFFF || vx[1] == 0x0FFFFFFFF; + return vx[0] == 0xFFFFFFFF || vx[1] == 0xFFFFFFFF; } #if MESH_NUM_X_POINTS>=5 && MESH_NUM_Y_POINTS>=5 && (MESH_NUM_X_POINTS&1)==1 && (MESH_NUM_Y_POINTS&1)==1 @@ -33,13 +37,10 @@ void mesh_bed_leveling::upsample_3x3() static const float x0 = MESH_MIN_X; static const float x1 = 0.5f * float(MESH_MIN_X + MESH_MAX_X); static const float x2 = MESH_MAX_X; - for (int j = 0; j < 3; ++ j) { - // 1) Copy the source points to their new destination. - z_values[j][idx2] = z_values[j][2]; - z_values[j][idx1] = z_values[j][1]; - // 2) Interpolate the remaining values by Largrangian polynomials. - for (int i = idx0 + 1; i < idx2; ++ i) { - if (i == idx1) + for (int j = 0; j < MESH_NUM_Y_POINTS; ++ j) { + // Interpolate the remaining values by Largrangian polynomials. + for (int i = 0; i < MESH_NUM_X_POINTS; ++ i) { + if (!isnan(z_values[j][i])) continue; float x = get_x(i); #ifdef MBL_BILINEAR @@ -61,12 +62,9 @@ void mesh_bed_leveling::upsample_3x3() static const float y1 = 0.5f * float(MESH_MIN_Y + MESH_MAX_Y); static const float y2 = MESH_MAX_Y; for (int i = 0; i < MESH_NUM_X_POINTS; ++ i) { - // 1) Copy the intermediate points to their new destination. - z_values[idx2][i] = z_values[2][i]; - z_values[idx1][i] = z_values[1][i]; - // 2) Interpolate the remaining values by Largrangian polynomials. + // Interpolate the remaining values by Largrangian polynomials. for (int j = 1; j + 1 < MESH_NUM_Y_POINTS; ++ j) { - if (j == idx1) + if (!isnan(z_values[j][i])) continue; float y = get_y(j); #ifdef MBL_BILINEAR From a4ef72b1fca4d66f2f1a911fcca223fd8f8473dc Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Mon, 1 May 2023 11:46:41 +0200 Subject: [PATCH 03/34] Use mesh from eeprom during print area MBL --- Firmware/Marlin_main.cpp | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 954aec2a2..0d75b541b 100644 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -2916,28 +2916,12 @@ static void gcode_G80() float x_pos = BED_X(ix, MESH_NUM_X_POINTS); float y_pos = BED_Y(iy, MESH_NUM_X_POINTS); - if ((nMeasPoints == 3) && !isOn3x3Mesh) { - mesh_point++; - continue; //skip - } - - if ((nMeasPoints == 7) && !isOn3x3Mesh && (x_pos < area_min_x || x_pos > area_max_x || y_pos < area_min_y || y_pos > area_max_y)) { - mesh_point++; - custom_message_state--; - continue; //skip - } - - /*if (!mbl_point_measurement_valid(ix, iy, nMeasPoints, true)) { - printf_P(PSTR("Skipping point [%d;%d] \n"), ix, iy); - custom_message_state--; - mesh_point++; - continue; //skip - }*/ - + // Reconstruct the mesh saved in eeprom float z0 = 0.f; if (has_z && isOn3x3Mesh && (mesh_point > 0)) { uint16_t z_offset_u = eeprom_read_word((uint16_t*)(EEPROM_BED_CALIBRATION_Z_JITTER + 2 * ((ix/3) + iy - 1))); z0 = mbl.z_values[0][0] + *reinterpret_cast(&z_offset_u) * 0.01; + mbl.set_z(ix, iy, z0); #ifdef SUPPORT_VERBOSITY if (verbosity_level >= 1) { printf_P(PSTR("Bed leveling, point: %d, calibration Z stored in eeprom: %d, calibration z: %f \n"), mesh_point, z_offset_u, z0); @@ -2945,6 +2929,17 @@ static void gcode_G80() #endif // SUPPORT_VERBOSITY } + if ((nMeasPoints == 3) && !isOn3x3Mesh) { + mesh_point++; + continue; //skip + } + + if ((nMeasPoints == 7) && (x_pos < area_min_x || x_pos > area_max_x || y_pos < area_min_y || y_pos > area_max_y) && (mesh_point > 0) && (!isOn3x3Mesh || has_z)) { + mesh_point++; + custom_message_state--; + continue; //skip + } + // Move Z up to MESH_HOME_Z_SEARCH. if((ix == 0) && (iy == 0)) current_position[Z_AXIS] = MESH_HOME_Z_SEARCH; else current_position[Z_AXIS] += 2.f / nMeasPoints; //use relative movement from Z coordinate where PINDa triggered on previous point. This makes calibration faster. From 8edfff39e4549a92b9f2e202d73845064fc79ac2 Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Tue, 2 May 2023 10:47:06 +0200 Subject: [PATCH 04/34] MBL code cleanup --- Firmware/mesh_bed_calibration.cpp | 2 +- Firmware/mesh_bed_leveling.cpp | 110 +++++++++++++++++++++++------- Firmware/mesh_bed_leveling.h | 103 +++------------------------- 3 files changed, 96 insertions(+), 119 deletions(-) diff --git a/Firmware/mesh_bed_calibration.cpp b/Firmware/mesh_bed_calibration.cpp index d7fd2b4db..a04b3a44a 100644 --- a/Firmware/mesh_bed_calibration.cpp +++ b/Firmware/mesh_bed_calibration.cpp @@ -776,7 +776,7 @@ void world2machine_revert_to_uncorrected() static inline bool vec_undef(const float v[2]) { const uint32_t *vx = (const uint32_t*)v; - return vx[0] == 0x0FFFFFFFF || vx[1] == 0x0FFFFFFFF; + return vx[0] == 0xFFFFFFFF || vx[1] == 0xFFFFFFFF; } diff --git a/Firmware/mesh_bed_leveling.cpp b/Firmware/mesh_bed_leveling.cpp index 70c9816e5..60cd341c5 100644 --- a/Firmware/mesh_bed_leveling.cpp +++ b/Firmware/mesh_bed_leveling.cpp @@ -6,8 +6,6 @@ mesh_bed_leveling mbl; -mesh_bed_leveling::mesh_bed_leveling() { reset(); } - void mesh_bed_leveling::reset() { active = 0; for (uint8_t row = 0; row < MESH_NUM_Y_POINTS; ++row) { @@ -17,10 +15,91 @@ void mesh_bed_leveling::reset() { } } -static inline bool vec_undef(const float v[2]) -{ - const uint32_t *vx = (const uint32_t*)v; - return vx[0] == 0xFFFFFFFF || vx[1] == 0xFFFFFFFF; +float mesh_bed_leveling::get_z(float x, float y) { + int i, j; + float s, t; + +#if MESH_NUM_X_POINTS==3 && MESH_NUM_Y_POINTS==3 +#define MESH_MID_X (0.5f*(MESH_MIN_X+MESH_MAX_X)) +#define MESH_MID_Y (0.5f*(MESH_MIN_Y+MESH_MAX_Y)) + if (x < MESH_MID_X) { + i = 0; + s = (x - MESH_MIN_X) / MESH_X_DIST; + if (s > 1.f) + s = 1.f; + } else { + i = 1; + s = (x - MESH_MID_X) / MESH_X_DIST; + if (s < 0) + s = 0; + } + if (y < MESH_MID_Y) { + j = 0; + t = (y - MESH_MIN_Y) / MESH_Y_DIST; + if (t > 1.f) + t = 1.f; + } else { + j = 1; + t = (y - MESH_MID_Y) / MESH_Y_DIST; + if (t < 0) + t = 0; + } +#else + i = int(floor((x - MESH_MIN_X) / MESH_X_DIST)); + if (i < 0) { + i = 0; + s = (x - MESH_MIN_X) / MESH_X_DIST; + if (s > 1.f) + s = 1.f; + } + else if (i > MESH_NUM_X_POINTS - 2) { + i = MESH_NUM_X_POINTS - 2; + s = (x - get_x(i)) / MESH_X_DIST; + if (s < 0) + s = 0; + } else { + s = (x - get_x(i)) / MESH_X_DIST; + if (s < 0) + s = 0; + else if (s > 1.f) + s = 1.f; + } + j = int(floor((y - MESH_MIN_Y) / MESH_Y_DIST)); + if (j < 0) { + j = 0; + t = (y - MESH_MIN_Y) / MESH_Y_DIST; + if (t > 1.f) + t = 1.f; + } else if (j > MESH_NUM_Y_POINTS - 2) { + j = MESH_NUM_Y_POINTS - 2; + t = (y - get_y(j)) / MESH_Y_DIST; + if (t < 0) + t = 0; + } else { + t = (y - get_y(j)) / MESH_Y_DIST; + if (t < 0) + t = 0; + else if (t > 1.f) + t = 1.f; + } +#endif /* MESH_NUM_X_POINTS==3 && MESH_NUM_Y_POINTS==3 */ + + float si = 1.f-s; + float z0 = si * z_values[j ][i] + s * z_values[j ][i+1]; + float z1 = si * z_values[j+1][i] + s * z_values[j+1][i+1]; + return (1.f-t) * z0 + t * z1; +} + +int mesh_bed_leveling::select_x_index(float x) { + int i = 1; + while (x > get_x(i) && i < MESH_NUM_X_POINTS - 1) i++; + return i - 1; +} + +int mesh_bed_leveling::select_y_index(float y) { + int i = 1; + while (y > get_y(i) && i < MESH_NUM_Y_POINTS - 1) i++; + return i - 1; } #if MESH_NUM_X_POINTS>=5 && MESH_NUM_Y_POINTS>=5 && (MESH_NUM_X_POINTS&1)==1 && (MESH_NUM_Y_POINTS&1)==1 @@ -80,24 +159,7 @@ void mesh_bed_leveling::upsample_3x3() } } } - -/* - // Relax the non-measured points. - const float weight = 0.2f; - for (uint8_t iter = 0; iter < 20; ++ iter) { - for (int8_t j = 1; j < 6; ++ j) { - for (int8_t i = 1; i < 6; ++ i) { - if (i == 3 || j == 3) - continue; - if ((i % 3) == 0 && (j % 3) == 0) - continue; - float avg = 0.25f * (z_values[j][i-1]+z_values[j][i+1]+z_values[j-1][i]+z_values[j+1][i]); - z_values[j][i] = (1.f-weight)*z_values[j][i] + weight*avg; - } - } - } -*/ } -#endif +#endif // (MESH_NUM_X_POINTS>=5 && MESH_NUM_Y_POINTS>=5 && (MESH_NUM_X_POINTS&1)==1 && (MESH_NUM_Y_POINTS&1)==1) #endif // MESH_BED_LEVELING diff --git a/Firmware/mesh_bed_leveling.h b/Firmware/mesh_bed_leveling.h index 7df04844a..b7d33379a 100644 --- a/Firmware/mesh_bed_leveling.h +++ b/Firmware/mesh_bed_leveling.h @@ -13,106 +13,21 @@ public: uint8_t active; float z_values[MESH_NUM_Y_POINTS][MESH_NUM_X_POINTS]; - mesh_bed_leveling(); + mesh_bed_leveling() { reset(); } void reset(); + + static float get_x(int i) { return float(MESH_MIN_X) + float(MESH_X_DIST) * float(i); } + static float get_y(int i) { return float(MESH_MIN_Y) + float(MESH_Y_DIST) * float(i); } + float get_z(float x, float y); + void set_z(uint8_t ix, uint8_t iy, float z) { z_values[iy][ix] = z; } + + int select_x_index(float x); + int select_y_index(float y); #if MESH_NUM_X_POINTS>=5 && MESH_NUM_Y_POINTS>=5 && (MESH_NUM_X_POINTS&1)==1 && (MESH_NUM_Y_POINTS&1)==1 void upsample_3x3(); #endif - - static float get_x(int i) { return float(MESH_MIN_X) + float(MESH_X_DIST) * float(i); } - static float get_y(int i) { return float(MESH_MIN_Y) + float(MESH_Y_DIST) * float(i); } - - void set_z(uint8_t ix, uint8_t iy, float z) { z_values[iy][ix] = z; } - - int select_x_index(float x) { - int i = 1; - while (x > get_x(i) && i < MESH_NUM_X_POINTS - 1) i++; - return i - 1; - } - - int select_y_index(float y) { - int i = 1; - while (y > get_y(i) && i < MESH_NUM_Y_POINTS - 1) i++; - return i - 1; - } - - float get_z(float x, float y) { - int i, j; - float s, t; - -#if MESH_NUM_X_POINTS==3 && MESH_NUM_Y_POINTS==3 -#define MESH_MID_X (0.5f*(MESH_MIN_X+MESH_MAX_X)) -#define MESH_MID_Y (0.5f*(MESH_MIN_Y+MESH_MAX_Y)) - if (x < MESH_MID_X) { - i = 0; - s = (x - MESH_MIN_X) / MESH_X_DIST; - if (s > 1.f) - s = 1.f; - } else { - i = 1; - s = (x - MESH_MID_X) / MESH_X_DIST; - if (s < 0) - s = 0; - } - if (y < MESH_MID_Y) { - j = 0; - t = (y - MESH_MIN_Y) / MESH_Y_DIST; - if (t > 1.f) - t = 1.f; - } else { - j = 1; - t = (y - MESH_MID_Y) / MESH_Y_DIST; - if (t < 0) - t = 0; - } -#else - i = int(floor((x - MESH_MIN_X) / MESH_X_DIST)); - if (i < 0) { - i = 0; - s = (x - MESH_MIN_X) / MESH_X_DIST; - if (s > 1.f) - s = 1.f; - } - else if (i > MESH_NUM_X_POINTS - 2) { - i = MESH_NUM_X_POINTS - 2; - s = (x - get_x(i)) / MESH_X_DIST; - if (s < 0) - s = 0; - } else { - s = (x - get_x(i)) / MESH_X_DIST; - if (s < 0) - s = 0; - else if (s > 1.f) - s = 1.f; - } - j = int(floor((y - MESH_MIN_Y) / MESH_Y_DIST)); - if (j < 0) { - j = 0; - t = (y - MESH_MIN_Y) / MESH_Y_DIST; - if (t > 1.f) - t = 1.f; - } else if (j > MESH_NUM_Y_POINTS - 2) { - j = MESH_NUM_Y_POINTS - 2; - t = (y - get_y(j)) / MESH_Y_DIST; - if (t < 0) - t = 0; - } else { - t = (y - get_y(j)) / MESH_Y_DIST; - if (t < 0) - t = 0; - else if (t > 1.f) - t = 1.f; - } -#endif /* MESH_NUM_X_POINTS==3 && MESH_NUM_Y_POINTS==3 */ - - float si = 1.f-s; - float z0 = si * z_values[j ][i] + s * z_values[j ][i+1]; - float z1 = si * z_values[j+1][i] + s * z_values[j+1][i+1]; - return (1.f-t) * z0 + t * z1; - } - }; extern mesh_bed_leveling mbl; From fbfc6bf4a5a0e37b2188049512298931f7b0401d Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Tue, 2 May 2023 10:48:35 +0200 Subject: [PATCH 05/34] MBL remove MBL_BILINEAR --- Firmware/mesh_bed_leveling.cpp | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/Firmware/mesh_bed_leveling.cpp b/Firmware/mesh_bed_leveling.cpp index 60cd341c5..d8dbd3fb1 100644 --- a/Firmware/mesh_bed_leveling.cpp +++ b/Firmware/mesh_bed_leveling.cpp @@ -105,7 +105,6 @@ int mesh_bed_leveling::select_y_index(float y) { #if MESH_NUM_X_POINTS>=5 && MESH_NUM_Y_POINTS>=5 && (MESH_NUM_X_POINTS&1)==1 && (MESH_NUM_Y_POINTS&1)==1 // Works for an odd number of MESH_NUM_X_POINTS and MESH_NUM_Y_POINTS -// #define MBL_BILINEAR void mesh_bed_leveling::upsample_3x3() { int idx0 = 0; @@ -122,16 +121,10 @@ void mesh_bed_leveling::upsample_3x3() if (!isnan(z_values[j][i])) continue; float x = get_x(i); - #ifdef MBL_BILINEAR - z_values[j][i] = (x < x1) ? - ((z_values[j][idx0] * (x - x0) + z_values[j][idx1] * (x1 - x)) / (x1 - x0)) : - ((z_values[j][idx1] * (x - x1) + z_values[j][idx2] * (x2 - x)) / (x2 - x1)); - #else z_values[j][i] = z_values[j][idx0] * (x - x1) * (x - x2) / ((x0 - x1) * (x0 - x2)) + z_values[j][idx1] * (x - x0) * (x - x2) / ((x1 - x0) * (x1 - x2)) + z_values[j][idx2] * (x - x0) * (x - x1) / ((x2 - x0) * (x2 - x1)); - #endif } } } @@ -146,16 +139,10 @@ void mesh_bed_leveling::upsample_3x3() if (!isnan(z_values[j][i])) continue; float y = get_y(j); - #ifdef MBL_BILINEAR - z_values[j][i] = (y < y1) ? - ((z_values[idx0][i] * (y - y0) + z_values[idx1][i] * (y1 - y)) / (y1 - y0)) : - ((z_values[idx1][i] * (y - y1) + z_values[idx2][i] * (y2 - y)) / (y2 - y1)); - #else z_values[j][i] = z_values[idx0][i] * (y - y1) * (y - y2) / ((y0 - y1) * (y0 - y2)) + z_values[idx1][i] * (y - y0) * (y - y2) / ((y1 - y0) * (y1 - y2)) + z_values[idx2][i] * (y - y0) * (y - y1) / ((y2 - y0) * (y2 - y1)); - #endif } } } From 07b9447ee1b263fc2718dd2ede0df205b11edbb1 Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Fri, 5 May 2023 10:23:36 +0200 Subject: [PATCH 06/34] Fix correction nMeasPoints --- Firmware/Marlin_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 0d75b541b..d28857343 100644 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -3124,7 +3124,7 @@ static void gcode_G80() + correction[0] * (MESH_NUM_X_POINTS - 1 - col) + correction[1] * col + correction[2] * (MESH_NUM_Y_POINTS - 1 - row) - + correction[3] * row) / (float)(nMeasPoints - 1); + + correction[3] * row) / (float)(MESH_NUM_X_POINTS - 1); } } // SERIAL_ECHOLNPGM("Bed leveling correction finished"); From 46710c4b4e9add5024ae7152075393e9dee33ca9 Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Fri, 5 May 2023 10:34:07 +0200 Subject: [PATCH 07/34] G80 code cleanup --- Firmware/Marlin_main.cpp | 121 +++------------------------------------ 1 file changed, 8 insertions(+), 113 deletions(-) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index d28857343..e3f83504e 100644 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -2800,14 +2800,6 @@ static void gcode_G80() static bool run = false; // thermistor-less PINDA temperature compensation is running #endif // ndef PINDA_THERMISTOR -#ifdef SUPPORT_VERBOSITY - int8_t verbosity_level = 0; - if (code_seen('V')) { - // Just 'V' without a number counts as V1. - char c = strchr_pointer[1]; - verbosity_level = (c == ' ' || c == '\t' || c == 0) ? 1 : code_value_short(); - } -#endif //SUPPORT_VERBOSITY // Firstly check if we know where we are if (!(axis_known_position[X_AXIS] && axis_known_position[Y_AXIS] && axis_known_position[Z_AXIS])) { // We don't know where we are! HOME! @@ -2877,15 +2869,7 @@ static void gcode_G80() current_position[X_AXIS] = BED_X0; current_position[Y_AXIS] = BED_Y0; -#ifdef SUPPORT_VERBOSITY - if (verbosity_level >= 1) - { - bool clamped = world2machine_clamp(current_position[X_AXIS], current_position[Y_AXIS]); - clamped ? SERIAL_PROTOCOLPGM("First calibration point clamped.\n") : SERIAL_PROTOCOLPGM("No clamping for first calibration point.\n"); - } -#else //SUPPORT_VERBOSITY world2machine_clamp(current_position[X_AXIS], current_position[Y_AXIS]); -#endif //SUPPORT_VERBOSITY int XY_AXIS_FEEDRATE = homing_feedrate[X_AXIS] / 20; plan_buffer_line_curposXYZE(XY_AXIS_FEEDRATE); @@ -2901,11 +2885,6 @@ static void gcode_G80() uint8_t mesh_point = 0; //index number of calibration point int Z_LIFT_FEEDRATE = homing_feedrate[Z_AXIS] / 40; bool has_z = is_bed_z_jitter_data_valid(); //checks if we have data from Z calibration (offsets of the Z heiths of the 8 calibration points from the first point) -#ifdef SUPPORT_VERBOSITY - if (verbosity_level >= 1) { - has_z ? SERIAL_PROTOCOLPGM("Z jitter data from Z cal. valid.\n") : SERIAL_PROTOCOLPGM("Z jitter data from Z cal. not valid.\n"); - } -#endif // SUPPORT_VERBOSITY int l_feedmultiply = setup_for_endstop_move(false); //save feedrate and feedmultiply, sets feedmultiply to 100 while (mesh_point != MESH_NUM_X_POINTS * MESH_NUM_Y_POINTS) { // Get coords of a measuring point. @@ -2922,11 +2901,6 @@ static void gcode_G80() uint16_t z_offset_u = eeprom_read_word((uint16_t*)(EEPROM_BED_CALIBRATION_Z_JITTER + 2 * ((ix/3) + iy - 1))); z0 = mbl.z_values[0][0] + *reinterpret_cast(&z_offset_u) * 0.01; mbl.set_z(ix, iy, z0); -#ifdef SUPPORT_VERBOSITY - if (verbosity_level >= 1) { - printf_P(PSTR("Bed leveling, point: %d, calibration Z stored in eeprom: %d, calibration z: %f \n"), mesh_point, z_offset_u, z0); - } -#endif // SUPPORT_VERBOSITY } if ((nMeasPoints == 3) && !isOn3x3Mesh) { @@ -2951,20 +2925,8 @@ static void gcode_G80() current_position[X_AXIS] = x_pos; current_position[Y_AXIS] = y_pos; - //printf_P(PSTR("[%f;%f]\n"), current_position[X_AXIS], current_position[Y_AXIS]); - - -#ifdef SUPPORT_VERBOSITY - if (verbosity_level >= 1) { - bool clamped = world2machine_clamp(current_position[X_AXIS], current_position[Y_AXIS]); - SERIAL_PROTOCOL(mesh_point); - clamped ? SERIAL_PROTOCOLPGM(": xy clamped.\n") : SERIAL_PROTOCOLPGM(": no xy clamping\n"); - } -#else //SUPPORT_VERBOSITY world2machine_clamp(current_position[X_AXIS], current_position[Y_AXIS]); -#endif // SUPPORT_VERBOSITY - //printf_P(PSTR("after clamping: [%f;%f]\n"), current_position[X_AXIS], current_position[Y_AXIS]); plan_buffer_line_curposXYZE(XY_AXIS_FEEDRATE); st_synchronize(); if (planner_aborted) @@ -2981,7 +2943,6 @@ static void gcode_G80() break; } if (init_z_bckp - current_position[Z_AXIS] < 0.1f) { //broken cable or initial Z coordinate too low. Go to MESH_HOME_Z_SEARCH and repeat last step (z-probe) again to distinguish between these two cases. - //printf_P(PSTR("Another attempt! Current Z position: %f\n"), current_position[Z_AXIS]); current_position[Z_AXIS] = MESH_HOME_Z_SEARCH; plan_buffer_line_curposXYZE(Z_LIFT_FEEDRATE); st_synchronize(); @@ -2999,45 +2960,19 @@ static void gcode_G80() puts_P(PSTR("Bed leveling failed. Sensor triggered too high.")); break; } -#ifdef SUPPORT_VERBOSITY - if (verbosity_level >= 10) { - SERIAL_ECHOPGM("X: "); - MYSERIAL.print(current_position[X_AXIS], 5); - SERIAL_ECHOLNPGM(""); - SERIAL_ECHOPGM("Y: "); - MYSERIAL.print(current_position[Y_AXIS], 5); - SERIAL_PROTOCOLPGM("\n"); - } -#endif // SUPPORT_VERBOSITY - float offset_z = 0; #ifdef PINDA_THERMISTOR - offset_z = temp_compensation_pinda_thermistor_offset(current_temperature_pinda); -#endif //PINDA_THERMISTOR - // #ifdef SUPPORT_VERBOSITY - /* if (verbosity_level >= 1) - { - SERIAL_ECHOPGM("mesh bed leveling: "); - MYSERIAL.print(current_position[Z_AXIS], 5); - SERIAL_ECHOPGM(" offset: "); - MYSERIAL.print(offset_z, 5); - SERIAL_ECHOLNPGM(""); - }*/ - // #endif // SUPPORT_VERBOSITY + float offset_z = temp_compensation_pinda_thermistor_offset(current_temperature_pinda); mbl.set_z(ix, iy, current_position[Z_AXIS] - offset_z); //store measured z values z_values[iy][ix] = z - offset_z; +#else + mbl.set_z(ix, iy, current_position[Z_AXIS]); //store measured z values z_values[iy][ix] = z; +#endif //PINDA_THERMISTOR custom_message_state--; mesh_point++; lcd_update(1); } current_position[Z_AXIS] = MESH_HOME_Z_SEARCH; -#ifdef SUPPORT_VERBOSITY - if (verbosity_level >= 20) { - SERIAL_ECHOLNPGM("Mesh bed leveling while loop finished."); - SERIAL_ECHOLNPGM("MESH_HOME_Z_SEARCH: "); - MYSERIAL.print(current_position[Z_AXIS], 5); - } -#endif // SUPPORT_VERBOSITY plan_buffer_line_curposXYZE(Z_LIFT_FEEDRATE); st_synchronize(); if (mesh_point != MESH_NUM_X_POINTS * MESH_NUM_Y_POINTS) { @@ -3067,7 +3002,6 @@ static void gcode_G80() #endif // TMC2130 enable_z_endstop(bState); } while (st_get_position_mm(Z_AXIS) > MESH_HOME_Z_SEARCH); // i.e. Z-leveling not o.k. - // plan_set_z_position(MESH_HOME_Z_SEARCH); // is not necessary ('do-while' loop always ends at the expected Z-position) custom_message_type = custom_message_type_old; custom_message_state = custom_message_state_old; @@ -3077,19 +3011,12 @@ static void gcode_G80() return; } clean_up_after_endstop_move(l_feedmultiply); - // SERIAL_ECHOLNPGM("clean up finished "); #ifndef PINDA_THERMISTOR if(eeprom_read_byte((uint8_t *)EEPROM_TEMP_CAL_ACTIVE) && calibration_status_pinda() == true) temp_compensation_apply(); //apply PINDA temperature compensation #endif babystep_apply(); // Apply Z height correction aka baby stepping before mesh bed leveing gets activated. - // SERIAL_ECHOLNPGM("babystep applied"); bool eeprom_bed_correction_valid = eeprom_read_byte((unsigned char*)EEPROM_BED_CORRECTION_VALID) == 1; -#ifdef SUPPORT_VERBOSITY - if (verbosity_level >= 1) { - eeprom_bed_correction_valid ? SERIAL_PROTOCOLPGM("Bed correction data valid\n") : SERIAL_PROTOCOLPGM("Bed correction data not valid\n"); - } -#endif // SUPPORT_VERBOSITY const constexpr uint8_t sides = 4; int8_t correction[sides] = {0}; for (uint8_t i = 0; i < sides; ++i) { @@ -3127,46 +3054,15 @@ static void gcode_G80() + correction[3] * row) / (float)(MESH_NUM_X_POINTS - 1); } } - // SERIAL_ECHOLNPGM("Bed leveling correction finished"); + mbl.upsample_3x3(); //interpolation from 3x3 to 7x7 points using largrangian polynomials while using the same array z_values[iy][ix] for storing (just coppying measured data to new destination and interpolating between them) - /* - SERIAL_PROTOCOLPGM("Num X,Y: "); - SERIAL_PROTOCOL(MESH_NUM_X_POINTS); - SERIAL_PROTOCOLPGM(","); - SERIAL_PROTOCOL(MESH_NUM_Y_POINTS); - SERIAL_PROTOCOLPGM("\nZ search height: "); - SERIAL_PROTOCOL(MESH_HOME_Z_SEARCH); - SERIAL_PROTOCOLLNPGM("\nMeasured points:"); - for (int y = MESH_NUM_Y_POINTS-1; y >= 0; y--) { - for (int x = 0; x < MESH_NUM_X_POINTS; x++) { - printf_P(PSTR(" %.5f"), mbl.z_values[y][x]); - } - SERIAL_PROTOCOLPGM("\n"); - } - */ + if (nMeasPoints == 7 && magnet_elimination) { mbl_interpolation(nMeasPoints); } - /* - SERIAL_PROTOCOLPGM("Num X,Y: "); - SERIAL_PROTOCOL(MESH_NUM_X_POINTS); - SERIAL_PROTOCOLPGM(","); - SERIAL_PROTOCOL(MESH_NUM_Y_POINTS); - SERIAL_PROTOCOLPGM("\nZ search height: "); - SERIAL_PROTOCOL(MESH_HOME_Z_SEARCH); - SERIAL_PROTOCOLLNPGM("\nMeasured points:"); - for (int y = MESH_NUM_Y_POINTS-1; y >= 0; y--) { - for (int x = 0; x < MESH_NUM_X_POINTS; x++) { - printf_P(PSTR(" %.5f"), mbl.z_values[y][x]); - } - SERIAL_PROTOCOLPGM("\n"); - } - */ - // SERIAL_ECHOLNPGM("Upsample finished"); + mbl.active = 1; //activate mesh bed leveling - // SERIAL_ECHOLNPGM("Mesh bed leveling activated"); go_home_with_z_lift(); - // SERIAL_ECHOLNPGM("Go home finished"); #ifndef PINDA_THERMISTOR //unretract (after PINDA preheat retraction) if (temp_compensation_retracted) { @@ -4959,12 +4855,11 @@ void process_commands() Default 3x3 grid can be changed on MK2.5/s and MK3/s to 7x7 grid. #### Usage - G80 [ N | R | V | L | R | F | B | X | Y | W | H ] + G80 [ N | R | L | R | F | B | X | Y | W | H ] #### Parameters - `N` - Number of mesh points on x axis. Default is 3. Valid values are 3 and 7. - `R` - Probe retries. Default 3 max. 10 - - `V` - Verbosity level 1=low, 10=mid, 20=high. It only can be used if the firmware has been compiled with SUPPORT_VERBOSITY active. Using the following parameters enables additional "manual" bed leveling correction. Valid values are -100 microns to 100 microns. #### Additional Parameters From 83879fd10c1149e521ffc83b218b932650085663 Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Fri, 5 May 2023 10:50:18 +0200 Subject: [PATCH 08/34] Cleanup magnet compensation code --- Firmware/Marlin_main.cpp | 2 +- Firmware/mesh_bed_calibration.cpp | 39 +++++++++++-------------------- Firmware/mesh_bed_calibration.h | 5 ++-- 3 files changed, 17 insertions(+), 29 deletions(-) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index e3f83504e..8c1d4effe 100644 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -3058,7 +3058,7 @@ static void gcode_G80() mbl.upsample_3x3(); //interpolation from 3x3 to 7x7 points using largrangian polynomials while using the same array z_values[iy][ix] for storing (just coppying measured data to new destination and interpolating between them) if (nMeasPoints == 7 && magnet_elimination) { - mbl_interpolation(nMeasPoints); + mbl_magnet_elimination(); } mbl.active = 1; //activate mesh bed leveling diff --git a/Firmware/mesh_bed_calibration.cpp b/Firmware/mesh_bed_calibration.cpp index a04b3a44a..35516abf7 100644 --- a/Firmware/mesh_bed_calibration.cpp +++ b/Firmware/mesh_bed_calibration.cpp @@ -3116,15 +3116,14 @@ void mbl_settings_init() { //parameter ix: index of mesh bed leveling point in X-axis (for meas_points == 7 is valid range from 0 to 6; for meas_points == 3 is valid range from 0 to 2 ) //parameter iy: index of mesh bed leveling point in Y-axis (for meas_points == 7 is valid range from 0 to 6; for meas_points == 3 is valid range from 0 to 2 ) -//parameter meas_points: number of mesh bed leveling points in one axis; currently designed and tested for values 3 and 7 -//parameter zigzag: false if ix is considered 0 on left side of bed and ix rises with rising X coordinate; true if ix is considered 0 on the right side of heatbed for odd iy values (zig zag mesh bed leveling movements) //function returns true if point is considered valid (typicaly in safe distance from magnet or another object which inflences PINDA measurements) -bool mbl_point_measurement_valid(uint8_t ix, uint8_t iy, uint8_t meas_points, bool zigzag) { +bool mbl_point_measurement_valid(uint8_t ix, uint8_t iy) { //"human readable" heatbed plan //magnet proximity influence Z coordinate measurements significantly (40 - 100 um) //0 - measurement point is above magnet and Z coordinate can be influenced negatively //1 - we should be in safe distance from magnets, measurement should be accurate - if ((ix >= meas_points) || (iy >= meas_points)) return false; + if ((ix >= MESH_NUM_X_POINTS) || (iy >= MESH_NUM_Y_POINTS)) + return false; uint8_t valid_points_mask[7] = { //[X_MAX,Y_MAX] @@ -3138,36 +3137,26 @@ bool mbl_point_measurement_valid(uint8_t ix, uint8_t iy, uint8_t meas_points, bo 0b1111111,//0 //[0,0] }; - if (meas_points == 3) { - ix *= 3; - iy *= 3; - } - if (zigzag) { - if ((iy % 2) == 0) return (valid_points_mask[6 - iy] & (1 << (6 - ix))); - else return (valid_points_mask[6 - iy] & (1 << ix)); - } - else { - return (valid_points_mask[6 - iy] & (1 << (6 - ix))); - } + return (valid_points_mask[6 - iy] & (1 << (6 - ix))); } -void mbl_single_point_interpolation(uint8_t x, uint8_t y, uint8_t meas_points) { +void mbl_single_point_interpolation(uint8_t x, uint8_t y) { //printf_P(PSTR("x = %d; y = %d \n"), x, y); uint8_t count = 0; float z = 0; - if (mbl_point_measurement_valid(x, y + 1, meas_points, false)) { z += mbl.z_values[y + 1][x]; /*printf_P(PSTR("x; y+1: Z = %f \n"), mbl.z_values[y + 1][x]);*/ count++; } - if (mbl_point_measurement_valid(x, y - 1, meas_points, false)) { z += mbl.z_values[y - 1][x]; /*printf_P(PSTR("x; y-1: Z = %f \n"), mbl.z_values[y - 1][x]);*/ count++; } - if (mbl_point_measurement_valid(x + 1, y, meas_points, false)) { z += mbl.z_values[y][x + 1]; /*printf_P(PSTR("x+1; y: Z = %f \n"), mbl.z_values[y][x + 1]);*/ count++; } - if (mbl_point_measurement_valid(x - 1, y, meas_points, false)) { z += mbl.z_values[y][x - 1]; /*printf_P(PSTR("x-1; y: Z = %f \n"), mbl.z_values[y][x - 1]);*/ count++; } + if (mbl_point_measurement_valid(x, y + 1)) { z += mbl.z_values[y + 1][x]; /*printf_P(PSTR("x; y+1: Z = %f \n"), mbl.z_values[y + 1][x]);*/ count++; } + if (mbl_point_measurement_valid(x, y - 1)) { z += mbl.z_values[y - 1][x]; /*printf_P(PSTR("x; y-1: Z = %f \n"), mbl.z_values[y - 1][x]);*/ count++; } + if (mbl_point_measurement_valid(x + 1, y)) { z += mbl.z_values[y][x + 1]; /*printf_P(PSTR("x+1; y: Z = %f \n"), mbl.z_values[y][x + 1]);*/ count++; } + if (mbl_point_measurement_valid(x - 1, y)) { z += mbl.z_values[y][x - 1]; /*printf_P(PSTR("x-1; y: Z = %f \n"), mbl.z_values[y][x - 1]);*/ count++; } if(count != 0) mbl.z_values[y][x] = z / count; //if we have at least one valid point in surrounding area use average value, otherwise use inaccurately measured Z-coordinate //printf_P(PSTR("result: Z = %f \n\n"), mbl.z_values[y][x]); } -void mbl_interpolation(uint8_t meas_points) { - for (uint8_t x = 0; x < meas_points; x++) { - for (uint8_t y = 0; y < meas_points; y++) { - if (!mbl_point_measurement_valid(x, y, meas_points, false)) { - mbl_single_point_interpolation(x, y, meas_points); +void mbl_magnet_elimination() { + for (uint8_t y = 0; y < MESH_NUM_Y_POINTS; y++) { + for (uint8_t x = 0; x < MESH_NUM_X_POINTS; x++) { + if (!mbl_point_measurement_valid(x, y)) { + mbl_single_point_interpolation(x, y); } } } diff --git a/Firmware/mesh_bed_calibration.h b/Firmware/mesh_bed_calibration.h index fcfa9527b..41f81016a 100644 --- a/Firmware/mesh_bed_calibration.h +++ b/Firmware/mesh_bed_calibration.h @@ -203,6 +203,5 @@ extern void count_xyz_details(float (&distanceMin)[2]); extern bool sample_z(); extern void mbl_settings_init(); - -extern bool mbl_point_measurement_valid(uint8_t ix, uint8_t iy, uint8_t meas_points, bool zigzag); -extern void mbl_interpolation(uint8_t meas_points); +extern bool mbl_point_measurement_valid(uint8_t ix, uint8_t iy); +extern void mbl_magnet_elimination(); From 6af5f5e2a20857f40f10c1a950e68901ff50be1e Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Fri, 5 May 2023 11:10:37 +0200 Subject: [PATCH 09/34] Some code cleanup around homing_feedrate --- Firmware/Marlin.h | 2 +- Firmware/Marlin_main.cpp | 11 +++++------ Firmware/mesh_bed_calibration.cpp | 17 ++++++++++------- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/Firmware/Marlin.h b/Firmware/Marlin.h index 4f22e13e2..470b55e23 100755 --- a/Firmware/Marlin.h +++ b/Firmware/Marlin.h @@ -236,7 +236,7 @@ enum class HeatingStatus : uint8_t extern HeatingStatus heating_status; extern bool fans_check_enabled; -extern float homing_feedrate[]; +constexpr float homing_feedrate[] = HOMING_FEEDRATE; extern uint8_t axis_relative_modes; extern float feedrate; extern int feedmultiply; diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 8c1d4effe..581efca40 100644 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -157,8 +157,6 @@ uint8_t mbl_z_probe_nr = 3; //numer of Z measurements for each point in mesh bed float default_retraction = DEFAULT_RETRACTION; -float homing_feedrate[] = HOMING_FEEDRATE; - //Although this flag and many others like this could be represented with a struct/bitfield for each axis (more readable and efficient code), the implementation //would not be standard across all platforms. That being said, the code will continue to use bitmasks for independent axis. //Moreover, according to C/C++ standard, the ordering of bits is platform/compiler dependent and the compiler is allowed to align the bits arbitrarily, @@ -2791,6 +2789,8 @@ static void gcode_G28(bool home_x_axis, bool home_y_axis, bool home_z_axis) // G80 - Automatic mesh bed leveling static void gcode_G80() { + constexpr float XY_AXIS_FEEDRATE = (homing_feedrate[X_AXIS] * 3) / 60; + constexpr float Z_LIFT_FEEDRATE = homing_feedrate[Z_AXIS] / 60; st_synchronize(); if (planner_aborted) return; @@ -2864,14 +2864,14 @@ static void gcode_G80() // Cycle through all points and probe them // First move up. During this first movement, the babystepping will be reverted. current_position[Z_AXIS] = MESH_HOME_Z_SEARCH; - plan_buffer_line_curposXYZE(homing_feedrate[Z_AXIS] / 60); + plan_buffer_line_curposXYZE(Z_LIFT_FEEDRATE); // The move to the first calibration point. current_position[X_AXIS] = BED_X0; current_position[Y_AXIS] = BED_Y0; world2machine_clamp(current_position[X_AXIS], current_position[Y_AXIS]); - int XY_AXIS_FEEDRATE = homing_feedrate[X_AXIS] / 20; + plan_buffer_line_curposXYZE(XY_AXIS_FEEDRATE); // Wait until the move is finished. st_synchronize(); @@ -2883,7 +2883,6 @@ static void gcode_G80() } uint8_t mesh_point = 0; //index number of calibration point - int Z_LIFT_FEEDRATE = homing_feedrate[Z_AXIS] / 40; bool has_z = is_bed_z_jitter_data_valid(); //checks if we have data from Z calibration (offsets of the Z heiths of the 8 calibration points from the first point) int l_feedmultiply = setup_for_endstop_move(false); //save feedrate and feedmultiply, sets feedmultiply to 100 while (mesh_point != MESH_NUM_X_POINTS * MESH_NUM_Y_POINTS) { @@ -2995,7 +2994,7 @@ static void gcode_G80() tmc2130_home_enter(Z_AXIS_MASK); #endif // TMC2130 current_position[Z_AXIS] = MESH_HOME_Z_SEARCH; - plan_buffer_line_curposXYZE(homing_feedrate[Z_AXIS] / 40); + plan_buffer_line_curposXYZE(Z_LIFT_FEEDRATE); st_synchronize(); #ifdef TMC2130 tmc2130_home_exit(); diff --git a/Firmware/mesh_bed_calibration.cpp b/Firmware/mesh_bed_calibration.cpp index 35516abf7..5ec4a5315 100644 --- a/Firmware/mesh_bed_calibration.cpp +++ b/Firmware/mesh_bed_calibration.cpp @@ -2814,16 +2814,16 @@ void go_home_with_z_lift() // Go home. // First move up to a safe height. current_position[Z_AXIS] = MESH_HOME_Z_SEARCH; - go_to_current(homing_feedrate[Z_AXIS]/60); + go_to_current(homing_feedrate[Z_AXIS] / 60); // Second move to XY [0, 0]. - current_position[X_AXIS] = X_MIN_POS+0.2; - current_position[Y_AXIS] = Y_MIN_POS+0.2; + current_position[X_AXIS] = X_MIN_POS + 0.2; + current_position[Y_AXIS] = Y_MIN_POS + 0.2; // Clamp to the physical coordinates. world2machine_clamp(current_position[X_AXIS], current_position[Y_AXIS]); - go_to_current(homing_feedrate[X_AXIS]/20); + go_to_current((3 * homing_feedrate[X_AXIS]) / 60); // Third move up to a safe height. current_position[Z_AXIS] = Z_MIN_POS; - go_to_current(homing_feedrate[Z_AXIS]/60); + go_to_current(homing_feedrate[Z_AXIS] / 60); } // Sample the 9 points of the bed and store them into the EEPROM as a reference. @@ -3033,9 +3033,12 @@ bool scan_bed_induction_points(int8_t verbosity_level) // To replace loading of the babystep correction. static void shift_z(float delta) { - plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS] - delta, current_position[E_AXIS], homing_feedrate[Z_AXIS]/40); + const float curpos_z = current_position[Z_AXIS]; + current_position[Z_AXIS] -= delta; + plan_buffer_line_curposXYZE(homing_feedrate[Z_AXIS] / 60); st_synchronize(); - plan_set_z_position(current_position[Z_AXIS]); + current_position[Z_AXIS] = curpos_z; + plan_set_z_position(curpos_z); } // Number of baby steps applied From 6c97907507d1d0979448a360be198340994bc121 Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Fri, 5 May 2023 11:18:03 +0200 Subject: [PATCH 10/34] A bit more cleanup --- Firmware/Marlin_main.cpp | 31 +++++++++---------------------- 1 file changed, 9 insertions(+), 22 deletions(-) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 581efca40..f3cfcb812 100644 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -2796,9 +2796,6 @@ static void gcode_G80() return; mesh_bed_leveling_flag = true; -#ifndef PINDA_THERMISTOR - static bool run = false; // thermistor-less PINDA temperature compensation is running -#endif // ndef PINDA_THERMISTOR // Firstly check if we know where we are if (!(axis_known_position[X_AXIS] && axis_known_position[Y_AXIS] && axis_known_position[Z_AXIS])) { @@ -2810,28 +2807,17 @@ static void gcode_G80() return; } - uint8_t nMeasPoints = MESH_MEAS_NUM_X_POINTS; - if (code_seen('N')) { - nMeasPoints = code_value_uint8(); - if (nMeasPoints != 7) { - nMeasPoints = 3; - } - } - else { - nMeasPoints = eeprom_read_byte((uint8_t*)EEPROM_MBL_POINTS_NR); + uint8_t nMeasPoints = code_seen('N') ? code_value_uint8() : eeprom_read_byte((uint8_t*)EEPROM_MBL_POINTS_NR); + if (nMeasPoints != 7) { + nMeasPoints = 3; } - uint8_t nProbeRetry = 3; - if (code_seen('R')) { - nProbeRetry = code_value_uint8(); - if (nProbeRetry > 10) { - nProbeRetry = 10; - } + uint8_t nProbeRetry = code_seen('R') ? code_value_uint8() : eeprom_read_byte((uint8_t*)EEPROM_MBL_PROBE_NR); + if (nProbeRetry > 10) { + nProbeRetry = 10; } - else { - nProbeRetry = eeprom_read_byte((uint8_t*)EEPROM_MBL_PROBE_NR); - } - bool magnet_elimination = (eeprom_read_byte((uint8_t*)EEPROM_MBL_MAGNET_ELIMINATION) > 0); + + const uint8_t magnet_elimination = eeprom_read_byte((uint8_t*)EEPROM_MBL_MAGNET_ELIMINATION); float area_min_x = code_seen('X') ? code_value() - MESH_X_DIST - X_PROBE_OFFSET_FROM_EXTRUDER : -INFINITY; float area_min_y = code_seen('Y') ? code_value() - MESH_Y_DIST - Y_PROBE_OFFSET_FROM_EXTRUDER : -INFINITY; @@ -2839,6 +2825,7 @@ static void gcode_G80() float area_max_y = code_seen('H') ? area_min_y + code_value() + 2 * MESH_Y_DIST : INFINITY; #ifndef PINDA_THERMISTOR + static bool run = false; // thermistor-less PINDA temperature compensation is running if (run == false && eeprom_read_byte((uint8_t *)EEPROM_TEMP_CAL_ACTIVE) && calibration_status_pinda() == true && target_temperature_bed >= 50) { temp_compensation_start(); From 90c21425c6f7ce56d53dc69b8bc3db12f0b10744 Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Fri, 5 May 2023 11:46:35 +0200 Subject: [PATCH 11/34] Optimize is_bed_z_jitter_data_valid() --- Firmware/mesh_bed_calibration.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Firmware/mesh_bed_calibration.cpp b/Firmware/mesh_bed_calibration.cpp index 5ec4a5315..fbe9fdc03 100644 --- a/Firmware/mesh_bed_calibration.cpp +++ b/Firmware/mesh_bed_calibration.cpp @@ -685,11 +685,11 @@ bool is_bed_z_jitter_data_valid() // offsets of the Z heiths of the calibration points from the first point are saved as 16bit signed int, scaled to tenths of microns // if at least one 16bit integer has different value then -1 (0x0FFFF), data are considered valid and function returns true, otherwise it returns false { - bool data_valid = false; for (int8_t i = 0; i < 8; ++i) { - if (eeprom_read_word((uint16_t*)(EEPROM_BED_CALIBRATION_Z_JITTER + i * 2)) != 0x0FFFF) data_valid = true; + if (eeprom_read_word((uint16_t*)(EEPROM_BED_CALIBRATION_Z_JITTER + i * 2)) != 0x0FFFF) + return true; } - return data_valid; + return false; } static void world2machine_update(const float vec_x[2], const float vec_y[2], const float cntr[2]) From f94bc7223563e306a44189a0bc603303cca13ed7 Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Fri, 5 May 2023 12:32:20 +0200 Subject: [PATCH 12/34] Optimize G80 bed correction argument parsing --- Firmware/Marlin_main.cpp | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index f3cfcb812..836289e87 100644 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -3004,7 +3004,7 @@ static void gcode_G80() babystep_apply(); // Apply Z height correction aka baby stepping before mesh bed leveing gets activated. bool eeprom_bed_correction_valid = eeprom_read_byte((unsigned char*)EEPROM_BED_CORRECTION_VALID) == 1; const constexpr uint8_t sides = 4; - int8_t correction[sides] = {0}; + int8_t correction[sides]; for (uint8_t i = 0; i < sides; ++i) { static const char codes[sides] PROGMEM = { 'L', 'R', 'F', 'B' }; static uint8_t *const eep_addresses[sides] PROGMEM = { @@ -3013,23 +3013,21 @@ static void gcode_G80() (uint8_t*)EEPROM_BED_CORRECTION_FRONT, (uint8_t*)EEPROM_BED_CORRECTION_REAR, }; - if (code_seen(pgm_read_byte(&codes[i]))) - { // Verify value is within allowed range + if (code_seen(pgm_read_byte(&codes[i]))) { + // Verify value is within allowed range int32_t temp = code_value_long(); if (labs(temp) > BED_ADJUSTMENT_UM_MAX) { - SERIAL_ERROR_START; - SERIAL_ECHOPGM("Excessive bed leveling correction: "); - SERIAL_ECHO(temp); - SERIAL_ECHOLNPGM(" microns"); + printf_P(PSTR("%SExcessive bed leveling correction: %li microns\n"), errormagic, temp); correction[i] = 0; } else { // Value is valid, save it correction[i] = (int8_t)temp; } - } else if (eeprom_bed_correction_valid) + } else if (eeprom_bed_correction_valid) { correction[i] = (int8_t)eeprom_read_byte((uint8_t*)pgm_read_ptr(&eep_addresses[i])); - if (correction[i] == 0) - continue; + } else { + correction[i] = 0; + } } for (uint8_t row = 0; row < MESH_NUM_Y_POINTS; ++row) { for (uint8_t col = 0; col < MESH_NUM_X_POINTS; ++col) { From b234560b22a1c946a403cf525cb2936ef2a89c06 Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Fri, 5 May 2023 13:19:49 +0200 Subject: [PATCH 13/34] MBL print function optimization --- Firmware/Marlin_main.cpp | 15 +-------------- Firmware/mesh_bed_leveling.cpp | 13 +++++++++++++ Firmware/mesh_bed_leveling.h | 1 + 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 836289e87..dc3aaf3ef 100644 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -4870,20 +4870,7 @@ void process_commands() */ case 81: if (mbl.active) { - SERIAL_PROTOCOLPGM("Num X,Y: "); - SERIAL_PROTOCOL(MESH_NUM_X_POINTS); - SERIAL_PROTOCOL(','); - SERIAL_PROTOCOL(MESH_NUM_Y_POINTS); - SERIAL_PROTOCOLPGM("\nZ search height: "); - SERIAL_PROTOCOL(MESH_HOME_Z_SEARCH); - SERIAL_PROTOCOLLNPGM("\nMeasured points:"); - for (uint8_t y = MESH_NUM_Y_POINTS; y-- > 0;) { - for (uint8_t x = 0; x < MESH_NUM_X_POINTS; x++) { - SERIAL_PROTOCOLPGM(" "); - SERIAL_PROTOCOL_F(mbl.z_values[y][x], 5); - } - SERIAL_PROTOCOLLN(); - } + mbl.print(); } else SERIAL_PROTOCOLLNPGM("Mesh bed leveling not active."); diff --git a/Firmware/mesh_bed_leveling.cpp b/Firmware/mesh_bed_leveling.cpp index d8dbd3fb1..2d6388b0c 100644 --- a/Firmware/mesh_bed_leveling.cpp +++ b/Firmware/mesh_bed_leveling.cpp @@ -149,4 +149,17 @@ void mesh_bed_leveling::upsample_3x3() } #endif // (MESH_NUM_X_POINTS>=5 && MESH_NUM_Y_POINTS>=5 && (MESH_NUM_X_POINTS&1)==1 && (MESH_NUM_Y_POINTS&1)==1) +void mesh_bed_leveling::print() { + SERIAL_PROTOCOLLNPGM("Num X,Y: " STRINGIFY(MESH_NUM_X_POINTS) "," STRINGIFY(MESH_NUM_Y_POINTS)); + SERIAL_PROTOCOLLNPGM("Z search height: " STRINGIFY(MESH_HOME_Z_SEARCH)); + SERIAL_PROTOCOLLNPGM("Measured points:"); + for (uint8_t y = MESH_NUM_Y_POINTS; y-- > 0;) { + for (uint8_t x = 0; x < MESH_NUM_X_POINTS; x++) { + SERIAL_PROTOCOLPGM(" "); + SERIAL_PROTOCOL_F(z_values[y][x], 5); + } + SERIAL_PROTOCOLLN(); + } +} + #endif // MESH_BED_LEVELING diff --git a/Firmware/mesh_bed_leveling.h b/Firmware/mesh_bed_leveling.h index b7d33379a..cda0ea797 100644 --- a/Firmware/mesh_bed_leveling.h +++ b/Firmware/mesh_bed_leveling.h @@ -28,6 +28,7 @@ public: #if MESH_NUM_X_POINTS>=5 && MESH_NUM_Y_POINTS>=5 && (MESH_NUM_X_POINTS&1)==1 && (MESH_NUM_Y_POINTS&1)==1 void upsample_3x3(); #endif + void print(); }; extern mesh_bed_leveling mbl; From 36d8de07275646bac41194e8a4f37cc333d5e890 Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Fri, 5 May 2023 14:59:47 +0200 Subject: [PATCH 14/34] G80 general fixes Use interpolated eeprom mesh for skewed Z detection Use the interpolated eeprom mesh for raising Z for the next point Fix LCD countdown during MBL --- Firmware/Marlin_main.cpp | 144 +++++++++++++++++---------------- Firmware/mesh_bed_leveling.cpp | 6 +- 2 files changed, 75 insertions(+), 75 deletions(-) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index dc3aaf3ef..2458ee55f 100644 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -2791,6 +2791,7 @@ static void gcode_G80() { constexpr float XY_AXIS_FEEDRATE = (homing_feedrate[X_AXIS] * 3) / 60; constexpr float Z_LIFT_FEEDRATE = homing_feedrate[Z_AXIS] / 60; + constexpr float Z_CALIBRATION_THRESHOLD = 1.f; st_synchronize(); if (planner_aborted) return; @@ -2807,23 +2808,6 @@ static void gcode_G80() return; } - uint8_t nMeasPoints = code_seen('N') ? code_value_uint8() : eeprom_read_byte((uint8_t*)EEPROM_MBL_POINTS_NR); - if (nMeasPoints != 7) { - nMeasPoints = 3; - } - - uint8_t nProbeRetry = code_seen('R') ? code_value_uint8() : eeprom_read_byte((uint8_t*)EEPROM_MBL_PROBE_NR); - if (nProbeRetry > 10) { - nProbeRetry = 10; - } - - const uint8_t magnet_elimination = eeprom_read_byte((uint8_t*)EEPROM_MBL_MAGNET_ELIMINATION); - - float area_min_x = code_seen('X') ? code_value() - MESH_X_DIST - X_PROBE_OFFSET_FROM_EXTRUDER : -INFINITY; - float area_min_y = code_seen('Y') ? code_value() - MESH_Y_DIST - Y_PROBE_OFFSET_FROM_EXTRUDER : -INFINITY; - float area_max_x = code_seen('W') ? area_min_x + code_value() + 2 * MESH_X_DIST : INFINITY; - float area_max_y = code_seen('H') ? area_min_y + code_value() + 2 * MESH_Y_DIST : INFINITY; - #ifndef PINDA_THERMISTOR static bool run = false; // thermistor-less PINDA temperature compensation is running if (run == false && eeprom_read_byte((uint8_t *)EEPROM_TEMP_CAL_ACTIVE) && calibration_status_pinda() == true && target_temperature_bed >= 50) @@ -2836,42 +2820,72 @@ static void gcode_G80() } run = false; #endif //PINDA_THERMISTOR - // Save custom message state, set a new custom message state to display: Calibrating point 9. - CustomMsg custom_message_type_old = custom_message_type; - uint8_t custom_message_state_old = custom_message_state; - custom_message_type = CustomMsg::MeshBedLeveling; - custom_message_state = (nMeasPoints * nMeasPoints) + 10; - lcd_update(1); + + uint8_t nMeasPoints = code_seen('N') ? code_value_uint8() : eeprom_read_byte((uint8_t*)EEPROM_MBL_POINTS_NR); + if (nMeasPoints != 7) { + nMeasPoints = 3; + } + + uint8_t nProbeRetry = code_seen('R') ? code_value_uint8() : eeprom_read_byte((uint8_t*)EEPROM_MBL_PROBE_NR); + if (nProbeRetry > 10) { + nProbeRetry = 10; + } + + const uint8_t magnet_elimination = eeprom_read_byte((uint8_t*)EEPROM_MBL_MAGNET_ELIMINATION); + + const float area_min_x = code_seen('X') ? code_value() - MESH_X_DIST - X_PROBE_OFFSET_FROM_EXTRUDER : -INFINITY; + const float area_min_y = code_seen('Y') ? code_value() - MESH_Y_DIST - Y_PROBE_OFFSET_FROM_EXTRUDER : -INFINITY; + const float area_max_x = code_seen('W') ? area_min_x + code_value() + 2 * MESH_X_DIST : INFINITY; + const float area_max_y = code_seen('H') ? area_min_y + code_value() + 2 * MESH_Y_DIST : INFINITY; mbl.reset(); //reset mesh bed leveling // Reset baby stepping to zero, if the babystepping has already been loaded before. babystep_undo(); - // Cycle through all points and probe them - // First move up. During this first movement, the babystepping will be reverted. - current_position[Z_AXIS] = MESH_HOME_Z_SEARCH; - plan_buffer_line_curposXYZE(Z_LIFT_FEEDRATE); - // The move to the first calibration point. - current_position[X_AXIS] = BED_X0; - current_position[Y_AXIS] = BED_Y0; - - world2machine_clamp(current_position[X_AXIS], current_position[Y_AXIS]); - - - plan_buffer_line_curposXYZE(XY_AXIS_FEEDRATE); - // Wait until the move is finished. - st_synchronize(); - if (planner_aborted) - { - custom_message_type = custom_message_type_old; - custom_message_state = custom_message_state_old; - return; - } - - uint8_t mesh_point = 0; //index number of calibration point + // Initialize the default mesh from eeprom and calculate how many points are to be probed bool has_z = is_bed_z_jitter_data_valid(); //checks if we have data from Z calibration (offsets of the Z heiths of the 8 calibration points from the first point) + uint8_t meshPointsToProbe = 0; + for (uint8_t row = 0; row < MESH_NUM_Y_POINTS; row++) { + for (uint8_t col = 0; col < MESH_NUM_X_POINTS; col++) { + bool isOn3x3Mesh = ((row % 3 == 0) && (col % 3 == 0)); + if (isOn3x3Mesh) { + if (has_z && (row || col)) { + // Reconstruct the mesh saved in eeprom + uint16_t z_offset_u = eeprom_read_word((uint16_t*)(EEPROM_BED_CALIBRATION_Z_JITTER + 2 * ((col/3) + row - 1))); + const float z0 = mbl.z_values[0][0] + *reinterpret_cast(&z_offset_u) * 0.01; + mbl.set_z(col, row, z0); + } + } + + // check for points that are skipped + if (nMeasPoints == 3) { + if (!isOn3x3Mesh) + continue; + } else { + const float x_pos = BED_X(col, MESH_NUM_X_POINTS); + const float y_pos = BED_Y(row, MESH_NUM_Y_POINTS); + if ((x_pos < area_min_x || x_pos > area_max_x || y_pos < area_min_y || y_pos > area_max_y) && (row || col) && (!isOn3x3Mesh || has_z)) { + continue; + } + } + + // increment the total point counter if the points are not skipped + meshPointsToProbe++; + } + } + mbl.upsample_3x3(); //upsample the default mesh + + // Save custom message state, set a new custom message state to display: Calibrating point 9. + CustomMsg custom_message_type_old = custom_message_type; + uint8_t custom_message_state_old = custom_message_state; + custom_message_type = CustomMsg::MeshBedLeveling; + custom_message_state = meshPointsToProbe + 10; + lcd_update(1); + + // Cycle through all points and probe them int l_feedmultiply = setup_for_endstop_move(false); //save feedrate and feedmultiply, sets feedmultiply to 100 + uint8_t mesh_point = 0; //index number of calibration point while (mesh_point != MESH_NUM_X_POINTS * MESH_NUM_Y_POINTS) { // Get coords of a measuring point. uint8_t ix = mesh_point % MESH_NUM_X_POINTS; // from 0 to MESH_NUM_X_POINTS - 1 @@ -2879,31 +2893,22 @@ static void gcode_G80() if (iy & 1) ix = (MESH_NUM_X_POINTS - 1) - ix; // Zig zag bool isOn3x3Mesh = ((ix % 3 == 0) && (iy % 3 == 0)); float x_pos = BED_X(ix, MESH_NUM_X_POINTS); - float y_pos = BED_Y(iy, MESH_NUM_X_POINTS); - - // Reconstruct the mesh saved in eeprom - float z0 = 0.f; - if (has_z && isOn3x3Mesh && (mesh_point > 0)) { - uint16_t z_offset_u = eeprom_read_word((uint16_t*)(EEPROM_BED_CALIBRATION_Z_JITTER + 2 * ((ix/3) + iy - 1))); - z0 = mbl.z_values[0][0] + *reinterpret_cast(&z_offset_u) * 0.01; - mbl.set_z(ix, iy, z0); - } + float y_pos = BED_Y(iy, MESH_NUM_Y_POINTS); if ((nMeasPoints == 3) && !isOn3x3Mesh) { - mesh_point++; - continue; //skip + mesh_point++; + mbl.set_z(ix, iy, NAN); + continue; //skip + } else if ((x_pos < area_min_x || x_pos > area_max_x || y_pos < area_min_y || y_pos > area_max_y) && (mesh_point > 0) && (!isOn3x3Mesh || has_z)) { + mesh_point++; + continue; //skip } - if ((nMeasPoints == 7) && (x_pos < area_min_x || x_pos > area_max_x || y_pos < area_min_y || y_pos > area_max_y) && (mesh_point > 0) && (!isOn3x3Mesh || has_z)) { - mesh_point++; - custom_message_state--; - continue; //skip - } - - // Move Z up to MESH_HOME_Z_SEARCH. - if((ix == 0) && (iy == 0)) current_position[Z_AXIS] = MESH_HOME_Z_SEARCH; - else current_position[Z_AXIS] += 2.f / nMeasPoints; //use relative movement from Z coordinate where PINDa triggered on previous point. This makes calibration faster. - float init_z_bckp = current_position[Z_AXIS]; + // Move Z up to the probe height of the current Z point. + const float z0 = mbl.z_values[iy][ix]; + const float init_z_bckp = (!has_z || (mesh_point == 0)) ? MESH_HOME_Z_SEARCH : z0 + 0.5; + if (init_z_bckp > current_position[Z_AXIS]) + current_position[Z_AXIS] = init_z_bckp; plan_buffer_line_curposXYZE(Z_LIFT_FEEDRATE); st_synchronize(); @@ -2923,12 +2928,11 @@ static void gcode_G80() } // Go down until endstop is hit - const float Z_CALIBRATION_THRESHOLD = 1.f; if (!find_bed_induction_sensor_point_z((has_z && mesh_point > 0) ? z0 - Z_CALIBRATION_THRESHOLD : -10.f, nProbeRetry)) { //if we have data from z calibration max allowed difference is 1mm for each point, if we dont have data max difference is 10mm from initial point printf_P(_T(MSG_BED_LEVELING_FAILED_POINT_LOW)); break; } - if (init_z_bckp - current_position[Z_AXIS] < 0.1f) { //broken cable or initial Z coordinate too low. Go to MESH_HOME_Z_SEARCH and repeat last step (z-probe) again to distinguish between these two cases. + if (init_z_bckp - current_position[Z_AXIS] < 0.f) { //broken cable or initial Z coordinate too low. Go to MESH_HOME_Z_SEARCH and repeat last step (z-probe) again to distinguish between these two cases. current_position[Z_AXIS] = MESH_HOME_Z_SEARCH; plan_buffer_line_curposXYZE(Z_LIFT_FEEDRATE); st_synchronize(); @@ -3029,8 +3033,8 @@ static void gcode_G80() correction[i] = 0; } } - for (uint8_t row = 0; row < MESH_NUM_Y_POINTS; ++row) { - for (uint8_t col = 0; col < MESH_NUM_X_POINTS; ++col) { + for (uint8_t row = 0; row < MESH_NUM_Y_POINTS; row++) { + for (uint8_t col = 0; col < MESH_NUM_X_POINTS; col++) { mbl.z_values[row][col] +=0.001f * ( + correction[0] * (MESH_NUM_X_POINTS - 1 - col) + correction[1] * col diff --git a/Firmware/mesh_bed_leveling.cpp b/Firmware/mesh_bed_leveling.cpp index 2d6388b0c..32c057d49 100644 --- a/Firmware/mesh_bed_leveling.cpp +++ b/Firmware/mesh_bed_leveling.cpp @@ -8,11 +8,7 @@ mesh_bed_leveling mbl; void mesh_bed_leveling::reset() { active = 0; - for (uint8_t row = 0; row < MESH_NUM_Y_POINTS; ++row) { - for (uint8_t col = 0; col < MESH_NUM_X_POINTS; ++col) { - mbl.z_values[row][col] = NAN; - } - } + memset(z_values, 0, sizeof(z_values)); } float mesh_bed_leveling::get_z(float x, float y) { From a7d3dd720b7eb0b1ce3d0adf6bb59cd99de18050 Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Fri, 5 May 2023 15:04:52 +0200 Subject: [PATCH 15/34] Fix eeprom mesh interpolation --- Firmware/Marlin_main.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 2458ee55f..da71b0c32 100644 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -2856,6 +2856,8 @@ static void gcode_G80() const float z0 = mbl.z_values[0][0] + *reinterpret_cast(&z_offset_u) * 0.01; mbl.set_z(col, row, z0); } + } else { + mbl.set_z(col, row, NAN); } // check for points that are skipped From 40db9c92587d16b56d96a498e1e82f953dcd5b0e Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Fri, 5 May 2023 16:11:31 +0200 Subject: [PATCH 16/34] Fix eeprom mesh offset --- Firmware/Marlin_main.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index da71b0c32..9051e7a35 100644 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -2839,6 +2839,7 @@ static void gcode_G80() const float area_max_y = code_seen('H') ? area_min_y + code_value() + 2 * MESH_Y_DIST : INFINITY; mbl.reset(); //reset mesh bed leveling + mbl.z_values[0][0] = min_pos[Z_AXIS]; // Reset baby stepping to zero, if the babystepping has already been loaded before. babystep_undo(); @@ -2867,7 +2868,7 @@ static void gcode_G80() } else { const float x_pos = BED_X(col, MESH_NUM_X_POINTS); const float y_pos = BED_Y(row, MESH_NUM_Y_POINTS); - if ((x_pos < area_min_x || x_pos > area_max_x || y_pos < area_min_y || y_pos > area_max_y) && (row || col) && (!isOn3x3Mesh || has_z)) { + if ((x_pos < area_min_x || x_pos > area_max_x || y_pos < area_min_y || y_pos > area_max_y) && (!isOn3x3Mesh || has_z)) { continue; } } @@ -2885,6 +2886,10 @@ static void gcode_G80() custom_message_state = meshPointsToProbe + 10; lcd_update(1); + // Lift Z to a safe position before probing the first point + current_position[Z_AXIS] = MESH_HOME_Z_SEARCH; + plan_buffer_line_curposXYZE(Z_LIFT_FEEDRATE); + // Cycle through all points and probe them int l_feedmultiply = setup_for_endstop_move(false); //save feedrate and feedmultiply, sets feedmultiply to 100 uint8_t mesh_point = 0; //index number of calibration point @@ -2901,14 +2906,14 @@ static void gcode_G80() mesh_point++; mbl.set_z(ix, iy, NAN); continue; //skip - } else if ((x_pos < area_min_x || x_pos > area_max_x || y_pos < area_min_y || y_pos > area_max_y) && (mesh_point > 0) && (!isOn3x3Mesh || has_z)) { + } else if ((x_pos < area_min_x || x_pos > area_max_x || y_pos < area_min_y || y_pos > area_max_y) && (!isOn3x3Mesh || has_z)) { mesh_point++; continue; //skip } // Move Z up to the probe height of the current Z point. const float z0 = mbl.z_values[iy][ix]; - const float init_z_bckp = (!has_z || (mesh_point == 0)) ? MESH_HOME_Z_SEARCH : z0 + 0.5; + const float init_z_bckp = !has_z ? MESH_HOME_Z_SEARCH : z0 + 0.35; if (init_z_bckp > current_position[Z_AXIS]) current_position[Z_AXIS] = init_z_bckp; plan_buffer_line_curposXYZE(Z_LIFT_FEEDRATE); @@ -2930,7 +2935,7 @@ static void gcode_G80() } // Go down until endstop is hit - if (!find_bed_induction_sensor_point_z((has_z && mesh_point > 0) ? z0 - Z_CALIBRATION_THRESHOLD : -10.f, nProbeRetry)) { //if we have data from z calibration max allowed difference is 1mm for each point, if we dont have data max difference is 10mm from initial point + if (!find_bed_induction_sensor_point_z(has_z ? z0 - Z_CALIBRATION_THRESHOLD : -10.f, nProbeRetry)) { //if we have data from z calibration max allowed difference is 1mm for each point, if we dont have data max difference is 10mm from initial point printf_P(_T(MSG_BED_LEVELING_FAILED_POINT_LOW)); break; } @@ -2939,7 +2944,7 @@ static void gcode_G80() plan_buffer_line_curposXYZE(Z_LIFT_FEEDRATE); st_synchronize(); - if (!find_bed_induction_sensor_point_z((has_z && mesh_point > 0) ? z0 - Z_CALIBRATION_THRESHOLD : -10.f, nProbeRetry)) { //if we have data from z calibration max allowed difference is 1mm for each point, if we dont have data max difference is 10mm from initial point + if (!find_bed_induction_sensor_point_z(has_z ? z0 - Z_CALIBRATION_THRESHOLD : -10.f, nProbeRetry)) { //if we have data from z calibration max allowed difference is 1mm for each point, if we dont have data max difference is 10mm from initial point printf_P(_T(MSG_BED_LEVELING_FAILED_POINT_LOW)); break; } From de985516912793de1a3b2abc94cf0e615c3a0991 Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Fri, 5 May 2023 17:24:41 +0200 Subject: [PATCH 17/34] Extract hardcoded value --- Firmware/Marlin_main.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 9051e7a35..c41124ba9 100644 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -2792,6 +2792,7 @@ static void gcode_G80() constexpr float XY_AXIS_FEEDRATE = (homing_feedrate[X_AXIS] * 3) / 60; constexpr float Z_LIFT_FEEDRATE = homing_feedrate[Z_AXIS] / 60; constexpr float Z_CALIBRATION_THRESHOLD = 1.f; + constexpr float MESH_HOME_Z_SEARCH_FAST = 0.35f; st_synchronize(); if (planner_aborted) return; @@ -2913,7 +2914,7 @@ static void gcode_G80() // Move Z up to the probe height of the current Z point. const float z0 = mbl.z_values[iy][ix]; - const float init_z_bckp = !has_z ? MESH_HOME_Z_SEARCH : z0 + 0.35; + const float init_z_bckp = !has_z ? MESH_HOME_Z_SEARCH : z0 + MESH_HOME_Z_SEARCH_FAST; if (init_z_bckp > current_position[Z_AXIS]) current_position[Z_AXIS] = init_z_bckp; plan_buffer_line_curposXYZE(Z_LIFT_FEEDRATE); From a5c20a1c6e632bfe15ef7df350b7b28be4bd621a Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Fri, 5 May 2023 18:03:57 +0200 Subject: [PATCH 18/34] Do not plan a Z move if no move is actually performed --- Firmware/Marlin_main.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index c41124ba9..5d926ec54 100644 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -2915,10 +2915,11 @@ static void gcode_G80() // Move Z up to the probe height of the current Z point. const float z0 = mbl.z_values[iy][ix]; const float init_z_bckp = !has_z ? MESH_HOME_Z_SEARCH : z0 + MESH_HOME_Z_SEARCH_FAST; - if (init_z_bckp > current_position[Z_AXIS]) + if (init_z_bckp > current_position[Z_AXIS]) { current_position[Z_AXIS] = init_z_bckp; - plan_buffer_line_curposXYZE(Z_LIFT_FEEDRATE); - st_synchronize(); + plan_buffer_line_curposXYZE(Z_LIFT_FEEDRATE); + st_synchronize(); + } // Move to XY position of the sensor point. current_position[X_AXIS] = x_pos; From 67945579dea1c8c2c468458956929cf68d259b6a Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Fri, 5 May 2023 18:56:26 +0200 Subject: [PATCH 19/34] G80 minor optimization --- Firmware/Marlin_main.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 5d926ec54..253ba5fd9 100644 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -3015,6 +3015,7 @@ static void gcode_G80() if(eeprom_read_byte((uint8_t *)EEPROM_TEMP_CAL_ACTIVE) && calibration_status_pinda() == true) temp_compensation_apply(); //apply PINDA temperature compensation #endif babystep_apply(); // Apply Z height correction aka baby stepping before mesh bed leveing gets activated. + bool eeprom_bed_correction_valid = eeprom_read_byte((unsigned char*)EEPROM_BED_CORRECTION_VALID) == 1; const constexpr uint8_t sides = 4; int8_t correction[sides]; @@ -3036,19 +3037,18 @@ static void gcode_G80() // Value is valid, save it correction[i] = (int8_t)temp; } - } else if (eeprom_bed_correction_valid) { - correction[i] = (int8_t)eeprom_read_byte((uint8_t*)pgm_read_ptr(&eep_addresses[i])); } else { - correction[i] = 0; + correction[i] = eeprom_bed_correction_valid ? (int8_t)eeprom_read_byte((uint8_t*)pgm_read_ptr(&eep_addresses[i])) : 0; } } for (uint8_t row = 0; row < MESH_NUM_Y_POINTS; row++) { for (uint8_t col = 0; col < MESH_NUM_X_POINTS; col++) { - mbl.z_values[row][col] +=0.001f * ( + constexpr float scaler = 0.001f / (MESH_NUM_X_POINTS - 1); + mbl.z_values[row][col] += scaler * ( + correction[0] * (MESH_NUM_X_POINTS - 1 - col) + correction[1] * col + correction[2] * (MESH_NUM_Y_POINTS - 1 - row) - + correction[3] * row) / (float)(MESH_NUM_X_POINTS - 1); + + correction[3] * row); } } From 5b8c65e342fc4e330173ddd2584cdfe6af1b567c Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Fri, 5 May 2023 21:03:34 +0200 Subject: [PATCH 20/34] Minor magnet elimination optimization flash: -4B --- Firmware/Marlin_main.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 253ba5fd9..f15e7fe6e 100644 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -2832,8 +2832,6 @@ static void gcode_G80() nProbeRetry = 10; } - const uint8_t magnet_elimination = eeprom_read_byte((uint8_t*)EEPROM_MBL_MAGNET_ELIMINATION); - const float area_min_x = code_seen('X') ? code_value() - MESH_X_DIST - X_PROBE_OFFSET_FROM_EXTRUDER : -INFINITY; const float area_min_y = code_seen('Y') ? code_value() - MESH_Y_DIST - Y_PROBE_OFFSET_FROM_EXTRUDER : -INFINITY; const float area_max_x = code_seen('W') ? area_min_x + code_value() + 2 * MESH_X_DIST : INFINITY; @@ -3054,7 +3052,7 @@ static void gcode_G80() mbl.upsample_3x3(); //interpolation from 3x3 to 7x7 points using largrangian polynomials while using the same array z_values[iy][ix] for storing (just coppying measured data to new destination and interpolating between them) - if (nMeasPoints == 7 && magnet_elimination) { + if (nMeasPoints == 7 && eeprom_read_byte((uint8_t*)EEPROM_MBL_MAGNET_ELIMINATION)) { mbl_magnet_elimination(); } From 2d0b96fe6aee8e617a63a7f19a9bc3c6b41390ea Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Sat, 6 May 2023 15:27:11 +0200 Subject: [PATCH 21/34] Bed correction code optimization flash: -44 --- Firmware/Marlin_main.cpp | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index f15e7fe6e..e58e24ce3 100644 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -3014,31 +3014,28 @@ static void gcode_G80() #endif babystep_apply(); // Apply Z height correction aka baby stepping before mesh bed leveing gets activated. + // Apply the bed level correction to the mesh bool eeprom_bed_correction_valid = eeprom_read_byte((unsigned char*)EEPROM_BED_CORRECTION_VALID) == 1; - const constexpr uint8_t sides = 4; - int8_t correction[sides]; - for (uint8_t i = 0; i < sides; ++i) { - static const char codes[sides] PROGMEM = { 'L', 'R', 'F', 'B' }; - static uint8_t *const eep_addresses[sides] PROGMEM = { - (uint8_t*)EEPROM_BED_CORRECTION_LEFT, - (uint8_t*)EEPROM_BED_CORRECTION_RIGHT, - (uint8_t*)EEPROM_BED_CORRECTION_FRONT, - (uint8_t*)EEPROM_BED_CORRECTION_REAR, - }; - if (code_seen(pgm_read_byte(&codes[i]))) { + auto bedCorrectHelper = [&] (char code, uint8_t *eep_address) -> int8_t { + if (code_seen(code)) { // Verify value is within allowed range - int32_t temp = code_value_long(); - if (labs(temp) > BED_ADJUSTMENT_UM_MAX) { - printf_P(PSTR("%SExcessive bed leveling correction: %li microns\n"), errormagic, temp); - correction[i] = 0; + int16_t temp = code_value_short(); + if (abs(temp) > BED_ADJUSTMENT_UM_MAX) { + printf_P(PSTR("%SExcessive bed leveling correction: %i microns\n"), errormagic, temp); } else { - // Value is valid, save it - correction[i] = (int8_t)temp; + return (int8_t)temp; // Value is valid, use it } - } else { - correction[i] = eeprom_bed_correction_valid ? (int8_t)eeprom_read_byte((uint8_t*)pgm_read_ptr(&eep_addresses[i])) : 0; + } else if (eeprom_bed_correction_valid) { + return (int8_t)eeprom_read_byte(eep_address); } - } + return 0; + }; + int8_t correction[4] = { + bedCorrectHelper('L', (uint8_t*)EEPROM_BED_CORRECTION_LEFT), + bedCorrectHelper('R', (uint8_t*)EEPROM_BED_CORRECTION_RIGHT), + bedCorrectHelper('F', (uint8_t*)EEPROM_BED_CORRECTION_FRONT), + bedCorrectHelper('B', (uint8_t*)EEPROM_BED_CORRECTION_REAR), + }; for (uint8_t row = 0; row < MESH_NUM_Y_POINTS; row++) { for (uint8_t col = 0; col < MESH_NUM_X_POINTS; col++) { constexpr float scaler = 0.001f / (MESH_NUM_X_POINTS - 1); From be3465cf18643e643f5b1f6e091f7a23470ffd56 Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Sat, 6 May 2023 17:07:10 +0200 Subject: [PATCH 22/34] optimize lambda expression capture flash: -10 --- Firmware/Marlin_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index e58e24ce3..03363771f 100644 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -3016,7 +3016,7 @@ static void gcode_G80() // Apply the bed level correction to the mesh bool eeprom_bed_correction_valid = eeprom_read_byte((unsigned char*)EEPROM_BED_CORRECTION_VALID) == 1; - auto bedCorrectHelper = [&] (char code, uint8_t *eep_address) -> int8_t { + auto bedCorrectHelper = [eeprom_bed_correction_valid] (char code, uint8_t *eep_address) -> int8_t { if (code_seen(code)) { // Verify value is within allowed range int16_t temp = code_value_short(); From 3ccf2d60c07296115913e1522e6bbc296ef8c8c5 Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Sat, 6 May 2023 17:12:08 +0200 Subject: [PATCH 23/34] Make bed correction matrix const --- Firmware/Marlin_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 03363771f..41511e6f6 100644 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -3030,7 +3030,7 @@ static void gcode_G80() } return 0; }; - int8_t correction[4] = { + const int8_t correction[4] = { bedCorrectHelper('L', (uint8_t*)EEPROM_BED_CORRECTION_LEFT), bedCorrectHelper('R', (uint8_t*)EEPROM_BED_CORRECTION_RIGHT), bedCorrectHelper('F', (uint8_t*)EEPROM_BED_CORRECTION_FRONT), From 6b12be42d943d6541470c2d33c0aa3be170244d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gu=C3=B0ni=20M=C3=A1r=20Gilbert?= Date: Sat, 6 May 2023 20:34:38 +0000 Subject: [PATCH 24/34] optimisation: Make BED_X and BED_Y into functions Previously these preprocessor macros were always being inlined. By making these into a function we can control the inlining more directly. The number of points on the mesh is also now constant. This means 'n' can now be float at compile time. This removes one uint8_t to float conversion. Change in memory: Flash: -208 bytes SRAM: 0 bytes --- Firmware/Marlin_main.cpp | 8 ++++---- Firmware/mesh_bed_calibration.cpp | 22 ++++++++++++++++------ Firmware/mesh_bed_calibration.h | 14 +++++++++++--- 3 files changed, 31 insertions(+), 13 deletions(-) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 41511e6f6..1020b2ee1 100644 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -2865,8 +2865,8 @@ static void gcode_G80() if (!isOn3x3Mesh) continue; } else { - const float x_pos = BED_X(col, MESH_NUM_X_POINTS); - const float y_pos = BED_Y(row, MESH_NUM_Y_POINTS); + const float x_pos = BED_X(col); + const float y_pos = BED_Y(row); if ((x_pos < area_min_x || x_pos > area_max_x || y_pos < area_min_y || y_pos > area_max_y) && (!isOn3x3Mesh || has_z)) { continue; } @@ -2898,8 +2898,8 @@ static void gcode_G80() uint8_t iy = mesh_point / MESH_NUM_X_POINTS; if (iy & 1) ix = (MESH_NUM_X_POINTS - 1) - ix; // Zig zag bool isOn3x3Mesh = ((ix % 3 == 0) && (iy % 3 == 0)); - float x_pos = BED_X(ix, MESH_NUM_X_POINTS); - float y_pos = BED_Y(iy, MESH_NUM_Y_POINTS); + float x_pos = BED_X(ix); + float y_pos = BED_Y(iy); if ((nMeasPoints == 3) && !isOn3x3Mesh) { mesh_point++; diff --git a/Firmware/mesh_bed_calibration.cpp b/Firmware/mesh_bed_calibration.cpp index fbe9fdc03..4808a66f1 100644 --- a/Firmware/mesh_bed_calibration.cpp +++ b/Firmware/mesh_bed_calibration.cpp @@ -2184,6 +2184,16 @@ inline void scan_bed_induction_sensor_point() #define MESH_BED_CALIBRATION_SHOW_LCD +float __attribute__((noinline)) BED_X(const uint8_t col) +{ + return ((float)col * (BED_Xn - BED_X0) / (MESH_NUM_X_POINTS - 1) + BED_X0); +} + +float __attribute__((noinline)) BED_Y(const uint8_t row) +{ + return ((float)row * (BED_Yn - BED_Y0) / (MESH_NUM_Y_POINTS - 1) + BED_Y0); +} + BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t verbosity_level, uint8_t &too_far_mask) { // Don't let the manage_inactivity() function remove power from the motors. @@ -2481,8 +2491,8 @@ BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t verbosity_level uint8_t ix = mesh_point % MESH_MEAS_NUM_X_POINTS; // from 0 to MESH_NUM_X_POINTS - 1 uint8_t iy = mesh_point / MESH_MEAS_NUM_X_POINTS; if (iy & 1) ix = (MESH_MEAS_NUM_X_POINTS - 1) - ix; - current_position[X_AXIS] = BED_X(ix, MESH_MEAS_NUM_X_POINTS); - current_position[Y_AXIS] = BED_Y(iy, MESH_MEAS_NUM_Y_POINTS); + current_position[X_AXIS] = BED_X(ix); + current_position[Y_AXIS] = BED_Y(iy); go_to_current(homing_feedrate[X_AXIS] / 60); delay_keep_alive(3000); } @@ -2884,8 +2894,8 @@ bool sample_mesh_and_store_reference() uint8_t ix = mesh_point % MESH_MEAS_NUM_X_POINTS; uint8_t iy = mesh_point / MESH_MEAS_NUM_X_POINTS; if (iy & 1) ix = (MESH_MEAS_NUM_X_POINTS - 1) - ix; // Zig zag - current_position[X_AXIS] = BED_X(ix, MESH_MEAS_NUM_X_POINTS); - current_position[Y_AXIS] = BED_Y(iy, MESH_MEAS_NUM_Y_POINTS); + current_position[X_AXIS] = BED_X(ix); + current_position[Y_AXIS] = BED_Y(iy); world2machine_clamp(current_position[X_AXIS], current_position[Y_AXIS]); go_to_current(homing_feedrate[X_AXIS]/60); #ifdef MESH_BED_CALIBRATION_SHOW_LCD @@ -3003,8 +3013,8 @@ bool scan_bed_induction_points(int8_t verbosity_level) uint8_t ix = mesh_point % MESH_MEAS_NUM_X_POINTS; // from 0 to MESH_NUM_X_POINTS - 1 uint8_t iy = mesh_point / MESH_MEAS_NUM_X_POINTS; if (iy & 1) ix = (MESH_MEAS_NUM_X_POINTS - 1) - ix; - float bedX = BED_X(ix, MESH_MEAS_NUM_X_POINTS); - float bedY = BED_Y(iy, MESH_MEAS_NUM_Y_POINTS); + float bedX = BED_X(ix); + float bedY = BED_Y(iy); current_position[X_AXIS] = vec_x[0] * bedX + vec_y[0] * bedY + cntr[0]; current_position[Y_AXIS] = vec_x[1] * bedX + vec_y[1] * bedY + cntr[1]; // The calibration points are very close to the min Y. diff --git a/Firmware/mesh_bed_calibration.h b/Firmware/mesh_bed_calibration.h index 41f81016a..c6c7c87e7 100644 --- a/Firmware/mesh_bed_calibration.h +++ b/Firmware/mesh_bed_calibration.h @@ -21,9 +21,6 @@ #endif //not HEATBED_V2 -#define BED_X(i, n) ((float)i * (BED_Xn - BED_X0) / (n - 1) + BED_X0) -#define BED_Y(i, n) ((float)i * (BED_Yn - BED_Y0) / (n - 1) + BED_Y0) - // Exact positions of the print head above the bed reference points, in the world coordinates. // The world coordinates match the machine coordinates only in case, when the machine // is built properly, the end stops are at the correct positions and the axes are perpendicular. @@ -145,6 +142,17 @@ inline bool world2machine_clamp(float &x, float &y) machine2world(tmpx, tmpy, x, y); return clamped; } + +/// @brief For a given column on the mesh calculate the bed X coordinate +/// @param col column index on mesh +/// @return Bed X coordinate +float BED_X(const uint8_t col); + +/// @brief For a given row on the mesh calculate the bed Y coordinate +/// @param row row index on mesh +/// @return Bed Y coordinate +float BED_Y(const uint8_t row); + /** * @brief Bed skew and offest detection result * From a9d0cc5e566fbd8d61887ffc95bb412479150321 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gu=C3=B0ni=20M=C3=A1r=20Gilbert?= Date: Sat, 6 May 2023 20:54:42 +0000 Subject: [PATCH 25/34] optimisation: Move divison into constexpr Change in memory: Flash: -12 bytes SRAM: 0 bytes --- Firmware/mesh_bed_calibration.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Firmware/mesh_bed_calibration.cpp b/Firmware/mesh_bed_calibration.cpp index 4808a66f1..464e46e30 100644 --- a/Firmware/mesh_bed_calibration.cpp +++ b/Firmware/mesh_bed_calibration.cpp @@ -2186,12 +2186,14 @@ inline void scan_bed_induction_sensor_point() float __attribute__((noinline)) BED_X(const uint8_t col) { - return ((float)col * (BED_Xn - BED_X0) / (MESH_NUM_X_POINTS - 1) + BED_X0); + constexpr float x_mesh_density = (BED_Xn - BED_X0) / (MESH_NUM_X_POINTS - 1); + return ((float)col * x_mesh_density + BED_X0); } float __attribute__((noinline)) BED_Y(const uint8_t row) { - return ((float)row * (BED_Yn - BED_Y0) / (MESH_NUM_Y_POINTS - 1) + BED_Y0); + constexpr float y_mesh_density = (BED_Yn - BED_Y0) / (MESH_NUM_Y_POINTS - 1); + return ((float)row * y_mesh_density + BED_Y0); } BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t verbosity_level, uint8_t &too_far_mask) From 42c27cabde95c1f49d0c3c4ee89378d0676aafa2 Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Sun, 7 May 2023 00:40:14 +0200 Subject: [PATCH 26/34] Remove unused code --- Firmware/mesh_bed_leveling.cpp | 42 ---------------------------------- Firmware/mesh_bed_leveling.h | 9 -------- 2 files changed, 51 deletions(-) diff --git a/Firmware/mesh_bed_leveling.cpp b/Firmware/mesh_bed_leveling.cpp index 32c057d49..c4af87e8d 100644 --- a/Firmware/mesh_bed_leveling.cpp +++ b/Firmware/mesh_bed_leveling.cpp @@ -15,32 +15,6 @@ float mesh_bed_leveling::get_z(float x, float y) { int i, j; float s, t; -#if MESH_NUM_X_POINTS==3 && MESH_NUM_Y_POINTS==3 -#define MESH_MID_X (0.5f*(MESH_MIN_X+MESH_MAX_X)) -#define MESH_MID_Y (0.5f*(MESH_MIN_Y+MESH_MAX_Y)) - if (x < MESH_MID_X) { - i = 0; - s = (x - MESH_MIN_X) / MESH_X_DIST; - if (s > 1.f) - s = 1.f; - } else { - i = 1; - s = (x - MESH_MID_X) / MESH_X_DIST; - if (s < 0) - s = 0; - } - if (y < MESH_MID_Y) { - j = 0; - t = (y - MESH_MIN_Y) / MESH_Y_DIST; - if (t > 1.f) - t = 1.f; - } else { - j = 1; - t = (y - MESH_MID_Y) / MESH_Y_DIST; - if (t < 0) - t = 0; - } -#else i = int(floor((x - MESH_MIN_X) / MESH_X_DIST)); if (i < 0) { i = 0; @@ -78,27 +52,12 @@ float mesh_bed_leveling::get_z(float x, float y) { else if (t > 1.f) t = 1.f; } -#endif /* MESH_NUM_X_POINTS==3 && MESH_NUM_Y_POINTS==3 */ float si = 1.f-s; float z0 = si * z_values[j ][i] + s * z_values[j ][i+1]; float z1 = si * z_values[j+1][i] + s * z_values[j+1][i+1]; return (1.f-t) * z0 + t * z1; } - -int mesh_bed_leveling::select_x_index(float x) { - int i = 1; - while (x > get_x(i) && i < MESH_NUM_X_POINTS - 1) i++; - return i - 1; -} - -int mesh_bed_leveling::select_y_index(float y) { - int i = 1; - while (y > get_y(i) && i < MESH_NUM_Y_POINTS - 1) i++; - return i - 1; -} - -#if MESH_NUM_X_POINTS>=5 && MESH_NUM_Y_POINTS>=5 && (MESH_NUM_X_POINTS&1)==1 && (MESH_NUM_Y_POINTS&1)==1 // Works for an odd number of MESH_NUM_X_POINTS and MESH_NUM_Y_POINTS void mesh_bed_leveling::upsample_3x3() @@ -143,7 +102,6 @@ void mesh_bed_leveling::upsample_3x3() } } } -#endif // (MESH_NUM_X_POINTS>=5 && MESH_NUM_Y_POINTS>=5 && (MESH_NUM_X_POINTS&1)==1 && (MESH_NUM_Y_POINTS&1)==1) void mesh_bed_leveling::print() { SERIAL_PROTOCOLLNPGM("Num X,Y: " STRINGIFY(MESH_NUM_X_POINTS) "," STRINGIFY(MESH_NUM_Y_POINTS)); diff --git a/Firmware/mesh_bed_leveling.h b/Firmware/mesh_bed_leveling.h index cda0ea797..6c9e6c7c6 100644 --- a/Firmware/mesh_bed_leveling.h +++ b/Firmware/mesh_bed_leveling.h @@ -2,9 +2,6 @@ #ifdef MESH_BED_LEVELING -#define MEAS_NUM_X_DIST (float(MESH_MAX_X - MESH_MIN_X)/float(MESH_MEAS_NUM_X_POINTS - 1)) -#define MEAS_NUM_Y_DIST (float(MESH_MAX_Y - MESH_MIN_Y)/float(MESH_MEAS_NUM_Y_POINTS - 1)) - #define MESH_X_DIST (float(MESH_MAX_X - MESH_MIN_X)/float(MESH_NUM_X_POINTS - 1)) #define MESH_Y_DIST (float(MESH_MAX_Y - MESH_MIN_Y)/float(MESH_NUM_Y_POINTS - 1)) @@ -21,13 +18,7 @@ public: static float get_y(int i) { return float(MESH_MIN_Y) + float(MESH_Y_DIST) * float(i); } float get_z(float x, float y); void set_z(uint8_t ix, uint8_t iy, float z) { z_values[iy][ix] = z; } - - int select_x_index(float x); - int select_y_index(float y); - -#if MESH_NUM_X_POINTS>=5 && MESH_NUM_Y_POINTS>=5 && (MESH_NUM_X_POINTS&1)==1 && (MESH_NUM_Y_POINTS&1)==1 void upsample_3x3(); -#endif void print(); }; From dd1bde74dc4579e8d2632ef4cc1be9b42c17e21a Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Sun, 7 May 2023 12:45:09 +0200 Subject: [PATCH 27/34] Fix Z calibration points --- Firmware/mesh_bed_calibration.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Firmware/mesh_bed_calibration.cpp b/Firmware/mesh_bed_calibration.cpp index 464e46e30..97b324e76 100644 --- a/Firmware/mesh_bed_calibration.cpp +++ b/Firmware/mesh_bed_calibration.cpp @@ -2493,8 +2493,8 @@ BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t verbosity_level uint8_t ix = mesh_point % MESH_MEAS_NUM_X_POINTS; // from 0 to MESH_NUM_X_POINTS - 1 uint8_t iy = mesh_point / MESH_MEAS_NUM_X_POINTS; if (iy & 1) ix = (MESH_MEAS_NUM_X_POINTS - 1) - ix; - current_position[X_AXIS] = BED_X(ix); - current_position[Y_AXIS] = BED_Y(iy); + current_position[X_AXIS] = BED_X(ix * 3); + current_position[Y_AXIS] = BED_Y(iy * 3); go_to_current(homing_feedrate[X_AXIS] / 60); delay_keep_alive(3000); } @@ -2896,8 +2896,8 @@ bool sample_mesh_and_store_reference() uint8_t ix = mesh_point % MESH_MEAS_NUM_X_POINTS; uint8_t iy = mesh_point / MESH_MEAS_NUM_X_POINTS; if (iy & 1) ix = (MESH_MEAS_NUM_X_POINTS - 1) - ix; // Zig zag - current_position[X_AXIS] = BED_X(ix); - current_position[Y_AXIS] = BED_Y(iy); + current_position[X_AXIS] = BED_X(ix * 3); + current_position[Y_AXIS] = BED_Y(iy * 3); world2machine_clamp(current_position[X_AXIS], current_position[Y_AXIS]); go_to_current(homing_feedrate[X_AXIS]/60); #ifdef MESH_BED_CALIBRATION_SHOW_LCD @@ -3015,8 +3015,8 @@ bool scan_bed_induction_points(int8_t verbosity_level) uint8_t ix = mesh_point % MESH_MEAS_NUM_X_POINTS; // from 0 to MESH_NUM_X_POINTS - 1 uint8_t iy = mesh_point / MESH_MEAS_NUM_X_POINTS; if (iy & 1) ix = (MESH_MEAS_NUM_X_POINTS - 1) - ix; - float bedX = BED_X(ix); - float bedY = BED_Y(iy); + float bedX = BED_X(ix * 3); + float bedY = BED_Y(iy * 3); current_position[X_AXIS] = vec_x[0] * bedX + vec_y[0] * bedY + cntr[0]; current_position[Y_AXIS] = vec_x[1] * bedX + vec_y[1] * bedY + cntr[1]; // The calibration points are very close to the min Y. From aba045061519f796e0efb425e43bc124e5a51421 Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Sun, 7 May 2023 01:00:55 +0200 Subject: [PATCH 28/34] mbl.get_z() optimizations Those constrains on t and s were useless. flash: -294 --- Firmware/mesh_bed_leveling.cpp | 30 +++++++----------------------- 1 file changed, 7 insertions(+), 23 deletions(-) diff --git a/Firmware/mesh_bed_leveling.cpp b/Firmware/mesh_bed_leveling.cpp index c4af87e8d..47cd07614 100644 --- a/Firmware/mesh_bed_leveling.cpp +++ b/Firmware/mesh_bed_leveling.cpp @@ -19,38 +19,22 @@ float mesh_bed_leveling::get_z(float x, float y) { if (i < 0) { i = 0; s = (x - MESH_MIN_X) / MESH_X_DIST; - if (s > 1.f) - s = 1.f; - } - else if (i > MESH_NUM_X_POINTS - 2) { - i = MESH_NUM_X_POINTS - 2; - s = (x - get_x(i)) / MESH_X_DIST; - if (s < 0) - s = 0; } else { + if (i > MESH_NUM_X_POINTS - 2) { + i = MESH_NUM_X_POINTS - 2; + } s = (x - get_x(i)) / MESH_X_DIST; - if (s < 0) - s = 0; - else if (s > 1.f) - s = 1.f; } + j = int(floor((y - MESH_MIN_Y) / MESH_Y_DIST)); if (j < 0) { j = 0; t = (y - MESH_MIN_Y) / MESH_Y_DIST; - if (t > 1.f) - t = 1.f; - } else if (j > MESH_NUM_Y_POINTS - 2) { - j = MESH_NUM_Y_POINTS - 2; - t = (y - get_y(j)) / MESH_Y_DIST; - if (t < 0) - t = 0; } else { + if (j > MESH_NUM_Y_POINTS - 2) { + j = MESH_NUM_Y_POINTS - 2; + } t = (y - get_y(j)) / MESH_Y_DIST; - if (t < 0) - t = 0; - else if (t > 1.f) - t = 1.f; } float si = 1.f-s; From a15f536ff45c2f7058c94c17b5862b7dc4057f45 Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Mon, 8 May 2023 00:03:31 +0200 Subject: [PATCH 29/34] Combine BED_X/Y() and mbl::get_x/y() flash: -112 --- Firmware/Marlin_main.cpp | 8 +++---- Firmware/mesh_bed_calibration.cpp | 2 -- Firmware/mesh_bed_calibration.h | 3 +++ Firmware/mesh_bed_leveling.cpp | 24 +++++++++---------- Firmware/mesh_bed_leveling.h | 8 +++---- Firmware/variants/MK25-RAMBo10a.h | 6 ----- Firmware/variants/MK25-RAMBo13a.h | 6 ----- Firmware/variants/MK25S-RAMBo10a.h | 6 ----- Firmware/variants/MK25S-RAMBo13a.h | 6 ----- Firmware/variants/MK3.h | 6 ----- Firmware/variants/MK3S.h | 6 ----- .../obsolete/1_75mm_MK2-RAMBo10a-E3Dv6full.h | 6 ----- .../obsolete/1_75mm_MK2-RAMBo13a-E3Dv6full.h | 6 ----- 13 files changed, 22 insertions(+), 71 deletions(-) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 1020b2ee1..7a8d0124c 100644 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -2832,10 +2832,10 @@ static void gcode_G80() nProbeRetry = 10; } - const float area_min_x = code_seen('X') ? code_value() - MESH_X_DIST - X_PROBE_OFFSET_FROM_EXTRUDER : -INFINITY; - const float area_min_y = code_seen('Y') ? code_value() - MESH_Y_DIST - Y_PROBE_OFFSET_FROM_EXTRUDER : -INFINITY; - const float area_max_x = code_seen('W') ? area_min_x + code_value() + 2 * MESH_X_DIST : INFINITY; - const float area_max_y = code_seen('H') ? area_min_y + code_value() + 2 * MESH_Y_DIST : INFINITY; + const float area_min_x = code_seen('X') ? code_value() - x_mesh_density - X_PROBE_OFFSET_FROM_EXTRUDER : -INFINITY; + const float area_min_y = code_seen('Y') ? code_value() - y_mesh_density - Y_PROBE_OFFSET_FROM_EXTRUDER : -INFINITY; + const float area_max_x = code_seen('W') ? area_min_x + code_value() + 2 * x_mesh_density : INFINITY; + const float area_max_y = code_seen('H') ? area_min_y + code_value() + 2 * y_mesh_density : INFINITY; mbl.reset(); //reset mesh bed leveling mbl.z_values[0][0] = min_pos[Z_AXIS]; diff --git a/Firmware/mesh_bed_calibration.cpp b/Firmware/mesh_bed_calibration.cpp index 97b324e76..ec8b205c3 100644 --- a/Firmware/mesh_bed_calibration.cpp +++ b/Firmware/mesh_bed_calibration.cpp @@ -2186,13 +2186,11 @@ inline void scan_bed_induction_sensor_point() float __attribute__((noinline)) BED_X(const uint8_t col) { - constexpr float x_mesh_density = (BED_Xn - BED_X0) / (MESH_NUM_X_POINTS - 1); return ((float)col * x_mesh_density + BED_X0); } float __attribute__((noinline)) BED_Y(const uint8_t row) { - constexpr float y_mesh_density = (BED_Yn - BED_Y0) / (MESH_NUM_Y_POINTS - 1); return ((float)row * y_mesh_density + BED_Y0); } diff --git a/Firmware/mesh_bed_calibration.h b/Firmware/mesh_bed_calibration.h index c6c7c87e7..651eaba71 100644 --- a/Firmware/mesh_bed_calibration.h +++ b/Firmware/mesh_bed_calibration.h @@ -21,6 +21,9 @@ #endif //not HEATBED_V2 +constexpr float x_mesh_density = (BED_Xn - BED_X0) / (MESH_NUM_X_POINTS - 1); +constexpr float y_mesh_density = (BED_Yn - BED_Y0) / (MESH_NUM_Y_POINTS - 1); + // Exact positions of the print head above the bed reference points, in the world coordinates. // The world coordinates match the machine coordinates only in case, when the machine // is built properly, the end stops are at the correct positions and the axes are perpendicular. diff --git a/Firmware/mesh_bed_leveling.cpp b/Firmware/mesh_bed_leveling.cpp index 47cd07614..9ffcbb59d 100644 --- a/Firmware/mesh_bed_leveling.cpp +++ b/Firmware/mesh_bed_leveling.cpp @@ -15,26 +15,26 @@ float mesh_bed_leveling::get_z(float x, float y) { int i, j; float s, t; - i = int(floor((x - MESH_MIN_X) / MESH_X_DIST)); + i = int(floor((x - (BED_X0 + X_PROBE_OFFSET_FROM_EXTRUDER)) / x_mesh_density)); if (i < 0) { i = 0; - s = (x - MESH_MIN_X) / MESH_X_DIST; + s = (x - (BED_X0 + X_PROBE_OFFSET_FROM_EXTRUDER)) / x_mesh_density; } else { if (i > MESH_NUM_X_POINTS - 2) { i = MESH_NUM_X_POINTS - 2; } - s = (x - get_x(i)) / MESH_X_DIST; + s = (x - get_x(i)) / x_mesh_density; } - j = int(floor((y - MESH_MIN_Y) / MESH_Y_DIST)); + j = int(floor((y - (BED_Y0 + Y_PROBE_OFFSET_FROM_EXTRUDER)) / y_mesh_density)); if (j < 0) { j = 0; - t = (y - MESH_MIN_Y) / MESH_Y_DIST; + t = (y - (BED_Y0 + Y_PROBE_OFFSET_FROM_EXTRUDER)) / y_mesh_density; } else { if (j > MESH_NUM_Y_POINTS - 2) { j = MESH_NUM_Y_POINTS - 2; } - t = (y - get_y(j)) / MESH_Y_DIST; + t = (y - get_y(j)) / y_mesh_density; } float si = 1.f-s; @@ -51,9 +51,9 @@ void mesh_bed_leveling::upsample_3x3() int idx2 = MESH_NUM_X_POINTS - 1; { // First interpolate the points in X axis. - static const float x0 = MESH_MIN_X; - static const float x1 = 0.5f * float(MESH_MIN_X + MESH_MAX_X); - static const float x2 = MESH_MAX_X; + static const float x0 = (BED_X0 + X_PROBE_OFFSET_FROM_EXTRUDER); + static const float x1 = 0.5f * float(BED_X0 + BED_Xn) + X_PROBE_OFFSET_FROM_EXTRUDER; + static const float x2 = BED_Xn + X_PROBE_OFFSET_FROM_EXTRUDER; for (int j = 0; j < MESH_NUM_Y_POINTS; ++ j) { // Interpolate the remaining values by Largrangian polynomials. for (int i = 0; i < MESH_NUM_X_POINTS; ++ i) { @@ -69,9 +69,9 @@ void mesh_bed_leveling::upsample_3x3() } { // Second interpolate the points in Y axis. - static const float y0 = MESH_MIN_Y; - static const float y1 = 0.5f * float(MESH_MIN_Y + MESH_MAX_Y); - static const float y2 = MESH_MAX_Y; + static const float y0 = (BED_Y0 + Y_PROBE_OFFSET_FROM_EXTRUDER); + static const float y1 = 0.5f * float(BED_Y0 + BED_Yn) + Y_PROBE_OFFSET_FROM_EXTRUDER; + static const float y2 = BED_Yn + Y_PROBE_OFFSET_FROM_EXTRUDER; for (int i = 0; i < MESH_NUM_X_POINTS; ++ i) { // Interpolate the remaining values by Largrangian polynomials. for (int j = 1; j + 1 < MESH_NUM_Y_POINTS; ++ j) { diff --git a/Firmware/mesh_bed_leveling.h b/Firmware/mesh_bed_leveling.h index 6c9e6c7c6..7b3313a12 100644 --- a/Firmware/mesh_bed_leveling.h +++ b/Firmware/mesh_bed_leveling.h @@ -1,10 +1,8 @@ #include "Marlin.h" +#include "mesh_bed_calibration.h" #ifdef MESH_BED_LEVELING -#define MESH_X_DIST (float(MESH_MAX_X - MESH_MIN_X)/float(MESH_NUM_X_POINTS - 1)) -#define MESH_Y_DIST (float(MESH_MAX_Y - MESH_MIN_Y)/float(MESH_NUM_Y_POINTS - 1)) - class mesh_bed_leveling { public: uint8_t active; @@ -14,8 +12,8 @@ public: void reset(); - static float get_x(int i) { return float(MESH_MIN_X) + float(MESH_X_DIST) * float(i); } - static float get_y(int i) { return float(MESH_MIN_Y) + float(MESH_Y_DIST) * float(i); } + static float get_x(int i) { return BED_X(i) + X_PROBE_OFFSET_FROM_EXTRUDER; } + static float get_y(int i) { return BED_Y(i) + Y_PROBE_OFFSET_FROM_EXTRUDER; } float get_z(float x, float y); void set_z(uint8_t ix, uint8_t iy, float z) { z_values[iy][ix] = z; } void upsample_3x3(); diff --git a/Firmware/variants/MK25-RAMBo10a.h b/Firmware/variants/MK25-RAMBo10a.h index 099ad329f..81289cbf9 100644 --- a/Firmware/variants/MK25-RAMBo10a.h +++ b/Firmware/variants/MK25-RAMBo10a.h @@ -273,12 +273,6 @@ #define MBL_Z_STEP 0.01 -// Mesh definitions -#define MESH_MIN_X 24 -#define MESH_MAX_X 228 -#define MESH_MIN_Y 6 -#define MESH_MAX_Y 210 - // Mesh upsample definition #define MESH_NUM_X_POINTS 7 #define MESH_NUM_Y_POINTS 7 diff --git a/Firmware/variants/MK25-RAMBo13a.h b/Firmware/variants/MK25-RAMBo13a.h index 7cce101be..ecce19774 100644 --- a/Firmware/variants/MK25-RAMBo13a.h +++ b/Firmware/variants/MK25-RAMBo13a.h @@ -274,12 +274,6 @@ #define MBL_Z_STEP 0.01 -// Mesh definitions -#define MESH_MIN_X 24 -#define MESH_MAX_X 228 -#define MESH_MIN_Y 6 -#define MESH_MAX_Y 210 - // Mesh upsample definition #define MESH_NUM_X_POINTS 7 #define MESH_NUM_Y_POINTS 7 diff --git a/Firmware/variants/MK25S-RAMBo10a.h b/Firmware/variants/MK25S-RAMBo10a.h index 254be0d09..c82be7c5d 100644 --- a/Firmware/variants/MK25S-RAMBo10a.h +++ b/Firmware/variants/MK25S-RAMBo10a.h @@ -273,12 +273,6 @@ #define MBL_Z_STEP 0.01 -// Mesh definitions -#define MESH_MIN_X 24 -#define MESH_MAX_X 228 -#define MESH_MIN_Y 6 -#define MESH_MAX_Y 210 - // Mesh upsample definition #define MESH_NUM_X_POINTS 7 #define MESH_NUM_Y_POINTS 7 diff --git a/Firmware/variants/MK25S-RAMBo13a.h b/Firmware/variants/MK25S-RAMBo13a.h index 2c375f920..a547aa083 100644 --- a/Firmware/variants/MK25S-RAMBo13a.h +++ b/Firmware/variants/MK25S-RAMBo13a.h @@ -274,12 +274,6 @@ #define MBL_Z_STEP 0.01 -// Mesh definitions -#define MESH_MIN_X 24 -#define MESH_MAX_X 228 -#define MESH_MIN_Y 6 -#define MESH_MAX_Y 210 - // Mesh upsample definition #define MESH_NUM_X_POINTS 7 #define MESH_NUM_Y_POINTS 7 diff --git a/Firmware/variants/MK3.h b/Firmware/variants/MK3.h index 78ee31d00..8135d9856 100644 --- a/Firmware/variants/MK3.h +++ b/Firmware/variants/MK3.h @@ -423,12 +423,6 @@ #define MBL_Z_STEP 0.01 -// Mesh definitions -#define MESH_MIN_X 24 -#define MESH_MAX_X 228 -#define MESH_MIN_Y 6 -#define MESH_MAX_Y 210 - // Mesh upsample definition #define MESH_NUM_X_POINTS 7 #define MESH_NUM_Y_POINTS 7 diff --git a/Firmware/variants/MK3S.h b/Firmware/variants/MK3S.h index 111d151c3..6b7513214 100644 --- a/Firmware/variants/MK3S.h +++ b/Firmware/variants/MK3S.h @@ -427,12 +427,6 @@ #define MBL_Z_STEP 0.01 -// Mesh definitions -#define MESH_MIN_X 24 -#define MESH_MAX_X 228 -#define MESH_MIN_Y 6 -#define MESH_MAX_Y 210 - // Mesh upsample definition #define MESH_NUM_X_POINTS 7 #define MESH_NUM_Y_POINTS 7 diff --git a/Firmware/variants/obsolete/1_75mm_MK2-RAMBo10a-E3Dv6full.h b/Firmware/variants/obsolete/1_75mm_MK2-RAMBo10a-E3Dv6full.h index 1700e0fc1..eb3769854 100644 --- a/Firmware/variants/obsolete/1_75mm_MK2-RAMBo10a-E3Dv6full.h +++ b/Firmware/variants/obsolete/1_75mm_MK2-RAMBo10a-E3Dv6full.h @@ -202,12 +202,6 @@ BED SETTINGS #define MBL_Z_STEP 0.01 -// Mesh definitions -#define MESH_MIN_X 35 -#define MESH_MAX_X 238 -#define MESH_MIN_Y 6 -#define MESH_MAX_Y 202 - // Mesh upsample definition #define MESH_NUM_X_POINTS 7 #define MESH_NUM_Y_POINTS 7 diff --git a/Firmware/variants/obsolete/1_75mm_MK2-RAMBo13a-E3Dv6full.h b/Firmware/variants/obsolete/1_75mm_MK2-RAMBo13a-E3Dv6full.h index 2349385e3..dda5f0606 100644 --- a/Firmware/variants/obsolete/1_75mm_MK2-RAMBo13a-E3Dv6full.h +++ b/Firmware/variants/obsolete/1_75mm_MK2-RAMBo13a-E3Dv6full.h @@ -201,12 +201,6 @@ BED SETTINGS #define MBL_Z_STEP 0.01 -// Mesh definitions -#define MESH_MIN_X 35 -#define MESH_MAX_X 238 -#define MESH_MIN_Y 6 -#define MESH_MAX_Y 202 - // Mesh upsample definition #define MESH_NUM_X_POINTS 7 #define MESH_NUM_Y_POINTS 7 From a984b2e609dfef19169a6f006f5f702e799c5ae1 Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Mon, 8 May 2023 08:31:29 +0200 Subject: [PATCH 30/34] G80 `O` parameter a --- Firmware/Marlin_main.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 7a8d0124c..186585638 100644 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -3054,7 +3054,14 @@ static void gcode_G80() } mbl.active = 1; //activate mesh bed leveling - go_home_with_z_lift(); + + if (code_seen('O') && !code_value_uint8()) { + // Don't let the manage_inactivity() function remove power from the motors. + refresh_cmd_timeout(); + } else { + go_home_with_z_lift(); + } + #ifndef PINDA_THERMISTOR //unretract (after PINDA preheat retraction) if (temp_compensation_retracted) { @@ -4852,6 +4859,7 @@ void process_commands() #### Parameters - `N` - Number of mesh points on x axis. Default is 3. Valid values are 3 and 7. - `R` - Probe retries. Default 3 max. 10 + - `O` - Return to origin. Default 1 (true) Using the following parameters enables additional "manual" bed leveling correction. Valid values are -100 microns to 100 microns. #### Additional Parameters From 7740a81edb986403ba855cb8e2c5c9d2bec14d5a Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Thu, 11 May 2023 17:37:40 +0200 Subject: [PATCH 31/34] Do not store a global mbl_z_probe_nr flash: -6 sram: 0? (somehow) --- Firmware/Marlin.h | 1 - Firmware/Marlin_main.cpp | 2 -- Firmware/mesh_bed_calibration.cpp | 2 +- Firmware/ultralcd.cpp | 3 ++- 4 files changed, 3 insertions(+), 5 deletions(-) diff --git a/Firmware/Marlin.h b/Firmware/Marlin.h index 470b55e23..b0c024c0e 100755 --- a/Firmware/Marlin.h +++ b/Firmware/Marlin.h @@ -22,7 +22,6 @@ #include "pins.h" #include "Timer.h" #include "mmu2.h" -extern uint8_t mbl_z_probe_nr; #ifndef AT90USB #define HardwareSerial_h // trick to disable the standard HWserial diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 186585638..d15ab8a8f 100644 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -148,8 +148,6 @@ CardReader card; #endif -uint8_t mbl_z_probe_nr = 3; //numer of Z measurements for each point in mesh bed leveling calibration - //used for PINDA temp calibration and pause print #define DEFAULT_RETRACTION 1 #define DEFAULT_RETRACTION_MM 4 //MM diff --git a/Firmware/mesh_bed_calibration.cpp b/Firmware/mesh_bed_calibration.cpp index ec8b205c3..979e57572 100644 --- a/Firmware/mesh_bed_calibration.cpp +++ b/Firmware/mesh_bed_calibration.cpp @@ -3124,7 +3124,7 @@ void mbl_settings_init() { //magnet elimination: use aaproximate Z-coordinate instead of measured values for points which are near magnets eeprom_init_default_byte((uint8_t*)EEPROM_MBL_MAGNET_ELIMINATION, 1); eeprom_init_default_byte((uint8_t*)EEPROM_MBL_POINTS_NR, 3); - mbl_z_probe_nr = eeprom_init_default_byte((uint8_t*)EEPROM_MBL_PROBE_NR, 3); + eeprom_init_default_byte((uint8_t*)EEPROM_MBL_PROBE_NR, 3); } //parameter ix: index of mesh bed leveling point in X-axis (for meas_points == 7 is valid range from 0 to 6; for meas_points == 3 is valid range from 0 to 2 ) diff --git a/Firmware/ultralcd.cpp b/Firmware/ultralcd.cpp index cf353d4ac..14c8d12ab 100644 --- a/Firmware/ultralcd.cpp +++ b/Firmware/ultralcd.cpp @@ -5457,7 +5457,7 @@ static void mbl_mesh_toggle() { } static void mbl_probe_nr_toggle() { - mbl_z_probe_nr = eeprom_read_byte((uint8_t*)EEPROM_MBL_PROBE_NR); + uint8_t mbl_z_probe_nr = eeprom_read_byte((uint8_t*)EEPROM_MBL_PROBE_NR); switch (mbl_z_probe_nr) { case 1: mbl_z_probe_nr = 3; break; case 3: mbl_z_probe_nr = 5; break; @@ -5472,6 +5472,7 @@ static void lcd_mesh_bed_leveling_settings() bool magnet_elimination = (eeprom_read_byte((uint8_t*)EEPROM_MBL_MAGNET_ELIMINATION) > 0); uint8_t points_nr = eeprom_read_byte((uint8_t*)EEPROM_MBL_POINTS_NR); + uint8_t mbl_z_probe_nr = eeprom_read_byte((uint8_t*)EEPROM_MBL_PROBE_NR); char sToggle[4]; //enough for nxn format MENU_BEGIN(); From f5f09f147c557e9c08329d6ae097844f3c11d020 Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Sat, 13 May 2023 22:03:34 +0200 Subject: [PATCH 32/34] Add a limit to how many times G80 can fail Flash: +80 SRAM: +1 --- Firmware/Marlin_main.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index d15ab8a8f..34de07b70 100644 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -2970,7 +2970,11 @@ static void gcode_G80() current_position[Z_AXIS] = MESH_HOME_Z_SEARCH; plan_buffer_line_curposXYZE(Z_LIFT_FEEDRATE); st_synchronize(); + static uint8_t g80_fail_cnt = 0; if (mesh_point != MESH_NUM_X_POINTS * MESH_NUM_Y_POINTS) { + if (g80_fail_cnt++ >= 2) { + kill(_i("Mesh bed leveling failed. Please run Z calibration")); + } Sound_MakeSound(e_SOUND_TYPE_StandardAlert); bool bState; do { // repeat until Z-leveling o.k. @@ -3005,6 +3009,8 @@ static void gcode_G80() repeatcommand_front(); // re-run (i.e. of "G80") return; } + g80_fail_cnt = 0; // no fail was detected. Reset the error counter. + clean_up_after_endstop_move(l_feedmultiply); #ifndef PINDA_THERMISTOR From 45823e7336831ec4880b1a65272bbd97e7c81ad4 Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Sat, 13 May 2023 22:18:51 +0200 Subject: [PATCH 33/34] Make the G80 Z threshold tighter --- Firmware/Marlin_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 34de07b70..30b627ce5 100644 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -2789,7 +2789,7 @@ static void gcode_G80() { constexpr float XY_AXIS_FEEDRATE = (homing_feedrate[X_AXIS] * 3) / 60; constexpr float Z_LIFT_FEEDRATE = homing_feedrate[Z_AXIS] / 60; - constexpr float Z_CALIBRATION_THRESHOLD = 1.f; + constexpr float Z_CALIBRATION_THRESHOLD = 0.35f; constexpr float MESH_HOME_Z_SEARCH_FAST = 0.35f; st_synchronize(); if (planner_aborted) From ede4cc5d30ffea13acc6b62acb80df256111345e Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Sat, 13 May 2023 22:19:46 +0200 Subject: [PATCH 34/34] Update error messages --- Firmware/Marlin_main.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 30b627ce5..636f9c7a2 100644 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -2947,12 +2947,12 @@ static void gcode_G80() break; } if (MESH_HOME_Z_SEARCH - current_position[Z_AXIS] < 0.1f) { - puts_P(PSTR("Bed leveling failed. Sensor disconnected or cable broken.")); + puts_P(PSTR("Bed leveling failed. Sensor triggered too soon")); break; } } if (has_z && fabs(z0 - current_position[Z_AXIS]) > Z_CALIBRATION_THRESHOLD) { //if we have data from z calibration, max. allowed difference is 1mm for each point - puts_P(PSTR("Bed leveling failed. Sensor triggered too high.")); + puts_P(PSTR("Bed leveling failed. Too much variation from eeprom mesh")); break; } @@ -2973,7 +2973,7 @@ static void gcode_G80() static uint8_t g80_fail_cnt = 0; if (mesh_point != MESH_NUM_X_POINTS * MESH_NUM_Y_POINTS) { if (g80_fail_cnt++ >= 2) { - kill(_i("Mesh bed leveling failed. Please run Z calibration")); + kill(PSTR("Mesh bed leveling failed. Please run Z calibration.")); } Sound_MakeSound(e_SOUND_TYPE_StandardAlert); bool bState;