I think i have located a bug, at least the behavior doesn’t seem intended.
Simplest steps to reproduce
Make sure bed_mesh fading is disabled
[bed_mesh]
fade_end: 0
Now load a mesh (or calibrate a new one and run M84) home X:
BED_MESH_LOAD PROFILE=default
G28 X
If we move X now, we’ll get an error
G0 X90
Result:
Must home axis first: 200.000 0.000 24.864 [0.000]
This seems unintended. The reason this happens is that both bed_mesh and z_thermal_adjust both apply their changes regardless of whether Z is homed or not. I propose to add a check to skip adjustment if Z isn’t homed.
Here’s a crude “Fix” for bed_mesh that solves that issue. Do note that i have not verified that the mesh is applied correctly after this change, and i’m also not sure if the check needs to be in both get_position()
and move()
.
diff --git a/klippy/extras/bed_mesh.py b/klippy/extras/bed_mesh.py
index 92c3ac54..2cc8c273 100644
--- a/klippy/extras/bed_mesh.py
+++ b/klippy/extras/bed_mesh.py
@@ -173,7 +173,9 @@ class BedMesh:
return 1.
def get_position(self):
# Return last, non-transformed position
- if self.z_mesh is None:
+ curtime = self.printer.get_reactor().monotonic()
+ kin_status = self.toolhead.get_kinematics().get_status(curtime)
+ if self.z_mesh is None or 'z' not in kin_status['homed_axes']:
# No mesh calibrated, so send toolhead position
self.last_position[:] = self.toolhead.get_position()
self.last_position[2] -= self.fade_target
@@ -198,9 +200,13 @@ class BedMesh:
return list(self.last_position)
def move(self, newpos, speed):
factor = self.get_z_factor(newpos[2])
- if self.z_mesh is None or not factor:
- # No mesh calibrated, or mesh leveling phased out.
+ curtime = self.printer.get_reactor().monotonic()
+ kin_status = self.toolhead.get_kinematics().get_status(curtime)
+ if self.z_mesh is None or not factor or 'z' not in kin_status['homed_axes']:
+ # No mesh calibrated, mesh leveling phased out or z not homed.
x, y, z, e = newpos
+ logging.info("bed_mesh no mesh adjustment: Current Z: %.4f fade_target: %.4f "
+ % (z, self.fade_target))
if self.log_fade_complete:
self.log_fade_complete = False
logging.info(
A use case where this causes a lot of problems is with [homing_override]
such as for sensorless homing where consistency on a CoreXY is vastly improved by centering the axes after homing. Another is in the case of [safe_z_home]
if you have a bed_mesh loaded, such as after finishing a print.
UPDATE:
To clarify, you cannot complete a G28 if you have a homing_override that centers each axis after homing, or if you use safe_z_home, if you load a bed_mesh first or have z_thermal_adjust defined in your config without setting z_adjust_off_above
to something lower than your homing z_hop (which is not the default).
This is a verifiable, reproducible bug, only using klipper as intended.
You could argue that you “just shouldn’t have a bed mesh loaded outside of a print”
But that is inconsistent with the default behavior of BED_MESH_CALIBRATE
which sets the calibrated mesh as active upon completion. Any re-homing after this will break. It also doesn’t solve the problem with z_thermal_adjust
at all.