diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index baa0433f1..7c8f2da94 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -1084,8 +1084,14 @@ #if HAS_BED_PROBE //#define PROBE_OFFSET_WIZARD #if ENABLED(PROBE_OFFSET_WIZARD) - #define PROBE_OFFSET_START -4.0 // Estimated nozzle-to-probe Z offset, plus a little extra - //#define PROBE_OFFSET_WIZARD_XY_POS XY_CENTER // Set a convenient position to do the measurement + // + // Enable to init the Probe Z-Offset when starting the Wizard. + // Use the estimated nozzle-to-probe Z offset, plus a little more. + // + //#define PROBE_OFFSET_WIZARD_START_Z -4.0 + + // Set a convenient position to do the calibration (probing point and nozzle/bed-distance) + //#define PROBE_OFFSET_WIZARD_XY_POS { X_CENTER, Y_CENTER } #endif #endif diff --git a/Marlin/src/gcode/calibrate/G28.cpp b/Marlin/src/gcode/calibrate/G28.cpp index c0bc17986..c4effe7d5 100644 --- a/Marlin/src/gcode/calibrate/G28.cpp +++ b/Marlin/src/gcode/calibrate/G28.cpp @@ -324,7 +324,7 @@ void GcodeSuite::G28() { ? 0 : (parser.seenval('R') ? parser.value_linear_units() : Z_HOMING_HEIGHT); - if (z_homing_height && (doX || doY || (ENABLED(Z_SAFE_HOMING) && doZ))) { + if (z_homing_height && (doX || doY || TERN0(Z_SAFE_HOMING, doZ))) { // Raise Z before homing any other axes and z is not already high enough (never lower z) if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR("Raise Z (before homing) by ", z_homing_height); do_z_clearance(z_homing_height, true, DISABLED(UNKNOWN_Z_NO_RAISE)); @@ -337,7 +337,7 @@ void GcodeSuite::G28() { #endif // Home Y (before X) - if (ENABLED(HOME_Y_BEFORE_X) && (doY || (ENABLED(CODEPENDENT_XY_HOMING) && doX))) + if (ENABLED(HOME_Y_BEFORE_X) && (doY || TERN0(CODEPENDENT_XY_HOMING, doX))) homeaxis(Y_AXIS); // Home X diff --git a/Marlin/src/inc/SanityCheck.h b/Marlin/src/inc/SanityCheck.h index 0dfa30584..9f4c10dd5 100644 --- a/Marlin/src/inc/SanityCheck.h +++ b/Marlin/src/inc/SanityCheck.h @@ -525,6 +525,8 @@ #error "EVENT_GCODE_SD_STOP is now EVENT_GCODE_SD_ABORT." #elif defined(GRAPHICAL_TFT_ROTATE_180) #error "GRAPHICAL_TFT_ROTATE_180 is now TFT_ROTATION set to TFT_ROTATE_180." +#elif defined(PROBE_OFFSET_START) + #error "PROBE_OFFSET_START is now PROBE_OFFSET_WIZARD_START_Z." #elif defined(POWER_LOSS_PULL) #error "POWER_LOSS_PULL is now specifically POWER_LOSS_PULL(UP|DOWN)." #elif defined(FIL_RUNOUT_INVERTING) @@ -1345,25 +1347,32 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS #error "Z_MIN_PROBE_PIN must be defined if Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN is not enabled." #endif + /** + * Check for improper NOZZLE_TO_PROBE_OFFSET + */ + constexpr xyz_pos_t sanity_nozzle_to_probe_offset = NOZZLE_TO_PROBE_OFFSET; #if ENABLED(NOZZLE_AS_PROBE) - constexpr float sanity_nozzle_to_probe_offset[] = NOZZLE_TO_PROBE_OFFSET; - static_assert(sanity_nozzle_to_probe_offset[0] == 0.0 && sanity_nozzle_to_probe_offset[1] == 0.0, - "NOZZLE_AS_PROBE requires the X,Y offsets in NOZZLE_TO_PROBE_OFFSET to be 0,0."); - #endif - - #if DISABLED(NOZZLE_AS_PROBE) - static_assert(PROBING_MARGIN >= 0, "PROBING_MARGIN must be >= 0."); - static_assert(PROBING_MARGIN_BACK >= 0, "PROBING_MARGIN_BACK must be >= 0."); + static_assert(sanity_nozzle_to_probe_offset.x == 0 && sanity_nozzle_to_probe_offset.y == 0, + "NOZZLE_AS_PROBE requires the XY offsets in NOZZLE_TO_PROBE_OFFSET to both be 0."); + #else + static_assert(sanity_nozzle_to_probe_offset.z <= 0.25, + "Are you sure your Probe triggers above the nozzle? Set a negative Z value in the NOZZLE_TO_PROBE_OFFSET."); + #ifdef PROBE_OFFSET_WIZARD_START_Z + static_assert(PROBE_OFFSET_WIZARD_START_Z <= 0.25, + "Are you sure your Probe triggers above the nozzle? Set a negative value for PROBE_OFFSET_WIZARD_START_Z."); + #endif + static_assert(PROBING_MARGIN >= 0, "PROBING_MARGIN must be >= 0."); + static_assert(PROBING_MARGIN_BACK >= 0, "PROBING_MARGIN_BACK must be >= 0."); static_assert(PROBING_MARGIN_FRONT >= 0, "PROBING_MARGIN_FRONT must be >= 0."); - static_assert(PROBING_MARGIN_LEFT >= 0, "PROBING_MARGIN_LEFT must be >= 0."); + static_assert(PROBING_MARGIN_LEFT >= 0, "PROBING_MARGIN_LEFT must be >= 0."); static_assert(PROBING_MARGIN_RIGHT >= 0, "PROBING_MARGIN_RIGHT must be >= 0."); #endif #define _MARGIN(A) TERN(IS_SCARA, SCARA_PRINTABLE_RADIUS, TERN(DELTA, DELTA_PRINTABLE_RADIUS, ((A##_BED_SIZE) / 2))) - static_assert(PROBING_MARGIN < _MARGIN(X), "PROBING_MARGIN is too large."); - static_assert(PROBING_MARGIN_BACK < _MARGIN(Y), "PROBING_MARGIN_BACK is too large."); + static_assert(PROBING_MARGIN < _MARGIN(X), "PROBING_MARGIN is too large."); + static_assert(PROBING_MARGIN_BACK < _MARGIN(Y), "PROBING_MARGIN_BACK is too large."); static_assert(PROBING_MARGIN_FRONT < _MARGIN(Y), "PROBING_MARGIN_FRONT is too large."); - static_assert(PROBING_MARGIN_LEFT < _MARGIN(X), "PROBING_MARGIN_LEFT is too large."); + static_assert(PROBING_MARGIN_LEFT < _MARGIN(X), "PROBING_MARGIN_LEFT is too large."); static_assert(PROBING_MARGIN_RIGHT < _MARGIN(X), "PROBING_MARGIN_RIGHT is too large."); #undef _MARGIN diff --git a/Marlin/src/lcd/language/language_en.h b/Marlin/src/lcd/language/language_en.h index 04487fa13..af0903b91 100644 --- a/Marlin/src/lcd/language/language_en.h +++ b/Marlin/src/lcd/language/language_en.h @@ -673,6 +673,8 @@ namespace Language_en { PROGMEM Language_Str MSG_REHEATING = _UxGT("Reheating..."); PROGMEM Language_Str MSG_PROBE_WIZARD = _UxGT("Z Probe Wizard"); + PROGMEM Language_Str MSG_PROBE_WIZARD_PROBING = _UxGT("Probing Z Reference"); + PROGMEM Language_Str MSG_PROBE_WIZARD_MOVING = _UxGT("Moving to Probing Pos"); PROGMEM Language_Str MSG_SOUND = _UxGT("Sound"); diff --git a/Marlin/src/lcd/marlinui.h b/Marlin/src/lcd/marlinui.h index ccf995bd7..8e968abda 100644 --- a/Marlin/src/lcd/marlinui.h +++ b/Marlin/src/lcd/marlinui.h @@ -624,7 +624,7 @@ public: // // Special handling if a move is underway // - #if EITHER(DELTA_CALIBRATION_MENU, DELTA_AUTO_CALIBRATION) || (ENABLED(LCD_BED_LEVELING) && EITHER(PROBE_MANUALLY, MESH_BED_LEVELING)) || (ENABLED(PROBE_OFFSET_WIZARD) && defined(PROBE_OFFSET_WIZARD_XY_POS)) + #if ANY(DELTA_CALIBRATION_MENU, DELTA_AUTO_CALIBRATION, PROBE_OFFSET_WIZARD) || (ENABLED(LCD_BED_LEVELING) && EITHER(PROBE_MANUALLY, MESH_BED_LEVELING)) #define LCD_HAS_WAIT_FOR_MOVE 1 static bool wait_for_move; #else diff --git a/Marlin/src/lcd/menu/menu.h b/Marlin/src/lcd/menu/menu.h index 5782d2070..cf2f6b163 100644 --- a/Marlin/src/lcd/menu/menu.h +++ b/Marlin/src/lcd/menu/menu.h @@ -220,7 +220,7 @@ void _lcd_draw_homing(); #endif #if ENABLED(PROBE_OFFSET_WIZARD) - void home_and_goto_probe_offset_wizard(); + void goto_probe_offset_wizard(); #endif #if ENABLED(LCD_BED_LEVELING) || (HAS_LEVELING && DISABLED(SLIM_LCD_MENUS)) diff --git a/Marlin/src/lcd/menu/menu_advanced.cpp b/Marlin/src/lcd/menu/menu_advanced.cpp index 268573beb..3f2a6da11 100644 --- a/Marlin/src/lcd/menu/menu_advanced.cpp +++ b/Marlin/src/lcd/menu/menu_advanced.cpp @@ -488,7 +488,7 @@ void menu_backlash(); EDIT_ITEM(LCD_Z_OFFSET_TYPE, MSG_ZPROBE_ZOFFSET, &probe.offset.z, Z_PROBE_OFFSET_RANGE_MIN, Z_PROBE_OFFSET_RANGE_MAX); #if ENABLED(PROBE_OFFSET_WIZARD) - SUBMENU(MSG_PROBE_WIZARD, home_and_goto_probe_offset_wizard); + SUBMENU(MSG_PROBE_WIZARD, goto_probe_offset_wizard); #endif END_MENU(); diff --git a/Marlin/src/lcd/menu/menu_probe_offset.cpp b/Marlin/src/lcd/menu/menu_probe_offset.cpp index 9f2155009..f2b08afd7 100644 --- a/Marlin/src/lcd/menu/menu_probe_offset.cpp +++ b/Marlin/src/lcd/menu/menu_probe_offset.cpp @@ -28,12 +28,6 @@ #if ENABLED(PROBE_OFFSET_WIZARD) -#ifndef PROBE_OFFSET_START - #error "PROBE_OFFSET_WIZARD requires a PROBE_OFFSET_START with a negative value." -#else - static_assert(PROBE_OFFSET_START < 0, "PROBE_OFFSET_START must be < 0. Please update your configuration."); -#endif - #include "menu_item.h" #include "menu_addon.h" #include "../../gcode/queue.h" @@ -46,21 +40,20 @@ #endif // Global storage -float z_offset_backup, calculated_z_offset; +float z_offset_backup, calculated_z_offset, z_offset_ref; TERN_(HAS_LEVELING, bool leveling_was_active); -void prepare_for_calibration() { - z_offset_backup = probe.offset.z; - - // Disable soft endstops for free Z movement - SET_SOFT_ENDSTOP_LOOSE(true); - - // Disable leveling for raw planner motion - #if HAS_LEVELING - leveling_was_active = planner.leveling_active; - set_bed_leveling_enabled(false); - #endif +inline void z_clearance_move() { + do_z_clearance( + #ifdef Z_AFTER_HOMING + Z_AFTER_HOMING + #elif defined(Z_HOMING_HEIGHT) + Z_HOMING_HEIGHT + #else + 10 + #endif + ); } void set_offset_and_go_back(const float &z) { @@ -77,7 +70,7 @@ void _goto_manual_move_z(const float scale) { void probe_offset_wizard_menu() { START_MENU(); - calculated_z_offset = probe.offset.z + current_position.z; + calculated_z_offset = probe.offset.z + current_position.z - z_offset_ref; if (LCD_HEIGHT >= 4) STATIC_ITEM(MSG_MOVE_NOZZLE_TO_BED, SS_CENTER|SS_INVERT); @@ -92,7 +85,7 @@ void probe_offset_wizard_menu() { char tmp[20], numstr[10]; // Determine digits needed right of decimal const uint8_t digs = !UNEAR_ZERO((SHORT_MANUAL_Z_MOVE) * 1000 - int((SHORT_MANUAL_Z_MOVE) * 1000)) ? 4 : - !UNEAR_ZERO((SHORT_MANUAL_Z_MOVE) * 100 - int((SHORT_MANUAL_Z_MOVE) * 100)) ? 3 : 2; + !UNEAR_ZERO((SHORT_MANUAL_Z_MOVE) * 100 - int((SHORT_MANUAL_Z_MOVE) * 100)) ? 3 : 2; sprintf_P(tmp, GET_TEXT(MSG_MOVE_Z_DIST), dtostrf(SHORT_MANUAL_Z_MOVE, 1, digs, numstr)); #if DISABLED(HAS_GRAPHICAL_TFT) extern const char NUL_STR[]; @@ -107,47 +100,86 @@ void probe_offset_wizard_menu() { ACTION_ITEM(MSG_BUTTON_DONE, []{ set_offset_and_go_back(calculated_z_offset); - do_z_clearance(20.0 - #ifdef Z_AFTER_HOMING - - 20.0 + Z_AFTER_HOMING - #endif - ); + current_position.z = z_offset_ref; // Set Z to z_offset_ref, as we can expect it is at probe height + sync_plan_position(); + z_clearance_move(); // Raise Z as if it was homed }); ACTION_ITEM(MSG_BUTTON_CANCEL, []{ set_offset_and_go_back(z_offset_backup); + // If wizard-homing was done by probe with with PROBE_OFFSET_WIZARD_START_Z + #if EITHER(Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN, USE_PROBE_FOR_Z_HOMING) && defined(PROBE_OFFSET_WIZARD_START_Z) + set_axis_never_homed(Z_AXIS); // On cancel the Z position needs correction + queue.inject_P(PSTR("G28Z")); + #else // Otherwise do a Z clearance move like after Homing + z_clearance_move(); + #endif }); END_MENU(); } -#ifdef PROBE_OFFSET_WIZARD_XY_POS +void prepare_for_probe_offset_wizard() { + if (ui.wait_for_move) return; - #define HAS_PROBE_OFFSET_WIZARD_XY_POS 1 + #if defined(PROBE_OFFSET_WIZARD_XY_POS) || NONE(Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN, USE_PROBE_FOR_Z_HOMING) + if (ui.should_draw()) MenuItem_static::draw(1, GET_TEXT(MSG_PROBE_WIZARD_PROBING)); - inline void goto_probe_offset_wizard() { - if (ui.wait_for_move) return; + #ifndef PROBE_OFFSET_WIZARD_XY_POS + #define PROBE_OFFSET_WIZARD_XY_POS XY_CENTER + #endif + // Get X and Y from configuration, or use center constexpr xy_pos_t wizard_pos = PROBE_OFFSET_WIZARD_XY_POS; - current_position = wizard_pos; + + // Probe for Z reference ui.wait_for_move = true; - line_to_current_position(MMM_TO_MMS(HOMING_FEEDRATE_XY)); // Could invoke idle() + z_offset_ref = probe.probe_at_point(wizard_pos, PROBE_PT_STOW, 0, true); ui.wait_for_move = false; - ui.synchronize(); - prepare_for_calibration(); - probe.offset.z = PROBE_OFFSET_START; - ui.goto_screen(probe_offset_wizard_menu); - ui.defer_status_screen(); - } -#endif + #endif -void home_and_goto_probe_offset_wizard() { + // Move Nozzle to Probing/Homing Position + ui.wait_for_move = true; + current_position += probe.offset_xy; + line_to_current_position(MMM_TO_MMS(HOMING_FEEDRATE_XY)); + ui.synchronize(GET_TEXT(MSG_PROBE_WIZARD_MOVING)); + ui.wait_for_move = false; + + // Go to Calibration Menu + ui.goto_screen(probe_offset_wizard_menu); + ui.defer_status_screen(); +} + +void goto_probe_offset_wizard() { + ui.defer_status_screen(); + set_all_unhomed(); + + // Store probe.offset.z for Case: Cancel + z_offset_backup = probe.offset.z; + + #ifdef PROBE_OFFSET_WIZARD_START_Z + probe.offset.z = PROBE_OFFSET_WIZARD_START_Z; + #endif + + // Store Bed-Leveling-State and disable + #if HAS_LEVELING + leveling_was_active = planner.leveling_active; + set_bed_leveling_enabled(false); + #endif + + // Home all axes queue.inject_P(G28_STR); + ui.goto_screen([]{ _lcd_draw_homing(); - if (all_axes_homed()) - ui.goto_screen(TERN(HAS_PROBE_OFFSET_WIZARD_XY_POS, goto_probe_offset_wizard, probe_offset_wizard_menu)); + if (all_axes_homed()) { + SET_SOFT_ENDSTOP_LOOSE(true); // Disable soft endstops for free Z movement + z_offset_ref = 0; // Set Z Value for Wizard Position to 0 + ui.goto_screen(prepare_for_probe_offset_wizard); + ui.defer_status_screen(); + } }); + } #endif // PROBE_OFFSET_WIZARD