Files
mangavalkandClaude Opus 5.5 e5be65834e LEDs: nozzle light follows the motion sensor, new logo status macro
The motion timeout switched the nozzle LEDs off during prints, motion
switched them off when idle or paused, the timeout counted from the first
movement, and every _status_* macro stopped the nozzle light.

- _LIGHTS sets case light and nozzle LEDs from presence, print state and
  CASELIGHT MODE=AUTO|ON|OFF; the timeout (60 s) starts at the sensor
  release
- _STATUS STATE=... replaces the _status_* macros; logo effects only
  cover the logo LEDs and use REPLACE=1
- heater gauge while heating, print progress, paused, error flash from
  _ERROR, part ready once the bed is cool, dim night mode when idle and
  nobody near, cleaning during BLOBIFIER_CLEAN
- removed unused effects and macros, 12 fps for the toolhead effects

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

221 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
_STATUS STATE=paused
# 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 STATE=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 STATE=ready
_LIGHTS_ON
[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