probe_eddy_contact: Add sanity checks to "tap" analysis

Implement some basic checks on the tap results and report an error if
the results look obviously incorrect.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
Kevin O'Connor
2026-04-06 20:09:33 -04:00
parent ec4b88db7b
commit db78babf91

View File

@@ -507,6 +507,7 @@ class EddyTap:
self._tap_z_offset = config.getfloat('tap_z_offset', 0.)
self._tap_threshold = config.getfloat('tap_threshold', 0., above=0.)
self._least_squares_cache = {}
self._current_tap_threshold = 0.
if self._tap_threshold:
self._setup_tap()
# Setup for "tap" probe request
@@ -536,6 +537,7 @@ class EddyTap:
self._tap_threshold, above=0.)
raw_threshold = convert_frequency(tap_threshold)
self._trigger_analog.set_trigger('diff_peak_gt', raw_threshold)
self._current_tap_threshold = tap_threshold
# Measurement analysis to determine "tap" position
def _validate_samples_time(self, measures, start_time, end_time):
cmderr = self._printer.command_error
@@ -697,17 +699,36 @@ class EddyTap:
bc[1], bc[2] + 2.*best_z*bc[3], bc[3])
#logging.info("probe_analysis: coeffs=%s", final_coeffs)
return final_coeffs
def _analyze_pullback(self, measures, start_time, end_time):
def _error_detect(self, msg):
raise self._printer.command_error("Unable to detect tap: %s" % (msg,))
def _analyze_pullback(self, measures, start_time, end_time, speed):
reactor = self._printer.get_reactor()
self._validate_samples_time(measures, start_time, end_time)
# Correlate measurements to toolhead position at time of measurement
data = [(sensor_freq, self._lookup_toolhead_pos(samp_time))
for samp_time, sensor_freq, sensor_z in measures]
reactor.pause(0.)
min_z = data[0][1][2]
max_z = data[-1][1][2]
if max_z - min_z < 0.350:
self._error_detect("insufficient lift (%.6f vs %.6f)"
% (max_z - min_z, 0.350))
# Find best fit for extracted measurements
coeffs = self._find_least_squares(data)
z_contact, freq_contact, depress_slope, slope, slope2 = coeffs
reactor.pause(0.)
sps = self._sensor_helper.get_samples_per_second()
contact_slope_delta_per_sample = (depress_slope - slope) * speed / sps
if contact_slope_delta_per_sample < self._current_tap_threshold:
self._error_detect("insufficient slope delta (%.6f vs %.6f)"
% (contact_slope_delta_per_sample,
self._current_tap_threshold))
if slope >= 0. or slope2 < 0.:
self._error_detect("invalid free air slope (s=%.6f s2=%.6f)"
% (slope, slope2))
if z_contact - min_z < 0.050 or z_contact - min_z > 0.250:
self._error_detect("invalid depress distance (%.6f vs %.6f:%.6f)"
% (z_contact - min_z, 0.050, 0.250))
# Report probe position
trig_idx = len(data)-1
while trig_idx > 0 and data[trig_idx-1][1][2] > z_contact:
@@ -741,7 +762,7 @@ class EddyTap:
start_time = retract_start_time - 0.010
end_time = retract_start_time + 0.150
self._gather.add_probe_request(self._analyze_pullback, start_time,
end_time, start_time, end_time)
end_time, start_time, end_time, speed)
def pull_probed_results(self):
return self._gather.pull_probed()
def end_probe_session(self):