diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 0ce37a2384..68784df5d7 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -1725,7 +1725,7 @@ //#define Z_CLEARANCE_FOR_HOMING 4 // (mm) Minimal Z height before homing (G28) for Z clearance above the bed, clamps, ... // Be sure to have this much clearance over your Z_MAX_POS to prevent grinding. -//#define Z_AFTER_HOMING 10 // (mm) Height to move to after homing Z +//#define Z_AFTER_HOMING 10 // (mm) Height to move to after homing (if Z was homed) // Direction of endstops when homing; 1=MAX, -1=MIN // :[-1,1] diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index cd19393551..f712a6921a 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -924,7 +924,7 @@ //#define QUICK_HOME // If G28 contains XY do a diagonal move first //#define HOME_Y_BEFORE_X // If G28 contains XY home Y before X -//#define HOME_Z_FIRST // Home Z first. Requires a Z-MIN endstop (not a probe). +//#define HOME_Z_FIRST // Home Z first. Requires a real endstop (not a probe). //#define CODEPENDENT_XY_HOMING // If X/Y can't home without homing Y/X first // @section bltouch diff --git a/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp b/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp index 7277b293aa..2fbd3bfbeb 100644 --- a/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp +++ b/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp @@ -112,7 +112,7 @@ * If omitted, the nozzle will raise by Z_CLEARANCE_BETWEEN_PROBES. * * H # Offset With P4, 'H' specifies the Offset above the mesh height to place the nozzle. - * If omitted, Z_CLEARANCE_BETWEEN_PROBES will be used. + * If omitted, Z_TWEEN_SAFE_CLEARANCE will be used. * * I # Invalidate Invalidate the specified number of Mesh Points near the given 'X' 'Y'. If X or Y are omitted, * the nozzle location is used. If no 'I' value is given, only the point nearest to the location @@ -790,10 +790,7 @@ void unified_bed_leveling::shift_mesh_height() { if (best.pos.x >= 0) { // mesh point found and is reachable by probe TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(best.pos, ExtUI::G29_POINT_START)); - const float measured_z = probe.probe_at_point( - best.meshpos(), - stow_probe ? PROBE_PT_STOW : PROBE_PT_RAISE, param.V_verbosity - ); + const float measured_z = probe.probe_at_point(best.meshpos(), stow_probe ? PROBE_PT_STOW : PROBE_PT_RAISE, param.V_verbosity); z_values[best.pos.x][best.pos.y] = measured_z; #if ENABLED(EXTENSIBLE_UI) ExtUI::onMeshUpdate(best.pos, ExtUI::G29_POINT_FINISH); @@ -1034,9 +1031,9 @@ void set_message_with_feedback(FSTR_P const fstr) { save_ubl_active_state_and_disable(); LCD_MESSAGE(MSG_UBL_FINE_TUNE_MESH); - ui.capture(); // Take over control of the LCD encoder + ui.capture(); // Take over control of the LCD encoder - do_blocking_move_to_xy_z(pos, Z_CLEARANCE_BETWEEN_PROBES); // Move to the given XY with probe clearance + do_blocking_move_to_xy_z(pos, Z_TWEEN_SAFE_CLEARANCE); // Move to the given XY with probe clearance MeshFlags done_flags{0}; const xy_int8_t &lpos = location.pos; @@ -1053,7 +1050,7 @@ void set_message_with_feedback(FSTR_P const fstr) { done_flags.mark(lpos); // Mark this location as 'adjusted' so a new // location is used on the next loop - const xyz_pos_t raw = { get_mesh_x(lpos.x), get_mesh_y(lpos.y), Z_CLEARANCE_BETWEEN_PROBES }; + const xyz_pos_t raw = { get_mesh_x(lpos.x), get_mesh_y(lpos.y), Z_TWEEN_SAFE_CLEARANCE }; if (!position_is_reachable(raw)) break; // SHOULD NOT OCCUR (find_closest_mesh_point_of_type only returns reachable) @@ -1063,7 +1060,7 @@ void set_message_with_feedback(FSTR_P const fstr) { KEEPALIVE_STATE(PAUSED_FOR_USER); - if (do_ubl_mesh_map) display_map(param.T_map_type); // Display the current point + if (do_ubl_mesh_map) display_map(param.T_map_type); // Display the current point #if IS_TFTGLCD_PANEL ui.ubl_plot(lpos.x, lpos.y); // update plot screen @@ -1093,7 +1090,7 @@ void set_message_with_feedback(FSTR_P const fstr) { // Button held down? Abort editing if (_click_and_hold([]{ ui.return_to_status(); - do_z_clearance(Z_CLEARANCE_BETWEEN_PROBES); + do_z_clearance(Z_TWEEN_SAFE_CLEARANCE); set_message_with_feedback(GET_TEXT_F(MSG_EDITING_STOPPED)); })) break; @@ -1113,7 +1110,7 @@ void set_message_with_feedback(FSTR_P const fstr) { if (do_ubl_mesh_map) display_map(param.T_map_type); restore_ubl_active_state_and_leave(); - do_blocking_move_to_xy_z(pos, Z_CLEARANCE_BETWEEN_PROBES); + do_blocking_move_to_xy_z(pos, Z_TWEEN_SAFE_CLEARANCE); LCD_MESSAGE(MSG_UBL_DONE_EDITING_MESH); SERIAL_ECHOLNPGM("Done Editing Mesh"); diff --git a/Marlin/src/gcode/bedlevel/G35.cpp b/Marlin/src/gcode/bedlevel/G35.cpp index 27c57cf62e..f5f395ee2e 100644 --- a/Marlin/src/gcode/bedlevel/G35.cpp +++ b/Marlin/src/gcode/bedlevel/G35.cpp @@ -98,7 +98,7 @@ void GcodeSuite::G35() { // Probe all positions LOOP_L_N(i, G35_PROBE_COUNT) { - const float z_probed_height = probe.probe_at_point(tramming_points[i], PROBE_PT_RAISE, 0, true); + const float z_probed_height = probe.probe_at_point(tramming_points[i], PROBE_PT_RAISE); if (isnan(z_probed_height)) { SERIAL_ECHOPGM("G35 failed at point ", i + 1, " ("); SERIAL_ECHOPGM_P((char *)pgm_read_ptr(&tramming_point_name[i])); diff --git a/Marlin/src/gcode/calibrate/G28.cpp b/Marlin/src/gcode/calibrate/G28.cpp index 782761ee14..ed2cda2932 100644 --- a/Marlin/src/gcode/calibrate/G28.cpp +++ b/Marlin/src/gcode/calibrate/G28.cpp @@ -356,6 +356,8 @@ void GcodeSuite::G28() { endstops.enable(true); // Enable endstops for next homing move + bool finalRaiseZ = false; + #if ENABLED(DELTA) constexpr bool doZ = true; // for NANODLP_Z_SYNC if your DLP is on a DELTA @@ -407,8 +409,9 @@ void GcodeSuite::G28() { UNUSED(needZ); UNUSED(homeZZ); - // Z may home first, e.g., when homing away from the bed - TERN_(HOME_Z_FIRST, if (doZ) homeaxis(Z_AXIS)); + // Z may home first, e.g., when homing away from the bed. + // This is also permitted when homing with a Z endstop. + if (TERN0(HOME_Z_FIRST, doZ)) homeaxis(Z_AXIS); // 'R' to specify a specific raise. 'R0' indicates no raise, e.g., for recovery.resume // When 'R0' is used, there should already be adequate clearance, e.g., from homing Z to max. @@ -517,7 +520,10 @@ void GcodeSuite::G28() { #else homeaxis(Z_AXIS); #endif - do_move_after_z_homing(); + + #if EITHER(Z_HOME_TO_MIN, ALLOW_Z_AFTER_HOMING) + finalRaiseZ = true; + #endif } #endif @@ -575,18 +581,6 @@ void GcodeSuite::G28() { // Clear endstop state for polled stallGuard endstops TERN_(SPI_ENDSTOPS, endstops.clear_endstop_state()); - // Move to a height where we can use the full xy-area - TERN_(DELTA_HOME_TO_SAFE_ZONE, do_blocking_move_to_z(delta_clip_start_height)); - - TERN_(CAN_SET_LEVELING_AFTER_G28, if (leveling_restore_state) set_bed_leveling_enabled()); - - restore_feedrate_and_scaling(); - - // Restore the active tool after homing - #if HAS_MULTI_HOTEND && (DISABLED(DELTA) || ENABLED(DELTA_HOME_TO_SAFE_ZONE)) - tool_change(old_tool_index, TERN(PARKING_EXTRUDER, !pe_final_change_must_unpark, DISABLED(DUAL_X_CARRIAGE))); // Do move if one of these - #endif - #if HAS_HOMING_CURRENT if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Restore driver current..."); #if HAS_CURRENT_HOME(X) @@ -627,6 +621,23 @@ void GcodeSuite::G28() { #endif #endif // HAS_HOMING_CURRENT + // Move to a height where we can use the full xy-area + TERN_(DELTA_HOME_TO_SAFE_ZONE, do_blocking_move_to_z(delta_clip_start_height)); + + // Move to the configured Z only if Z was homed to MIN, because machines that + // home to MAX historically expect 'G28 Z' to be safe to use at the end of a + // print, and do_move_after_z_homing is not very nuanced. + if (finalRaiseZ) do_move_after_z_homing(); + + TERN_(CAN_SET_LEVELING_AFTER_G28, if (leveling_restore_state) set_bed_leveling_enabled()); + + // Restore the active tool after homing + #if HAS_MULTI_HOTEND && (DISABLED(DELTA) || ENABLED(DELTA_HOME_TO_SAFE_ZONE)) + tool_change(old_tool_index, TERN(PARKING_EXTRUDER, !pe_final_change_must_unpark, DISABLED(DUAL_X_CARRIAGE))); // Do move if one of these + #endif + + restore_feedrate_and_scaling(); + ui.refresh(); TERN_(HAS_DWIN_E3V2_BASIC, DWIN_HomingDone()); diff --git a/Marlin/src/gcode/calibrate/G33.cpp b/Marlin/src/gcode/calibrate/G33.cpp index 61320c0576..08734073d6 100644 --- a/Marlin/src/gcode/calibrate/G33.cpp +++ b/Marlin/src/gcode/calibrate/G33.cpp @@ -170,7 +170,7 @@ static float std_dev_points(float z_pt[NPP + 1], const bool _0p_cal, const bool */ static float calibration_probe(const xy_pos_t &xy, const bool stow, const bool probe_at_offset) { #if HAS_BED_PROBE - return probe.probe_at_point(xy, stow ? PROBE_PT_STOW : PROBE_PT_RAISE, 0, probe_at_offset, false); + return probe.probe_at_point(xy, stow ? PROBE_PT_STOW : PROBE_PT_RAISE, 0, probe_at_offset, false, Z_PROBE_LOW_POINT, Z_TWEEN_SAFE_CLEARANCE, true); #else UNUSED(stow); return lcd_probe_pt(xy); diff --git a/Marlin/src/gcode/calibrate/G34_M422.cpp b/Marlin/src/gcode/calibrate/G34_M422.cpp index db6ef874d9..3e7ed08b6c 100644 --- a/Marlin/src/gcode/calibrate/G34_M422.cpp +++ b/Marlin/src/gcode/calibrate/G34_M422.cpp @@ -153,7 +153,8 @@ void GcodeSuite::G34() { const xy_pos_t diff = z_stepper_align.xy[i] - z_stepper_align.xy[j]; return HYPOT2(diff.x, diff.y); }; - float z_probe = (Z_PROBE_SAFE_CLEARANCE) + (G34_MAX_GRADE) * 0.01f * SQRT(_MAX(0, magnitude2(0, 1) + const float zoffs = (probe.offset.z < 0) ? -probe.offset.z : 0.0f; + float z_probe = (Z_TWEEN_SAFE_CLEARANCE + zoffs) + (G34_MAX_GRADE) * 0.01f * SQRT(_MAX(0, magnitude2(0, 1) #if TRIPLE_Z , magnitude2(2, 1), magnitude2(2, 0) #if QUAD_Z @@ -165,12 +166,6 @@ void GcodeSuite::G34() { // Home before the alignment procedure home_if_needed(); - // Move the Z coordinate realm towards the positive - dirty trick - current_position.z += z_probe * 0.5f; - sync_plan_position(); - // Now, the Z origin lies below the build plate. That allows to probe deeper, before run_z_probe throws an error. - // This hack is un-done at the end of G34 - either by re-homing, or by using the probed heights of the last iteration. - #if !HAS_Z_STEPPER_ALIGN_STEPPER_XY float last_z_align_move[NUM_Z_STEPPERS] = ARRAY_N_1(NUM_Z_STEPPERS, 10000.0f); #else @@ -213,20 +208,16 @@ void GcodeSuite::G34() { // iteration odd/even --> downward / upward stepper sequence const uint8_t iprobe = (iteration & 1) ? NUM_Z_STEPPERS - 1 - i : i; - // Safe clearance even on an incline - if ((iteration == 0 || i > 0) && z_probe > current_position.z) do_blocking_move_to_z(z_probe); - xy_pos_t &ppos = z_stepper_align.xy[iprobe]; - if (DEBUGGING(LEVELING)) - DEBUG_ECHOLNPGM_P(PSTR("Probing X"), ppos.x, SP_Y_STR, ppos.y); + if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM_P(PSTR("Probing X"), ppos.x, SP_Y_STR, ppos.y); // Probe a Z height for each stepper. // Probing sanity check is disabled, as it would trigger even in normal cases because // current_position.z has been manually altered in the "dirty trick" above. - const float z_probed_height = probe.probe_at_point(DIFF_TERN(HAS_HOME_OFFSET, ppos, xy_pos_t(home_offset)), raise_after, 0, true, false); + const float z_probed_height = probe.probe_at_point(DIFF_TERN(HAS_HOME_OFFSET, ppos, xy_pos_t(home_offset)), raise_after, 0, true, false, (Z_PROBE_LOW_POINT) - z_probe * 0.5f, z_probe * 0.5f); if (isnan(z_probed_height)) { - SERIAL_ECHOLNPGM("Probing failed"); + SERIAL_ECHOLNPGM(STR_ERR_PROBING_FAILED); LCD_MESSAGE(MSG_LCD_PROBING_FAILED); err_break = true; break; @@ -234,7 +225,7 @@ void GcodeSuite::G34() { // Add height to each value, to provide a more useful target height for // the next iteration of probing. This allows adjustments to be made away from the bed. - z_measured[iprobe] = z_probed_height + (Z_CLEARANCE_BETWEEN_PROBES); + z_measured[iprobe] = z_probed_height + (Z_TWEEN_SAFE_CLEARANCE + zoffs); //do we need to add the clearance to this? if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("> Z", iprobe + 1, " measured position is ", z_measured[iprobe]); @@ -248,7 +239,7 @@ void GcodeSuite::G34() { // Adapt the next probe clearance height based on the new measurements. // Safe_height = lowest distance to bed (= highest measurement) plus highest measured misalignment. z_maxdiff = z_measured_max - z_measured_min; - z_probe = (Z_PROBE_SAFE_CLEARANCE) + z_measured_max + z_maxdiff; + z_probe = (Z_TWEEN_SAFE_CLEARANCE + zoffs) + z_measured_max + z_maxdiff; //Not sure we need z_maxdiff, but leaving it in for safety. #if HAS_Z_STEPPER_ALIGN_STEPPER_XY // Replace the initial values in z_measured with calculated heights at @@ -428,15 +419,13 @@ void GcodeSuite::G34() { IF_DISABLED(TOUCH_MI_PROBE, probe.stow()); #if ENABLED(HOME_AFTER_G34) - // After this operation the z position needs correction - set_axis_never_homed(Z_AXIS); // Home Z after the alignment procedure process_subcommands_now(F("G28Z")); #else // Use the probed height from the last iteration to determine the Z height. // z_measured_min is used, because all steppers are aligned to z_measured_min. // Ideally, this would be equal to the 'z_probe * 0.5f' which was added earlier. - current_position.z -= z_measured_min - float(Z_CLEARANCE_BETWEEN_PROBES); + current_position.z -= z_measured_min - (Z_TWEEN_SAFE_CLEARANCE + zoffs); //we shouldn't want to subtract the clearance from here right? (Depends if we added it further up) sync_plan_position(); #endif diff --git a/Marlin/src/gcode/calibrate/M48.cpp b/Marlin/src/gcode/calibrate/M48.cpp index 5e0c21b42e..701e938697 100644 --- a/Marlin/src/gcode/calibrate/M48.cpp +++ b/Marlin/src/gcode/calibrate/M48.cpp @@ -223,7 +223,7 @@ void GcodeSuite::M48() { } // n_legs // Probe a single point - const float pz = probe.probe_at_point(test_position, raise_after, 0); + const float pz = probe.probe_at_point(test_position, raise_after); // Break the loop if the probe fails probing_good = !isnan(pz); diff --git a/Marlin/src/gcode/probe/G30.cpp b/Marlin/src/gcode/probe/G30.cpp index 468189bf5a..8e64ba7cca 100644 --- a/Marlin/src/gcode/probe/G30.cpp +++ b/Marlin/src/gcode/probe/G30.cpp @@ -77,7 +77,7 @@ void GcodeSuite::G30() { const ProbePtRaise raise_after = parser.boolval('E', true) ? PROBE_PT_STOW : PROBE_PT_NONE; TERN_(HAS_PTC, ptc.set_enabled(!parser.seen('C') || parser.value_bool())); - const float measured_z = probe.probe_at_point(probepos, raise_after, 1); + const float measured_z = probe.probe_at_point(probepos, raise_after); TERN_(HAS_PTC, ptc.set_enabled(true)); if (!isnan(measured_z)) { SERIAL_ECHOLNPGM("Bed X: ", probepos.asLogical().x, " Y: ", probepos.asLogical().y, " Z: ", measured_z); diff --git a/Marlin/src/inc/SanityCheck.h b/Marlin/src/inc/SanityCheck.h index d4f9423080..687ef28a37 100644 --- a/Marlin/src/inc/SanityCheck.h +++ b/Marlin/src/inc/SanityCheck.h @@ -2350,6 +2350,10 @@ static_assert(COUNT(arm) == LOGICAL_AXES, "AXIS_RELATIVE_MODES must contain " _L #error "HOME_Z_FIRST can't be used when homing Z with a probe." #endif +#if Z_HOME_TO_MAX && defined(Z_AFTER_HOMING) && DISABLED(ALLOW_Z_AFTER_HOMING) + #error "Z_AFTER_HOMING shouldn't be used with Z max homing to keep 'G28 Z' safe for end-of-print usage. Define ALLOW_Z_AFTER_HOMING to allow this at your own risk." +#endif + // Dual/multiple endstops requirements #if ENABLED(X_DUAL_ENDSTOPS) #if ENABLED(DELTA) diff --git a/Marlin/src/lcd/e3v2/jyersui/dwin.cpp b/Marlin/src/lcd/e3v2/jyersui/dwin.cpp index e685fe16fd..c4098bdb49 100644 --- a/Marlin/src/lcd/e3v2/jyersui/dwin.cpp +++ b/Marlin/src/lcd/e3v2/jyersui/dwin.cpp @@ -1409,6 +1409,13 @@ void CrealityDWINClass::Menu_Item_Handler(const uint8_t menu, const uint8_t item static float mlev_z_pos = 0; static bool use_probe = false; + #if HAS_BED_PROBE + constexpr float probe_x_min = _MAX(0 + corner_pos, X_MIN_POS + probe.offset.x, X_MIN_POS + PROBING_MARGIN) - probe.offset.x, + probe_x_max = _MIN((X_BED_SIZE + X_MIN_POS) - corner_pos, X_MAX_POS + probe.offset.x, X_MAX_POS - PROBING_MARGIN) - probe.offset.x, + probe_y_min = _MAX(0 + corner_pos, Y_MIN_POS + probe.offset.y, Y_MIN_POS + PROBING_MARGIN) - probe.offset.y, + probe_y_max = _MIN((Y_BED_SIZE + Y_MIN_POS) - corner_pos, Y_MAX_POS + probe.offset.y, Y_MAX_POS - PROBING_MARGIN) - probe.offset.y; + #endif + switch (item) { case MLEVEL_BACK: if (draw) @@ -1425,19 +1432,22 @@ void CrealityDWINClass::Menu_Item_Handler(const uint8_t menu, const uint8_t item Draw_Checkbox(row, use_probe); } else { - use_probe = !use_probe; + use_probe ^= true; Draw_Checkbox(row, use_probe); if (use_probe) { Popup_Handler(Level); + constexpr struct { xy_pos_t p, ProbePtRaise r } points[] = { + { { probe_x_min, probe_y_min }, PROBE_PT_RAISE }, + { { probe_x_min, probe_y_max }, PROBE_PT_RAISE }, + { { probe_x_max, probe_y_max }, PROBE_PT_RAISE }, + { { probe_x_max, probe_y_min }, PROBE_PT_STOW } + }; corner_avg = 0; - #define PROBE_X_MIN _MAX(0 + corner_pos, X_MIN_POS + probe.offset.x, X_MIN_POS + PROBING_MARGIN) - probe.offset.x - #define PROBE_X_MAX _MIN((X_BED_SIZE + X_MIN_POS) - corner_pos, X_MAX_POS + probe.offset.x, X_MAX_POS - PROBING_MARGIN) - probe.offset.x - #define PROBE_Y_MIN _MAX(0 + corner_pos, Y_MIN_POS + probe.offset.y, Y_MIN_POS + PROBING_MARGIN) - probe.offset.y - #define PROBE_Y_MAX _MIN((Y_BED_SIZE + Y_MIN_POS) - corner_pos, Y_MAX_POS + probe.offset.y, Y_MAX_POS - PROBING_MARGIN) - probe.offset.y - corner_avg += probe.probe_at_point(PROBE_X_MIN, PROBE_Y_MIN, PROBE_PT_RAISE, 0, false); - corner_avg += probe.probe_at_point(PROBE_X_MIN, PROBE_Y_MAX, PROBE_PT_RAISE, 0, false); - corner_avg += probe.probe_at_point(PROBE_X_MAX, PROBE_Y_MAX, PROBE_PT_RAISE, 0, false); - corner_avg += probe.probe_at_point(PROBE_X_MAX, PROBE_Y_MIN, PROBE_PT_STOW, 0, false); + for (uint8_t i = 0; i < COUNT(points); i++) { + const float mz = probe.probe_at_point(points[i].p, points[i].r, 0, false); + if (isnan(mz)) { corner_avg = 0; break; } + corner_avg += mz; + } corner_avg /= 4; Redraw_Menu(); } @@ -1451,7 +1461,7 @@ void CrealityDWINClass::Menu_Item_Handler(const uint8_t menu, const uint8_t item Popup_Handler(MoveWait); if (use_probe) { #if HAS_BED_PROBE - sprintf_P(cmd, PSTR("G0 F4000\nG0 Z10\nG0 X%s Y%s"), dtostrf(PROBE_X_MIN, 1, 3, str_1), dtostrf(PROBE_Y_MIN, 1, 3, str_2)); + sprintf_P(cmd, PSTR("G0 F4000\nG0 Z10\nG0 X%s Y%s"), dtostrf(probe_x_min, 1, 3, str_1), dtostrf(probe_y_min, 1, 3, str_2)); gcode.process_subcommands_now(cmd); planner.synchronize(); Popup_Handler(ManualProbing); @@ -1472,7 +1482,7 @@ void CrealityDWINClass::Menu_Item_Handler(const uint8_t menu, const uint8_t item Popup_Handler(MoveWait); if (use_probe) { #if HAS_BED_PROBE - sprintf_P(cmd, PSTR("G0 F4000\nG0 Z10\nG0 X%s Y%s"), dtostrf(PROBE_X_MIN, 1, 3, str_1), dtostrf(PROBE_Y_MAX, 1, 3, str_2)); + sprintf_P(cmd, PSTR("G0 F4000\nG0 Z10\nG0 X%s Y%s"), dtostrf(probe_x_min, 1, 3, str_1), dtostrf(probe_y_max, 1, 3, str_2)); gcode.process_subcommands_now(cmd); planner.synchronize(); Popup_Handler(ManualProbing); @@ -1493,7 +1503,7 @@ void CrealityDWINClass::Menu_Item_Handler(const uint8_t menu, const uint8_t item Popup_Handler(MoveWait); if (use_probe) { #if HAS_BED_PROBE - sprintf_P(cmd, PSTR("G0 F4000\nG0 Z10\nG0 X%s Y%s"), dtostrf(PROBE_X_MAX, 1, 3, str_1), dtostrf(PROBE_Y_MAX, 1, 3, str_2)); + sprintf_P(cmd, PSTR("G0 F4000\nG0 Z10\nG0 X%s Y%s"), dtostrf(probe_x_max, 1, 3, str_1), dtostrf(probe_y_max, 1, 3, str_2)); gcode.process_subcommands_now(cmd); planner.synchronize(); Popup_Handler(ManualProbing); @@ -1514,7 +1524,7 @@ void CrealityDWINClass::Menu_Item_Handler(const uint8_t menu, const uint8_t item Popup_Handler(MoveWait); if (use_probe) { #if HAS_BED_PROBE - sprintf_P(cmd, PSTR("G0 F4000\nG0 Z10\nG0 X%s Y%s"), dtostrf(PROBE_X_MAX, 1, 3, str_1), dtostrf(PROBE_Y_MIN, 1, 3, str_2)); + sprintf_P(cmd, PSTR("G0 F4000\nG0 Z10\nG0 X%s Y%s"), dtostrf(probe_x_max, 1, 3, str_1), dtostrf(probe_y_min, 1, 3, str_2)); gcode.process_subcommands_now(cmd); planner.synchronize(); Popup_Handler(ManualProbing); diff --git a/Marlin/src/lcd/menu/menu_probe_offset.cpp b/Marlin/src/lcd/menu/menu_probe_offset.cpp index 62704cdede..0dd118ed22 100644 --- a/Marlin/src/lcd/menu/menu_probe_offset.cpp +++ b/Marlin/src/lcd/menu/menu_probe_offset.cpp @@ -102,7 +102,7 @@ void prepare_for_probe_offset_wizard() { // Probe for Z reference ui.wait_for_move = true; - z_offset_ref = probe.probe_at_point(wizard_pos, PROBE_PT_RAISE, 0, true); + z_offset_ref = probe.probe_at_point(wizard_pos, PROBE_PT_RAISE); ui.wait_for_move = false; // Stow the probe, as the last call to probe.probe_at_point(...) left diff --git a/Marlin/src/lcd/menu/menu_tramming_wizard.cpp b/Marlin/src/lcd/menu/menu_tramming_wizard.cpp index 4ce2cd6460..8fb251c238 100644 --- a/Marlin/src/lcd/menu/menu_tramming_wizard.cpp +++ b/Marlin/src/lcd/menu/menu_tramming_wizard.cpp @@ -53,7 +53,7 @@ static int8_t reference_index; // = 0 #endif static bool probe_single_point() { - const float z_probed_height = probe.probe_at_point(tramming_points[tram_index], PROBE_PT_RAISE, 0, true); + const float z_probed_height = probe.probe_at_point(tramming_points[tram_index], PROBE_PT_RAISE); z_measured[tram_index] = z_probed_height; if (reference_index < 0) reference_index = tram_index; move_to_tramming_wait_pos(); diff --git a/Marlin/src/module/probe.cpp b/Marlin/src/module/probe.cpp index a03125a73a..96606f30a8 100644 --- a/Marlin/src/module/probe.cpp +++ b/Marlin/src/module/probe.cpp @@ -522,7 +522,7 @@ bool Probe::set_deployed(const bool deploy, const bool no_return/*=false*/) { #endif if (z_raise_wanted) { - const float zdest = DIFF_TERN(HAS_HOTEND_OFFSET, _MAX(Z_CLEARANCE_BETWEEN_PROBES, Z_CLEARANCE_DEPLOY_PROBE), hotend_offset[active_extruder].z); + const float zdest = DIFF_TERN(HAS_HOTEND_OFFSET, Z_CLEARANCE_DEPLOY_PROBE, hotend_offset[active_extruder].z); if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Raise Z to ", zdest); do_z_clearance(zdest); } @@ -716,10 +716,12 @@ bool Probe::probe_down_to_z(const_float_t z, const_feedRate_t fr_mm_s) { * @param sanity_check Flag to compare the probe result with the expected result * based on the probe Z offset. If the result is too far away * (more than 2mm too early) then consider it an error. + * @param z_min_point Override the minimum probing height (-2mm), to allow deeper probing. + * @param z_clearance Z clearance to apply on probe failure. * * @return The Z position of the bed at the current XY or NAN on error. */ -float Probe::run_z_probe(const bool sanity_check/*=true*/) { +float Probe::run_z_probe(const bool sanity_check/*=true*/, const_float_t z_min_point/*=Z_PROBE_LOW_POINT*/, const_float_t z_clearance/*=Z_TWEEN_SAFE_CLEARANCE*/) { DEBUG_SECTION(log_probe, "Probe::run_z_probe", DEBUGGING(LEVELING)); const float zoffs = SUM_TERN(HAS_HOTEND_OFFSET, -offset.z, hotend_offset[active_extruder].z); @@ -750,9 +752,8 @@ float Probe::run_z_probe(const bool sanity_check/*=true*/) { }; // Stop the probe before it goes too low to prevent damage. - // For known Z probe below the expected trigger point, otherwise -10mm. - const float z_probe_low_point = axis_is_trusted(Z_AXIS) ? zoffs + Z_PROBE_LOW_POINT : -10.0f; - + // For known Z probe below the expected trigger point, otherwise -10mm lower. + const float z_probe_low_point = zoffs + z_min_point -float((!axis_is_trusted(Z_AXIS)) * 10); if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Probe Low Point: ", z_probe_low_point); // Double-probing does a fast probe followed by a slow probe @@ -768,7 +769,7 @@ float Probe::run_z_probe(const bool sanity_check/*=true*/) { if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("1st Probe Z:", z1); // Raise to give the probe clearance - do_z_clearance(Z_CLEARANCE_MULTI_PROBE); + do_z_clearance(z1 + (Z_CLEARANCE_MULTI_PROBE), false); #elif Z_PROBE_FEEDRATE_FAST != Z_PROBE_FEEDRATE_SLOW @@ -778,7 +779,7 @@ float Probe::run_z_probe(const bool sanity_check/*=true*/) { if (current_position.z > z) { // Probe down fast. If the probe never triggered, raise for probe clearance if (!probe_down_to_z(z, z_probe_fast_mm_s)) - do_z_clearance(Z_PROBE_SAFE_CLEARANCE); + do_z_clearance(z_clearance); } #endif @@ -911,7 +912,11 @@ float Probe::run_z_probe(const bool sanity_check/*=true*/) { * with the previously active tool. * */ -float Probe::probe_at_point(const_float_t rx, const_float_t ry, const ProbePtRaise raise_after/*=PROBE_PT_NONE*/, const uint8_t verbose_level/*=0*/, const bool probe_relative/*=true*/, const bool sanity_check/*=true*/) { +float Probe::probe_at_point(const_float_t rx, const_float_t ry, const ProbePtRaise raise_after/*=PROBE_PT_NONE*/, + const uint8_t verbose_level/*=0*/, const bool probe_relative/*=true*/, const bool sanity_check/*=true*/, + const_float_t z_min_point/*=Z_PROBE_LOW_POINT*/, const_float_t z_clearance/*=Z_TWEEN_SAFE_CLEARANCE*/, + const bool raise_after_is_relative/*=false*/ +) { DEBUG_SECTION(log_probe, "Probe::probe_at_point", DEBUGGING(LEVELING)); if (DEBUGGING(LEVELING)) { @@ -930,7 +935,7 @@ float Probe::probe_at_point(const_float_t rx, const_float_t ry, const ProbePtRai #endif // Use a safe Z height for the XY move - const float safe_z = _MAX(current_position.z, Z_PROBE_SAFE_CLEARANCE); + const float safe_z = _MAX(current_position.z, z_clearance); // On delta keep Z below clip height or do_blocking_move_to will abort xyz_pos_t npos = NUM_AXIS_ARRAY( @@ -959,7 +964,7 @@ float Probe::probe_at_point(const_float_t rx, const_float_t ry, const ProbePtRai #else // !BD_SENSOR - float measured_z = deploy() ? NAN : run_z_probe(sanity_check) + offset.z; + float measured_z = deploy() ? NAN : run_z_probe(sanity_check, z_min_point, z_clearance) + offset.z; // Deploy succeeded and a successful measurement was done. // Raise and/or stow the probe depending on 'raise_after' and settings. @@ -967,7 +972,10 @@ float Probe::probe_at_point(const_float_t rx, const_float_t ry, const ProbePtRai switch (raise_after) { default: break; case PROBE_PT_RAISE: - do_z_clearance(Z_PROBE_SAFE_CLEARANCE); + if (raise_after_is_relative) + do_z_clearance(current_position.z + z_clearance, false); + else + do_z_clearance(z_clearance); break; case PROBE_PT_STOW: case PROBE_PT_LAST_STOW: if (stow()) measured_z = NAN; // Error on stow? diff --git a/Marlin/src/module/probe.h b/Marlin/src/module/probe.h index fd0302c665..715f3f3a73 100644 --- a/Marlin/src/module/probe.h +++ b/Marlin/src/module/probe.h @@ -29,6 +29,10 @@ #include "motion.h" +#if ENABLED(BLTOUCH) + #include "../feature/bltouch.h" +#endif + #define DEBUG_OUT ENABLED(DEBUG_LEVELING_FEATURE) #include "../core/debug_out.h" @@ -48,7 +52,7 @@ #endif // In BLTOUCH HS mode, the probe travels in a deployed state. -#define Z_PROBE_SAFE_CLEARANCE SUM_TERN(BLTOUCH, Z_CLEARANCE_BETWEEN_PROBES, bltouch.z_extra_clearance()) +#define Z_TWEEN_SAFE_CLEARANCE SUM_TERN(BLTOUCH, Z_CLEARANCE_BETWEEN_PROBES, bltouch.z_extra_clearance()) #if ENABLED(PREHEAT_BEFORE_LEVELING) #ifndef LEVELING_NOZZLE_TEMP @@ -159,9 +163,17 @@ public: #endif // !IS_KINEMATIC - static float probe_at_point(const_float_t rx, const_float_t ry, const ProbePtRaise raise_after=PROBE_PT_NONE, const uint8_t verbose_level=0, const bool probe_relative=true, const bool sanity_check=true); - static float probe_at_point(const xy_pos_t &pos, const ProbePtRaise raise_after=PROBE_PT_NONE, const uint8_t verbose_level=0, const bool probe_relative=true, const bool sanity_check=true) { - return probe_at_point(pos.x, pos.y, raise_after, verbose_level, probe_relative, sanity_check); + static float probe_at_point(const_float_t rx, const_float_t ry, const ProbePtRaise raise_after=PROBE_PT_NONE, + const uint8_t verbose_level=0, const bool probe_relative=true, const bool sanity_check=true, + const_float_t z_min_point=Z_PROBE_LOW_POINT, const_float_t z_clearance=Z_TWEEN_SAFE_CLEARANCE, + const bool raise_after_is_relative=false); + + static float probe_at_point(const xy_pos_t &pos, const ProbePtRaise raise_after=PROBE_PT_NONE, + const uint8_t verbose_level=0, const bool probe_relative=true, const bool sanity_check=true, + const_float_t z_min_point=Z_PROBE_LOW_POINT, float z_clearance=Z_TWEEN_SAFE_CLEARANCE, + const bool raise_after_is_relative=false + ) { + return probe_at_point(pos.x, pos.y, raise_after, verbose_level, probe_relative, sanity_check, z_min_point, z_clearance, raise_after_is_relative); } #else // !HAS_BED_PROBE @@ -330,7 +342,7 @@ public: private: static bool probe_down_to_z(const_float_t z, const_feedRate_t fr_mm_s); - static float run_z_probe(const bool sanity_check=true); + static float run_z_probe(const bool sanity_check=true, const_float_t z_min_point=Z_PROBE_LOW_POINT, const_float_t z_clearance=Z_TWEEN_SAFE_CLEARANCE); }; extern Probe probe;