From 419d12ca1be19d1792db05062b4fa2808b05d165 Mon Sep 17 00:00:00 2001
From: Scott Lahteine <github@thinkyhead.com>
Date: Fri, 9 Mar 2018 23:18:47 -0600
Subject: [PATCH] Add UNKNOWN_Z_NO_RAISE option

With this option enabled, Z won't ever be raised until after `G28` has been completed, and it won't raise if Z becomes unknown. This is good for machines whose beds fall when Z is powered off.
---
 Marlin/Configuration.h             |  2 ++
 Marlin/src/gcode/calibrate/G28.cpp | 10 ++++++++--
 Marlin/src/module/probe.cpp        | 22 +++++++++++++++-------
 3 files changed, 25 insertions(+), 9 deletions(-)

diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h
index 6bbcaeae2..9ac20ae0d 100644
--- a/Marlin/Configuration.h
+++ b/Marlin/Configuration.h
@@ -804,6 +804,8 @@
 
 //#define NO_MOTION_BEFORE_HOMING  // Inhibit movement until all axes have been homed
 
+//#define UNKNOWN_Z_NO_RAISE // Don't raise Z (lower the bed) if Z is "unknown." For beds that fall when Z is powered off.
+
 //#define Z_HOMING_HEIGHT 4  // (in mm) Minimal z height before homing (G28) for Z clearance above the bed, clamps, ...
                              // Be sure you have this distance over your Z_MAX_POS in case.
 
diff --git a/Marlin/src/gcode/calibrate/G28.cpp b/Marlin/src/gcode/calibrate/G28.cpp
index 92526e102..f76a45f6e 100644
--- a/Marlin/src/gcode/calibrate/G28.cpp
+++ b/Marlin/src/gcode/calibrate/G28.cpp
@@ -221,9 +221,15 @@ void GcodeSuite::G28(const bool always_home_all) {
 
     #endif
 
-    if (home_all || homeX || homeY) {
+    #if ENABLED(UNKNOWN_Z_NO_RAISE)
+      const float z_homing_height = axis_known_position[Z_AXIS] ? Z_HOMING_HEIGHT : 0;
+    #else
+      constexpr float z_homing_height = Z_HOMING_HEIGHT;
+    #endif
+
+    if (z_homing_height && (home_all || homeX || homeY)) {
       // Raise Z before homing any other axes and z is not already high enough (never lower z)
-      destination[Z_AXIS] = Z_HOMING_HEIGHT;
+      destination[Z_AXIS] = z_homing_height;
       if (destination[Z_AXIS] > current_position[Z_AXIS]) {
 
         #if ENABLED(DEBUG_LEVELING_FEATURE)
diff --git a/Marlin/src/module/probe.cpp b/Marlin/src/module/probe.cpp
index 9d54d5c5a..6bda510d2 100644
--- a/Marlin/src/module/probe.cpp
+++ b/Marlin/src/module/probe.cpp
@@ -378,13 +378,21 @@ bool set_probe_deployed(const bool deploy) {
 
   // Make room for probe to deploy (or stow)
   // Fix-mounted probe should only raise for deploy
-  if (
-    #if ENABLED(FIX_MOUNTED_PROBE)
-      deploy
-    #else
-      true
-    #endif
-  ) do_probe_raise(max(Z_CLEARANCE_BETWEEN_PROBES, Z_CLEARANCE_DEPLOY_PROBE));
+  #if ENABLED(FIX_MOUNTED_PROBE)
+    const bool deploy_stow_condition = deploy;
+  #else
+    constexpr bool deploy_stow_condition = true;
+  #endif
+
+  // For beds that fall when Z is powered off only raise for trusted Z
+  #if ENABLED(UNKNOWN_Z_NO_RAISE)
+    const bool unknown_condition = axis_known_position[Z_AXIS];
+  #else
+    constexpr float unknown_condition = true;
+  #endif
+
+  if (deploy_stow_condition && unknown_condition)
+    do_probe_raise(max(Z_CLEARANCE_BETWEEN_PROBES, Z_CLEARANCE_DEPLOY_PROBE));
 
   #if ENABLED(Z_PROBE_SLED) || ENABLED(Z_PROBE_ALLEN_KEY)
     #if ENABLED(Z_PROBE_SLED)