- Split the macro files into folders by topic (print, heating, afc, pressure_advance, spoolman, leds, sensors); klipper-macros.cfg is the one file printer.cfg includes. Macros moved unchanged; the effective config is identical apart from the paths of the PA shell scripts. - Add the modified Blobifier (Turtleblobifier for AFC) and define [save_variables] once in save_variables.cfg instead of in both blobifier.cfg and the PA macros (same file, bd_pa_variables.cfg). - PRINT_WARMUP: heat to the loaded lane's temperature before the first tool change. AFC skips heating when the loaded lane's tool number is not in the print file's temperature list, and the unload then failed below min_extrude_temp. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
128 lines
6.4 KiB
INI
128 lines
6.4 KiB
INI
#####################################################################
|
|
# 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 %}
|
|
{action_raise_error("PURGE_UNTIL_EMPTY: needs bdpressure_check.py and [bdpressure_check]")}
|
|
{% elif printer.print_stats.state == "printing" %}
|
|
{action_raise_error("PURGE_UNTIL_EMPTY: printer is printing, pause the print first")}
|
|
{% elif "xyz" not in printer.toolhead.homed_axes %}
|
|
{action_raise_error("PURGE_UNTIL_EMPTY: home the printer first")}
|
|
{% elif temp < min_temp %}
|
|
{action_raise_error("PURGE_UNTIL_EMPTY: give the filament temperature, e.g. PURGE_UNTIL_EMPTY TEMP=240")}
|
|
{% 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 %}
|
|
{action_raise_error("PURGE_UNTIL_EMPTY: bd_pressure load-check firmware not found")}
|
|
{% 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 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 %}
|
|
{action_raise_error("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")}
|
|
{% 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 %}
|
|
RESPOND TYPE=error 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."
|
|
{% endif %}
|