From a2e17db15230e6d5c986bfced546076320484819 Mon Sep 17 00:00:00 2001
From: James Gilliland <neclimdul@gmail.com>
Date: Sat, 11 Mar 2023 14:19:43 -0600
Subject: [PATCH 1/3] Offset XY movement during Z-Probe Wizard prep

Ensure Z-Probe Wizard follows probe offset logic to safely move to the
probe position.

Fixes #25491
---
 Marlin/src/lcd/menu/menu_probe_offset.cpp | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Marlin/src/lcd/menu/menu_probe_offset.cpp b/Marlin/src/lcd/menu/menu_probe_offset.cpp
index c7cbebaade82..7ea1f3b1c042 100644
--- a/Marlin/src/lcd/menu/menu_probe_offset.cpp
+++ b/Marlin/src/lcd/menu/menu_probe_offset.cpp
@@ -106,6 +106,7 @@ void prepare_for_probe_offset_wizard() {
 
     // Probe for Z reference
     ui.wait_for_move = true;
+    do_blocking_move_to_z(TERN(BLTOUCH, Z_CLEARANCE_DEPLOY_PROBE, Z_CLEARANCE_BETWEEN_PROBES));
     z_offset_ref = probe.probe_at_point(wizard_pos, PROBE_PT_RAISE, 0, true);
     ui.wait_for_move = false;
 

From 50a2094e3f2335498a540d693c6dbd1c0d09f452 Mon Sep 17 00:00:00 2001
From: Scott Lahteine <thinkyhead@users.noreply.github.com>
Date: Tue, 14 Mar 2023 17:47:43 -0500
Subject: [PATCH 2/3] Safe height for all probe_at_point XY moves

---
 Marlin/src/gcode/bedlevel/G35.cpp         |  1 -
 Marlin/src/gcode/calibrate/G76_M871.cpp   |  1 -
 Marlin/src/lcd/menu/menu_probe_offset.cpp |  1 -
 Marlin/src/lcd/menu/menu_tramming.cpp     |  4 +---
 Marlin/src/module/probe.cpp               | 20 ++++++++++++++------
 5 files changed, 15 insertions(+), 12 deletions(-)

diff --git a/Marlin/src/gcode/bedlevel/G35.cpp b/Marlin/src/gcode/bedlevel/G35.cpp
index dd828bf0c873..ff0321e4aa5c 100644
--- a/Marlin/src/gcode/bedlevel/G35.cpp
+++ b/Marlin/src/gcode/bedlevel/G35.cpp
@@ -108,7 +108,6 @@ void GcodeSuite::G35() {
     // length of the deployed pin (BLTOUCH stroke < 7mm)
 
     // Unsure if this is even required. The probe seems to lift correctly after probe done.
-    do_blocking_move_to_z(SUM_TERN(BLTOUCH, Z_CLEARANCE_BETWEEN_PROBES, bltouch.z_extra_clearance()));
     const float z_probed_height = probe.probe_at_point(tramming_points[i], PROBE_PT_RAISE, 0, true);
 
     if (isnan(z_probed_height)) {
diff --git a/Marlin/src/gcode/calibrate/G76_M871.cpp b/Marlin/src/gcode/calibrate/G76_M871.cpp
index c484d4f1b770..9bea0a0b863b 100644
--- a/Marlin/src/gcode/calibrate/G76_M871.cpp
+++ b/Marlin/src/gcode/calibrate/G76_M871.cpp
@@ -108,7 +108,6 @@
     };
 
     auto g76_probe = [](const TempSensorID sid, celsius_t &targ, const xy_pos_t &nozpos) {
-      do_z_clearance(5.0); // Raise nozzle before probing
       ptc.set_enabled(false);
       const float measured_z = probe.probe_at_point(nozpos, PROBE_PT_STOW, 0, false);  // verbose=0, probe_relative=false
       ptc.set_enabled(true);
diff --git a/Marlin/src/lcd/menu/menu_probe_offset.cpp b/Marlin/src/lcd/menu/menu_probe_offset.cpp
index 7ea1f3b1c042..c7cbebaade82 100644
--- a/Marlin/src/lcd/menu/menu_probe_offset.cpp
+++ b/Marlin/src/lcd/menu/menu_probe_offset.cpp
@@ -106,7 +106,6 @@ void prepare_for_probe_offset_wizard() {
 
     // Probe for Z reference
     ui.wait_for_move = true;
-    do_blocking_move_to_z(TERN(BLTOUCH, Z_CLEARANCE_DEPLOY_PROBE, Z_CLEARANCE_BETWEEN_PROBES));
     z_offset_ref = probe.probe_at_point(wizard_pos, PROBE_PT_RAISE, 0, true);
     ui.wait_for_move = false;
 
diff --git a/Marlin/src/lcd/menu/menu_tramming.cpp b/Marlin/src/lcd/menu/menu_tramming.cpp
index 1dd8a1cab6fd..4ce2cd646018 100644
--- a/Marlin/src/lcd/menu/menu_tramming.cpp
+++ b/Marlin/src/lcd/menu/menu_tramming.cpp
@@ -53,9 +53,7 @@ static int8_t reference_index; // = 0
 #endif
 
 static bool probe_single_point() {
-  do_blocking_move_to_z(TERN(BLTOUCH, Z_CLEARANCE_DEPLOY_PROBE, Z_CLEARANCE_BETWEEN_PROBES));
-  // Stow after each point with BLTouch "HIGH SPEED" mode for push-pin safety
-  const float z_probed_height = probe.probe_at_point(tramming_points[tram_index], TERN0(BLTOUCH, bltouch.high_speed_mode) ? PROBE_PT_STOW : PROBE_PT_RAISE, 0, true);
+  const float z_probed_height = probe.probe_at_point(tramming_points[tram_index], PROBE_PT_RAISE, 0, true);
   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 7daafd113981..414a181e083d 100644
--- a/Marlin/src/module/probe.cpp
+++ b/Marlin/src/module/probe.cpp
@@ -878,13 +878,16 @@ float Probe::probe_at_point(const_float_t rx, const_float_t ry, const ProbePtRai
   }
 
   #if ENABLED(BLTOUCH)
-    if (bltouch.high_speed_mode && bltouch.triggered())
-      bltouch._reset();
+    // Reset a BLTouch in HS mode if already triggered
+    if (bltouch.high_speed_mode && bltouch.triggered()) bltouch._reset();
   #endif
 
+  // Use a safe Z height for the XY move
+  const float safe_z = _MAX(current_position.z, SUM_TERN(BLTOUCH, Z_CLEARANCE_BETWEEN_PROBES, bltouch.z_extra_clearance()));
+
   // On delta keep Z below clip height or do_blocking_move_to will abort
   xyz_pos_t npos = NUM_AXIS_ARRAY(
-    rx, ry, TERN(DELTA, _MIN(delta_clip_start_height, current_position.z), current_position.z),
+    rx, ry, TERN(DELTA, _MIN(delta_clip_start_height, safe_z), safe_z),
     current_position.i, current_position.j, current_position.k,
     current_position.u, current_position.v, current_position.w
   );
@@ -907,17 +910,22 @@ float Probe::probe_at_point(const_float_t rx, const_float_t ry, const ProbePtRai
     TERN_(HAS_PTC, ptc.apply_compensation(measured_z));
     TERN_(X_AXIS_TWIST_COMPENSATION, measured_z += xatc.compensation(npos + offset_xy));
   }
+
+  // Deploy succeeded and a successful measurement was done.
+  // Raise and/or stow the probe depending on 'raise_after' and settings.
   if (!isnan(measured_z)) {
-    const bool big_raise = raise_after == PROBE_PT_BIG_RAISE;
-    if (big_raise || raise_after == PROBE_PT_RAISE)
+    const ProbePtRaise raise_type = (TERN0(BLTOUCH, !bltouch.high_speed_mode) && raise_after == PROBE_PT_RAISE) ? PROBE_PT_STOW : raise_after;
+    const bool big_raise = raise_type == PROBE_PT_BIG_RAISE;
+    if (big_raise || raise_type == PROBE_PT_RAISE)
       do_blocking_move_to_z(current_position.z + (big_raise ? 25 : Z_CLEARANCE_BETWEEN_PROBES), z_probe_fast_mm_s);
-    else if (raise_after == PROBE_PT_STOW || raise_after == PROBE_PT_LAST_STOW)
+    else if (raise_type == PROBE_PT_STOW || raise_type == PROBE_PT_LAST_STOW)
       if (stow()) measured_z = NAN;   // Error on stow?
 
     if (verbose_level > 2)
       SERIAL_ECHOLNPGM("Bed X: ", LOGICAL_X_POSITION(rx), " Y: ", LOGICAL_Y_POSITION(ry), " Z: ", measured_z);
   }
 
+  // If any error occurred stow the probe and set an alert
   if (isnan(measured_z)) {
     stow();
     LCD_MESSAGE(MSG_LCD_PROBING_FAILED);

From 27d3457bd9d663c21a001d96cebb9807ac64f43d Mon Sep 17 00:00:00 2001
From: Scott Lahteine <thinkyhead@users.noreply.github.com>
Date: Tue, 14 Mar 2023 19:02:06 -0500
Subject: [PATCH 3/3] Use do_z_clearance

---
 Marlin/src/module/probe.cpp | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/Marlin/src/module/probe.cpp b/Marlin/src/module/probe.cpp
index 414a181e083d..f1281184fb73 100644
--- a/Marlin/src/module/probe.cpp
+++ b/Marlin/src/module/probe.cpp
@@ -147,7 +147,7 @@ xyz_pos_t Probe::offset; // Initialized by settings.load()
     WRITE(MAGLEV_TRIGGER_PIN, LOW);
   }
 
-  inline void maglev_idle() { do_blocking_move_to_z(10); }
+  inline void maglev_idle() { do_z_clearance(10); }
 
 #elif ENABLED(TOUCH_MI_PROBE)
 
@@ -749,7 +749,7 @@ float Probe::run_z_probe(const bool sanity_check/*=true*/) {
     if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("1st Probe Z:", first_probe_z);
 
     // Raise to give the probe clearance
-    do_blocking_move_to_z(current_position.z + Z_CLEARANCE_MULTI_PROBE, z_probe_fast_mm_s);
+    do_z_clearance(current_position.z + Z_CLEARANCE_MULTI_PROBE);
 
   #elif Z_PROBE_FEEDRATE_FAST != Z_PROBE_FEEDRATE_SLOW
 
@@ -759,7 +759,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_blocking_move_to_z(current_position.z + Z_CLEARANCE_BETWEEN_PROBES, z_probe_fast_mm_s);
+        do_z_clearance(current_position.z + Z_CLEARANCE_BETWEEN_PROBES);
     }
   #endif
 
@@ -810,7 +810,7 @@ float Probe::run_z_probe(const bool sanity_check/*=true*/) {
           #if EXTRA_PROBING > 0
             < TOTAL_PROBING - 1
           #endif
-        ) do_blocking_move_to_z(z + Z_CLEARANCE_MULTI_PROBE, z_probe_fast_mm_s);
+        ) do_z_clearance(z + Z_CLEARANCE_MULTI_PROBE);
       #endif
     }
 
@@ -917,7 +917,7 @@ float Probe::probe_at_point(const_float_t rx, const_float_t ry, const ProbePtRai
     const ProbePtRaise raise_type = (TERN0(BLTOUCH, !bltouch.high_speed_mode) && raise_after == PROBE_PT_RAISE) ? PROBE_PT_STOW : raise_after;
     const bool big_raise = raise_type == PROBE_PT_BIG_RAISE;
     if (big_raise || raise_type == PROBE_PT_RAISE)
-      do_blocking_move_to_z(current_position.z + (big_raise ? 25 : Z_CLEARANCE_BETWEEN_PROBES), z_probe_fast_mm_s);
+      do_z_clearance(current_position.z + (big_raise ? 25 : Z_CLEARANCE_BETWEEN_PROBES));
     else if (raise_type == PROBE_PT_STOW || raise_type == PROBE_PT_LAST_STOW)
       if (stow()) measured_z = NAN;   // Error on stow?