diff --git a/Marlin/G26_Mesh_Validation_Tool.cpp b/Marlin/G26_Mesh_Validation_Tool.cpp index d605cc70e..ff329bf16 100644 --- a/Marlin/G26_Mesh_Validation_Tool.cpp +++ b/Marlin/G26_Mesh_Validation_Tool.cpp @@ -144,7 +144,7 @@ void un_retract_filament(float where[XYZE]); void retract_filament(float where[XYZE]); - void look_for_lines_to_connect(); + bool look_for_lines_to_connect(); bool parse_G26_parameters(); void move_to(const float&, const float&, const float&, const float&) ; void print_line_from_here_to_there(const float&, const float&, const float&, const float&, const float&, const float&); @@ -249,24 +249,6 @@ } do { - - if (ubl_lcd_clicked()) { // Check if the user wants to stop the Mesh Validation - #if ENABLED(ULTRA_LCD) - lcd_setstatuspgm(PSTR("Mesh Validation Stopped."), 99); - lcd_quick_feedback(); - #endif - while (!ubl_lcd_clicked()) { // Wait until the user is done pressing the - idle(); // Encoder Wheel if that is why we are leaving - lcd_reset_alert_level(); - lcd_setstatuspgm(PSTR("")); - } - while (ubl_lcd_clicked()) { // Wait until the user is done pressing the - idle(); // Encoder Wheel if that is why we are leaving - lcd_setstatuspgm(PSTR("Unpress Wheel"), 99); - } - goto LEAVE; - } - location = continue_with_closest ? find_closest_circle_to_print(current_position[X_AXIS], current_position[Y_AXIS]) : find_closest_circle_to_print(x_pos, y_pos); // Find the closest Mesh Intersection to where we are now. @@ -317,6 +299,27 @@ } for (tmp = start_angle; tmp < end_angle - 0.1; tmp += 30.0) { + + // this sequence to detect an ubl_lcd_clicked() debounce it and leave if it is + // a Press and Hold is repeated in a lot of places (including ubl_G29.cpp). This + // should be redone and compressed. + if (ubl_lcd_clicked()) { // Check if the user wants to stop the Mesh Validation + #if ENABLED(ULTRA_LCD) + lcd_setstatuspgm(PSTR("Mesh Validation Stopped."), 99); + lcd_quick_feedback(); + #endif + while (!ubl_lcd_clicked()) { // Wait until the user is done pressing the + idle(); // Encoder Wheel if that is why we are leaving + lcd_reset_alert_level(); + lcd_setstatuspgm(PSTR("")); + } + while (ubl_lcd_clicked()) { // Wait until the user is done pressing the + idle(); // Encoder Wheel if that is why we are leaving + lcd_setstatuspgm(PSTR("Unpress Wheel"), 99); + } + goto LEAVE; + } + int tmp_div_30 = tmp / 30.0; if (tmp_div_30 < 0) tmp_div_30 += 360 / 30; if (tmp_div_30 > 11) tmp_div_30 -= 360 / 30; @@ -349,14 +352,9 @@ print_line_from_here_to_there(LOGICAL_X_POSITION(x), LOGICAL_Y_POSITION(y), layer_height, LOGICAL_X_POSITION(xe), LOGICAL_Y_POSITION(ye), layer_height); } - - //debug_current_and_destination(PSTR("Looking for lines to connect.")); - look_for_lines_to_connect(); - //debug_current_and_destination(PSTR("Done with line connect.")); + if (look_for_lines_to_connect()) + goto LEAVE; } - - //debug_current_and_destination(PSTR("Done with current circle.")); - } while (--g26_repeats && location.x_index >= 0 && location.y_index >= 0); LEAVE: @@ -432,12 +430,32 @@ return return_val; } - void look_for_lines_to_connect() { + bool look_for_lines_to_connect() { float sx, sy, ex, ey; for (uint8_t i = 0; i < GRID_MAX_POINTS_X; i++) { for (uint8_t j = 0; j < GRID_MAX_POINTS_Y; j++) { + // this sequence to detect an ubl_lcd_clicked() debounce it and leave if it is + // a Press and Hold is repeated in a lot of places (including ubl_G29.cpp). This + // should be redone and compressed. + if (ubl_lcd_clicked()) { // Check if the user wants to stop the Mesh Validation + #if ENABLED(ULTRA_LCD) + lcd_setstatuspgm(PSTR("Mesh Validation Stopped."), 99); + lcd_quick_feedback(); + #endif + while (!ubl_lcd_clicked()) { // Wait until the user is done pressing the + idle(); // Encoder Wheel if that is why we are leaving + lcd_reset_alert_level(); + lcd_setstatuspgm(PSTR("")); + } + while (ubl_lcd_clicked()) { // Wait until the user is done pressing the + idle(); // Encoder Wheel if that is why we are leaving + lcd_setstatuspgm(PSTR("Unpress Wheel"), 99); + } + return true; + } + if (i < GRID_MAX_POINTS_X) { // We can't connect to anything to the right than GRID_MAX_POINTS_X. // This is already a half circle because we are at the edge of the bed. @@ -509,6 +527,7 @@ } } } + return false; } void move_to(const float &x, const float &y, const float &z, const float &e_delta) { @@ -517,11 +536,7 @@ bool has_xy_component = (x != current_position[X_AXIS] || y != current_position[Y_AXIS]); // Check if X or Y is involved in the movement. - //if (ubl.g26_debug_flag) SERIAL_ECHOLNPAIR("in move_to() has_xy_component:", (int)has_xy_component); - if (z != last_z) { - //if (ubl.g26_debug_flag) SERIAL_ECHOLNPAIR("in move_to() changing Z to ", (int)z); - last_z = z; feed_value = planner.max_feedrate_mm_s[Z_AXIS]/(3.0); // Base the feed rate off of the configured Z_AXIS feed rate @@ -534,8 +549,6 @@ stepper.synchronize(); set_destination_to_current(); - - //if (ubl.g26_debug_flag) debug_current_and_destination(PSTR(" in move_to() done with Z move")); } // Check if X or Y is involved in the movement. @@ -548,12 +561,8 @@ destination[Y_AXIS] = y; destination[E_AXIS] += e_delta; - //if (ubl.g26_debug_flag) debug_current_and_destination(PSTR(" in move_to() doing last move")); - G26_line_to_destination(feed_value); - //if (ubl.g26_debug_flag) debug_current_and_destination(PSTR(" in move_to() after last move")); - stepper.synchronize(); set_destination_to_current(); @@ -562,9 +571,7 @@ void retract_filament(float where[XYZE]) { if (!g26_retracted) { // Only retract if we are not already retracted! g26_retracted = true; - //if (ubl.g26_debug_flag) SERIAL_ECHOLNPGM(" Decided to do retract."); move_to(where[X_AXIS], where[Y_AXIS], where[Z_AXIS], -1.0 * retraction_multiplier); - //if (ubl.g26_debug_flag) SERIAL_ECHOLNPGM(" Retraction done."); } } @@ -572,7 +579,6 @@ if (g26_retracted) { // Only un-retract if we are retracted. move_to(where[X_AXIS], where[Y_AXIS], where[Z_AXIS], 1.2 * retraction_multiplier); g26_retracted = false; - //if (ubl.g26_debug_flag) SERIAL_ECHOLNPGM(" unretract done."); } } @@ -605,7 +611,6 @@ // If the end point of the line is closer to the nozzle, flip the direction, // moving from the end to the start. On very small lines the optimization isn't worth it. if (dist_end < dist_start && (SIZE_OF_INTERSECTION_CIRCLES) < abs(line_length)) { - //if (ubl.g26_debug_flag) SERIAL_ECHOLNPGM(" Reversing start and end of print_line_from_here_to_there()"); return print_line_from_here_to_there(ex, ey, ez, sx, sy, sz); } @@ -613,9 +618,6 @@ if (dist_start > 2.0) { retract_filament(destination); - //if (ubl.g26_debug_flag) SERIAL_ECHOLNPGM(" filament retracted."); - - //if (ubl.g26_debug_flag) SERIAL_ECHOLNPGM(" Z bumping by 0.500 to minimize scraping."); //todo: parameterize the bump height with a define move_to(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS] + 0.500, 0.0); // Z bump to minimize scraping move_to(sx, sy, sz + 0.500, 0.0); // Get to the starting point with no extrusion while bumped @@ -626,11 +628,6 @@ const float e_pos_delta = line_length * g26_e_axis_feedrate * extrusion_multiplier; un_retract_filament(destination); - - //if (ubl.g26_debug_flag) { - // SERIAL_ECHOLNPGM(" doing printing move."); - // debug_current_and_destination(PSTR("doing final move_to() inside print_line_from_here_to_there()")); - //} move_to(ex, ey, ez, e_pos_delta); // Get to the ending point with an appropriate amount of extrusion } @@ -754,7 +751,6 @@ } bool exit_from_g26() { - //strcpy(lcd_status_message, "Leaving G26"); // We can't do lcd_setstatus() without having it continue; lcd_reset_alert_level(); lcd_setstatuspgm(PSTR("Leaving G26")); while (ubl_lcd_clicked()) idle(); diff --git a/Marlin/SanityCheck.h b/Marlin/SanityCheck.h index cc466b233..952200d14 100644 --- a/Marlin/SanityCheck.h +++ b/Marlin/SanityCheck.h @@ -160,6 +160,8 @@ #error "UBL_MESH_EDIT_ENABLED is now UBL_G26_MESH_VALIDATION. Please update your configuration." #elif defined(UBL_MESH_EDITING) #error "UBL_MESH_EDITING is now UBL_G26_MESH_VALIDATION. Please update your configuration." +#elif defined(BLTOUCH_HEATERS_OFF) + #error "BLTOUCH_HEATERS_OFF is now PROBING_HEATERS_OFF. Please update your configuration." #elif defined(BEEPER) #error "BEEPER is now BEEPER_PIN. Please update your pins definitions." #elif defined(SDCARDDETECT) diff --git a/Marlin/thermistortables.h b/Marlin/thermistortables.h index 3777cf2e4..164afa5ea 100644 --- a/Marlin/thermistortables.h +++ b/Marlin/thermistortables.h @@ -89,7 +89,7 @@ #include "thermistortable_52.h" #endif #if ANY_THERMISTOR_IS(55) // 100k ATC Semitec 104GT-2 (Used on ParCan) (WITH 1kohm RESISTOR FOR PULLUP, R9 ON SANGUINOLOLU! NOT FOR 4.7kohm PULLUP! THIS IS NOT NORMAL!) - #include "thermistortable_53.h" + #include "thermistortable_55.h" #endif #if ANY_THERMISTOR_IS(60) // Maker's Tool Works Kapton Bed Thermistor #include "thermistortable_60.h" diff --git a/Marlin/ubl.cpp b/Marlin/ubl.cpp index 8ca43c5be..8e6190953 100644 --- a/Marlin/ubl.cpp +++ b/Marlin/ubl.cpp @@ -29,6 +29,8 @@ #include "hex_print_routines.h" #include "temperature.h" + extern Planner planner; + /** * These support functions allow the use of large bit arrays of flags that take very * little RAM. Currently they are limited to being 16x16 in size. Changing the declaration @@ -76,7 +78,7 @@ volatile int unified_bed_leveling::encoder_diff; unified_bed_leveling::unified_bed_leveling() { - ubl_cnt++; // Debug counter to insure we only have one UBL object present in memory. + ubl_cnt++; // Debug counter to insure we only have one UBL object present in memory. We can eliminate this (and all references to ubl_cnt) very soon. reset(); } @@ -84,9 +86,10 @@ state.active = false; state.z_offset = 0; state.storage_slot = -1; - + #if ENABLED(ENABLE_LEVELING_FADE_HEIGHT) + planner.z_fade_height = 10.0; + #endif ZERO(z_values); - last_specified_z = -999.9; } @@ -100,7 +103,7 @@ void unified_bed_leveling::display_map(const int map_type) { const bool map0 = map_type == 0; - constexpr uint8_t spaces = 9 * (GRID_MAX_POINTS_X - 2); + constexpr uint8_t spaces = 8 * (GRID_MAX_POINTS_X - 2); if (map0) { SERIAL_PROTOCOLLNPGM("\nBed Topography Report:\n"); @@ -126,7 +129,7 @@ const float f = z_values[i][j]; if (isnan(f)) { - serialprintPGM(map0 ? PSTR(" . ") : PSTR("NAN")); + serialprintPGM(map0 ? PSTR(" . ") : PSTR("NAN")); } else { // if we don't do this, the columns won't line up nicely diff --git a/Marlin/ubl_G29.cpp b/Marlin/ubl_G29.cpp index b8b992baa..1b718dd64 100644 --- a/Marlin/ubl_G29.cpp +++ b/Marlin/ubl_G29.cpp @@ -1009,6 +1009,9 @@ } } + // this sequence to detect an ubl_lcd_clicked() debounce it and leave if it is + // a Press and Hold is repeated in a lot of places (including G26_Mesh_Validation.cpp). This + // should be redone and compressed. const millis_t nxt = millis() + 1500L; while (ubl_lcd_clicked()) { // debounce and watch for abort idle(); @@ -1327,10 +1330,9 @@ // Get our reference position. Either the nozzle or probe location. const float px = RAW_X_POSITION(lx) - (probe_as_reference == USE_PROBE_AS_REFERENCE ? X_PROBE_OFFSET_FROM_EXTRUDER : 0), - py = RAW_Y_POSITION(ly) - (probe_as_reference == USE_PROBE_AS_REFERENCE ? Y_PROBE_OFFSET_FROM_EXTRUDER : 0), - raw_x = RAW_CURRENT_POSITION(X), raw_y = RAW_CURRENT_POSITION(Y); + py = RAW_Y_POSITION(ly) - (probe_as_reference == USE_PROBE_AS_REFERENCE ? Y_PROBE_OFFSET_FROM_EXTRUDER : 0); - float closest = far_flag ? -99999.99 : 99999.99; + float best_so_far = far_flag ? -99999.99 : 99999.99; for (uint8_t i = 0; i < GRID_MAX_POINTS_X; i++) { for (uint8_t j = 0; j < GRID_MAX_POINTS_Y; j++) { @@ -1339,10 +1341,10 @@ || (type == REAL && !isnan(ubl.z_values[i][j])) || (type == SET_IN_BITMAP && is_bit_set(bits, i, j)) ) { - // We only get here if we found a Mesh Point of the specified type - const float mx = pgm_read_float(&ubl.mesh_index_to_xpos[i]), // Check if we can probe this mesh location + float raw_x = RAW_CURRENT_POSITION(X), raw_y = RAW_CURRENT_POSITION(Y); + const float mx = pgm_read_float(&ubl.mesh_index_to_xpos[i]), my = pgm_read_float(&ubl.mesh_index_to_ypos[j]); // If using the probe as the reference there are some unreachable locations. @@ -1352,10 +1354,10 @@ if (probe_as_reference ? !position_is_reachable_by_probe_raw_xy(mx, my) : !position_is_reachable_raw_xy(mx, my)) continue; - // Reachable. Check if it's the closest location to the nozzle. + // Reachable. Check if it's the best_so_far location to the nozzle. // Add in a weighting factor that considers the current location of the nozzle. - float distance = HYPOT(px - mx, py - my) + HYPOT(raw_x - mx, raw_y - my) * 0.1; + float distance = HYPOT(px - mx, py - my); /** * If doing the far_flag action, we want to be as far as possible @@ -1367,20 +1369,24 @@ if (far_flag) { for (uint8_t k = 0; k < GRID_MAX_POINTS_X; k++) { for (uint8_t l = 0; l < GRID_MAX_POINTS_Y; l++) { - if (!isnan(ubl.z_values[k][l])) { - distance += sq(i - k) * (MESH_X_DIST) * .05 - + sq(j - l) * (MESH_Y_DIST) * .05; + if (i != k && j != l && !isnan(ubl.z_values[k][l])) { +// distance += pow((float) abs(i - k) * (MESH_X_DIST), 2) + pow((float) abs(j - l) * (MESH_Y_DIST), 2); // working here + distance += HYPOT((MESH_X_DIST),(MESH_Y_DIST)) / log(HYPOT((i - k) * (MESH_X_DIST)+.001, (j - l) * (MESH_Y_DIST))+.001); } } } } + else + // factor in the distance from the current location for the normal case + // so the nozzle isn't running all over the bed. + distance += HYPOT(raw_x - mx, raw_y - my) * 0.1; // if far_flag, look for farthest point - if (far_flag == (distance > closest) && distance != closest) { - closest = distance; // We found a closer/farther location with + if (far_flag == (distance > best_so_far) && distance != best_so_far) { + best_so_far = distance; // We found a closer/farther location with out_mesh.x_index = i; // the specified type of mesh value. out_mesh.y_index = j; - out_mesh.distance = closest; + out_mesh.distance = best_so_far; } } } // for j @@ -1408,7 +1414,7 @@ LCD_MESSAGEPGM("Fine Tuning Mesh"); // TODO: Make translatable string - do_blocking_move_to_z(Z_CLEARANCE_DEPLOY_PROBE); + do_blocking_move_to_z(Z_CLEARANCE_BETWEEN_PROBES); do_blocking_move_to_xy(lx, ly); do { location = find_closest_mesh_point_of_type(SET_IN_BITMAP, lx, ly, USE_NOZZLE_AS_REFERENCE, not_done, false); @@ -1426,42 +1432,48 @@ float new_z = ubl.z_values[location.x_index][location.y_index]; - if (!isnan(new_z)) { //can't fine tune a point that hasn't been probed + if (isnan(new_z)) // if the mesh point is invalid, set it to 0.0 so it can be edited + new_z = 0.0; - do_blocking_move_to_z(Z_CLEARANCE_DEPLOY_PROBE); // Move the nozzle to where we are going to edit - do_blocking_move_to_xy(LOGICAL_X_POSITION(rawx), LOGICAL_Y_POSITION(rawy)); + do_blocking_move_to_z(Z_CLEARANCE_BETWEEN_PROBES); // Move the nozzle to where we are going to edit + do_blocking_move_to_xy(LOGICAL_X_POSITION(rawx), LOGICAL_Y_POSITION(rawy)); - new_z = floor(new_z * 1000.0) * 0.001; // Chop off digits after the 1000ths place + new_z = floor(new_z * 1000.0) * 0.001; // Chop off digits after the 1000ths place - KEEPALIVE_STATE(PAUSED_FOR_USER); - ubl.has_control_of_lcd_panel = true; + KEEPALIVE_STATE(PAUSED_FOR_USER); + ubl.has_control_of_lcd_panel = true; - if (do_ubl_mesh_map) ubl.display_map(map_type); // show the user which point is being adjusted + if (do_ubl_mesh_map) ubl.display_map(map_type); // show the user which point is being adjusted - lcd_implementation_clear(); + lcd_implementation_clear(); - lcd_mesh_edit_setup(new_z); + lcd_mesh_edit_setup(new_z); - do { - new_z = lcd_mesh_edit(); - idle(); - } while (!ubl_lcd_clicked()); + do { + new_z = lcd_mesh_edit(); + #ifdef UBL_MESH_EDIT_MOVES_Z + do_blocking_move_to_z(Z_CLEARANCE_BETWEEN_PROBES+new_z); // Move the nozzle as the point is edited + #endif + idle(); + } while (!ubl_lcd_clicked()); - lcd_return_to_status(); + lcd_return_to_status(); - // The technique used here generates a race condition for the encoder click. - // It could get detected in lcd_mesh_edit (actually _lcd_mesh_fine_tune) or here. - // Let's work on specifying a proper API for the LCD ASAP, OK? - ubl.has_control_of_lcd_panel = true; - } + // The technique used here generates a race condition for the encoder click. + // It could get detected in lcd_mesh_edit (actually _lcd_mesh_fine_tune) or here. + // Let's work on specifying a proper API for the LCD ASAP, OK? + ubl.has_control_of_lcd_panel = true; + // this sequence to detect an ubl_lcd_clicked() debounce it and leave if it is + // a Press and Hold is repeated in a lot of places (including G26_Mesh_Validation.cpp). This + // should be redone and compressed. const millis_t nxt = millis() + 1500UL; while (ubl_lcd_clicked()) { // debounce and watch for abort idle(); if (ELAPSED(millis(), nxt)) { lcd_return_to_status(); //SERIAL_PROTOCOLLNPGM("\nFine Tuning of Mesh Stopped."); - do_blocking_move_to_z(Z_CLEARANCE_DEPLOY_PROBE); + do_blocking_move_to_z(Z_CLEARANCE_BETWEEN_PROBES); LCD_MESSAGEPGM("Mesh Editing Stopped"); // TODO: Make translatable string while (ubl_lcd_clicked()) idle(); @@ -1485,7 +1497,7 @@ if (do_ubl_mesh_map) ubl.display_map(map_type); ubl.restore_ubl_active_state_and_leave(); - do_blocking_move_to_z(Z_CLEARANCE_DEPLOY_PROBE); + do_blocking_move_to_z(Z_CLEARANCE_BETWEEN_PROBES); do_blocking_move_to_xy(lx, ly); diff --git a/Marlin/ultralcd.cpp b/Marlin/ultralcd.cpp index 7edbdc519..894c6276f 100644 --- a/Marlin/ultralcd.cpp +++ b/Marlin/ultralcd.cpp @@ -958,11 +958,13 @@ void kill_screen(const char* lcd_msg) { } void _lcd_mesh_edit() { + lcdDrawUpdate = LCDVIEW_REDRAW_NOW; _lcd_mesh_fine_tune(PSTR("Mesh Editor")); } float lcd_mesh_edit() { lcd_goto_screen(_lcd_mesh_edit_NOP); + lcdDrawUpdate = LCDVIEW_REDRAW_NOW; _lcd_mesh_fine_tune(PSTR("Mesh Editor")); return mesh_edit_value; }