From 6c8c8d24d7c07864857f80c3ecb232832cf33e62 Mon Sep 17 00:00:00 2001 From: Kevin O'Connor Date: Tue, 3 Mar 2026 15:33:39 -0500 Subject: [PATCH] probe_eddy_current: Support new tap_z_offset config parameter Theoretically a "tap" probe should detect the exact point that the nozzle contacts the bed. In practice, however, there can be a systemic bias that one may wish to account for. This bias may be due to backlash, thermal expansion, a detection bias, or similar issues. Add a new tap_z_offset config parameter to allow users to specify an offset. Also, update the Z_OFFSET_APPLY_PROBE command to support modifying this value. Signed-off-by: Kevin O'Connor --- docs/Config_Reference.md | 6 ++++++ docs/G-Codes.md | 8 ++++++++ klippy/extras/probe_eddy_current.py | 20 +++++++++++++++++++- 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/docs/Config_Reference.md b/docs/Config_Reference.md index 94b332296..db0ca25f2 100644 --- a/docs/Config_Reference.md +++ b/docs/Config_Reference.md @@ -2348,6 +2348,12 @@ sensor_type: ldc1612 # the bed. If this value is specified then one may override its # value at run-time using the "TAP_THRESHOLD" parameter on probe # commands. The default is to not enable support for "tap" probing. +#tap_z_offset: 0.0 +# The Z height (in mm) of the nozzle relative to the bed at the +# contact point detected during "tap" probing. Nominally this would +# be 0.0 to indicate the contact point has zero distance, but one +# may set this to account for backlash, thermal expansion, a +# systemic probing bias, or similar. The default is zero. ``` ### [axis_twist_compensation] diff --git a/docs/G-Codes.md b/docs/G-Codes.md index 9b876a059..1afaa2bb8 100644 --- a/docs/G-Codes.md +++ b/docs/G-Codes.md @@ -1251,6 +1251,14 @@ additional parameters if a `[probe_eddy_current]` section is defined: specified in the `[probe_eddy_current]` config section when probing using `METHOD=tap`. +The `Z_OFFSET_APPLY_PROBE` command is also extended to support a +`METHOD=tap` parameter. When no METHOD parameter is provided, the +`Z_OFFSET_APPLY_PROBE` command alters the probe calibration to apply +the current Z G-Code offset to future `scan`, `rapid_scan`, and +default probes. If `METHOD=tap` is specified then the command instead +applies the change to `tap_z_offset` so that future `tap` probes are +updated to use the current Z G-Code offset. + #### PROBE_EDDY_CURRENT_CALIBRATE `PROBE_EDDY_CURRENT_CALIBRATE CHIP=`: This starts a tool that calibrates the sensor resonance frequencies to corresponding Z diff --git a/klippy/extras/probe_eddy_current.py b/klippy/extras/probe_eddy_current.py index 11e05698b..f3567e8b6 100644 --- a/klippy/extras/probe_eddy_current.py +++ b/klippy/extras/probe_eddy_current.py @@ -260,6 +260,19 @@ class EddyCalibration: cal_contents.pop() configfile = self.printer.lookup_object('configfile') configfile.set(self.name, 'calibrate', ''.join(cal_contents)) + def _save_tap_z_offset(self, gcmd, homing_z): + eventtime = self.printer.get_reactor().monotonic() + configfile = self.printer.lookup_object('configfile') + cstatus = configfile.get_status(eventtime) + csettings = cstatus.get('settings', {}).get(self.name, {}) + tap_z_offset = csettings.get('tap_z_offset', 0.) + new_calibrate = tap_z_offset - homing_z + gcmd.respond_info( + "%s: tap_z_offset: %.3f\n" + "The SAVE_CONFIG command will update the printer config file\n" + "with the above and restart the printer." + % (self.name, new_calibrate)) + configfile.set(self.name, 'tap_z_offset', "%.3f" % (new_calibrate,)) cmd_EDDY_CALIBRATE_help = "Calibrate eddy current probe" def cmd_EDDY_CALIBRATE(self, gcmd): self.probe_speed = gcmd.get_float("PROBE_SPEED", 5., above=0.) @@ -273,6 +286,9 @@ class EddyCalibration: if offset == 0: gcmd.respond_info("Nothing to do: Z Offset is 0") return + if gcmd.get("METHOD", "").lower() == "tap": + self._save_tap_z_offset(gcmd, offset) + return cal_zpos = [z - offset for z in self.cal_zpos] z_freq_pairs = zip(cal_zpos, self.cal_freqs) z_freq_pairs = sorted(z_freq_pairs) @@ -488,6 +504,7 @@ class EddyTap: self._z_min_position = probe.lookup_minimum_z(config) self._gather = None self._filter_design = None + self._tap_z_offset = config.getfloat('tap_z_offset', 0.) self._tap_threshold = config.getfloat('tap_threshold', 0., above=0.) if self._tap_threshold: self._setup_tap() @@ -572,7 +589,8 @@ class EddyTap: self._validate_samples_time(measures, start_time, end_time) pos_time = self._pull_tap_time(measures) trig_pos = self._lookup_toolhead_pos(pos_time) - return manual_probe.create_probe_result(trig_pos) + return manual_probe.create_probe_result(trig_pos, + (0., 0., self._tap_z_offset)) # Probe session interface def start_probe_session(self, gcmd): self._prep_trigger_analog_tap(gcmd)