From a63b66a7d808a1f4381b541b5399c71e09bf64d8 Mon Sep 17 00:00:00 2001 From: MangaValk Date: Mon, 19 Oct 2026 16:34:26 +0200 Subject: [PATCH] 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 --- extras/bdp_guard.py | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/extras/bdp_guard.py b/extras/bdp_guard.py index e64973a..efaa1ab 100644 --- a/extras/bdp_guard.py +++ b/extras/bdp_guard.py @@ -8,6 +8,10 @@ # row at or above THRESHOLD shut Klipper down at once (like M112, without # 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 # around contact homing, extrusion, purges or AFC cuts and loads, which # 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.available = False self.timer = None + self.zeroing = False self.phase_mode = self.mode self._reset_phase('') self.printer.register_event_handler('klippy:connect', @@ -162,6 +167,23 @@ class BDPGuard: logging.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): if self.timer is not None: self.reactor.unregister_timer(self.timer) @@ -179,8 +201,9 @@ class BDPGuard: self._stop_timer() self.phase = '' return self.reactor.NEVER - # PA mode (SET_BDPRESSURE START): the delta means nothing then - if getattr(self.sensor, 'last_state', 0): + # PA mode (SET_BDPRESSURE START): the delta means nothing then; + # 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 data = bytearray(self.i2c.i2c_read([REG_DELTA], 2)['response']) if len(data) != 2: @@ -229,6 +252,7 @@ class BDPGuard: "extension not found, guard not armed") return self._ensure_probe_mode(gcmd) + self._rezero() self.phase_mode = mode self._reset_phase(phase) self.armed_until = self.reactor.monotonic() + self.timeout