From a67e99015ffc5053d4b250d918c70967e5c467d2 Mon Sep 17 00:00:00 2001 From: MangaValk Date: Thu, 15 Oct 2026 22:12:53 +0200 Subject: [PATCH] RESUME: check the AFC lane, add AFC_CLEAR_ALL_MESSAGES PAUSE stores the lane the print needs (AFC's next_lane during a failed tool change, otherwise the loaded lane). RESUME stops with an error when another lane or none is loaded; RESUME LANE_CHECK=0 skips the check. AFC_CLEAR_ALL_MESSAGES clears AFC's whole message queue (AFC_CLEAR_MESSAGE only removes the first message). Co-Authored-By: Claude Opus 5.5 --- macros/afc/lane_tools.cfg | 15 ++++++++++++++- macros/print/pause_resume.cfg | 29 +++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/macros/afc/lane_tools.cfg b/macros/afc/lane_tools.cfg index dee5828..3e489ab 100644 --- a/macros/afc/lane_tools.cfg +++ b/macros/afc/lane_tools.cfg @@ -1,4 +1,4 @@ -# AFC lane tools: LANE_FEED_UNTIL_HUB_OPEN, LANE_FEED_ABORT +# AFC lane tools: LANE_FEED_UNTIL_HUB_OPEN, LANE_FEED_ABORT, AFC_CLEAR_ALL_MESSAGES ##################################################################### ## unloading help @@ -98,3 +98,16 @@ gcode: # T1 ; Unload # G4 P3000 ; Wait 3s # {% endfor %} + +##################################################################### +## AFC messages +##################################################################### +# AFC queues every error and warning; the UI shows only the first one and +# AFC_CLEAR_MESSAGE removes only that one. AFC does not expose the queue +# length, so clear MAX times (clearing an empty queue does nothing). +[gcode_macro AFC_CLEAR_ALL_MESSAGES] +description: Clear all AFC error and warning messages (MAX=50) +gcode: + {% for i in range(params.MAX|default(50)|int) %} + AFC_CLEAR_MESSAGE + {% endfor %} diff --git a/macros/print/pause_resume.cfg b/macros/print/pause_resume.cfg index 216ce35..f98e758 100644 --- a/macros/print/pause_resume.cfg +++ b/macros/print/pause_resume.cfg @@ -10,6 +10,10 @@ # (BLOBIFIER_CHECKED, afc/purge_check.cfg) before going back to the print, so # the nozzle is primed and clean. If the check fails the resume stops with an # error and the printer stays paused. RESUME PURGE=0 resumes without the purge. +# Before that it checks the AFC lane: PAUSE stores the lane the print needs +# (the lane AFC was loading when a tool change failed, otherwise the loaded +# lane), and RESUME stops with an error when another lane (or none) is loaded. +# RESUME LANE_CHECK=0 resumes anyway (e.g. after remapping with SET_MAP). # https://klipperscreen.readthedocs.io/en/latest/macros/#recommended [gcode_macro PAUSE] @@ -17,8 +21,15 @@ description: Pause the actual running print rename_existing: PAUSE_BASE variable_saved_fan_speed: 0.0 variable_parked: False # set by PAUSE, used by _RESUME_PRINT +variable_expected_lane: '' # AFC lane the print needs after RESUME ('' = no check) gcode: {% if not printer.pause_resume.is_paused %} + # AFC sets next_lane during a tool change and still has it when a failed + # change pauses the print; it clears it once CHANGE_TOOL returns + {% if 'AFC' in printer %} + {% set lane = printer.AFC.next_lane or printer.AFC.current_load or '' %} + SET_GCODE_VARIABLE MACRO=PAUSE VARIABLE=expected_lane VALUE="'{lane}'" + {% endif %} SET_GCODE_VARIABLE MACRO=PAUSE VARIABLE=saved_fan_speed VALUE={printer.fan.speed} # Pause first, so the saved state is the print position, then retract and park PAUSE_BASE @@ -52,6 +63,7 @@ gcode: ##### end of definitions ##### # Only undo what PAUSE did; HEAT_SOAK pauses with PAUSE_BASE (no retract, no park) {% if pause.parked %} + _RESUME_LANE_CHECK {'LANE_CHECK=%s' % params.LANE_CHECK if 'LANE_CHECK' in params else ''} {% if printer.extruder.can_extrude|lower == 'true' %} {% if purge > 0 and 'gcode_macro BLOBIFIER' in printer %} _RESUME_PURGE LENGTH={purge} ; also replaces the unretract; stops here if the check fails @@ -72,11 +84,28 @@ gcode: M107 {% endif %} SET_GCODE_VARIABLE MACRO=PAUSE VARIABLE=parked VALUE=False + SET_GCODE_VARIABLE MACRO=PAUSE VARIABLE=expected_lane VALUE="''" {% endif %} RESUME_BASE {get_params} _status_printing +# Raising an error aborts the whole RESUME like a failed purge check: the +# printer stays paused and the next RESUME checks again. +[gcode_macro _RESUME_LANE_CHECK] +description: Stop the resume when AFC has another lane loaded than the one the print needs +gcode: + {% set expected = printer["gcode_macro PAUSE"].expected_lane %} + {% if expected and 'AFC' in printer and params.LANE_CHECK|default(1)|int %} + {% set loaded = printer.AFC.current_load %} + {% if loaded != expected %} + {% set obj = 'AFC_stepper ' ~ expected %} + {% set tool = printer[obj].map if obj in printer else '?' %} + {action_raise_error("Lane check: the print needs %s (%s) but %s is loaded. Load %s with %s, then RESUME again (RESUME LANE_CHECK=0 resumes anyway)." % (expected, tool, loaded or 'no lane', expected, tool))} + {% endif %} + RESPOND MSG="Lane check: {expected} loaded, OK" + {% endif %} + [gcode_macro _RESUME_PURGE] description: Purge LENGTH mm into the Blobifier (with the purge check if installed) before resuming gcode: