Files
klipper-macros/macros/print/pause_resume.cfg
T
mangavalkandClaude Opus 5.5 fbdb2d5e1d Show errors and warnings on the display (_ERROR, _WARN)
action_raise_error aborts while the macro renders, so an M117 in the same
macro never ran and errors such as the RESUME lane check only reached the
console. messages.cfg adds _ERROR (M117, then raise in a separate macro)
and _WARN (RESPOND TYPE=error + M117); all errors and warnings use them.
PAUSE shows AFC's error as the pause reason; RESUME, CANCEL_PRINT and
PRINT_WARMUP clear the display.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 17:41:41 +02:00

219 lines
9.2 KiB
INI

# PAUSE, RESUME, CANCEL_PRINT, M600 (based on the KlipperScreen recommended macros)
#
# Chain on this printer (AFC renames PAUSE/RESUME at startup):
# PAUSE -> AFC_PAUSE (saves position, z-hop) -> this PAUSE -> PAUSE_BASE
# RESUME -> AFC_RESUME -> this RESUME -> HEAT_SOAK_RESUME -> _RESUME_PRINT
# -> RESUME_BASE, then AFC restores the saved position
# RESUME is defined only here: heating/heat_soak.cfg used to define its own,
# which replaced this one completely (no unretract, no fan restore).
# After a PAUSE, _RESUME_PRINT purges into the Blobifier with the purge check
# (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]
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}'"
# AFC pauses after an error: show its first line. Pauses from these
# macros set their own display text before calling PAUSE.
{% set afc_msg = printer.AFC.message|default({}) %}
{% if printer.AFC.error_state and afc_msg.type|default('') == 'error' and afc_msg.message|default('') %}
M117 Paused: {afc_msg.message.split('\n')[0]|trim}
{% endif %}
{% 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
_TOOLHEAD_PARK_PAUSE_CANCEL
SET_GCODE_VARIABLE MACRO=PAUSE VARIABLE=parked VALUE=True
# Set fan to S28 (28/255 ≈ 0.1098)
M106 S28
{% else %}
PAUSE_BASE
{% endif %}
[gcode_macro RESUME]
description: Resume the print (while HEAT_SOAK runs: skip the soak phase)
rename_existing: RESUME_BASE
gcode:
HEAT_SOAK_RESUME ON_RESUME=_RESUME_PRINT {rawparams}
[gcode_macro _RESUME_PRINT]
description: Resume after PAUSE: purge and check (or unretract), restore the part fan, continue the print
variable_purge_length: 40 # mm purged before resuming after a PAUSE; 0 = only unretract
gcode:
{% set pause = printer["gcode_macro PAUSE"] %}
{% set extrude = printer['gcode_macro _TOOLHEAD_PARK_PAUSE_CANCEL'].extrude %}
{% set purge = params.PURGE|default(purge_length)|float %}
#### get VELOCITY parameter if specified ####
{% if 'VELOCITY' in params|upper %}
{% set get_params = ('VELOCITY=' + params.VELOCITY) %}
{%else %}
{% set get_params = "" %}
{% endif %}
##### 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
{% else %}
M83
G1 E{extrude} F2100
{% if printer.gcode_move.absolute_extrude |lower == 'true' %} M82 {% endif %}
{% endif %}
{% else %}
{action_respond_info("Extruder not hot enough")}
{% endif %}
# Restore saved fan speed
{% set old_fan = pause.saved_fan_speed %}
{% if old_fan > 0 %}
M106 S{[(old_fan * 255)|int, 255]|min}
{% else %}
M107
{% endif %}
SET_GCODE_VARIABLE MACRO=PAUSE VARIABLE=parked VALUE=False
SET_GCODE_VARIABLE MACRO=PAUSE VARIABLE=expected_lane VALUE="''"
# Clear the pause reason from the display (no comment on an M117 line: it would show)
M117
{% endif %}
RESUME_BASE {get_params}
_status_printing
# Raising an error (_ERROR, also shown on the display) 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 '?' %}
_ERROR MSG="Lane check: the print needs {expected} ({tool}) but {loaded or 'no lane'} is loaded. Load {expected} with {tool}, then RESUME again (RESUME LANE_CHECK=0 resumes anyway)." DISPLAY="Lane check: load {expected} with {tool}, then RESUME"
{% else %}
RESPOND MSG="Lane check: {expected} loaded, OK"
{% endif %}
{% endif %}
[gcode_macro _RESUME_PURGE]
description: Purge LENGTH mm into the Blobifier (with the purge check if installed) before resuming
gcode:
{% if 'gcode_macro BLOBIFIER_CHECKED' in printer %}
SET_GCODE_VARIABLE MACRO=_PURGE_CHECK_CFG VARIABLE=last_failed VALUE=False
BLOBIFIER_CHECKED PURGE_LENGTH={params.LENGTH}
_RESUME_PURGE_VERIFY
{% else %}
BLOBIFIER PURGE_LENGTH={params.LENGTH}
{% endif %}
# Separate macro so the check result is read after the purge. Raising an
# error aborts the whole RESUME (AFC_RESUME included): the printer stays
# paused at the bucket and PAUSE.parked stays set, so the next RESUME purges
# and checks again.
[gcode_macro _RESUME_PURGE_VERIFY]
gcode:
{% if printer["gcode_macro _PURGE_CHECK_CFG"].last_failed %}
_ERROR MSG="Purge check failed: the print stays paused. Check the extruder and lane, then RESUME again (RESUME PURGE=0 resumes without purging)." DISPLAY="Purge check failed: still paused, see console"
{% endif %}
[gcode_macro _TOOLHEAD_PARK_PAUSE_CANCEL]
description: Helper: park toolhead used in PAUSE and CANCEL_PRINT
variable_extrude: 2.0
gcode:
##### set park positon for x and y #####
# default is your max posion from your printer.cfg
# {% set x_park = printer.toolhead.axis_maximum.x|float - 5.0 %}
{% set x_park = 20.0 %}
{% set y_park = printer.toolhead.axis_maximum.y|float - 5.0 %}
{% set z_park_delta = 2.0 %}
##### calculate save lift position #####
{% set max_z = printer.toolhead.axis_maximum.z|float %}
{% set act_z = printer.toolhead.position.z|float %}
{% if act_z < (max_z - z_park_delta) %}
{% set z_safe = z_park_delta %}
{% else %}
{% set z_safe = max_z - act_z %}
{% endif %}
##### end of definitions #####
{% if printer.extruder.can_extrude|lower == 'true' %}
M83
G1 E-{extrude} F2100
{% if printer.gcode_move.absolute_extrude |lower == 'true' %} M82 {% endif %}
{% else %}
{action_respond_info("Extruder not hot enough")}
{% endif %}
{% if "xyz" in printer.toolhead.homed_axes %}
G91
G1 Z{z_safe} F900
G90
G1 X{x_park} Y{y_park} F6000
{% if printer.gcode_move.absolute_coordinates|lower == 'false' %} G91 {% endif %}
{% else %}
{action_respond_info("Printer not homed")}
{% endif %}
[gcode_macro CANCEL_PRINT]
description: Cancel the actual running print
rename_existing: CANCEL_PRINT_BASE_KLIPPERSCREEN
variable_park: True
gcode:
{% set pause = printer["gcode_macro PAUSE"] %}
{% set park_retract = printer['gcode_macro _TOOLHEAD_PARK_PAUSE_CANCEL'].extrude %}
## Move head and retract only if not already in the pause state and park set to true
{% if printer.pause_resume.is_paused|lower == 'false' and park|lower == 'true'%}
_TOOLHEAD_PARK_PAUSE_CANCEL
{% endif %}
STOP_HEAT_SOAK
CANCEL_PRINT_BASE_KLIPPERSCREEN
# Same end-of-print retract as PRINT_END (skipped if the nozzle is already cold);
# EXTRA: the park retract of PAUSE or of the park above, so PRINT_START undoes it too
{% if printer.pause_resume.is_paused %}
_NOZZLE_RETRACT EXTRA={park_retract if pause.parked else 0}
{% elif park and printer.extruder.can_extrude %}
_NOZZLE_RETRACT EXTRA={park_retract}
{% else %}
_NOZZLE_RETRACT
{% endif %}
# Same cleanup as PRINT_END: heaters incl. chamber heater, fan, flow, bdwidth
_PRINT_CLEANUP
SET_GCODE_VARIABLE MACRO=PAUSE VARIABLE=parked VALUE=False
# Clear a pause reason from the display
M117
_status_ready
[gcode_macro M600]
#
# M600
# https://github.com/simplisticton/common-macros/tree/main
#
# Mimic Marlin's Pause for filament change command
description: Pause for filament change
gcode:
PAUSE
M117 Paused
M118 Print paused for filament change... type "Resume" to continue