Reject PA calibrations with no result or bad sensor data
bdpressure.py leaves the extruder at the last PA_CALIBRATE test value (0.098) when it finds no result, and _PA_AFTER_CALIBRATE saved that as the calibrated PA (lane1 after an AFC pause, lane5 after the sensor went silent). A run is now rejected, with nothing cached or written to Spoolman, when the PA is still at the end of the scan, the printer paused during the test, or bd_pressure gave too few or too few different readings. The previous valid PA (or fallback_pa) is applied instead. bdpressure_check reports pa_points and pa_distinct from the bdpressure module's last PA_CALIBRATE data for this. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
82f9486160
commit
25891640b8
3 files changed
+60
-3
No files matched your search
@@ -37,7 +37,7 @@ everything below, grouped by topic. Comment out what you do not use there.
|
||||
| `purge_check.cfg` | `BLOBIFIER_CHECKED`: checks every AFC purge with bd_pressure (and optionally bdwidth motion) | Blobifier, AFC, `extras/bdpressure_check.py` + bd_pressure load-check firmware, `extras/bdwidth_status.py` |
|
||||
| `purge_until_empty.cfg` | `PURGE_UNTIL_EMPTY`: purges a snapped filament out until there is no more nozzle pressure | same as `purge_check.cfg` |
|
||||
| **pressure_advance/** | | |
|
||||
| `bd_pa_spoolman.cfg` + `bd_pa_*.sh` | `LANE_CALIBRATE_PA`, `PA_CALIBRATE_ALL_LANES`, `LANE_RECAL_PA`, `SET_SPOOL_ID`, `PA_STATUS`: pressure advance per lane/spool, cached locally and in Spoolman | bd_pressure, AFC, Spoolman, `gcode_shell_command` |
|
||||
| `bd_pa_spoolman.cfg` + `bd_pa_*.sh` | `LANE_CALIBRATE_PA`, `PA_CALIBRATE_ALL_LANES`, `LANE_RECAL_PA`, `SET_SPOOL_ID`, `PA_STATUS`: pressure advance per lane/spool, cached locally and in Spoolman; a calibration with no result, a pause during the test or too few/stuck sensor readings is rejected and not saved | bd_pressure, AFC, Spoolman, `gcode_shell_command` |
|
||||
| **spoolman/** | | |
|
||||
| `active_spool.cfg` | `SET_ACTIVE_SPOOL`, `CLEAR_ACTIVE_SPOOL` | Spoolman in Moonraker |
|
||||
| **leds/** | | |
|
||||
@@ -51,7 +51,7 @@ everything below, grouped by topic. Comment out what you do not use there.
|
||||
|---|---|
|
||||
| `xy_drift.py` | `AFC_XY_SAFETY_CHECK`: measures lost XY steps from the stepper step counts at the endstop triggers (CoreXY). The toolhead position after homing cannot show lost steps. |
|
||||
| `bdwidth_status.py` | exposes bdwidth's motion counter and width to macros (`present: False` with neutral values when no bdwidth is configured, so the macros also work without it), and keeps a USB dropout of bdwidth (port: usb) from shutting down Klipper: the read is retried every 10 s and the port reopened |
|
||||
| `bdpressure_check.py` | bd_pressure load check (`BDP_CHECK_START/STOP/QUERY`). Needs the load-check firmware from the bd_pressure `load-check-extension` branch; on stock firmware it reports "not available" and does nothing. |
|
||||
| `bdpressure_check.py` | bd_pressure load check (`BDP_CHECK_START/STOP/QUERY`). Needs the load-check firmware from the bd_pressure `load-check-extension` branch; on stock firmware it reports "not available" and does nothing. Also reports how many readings the last `PA_CALIBRATE` got (`pa_points`, `pa_distinct`), used to reject runs with a silent or stuck sensor. |
|
||||
|
||||
### Scripts (`scripts/`)
|
||||
|
||||
|
||||
@@ -19,6 +19,11 @@
|
||||
#
|
||||
# Status (printer.bdpressure_check), updated by the commands above:
|
||||
# available, running, peak, above_ms, longest_ms, delta
|
||||
# pa_points, pa_distinct - readings the [bdpressure] module collected in
|
||||
# its last PA_CALIBRATE, and how many of them differ (read
|
||||
# from that module, not from the sensor). A sensor that
|
||||
# stops answering gives few points; one that hangs repeats
|
||||
# the same reading. LANE_CALIBRATE_PA rejects such runs.
|
||||
|
||||
REG_EXT = 54 # first byte of the extension
|
||||
REG_CTRL = 56
|
||||
@@ -31,6 +36,7 @@ class BDPressureCheck:
|
||||
self.printer = config.get_printer()
|
||||
self.sensor_name = 'bdpressure ' + config.get('sensor', 'bd_pa')
|
||||
self.i2c = None
|
||||
self.sensor = None
|
||||
self.status = {'available': False, 'running': False, 'peak': 0,
|
||||
'above_ms': 0, 'longest_ms': 0, 'delta': 0}
|
||||
self.printer.register_event_handler('klippy:connect',
|
||||
@@ -45,6 +51,7 @@ class BDPressureCheck:
|
||||
|
||||
def _handle_connect(self):
|
||||
sensor = self.printer.lookup_object(self.sensor_name)
|
||||
self.sensor = sensor
|
||||
self.i2c = getattr(sensor, 'i2c', None)
|
||||
|
||||
def _read(self):
|
||||
@@ -100,7 +107,15 @@ class BDPressureCheck:
|
||||
self._respond(gcmd, "BDP_CHECK_QUERY")
|
||||
|
||||
def get_status(self, eventtime):
|
||||
return dict(self.status)
|
||||
status = dict(self.status)
|
||||
# [val, res, lk, rk, Hk, Ha] per reading, see bdpressure.py
|
||||
try:
|
||||
data = list(getattr(self.sensor, 'PA_data', None) or [])
|
||||
status['pa_points'] = len(data)
|
||||
status['pa_distinct'] = len(set(tuple(d[1:]) for d in data))
|
||||
except Exception:
|
||||
status['pa_points'] = status['pa_distinct'] = -1
|
||||
return status
|
||||
|
||||
|
||||
def load_config(config):
|
||||
|
||||
@@ -196,6 +196,19 @@ variable_travel_speed: 300
|
||||
variable_acc_to_decel_factor: 50
|
||||
# Minimum PA delta before we bother re-saving the cached value
|
||||
variable_write_threshold: 0.002
|
||||
# A calibration is rejected (nothing cached or written to Spoolman, the
|
||||
# previous PA is kept) when:
|
||||
# - its result is the last PA_CALIBRATE test value: bdpressure.py found no
|
||||
# result and left the extruder at the end of its scan (0..49 x 0.002),
|
||||
# - the printer paused during the test (e.g. an AFC filament fault),
|
||||
# - bd_pressure gave fewer than min_points readings or fewer than
|
||||
# min_distinct different ones (sensor silent or hung; needs
|
||||
# bdpressure_check.py, otherwise this check is skipped).
|
||||
variable_sweep_end_pa: 0.098
|
||||
variable_min_points: 10
|
||||
variable_min_distinct: 8
|
||||
# PA applied when a rejected lane has no earlier cached value
|
||||
variable_fallback_pa: 0.04
|
||||
# Spoolman URL and the custom "extra" field name used to push calibrated
|
||||
# PA values back to the spool record (so the value travels with the
|
||||
# spool, not just with this printer's local save_variables cache).
|
||||
@@ -469,6 +482,34 @@ gcode:
|
||||
# triggered -- which happens after PA_CALIBRATE (queued earlier by
|
||||
# the caller) has fully completed. So this read is fresh and correct.
|
||||
{% set new_pa = printer.extruder.pressure_advance|default(0.0)|float %}
|
||||
|
||||
# Reject runs where the sensor or the printer had a problem
|
||||
{% set problems = [] %}
|
||||
{% if new_pa >= cfg.sweep_end_pa|float - 0.0001 %}
|
||||
{% set _ = problems.append("no result (PA left at the end of the test range, %.3f)" % new_pa) %}
|
||||
{% endif %}
|
||||
{% if printer.pause_resume.is_paused %}
|
||||
{% set _ = problems.append("the printer paused during the test") %}
|
||||
{% endif %}
|
||||
{% if 'bdpressure_check' in printer %}
|
||||
{% set bdp = printer.bdpressure_check %}
|
||||
{% set points = bdp.pa_points|default(-1)|int %}
|
||||
{% set distinct = bdp.pa_distinct|default(-1)|int %}
|
||||
{% if points >= 0 and points < cfg.min_points|int %}
|
||||
{% set _ = problems.append("only %d readings from bd_pressure (sensor not answering?)" % points) %}
|
||||
{% elif distinct >= 0 and distinct < cfg.min_distinct|int %}
|
||||
{% set _ = problems.append("only %d different readings out of %d (sensor stuck?)" % (distinct, points)) %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% if problems %}
|
||||
# A cached value at the end of the scan is an earlier failed run, not a PA
|
||||
{% set use_cache = cache_found and cached_pa < cfg.sweep_end_pa|float - 0.0001 %}
|
||||
{% set keep = cached_pa if use_cache else cfg.fallback_pa|float %}
|
||||
RESPOND TYPE=error MSG="PA calibration for {lane} (spool {spool_id}) rejected: {problems|join('; ')}. Nothing saved; using PA={'%.4f' % keep} ({'cached' if use_cache else 'fallback'}). Fix the cause, then LANE_CALIBRATE_PA LANE={lane} FORCE=1"
|
||||
SET_PRESSURE_ADVANCE ADVANCE={keep}
|
||||
M117 PA cal rejected: {lane}
|
||||
{% else %}
|
||||
{action_respond_info("Calibration complete for %s: PA=%.4f" % (lane, new_pa))}
|
||||
M117 PA cal done: {new_pa|round(4)}
|
||||
|
||||
@@ -480,6 +521,7 @@ gcode:
|
||||
{% else %}
|
||||
{action_respond_info("PA change below threshold (%.4f), skipping cache/Spoolman write" % cfg.write_threshold|float)}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user