bdp_guard: new zero at every ARM

With TPU in a nozzle heating to 150C the pressure kept changing for
minutes (+43, then -56 as it oozed), faster than the sensor's own
baseline update, and the guard stopped the printer at the start of
z_check and home_xy with the nozzle in the air. Every ARM (also a phase
switch) now writes reset_probe (register 52) and waits 0.2 s without
reading, so only force during the guarded moves counts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
mangavalkandClaude Opus 5.5 committed 2026-10-19 16:34:26 +02:00
1 parent 29604b2f1e
commit a63b66a7d8
1 file changed
+26 -2
+26 -2
View File
@@ -8,6 +8,10 @@
# row at or above THRESHOLD shut Klipper down at once (like M112, without # row at or above THRESHOLD shut Klipper down at once (like M112, without
# waiting for the running macro to finish). # waiting for the running macro to finish).
# #
# Every ARM (also a phase switch) first sets a new zero (register 52), so
# slow pressure changes before the guarded moves do not count (TPU in a
# nozzle that heats up keeps changing pressure for minutes).
#
# Arm it only around moves where the nozzle must not touch anything: not # Arm it only around moves where the nozzle must not touch anything: not
# around contact homing, extrusion, purges or AFC cuts and loads, which # around contact homing, extrusion, purges or AFC cuts and loads, which
# press on the nozzle on purpose. ARM and DISARM act immediately, not in # press on the nozzle on purpose. ARM and DISARM act immediately, not in
@@ -95,6 +99,7 @@ class BDPGuard:
self.sensor = self.i2c = None self.sensor = self.i2c = None
self.available = False self.available = False
self.timer = None self.timer = None
self.zeroing = False
self.phase_mode = self.mode self.phase_mode = self.mode
self._reset_phase('') self._reset_phase('')
self.printer.register_event_handler('klippy:connect', self.printer.register_event_handler('klippy:connect',
@@ -162,6 +167,23 @@ class BDPGuard:
logging.info(msg) logging.info(msg)
gcmd.respond_info(msg) gcmd.respond_info(msg)
def _rezero(self):
# A fresh zero at every ARM: only force that appears during the
# guarded moves counts, not slow changes before them. Seen with TPU
# in a nozzle heating to 150C: the pressure kept rising (+43) or
# falling as it oozed (-56) for minutes, faster than the sensor's
# own baseline update (only when steady, about every 7 s), and
# stopped the printer at the start of a phase with the nozzle in
# the air. ARM comes after M400, with the nozzle clear of
# everything, so this does not hide a real touch.
self.zeroing = True
try:
self.i2c.i2c_write([REG_RESET_PROBE, 1])
self.reactor.pause(self.reactor.monotonic() + 0.2)
except Exception:
logging.exception("bdp_guard: setting a new zero failed")
self.zeroing = False
def _stop_timer(self): def _stop_timer(self):
if self.timer is not None: if self.timer is not None:
self.reactor.unregister_timer(self.timer) self.reactor.unregister_timer(self.timer)
@@ -179,8 +201,9 @@ class BDPGuard:
self._stop_timer() self._stop_timer()
self.phase = '' self.phase = ''
return self.reactor.NEVER return self.reactor.NEVER
# PA mode (SET_BDPRESSURE START): the delta means nothing then # PA mode (SET_BDPRESSURE START): the delta means nothing then;
if getattr(self.sensor, 'last_state', 0): # while ARM sets a new zero the readings are in between
if self.zeroing or getattr(self.sensor, 'last_state', 0):
return eventtime + self.interval return eventtime + self.interval
data = bytearray(self.i2c.i2c_read([REG_DELTA], 2)['response']) data = bytearray(self.i2c.i2c_read([REG_DELTA], 2)['response'])
if len(data) != 2: if len(data) != 2:
@@ -229,6 +252,7 @@ class BDPGuard:
"extension not found, guard not armed") "extension not found, guard not armed")
return return
self._ensure_probe_mode(gcmd) self._ensure_probe_mode(gcmd)
self._rezero()
self.phase_mode = mode self.phase_mode = mode
self._reset_phase(phase) self._reset_phase(phase)
self.armed_until = self.reactor.monotonic() + self.timeout self.armed_until = self.reactor.monotonic() + self.timeout