Skip to content

New probe_eddy_current "tap" logic#7220

Open
KevinOConnor wants to merge 8 commits intomasterfrom
work-eddy-20260303
Open

New probe_eddy_current "tap" logic#7220
KevinOConnor wants to merge 8 commits intomasterfrom
work-eddy-20260303

Conversation

@KevinOConnor
Copy link
Collaborator

@KevinOConnor KevinOConnor commented Mar 5, 2026

This changes the recent ldc1612 eddy current "tap" support to determine the bed/nozzle contact point by analyzing the post-contact lift movement (previously the code determined the point of contact by analyzing the descent).

There are some advantages to calculating the probe position by analyzing the lift movement:

  • When the nozzle makes contact on the descent it can often induce an oscillation in the bed and/or toolhead. Similarly, an oscillation can also be induced when the Z motor are commanded to abruptly stop. These oscillations make it difficult to obtain reliable Z sensor measurements immediately following the bed/nozzle contact. This limits the amount of reliable data that can be used to determine a precise contact point. In particular, any measurement noise in the last measurement just prior to contact can have a notable impact on the final calculated contact position.
  • In contrast, the lifting movement is less likely to have these types of oscillations which allows more data to be used. In particular, we can utilize measurements from both before and after the contact point.
  • The code on this PR is less dependent on individual ldc1612 measurements and therefore less susceptible to sensor noise. The code is also capable of reliably calculating contact positions in between sensor measurements. That is, even if the sensor is only taking a measurement after every 20um of movement, the code on this PR can still reliably produce contact positions in the ~1um range.

The code on this PR implements a kind of "least squares" search of the measurement data to find the point of contact. Specifically, putting noise aside, the sensor readings around the point of contact are expected to follow:

  • At the point of contact (z=contact_z): sensor_frequency(z) = k0
  • At positions below the point of contact (z<=contact_z): sensor_frequency(z) = k0 + k1*(z - contact_z)
  • At positions above the point of contact (z>=contact_z): sensor_frequency(z) = k0 + k2*(z - contact_z) + k3*(z - contact_z)*(z - contact_z)

Given the above formulas the code tries to find solutions for contact_z, k0, k1, k2, and k3 such that it minimizes the squares of the deviation from the actual sensor frequency measurements (ie, a "least squares solution").

This may best be seen with a picture:
tap-analysis
In this example, the line shown was the "best fit" for the measurement data. (Note how the final "contact point" of z=1.054421 is actually between two measurements.)

Initial tests are indicating that this method of analyzing the tap position can produce more repeatable and more precise results. However, there are some known caveats:

  • The analysis may have some dependency on how far the bed is depressed during the descent movement. If measurement noise or communications delays causes slightly earlier or slightly later toolhead halting, then there might be more jitter in the estimated contact position.
  • The analysis code is sensitive to the "SAMPLE_RETRACT_DIST" and "LIFT_SPEED" settings.
  • The host code to analyze the results does consume more host cpu. It's unclear if that could cause scheduling jitter on low-end host cpus.

This PR also includes some additional changes that were needed as prerequisites:

  • Due to the change in analysis, the new code consistently finds contact points that are lower than the previous "tap" code. Users will likely need to recalibrate after this change. To facilitate this in the future, a new tap_z_offset config parameter has been provided. This is similar to the z_offset parameter found on other types of probes. It allows the user to specify a nominal Z offset between what the tap code provides and the actual desired Z value during prints. Even though the contact point would nominally occur at exactly Z=0, there can be cases where backlash, thermal expansion, and similar may make an offset desirable.
  • The existing [probe_eddy_current] z_offset parameter has been renamed to descend_z. This is to avoid confusion with the z_offset found in other common probe configs and to avoid confusion with the new tap_z_offset.
  • When utilizing "METHOD=tap" probing, the printer.cfg probe speed, lift_speed, etc. config options are no longer utilized. If a user wishes to change any of these settings from their defaults then they will need to provide the new values on the probe command-line (eg, PROBE_SPEED=9, LIFT_SPEED=3.0, etc.). This was implemented because the new code is sensitive to these types of probe settings and the defaults used for regular probing attempts would not be meaningful for "tap" probes.

-Kevin

Note, I also have a development branch at https://github.com/KevinOConnor/klipper-dev/tree/work-tap-20260224 . It has some debugging code. In particular it contains the scripts/tap_graph.py script that was used to generate the graph above.

…ce.md

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Add a new create_probe_result() helper function that can generate a
ProbeResult using a toolhead position and a set of probe offsets.

Use this helper in other modules.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
The config option 'z_offset' name is confusing as its behavior is
notably different from how other probe hardware uses 'z_offset'.
Rename to 'descend_z' to make its behavior more clear.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
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 <kevin@koconnor.net>
…nd "tap"

Add a new EddyParameterHelper to override ProbeParameterHelper.

Only use the printer.cfg lift_speed, samples, sample_retract_dist,
samples_result, samples_tolerance, and samples_tolerance_retries
settings for normal probe operations.  Don't use these defaults when
using a "METHOD" set to "scan", "rapid_scan", or "tap".  Each of these
probing mechanisms is distinct and it's unlikely a user could
meaningfully set a default for all of them.

Don't set sample_retract_dist when using "scan" and "rapid_scan"
modes.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Perform lifting at the end of EddyTap.run_probe().  This is in
preparation for performing tap analysis during retraction.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Don't calculate the nozzle/bed contact position from the descent
movement.  Instead, obtain the data during the lifting movement and
determine the contact point by analyzing where the nozzle separates
from the bed.

This improves the precision and repeatability of the "tap" results.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
# Recommended starting values for the tap
#samples: 3
#samples_tolerance: 0.025
#samples_tolerance_retries: 3
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JFYI: This does not make sense after adding the new interface, because they only make sense as the tap params, which now only apply from gcmd

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants