Files
klipper-macros/macros/afc/purge_until_empty.cfg
T

127 lines
6.6 KiB
INI
Raw Normal View History

#####################################################################
# PURGE_UNTIL_EMPTY - purge a broken filament out through the nozzle
#
# When the filament snaps inside the PTFE tube, the piece below the break
# is still in the extruder. This macro repeats the Blobifier purge and
# measures each one with bd_pressure (load-check firmware). It stops after
# the first purge without sustained nozzle pressure: the extruder no longer
# has filament to push.
#
# What stays behind: the extruder can only push filament its gears still
# grip. Once the tail has passed the gears, the last bit between the gears
# and the nozzle stays in the hotend. The next normal load pushes it out.
#
# The AFC lane is unsynced first (UNSET_LANE_LOADED). Otherwise AFC keeps
# feeding the lane together with the extruder, the spool side of the break
# can catch up and the purge never ends. Afterwards AFC sees no lane loaded:
# eject or reload the lane as usual.
#
# bdwidth sits at the start of the tube, so after the break it sees no
# filament while the extruder keeps pushing. Its runout response (motion or
# width) would pause the printer mid-purge, so it is switched off during the
# purges (SET_FILAMENT_SENSOR) and restored afterwards. bdwidth is not used
# to decide when to stop: only the nozzle pressure can see the last piece.
#
# Needs: bdpressure_check.py + [bdpressure_check] (see purge_check.cfg)
# Blobifier, homed printer, hot nozzle (the macro heats if needed)
#
# Usage (printer idle or paused, not while printing):
# PURGE_UNTIL_EMPTY defaults below
# PURGE_UNTIL_EMPTY TEMP=240 MAX=10 filament temperature, purge limit
# PURGE_UNTIL_EMPTY LENGTH=100 mm per purge (default: Blobifier's)
# PURGE_UNTIL_EMPTY UNSYNC=0 keep the AFC lane synced
#
# Each purge prints one line; the end result says whether the nozzle ran
# empty or MAX purges were reached (lane still feeding, or nozzle blocked).
#####################################################################
[gcode_macro PURGE_UNTIL_EMPTY]
description: Repeat the Blobifier purge until bd_pressure measures no more filament
variable_max_purges: 15 # safety limit: ~1.2 m of bowden is ~8 purges of 150 mm
variable_empty_ms: 5000 # longest pressure below this = no filament (good purge ~17 s, empty ~30 ms)
variable_done: 0
variable_count: 0
gcode:
{% set cfg = printer["gcode_macro PURGE_UNTIL_EMPTY"] %}
{% set max_purges = params.MAX|default(cfg.max_purges)|int %}
{% set length = params.LENGTH|default(0)|float %}
{% set unsync = params.UNSYNC|default(1)|int %}
{% set min_temp = printer.configfile.settings.extruder.min_extrude_temp|float %}
{% set temp = params.TEMP|default([printer.extruder.target, 0]|max)|float %}
{% if 'bdpressure_check' not in printer %}
_ERROR MSG="PURGE_UNTIL_EMPTY: needs bdpressure_check.py and [bdpressure_check]"
{% elif printer.print_stats.state == "printing" %}
_ERROR MSG="PURGE_UNTIL_EMPTY: printer is printing, pause the print first"
{% elif "xyz" not in printer.toolhead.homed_axes %}
_ERROR MSG="PURGE_UNTIL_EMPTY: home the printer first"
{% elif temp < min_temp %}
_ERROR MSG="PURGE_UNTIL_EMPTY: give the filament temperature, e.g. PURGE_UNTIL_EMPTY TEMP=240" DISPLAY="PURGE_UNTIL_EMPTY: give TEMP=..."
{% else %}
BDP_CHECK_QUERY
_PURGE_UNTIL_EMPTY_RUN MAX={max_purges} LENGTH={length} UNSYNC={unsync} TEMP={temp}
{% endif %}
# Rendered after BDP_CHECK_QUERY, so 'available' is current.
[gcode_macro _PURGE_UNTIL_EMPTY_RUN]
gcode:
{% if not printer.bdpressure_check.available %}
_ERROR MSG="PURGE_UNTIL_EMPTY: bd_pressure load-check firmware not found" DISPLAY="PURGE_UNTIL_EMPTY: no bd_pressure"
{% endif %}
SET_GCODE_VARIABLE MACRO=PURGE_UNTIL_EMPTY VARIABLE=done VALUE=0
SET_GCODE_VARIABLE MACRO=PURGE_UNTIL_EMPTY VARIABLE=count VALUE=0
{% if params.UNSYNC|int and printer.AFC.current_load %}
RESPOND MSG="PURGE_UNTIL_EMPTY: unsyncing {printer.AFC.current_load} from the extruder (UNSET_LANE_LOADED)"
UNSET_LANE_LOADED
{% endif %}
{% set bdw = printer.bdwidth_status.name if 'bdwidth_status' in printer and printer.bdwidth_status.present|default(true) else '' %}
{% set runout_was = 1 if bdw and printer.bdwidth_status.enabled else 0 %}
{% if runout_was %}
RESPOND MSG="PURGE_UNTIL_EMPTY: bdwidth runout response off during the purges"
SET_FILAMENT_SENSOR SENSOR={bdw} ENABLE=0
{% endif %}
M109 S{params.TEMP}
{% for i in range(params.MAX|int) %}
_PURGE_UNTIL_EMPTY_STEP LENGTH={params.LENGTH}
{% endfor %}
_PURGE_UNTIL_EMPTY_RESULT MAX={params.MAX} BDW={bdw if runout_was else '-'}
# Rendered when it runs, so it sees the result of the previous purge.
[gcode_macro _PURGE_UNTIL_EMPTY_STEP]
gcode:
{% if not printer["gcode_macro PURGE_UNTIL_EMPTY"].done %}
{% set length = params.LENGTH|default(0)|float %}
M400
G4 P500
BDP_CHECK_START
BLOBIFIER {'PURGE_LENGTH=%.1f' % length if length > 0 else ''}
M400
BDP_CHECK_STOP
_PURGE_UNTIL_EMPTY_EVAL
{% endif %}
[gcode_macro _PURGE_UNTIL_EMPTY_EVAL]
gcode:
{% set cfg = printer["gcode_macro PURGE_UNTIL_EMPTY"] %}
{% set p = printer.bdpressure_check %}
{% set n = cfg.count + 1 %}
{% if not p.available %}
_ERROR MSG="PURGE_UNTIL_EMPTY: lost the bd_pressure load-check reading, stopped. bdwidth runout response may still be off: SET_FILAMENT_SENSOR SENSOR=<bdwidth name> ENABLE=1" DISPLAY="PURGE_UNTIL_EMPTY: lost bd_pressure, stopped"
{% endif %}
{% set empty = p.longest_ms < cfg.empty_ms %}
SET_GCODE_VARIABLE MACRO=PURGE_UNTIL_EMPTY VARIABLE=count VALUE={n}
RESPOND MSG="PURGE_UNTIL_EMPTY purge {n}: pressure longest {p.longest_ms} ms, total {p.above_ms} ms, peak {p.peak} -> {'empty' if empty else 'filament'}"
{% if empty %}
SET_GCODE_VARIABLE MACRO=PURGE_UNTIL_EMPTY VARIABLE=done VALUE=1
{% endif %}
[gcode_macro _PURGE_UNTIL_EMPTY_RESULT]
gcode:
{% set cfg = printer["gcode_macro PURGE_UNTIL_EMPTY"] %}
{% if params.BDW|default('-') != '-' %}
SET_FILAMENT_SENSOR SENSOR={params.BDW} ENABLE=1
{% endif %}
{% if cfg.done %}
RESPOND MSG="PURGE_UNTIL_EMPTY: no more filament after {cfg.count} purge{'s' if cfg.count != 1 else ''}. The last bit between the extruder gears and the nozzle is pushed out by the next load."
{% else %}
_WARN MSG="PURGE_UNTIL_EMPTY: still pressure after {params.MAX} purges. The lane may still be feeding, or the nozzle is blocked - check before running it again." DISPLAY="PURGE_UNTIL_EMPTY: still pressure, check lane and nozzle"
{% endif %}