Macros as they run on the printer (Voron 2.4 + AFC Box Turtle + Blobifier + Beacon + bd_pressure + bdwidth + iHeater), the Klipper modules they need (xy_drift, bdwidth_status, bdpressure_check), MCU firmware update scripts, install.sh with Moonraker update manager support, and READMEs. 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 %}
|