Flexible lanes load slower; purge at the previous filament's temperature

- flex_lanes.cfg: a 5 s poller sets SET_LONG_MOVE_SPEED to 50 mm/s (AFC's
  minimum) for lanes whose material is TPU/TPE/flex and back to the
  configured long_moves_speed otherwise; reapplied after a restart.
- BLOBIFIER_CHECKED: remembers the temperature of the filament in the
  nozzle (saved nozzle_last_temp). When it is more than flush_margin
  (10C) above the new filament's, the purge runs at that temperature and
  the nozzle cools back afterwards, so the leftover melts out (seen: ASA
  leftover with TPU loaded at 210C).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
mangavalkandClaude Opus 5.5 committed 2026-10-19 15:59:27 +02:00
1 parent 464a7c1046
commit d49e65c0bb
4 files changed
+98 -1

No files matched your search

+54
View File
@@ -0,0 +1,54 @@
# Flexible filament (TPU, TPE): slower long moves for the lanes holding it.
#
# Soft filament can buckle in the long tube at the normal 100-200 mm/s.
# A poller checks the material of every lane (from Spoolman via AFC) every
# 5 s and sets the lane's long-move speed: flex_speed for a flexible
# material, the configured long_moves_speed again when the lane holds
# something else. Only changes are sent. SET_LONG_MOVE_SPEED is runtime
# only; after a Klipper restart the poller applies it again.
#
# Not covered: the last stretch into the extruder (tool_load_speed in
# AFC/AFC_Hardware.cfg, 25 mm/s) has no runtime command and is the same
# for every lane. The purge after the load is already slow (2.5 mm/s).
[gcode_macro _FLEX_LANES_CFG]
variable_materials: ["tpu", "tpe", "flex"] # material containing one of these (any case) is flexible
variable_flex_speed: 50 # mm/s; AFC's minimum for SET_LONG_MOVE_SPEED is 50
variable_slowed: "" # runtime: comma list of lanes now at flex_speed
gcode:
[delayed_gcode _FLEX_LANES_POLL]
initial_duration: 10
gcode:
{% set cfg = printer["gcode_macro _FLEX_LANES_CFG"] %}
{% if 'AFC' in printer %}
{% set settings = printer.configfile.settings %}
{% set default_speed = settings.afc.long_moves_speed|default(150) if 'afc' in settings else 150 %}
{% set was = cfg.slowed.split(',')|reject('equalto', '')|list %}
{% set now = [] %}
{% for lane in printer.AFC.lanes %}
{% set key = 'AFC_stepper ' ~ lane %}
{% set mat = (printer[key].material if key in printer else '')|default('', true)|string %}
{% set ns = namespace(flex=false) %}
{% for m in cfg.materials %}
{% if m in mat|lower %}
{% set ns.flex = true %}
{% endif %}
{% endfor %}
{% if ns.flex %}
{% set _ = now.append(lane) %}
{% if lane not in was %}
SET_LONG_MOVE_SPEED LANE={lane} FWD_SPEED={cfg.flex_speed}
RESPOND MSG="{lane} holds {mat}: long moves at {cfg.flex_speed} mm/s (flexible)"
{% endif %}
{% elif lane in was %}
{% set speed = settings[key|lower].long_moves_speed|default(default_speed) if (key|lower) in settings else default_speed %}
SET_LONG_MOVE_SPEED LANE={lane} FWD_SPEED={speed}
RESPOND MSG="{lane} holds {mat or 'nothing'}: long moves back at {speed} mm/s"
{% endif %}
{% endfor %}
{% if now|join(',') != was|join(',') %}
SET_GCODE_VARIABLE MACRO=_FLEX_LANES_CFG VARIABLE=slowed VALUE='"{now|join(',')}"'
{% endif %}
{% endif %}
UPDATE_DELAYED_GCODE ID=_FLEX_LANES_POLL DURATION=5
+41
View File
@@ -54,6 +54,14 @@ variable_start_counts: 0
variable_start_e: 0.0
variable_last_failed: False # last check failed in enforce mode (read by _RESUME_PURGE_VERIFY)
variable_ignore_missing_sensor: False # set by PURGE_CHECK_IGNORE_SENSOR, cleared at print end
# Hotter purge: the leftover of the previous filament (the piece below the
# cutter) has to melt to be pushed out. When the filament that last went
# through the nozzle (saved variable nozzle_last_temp) needs more than the
# new one plus flush_margin, the purge runs at that temperature and the
# nozzle cools back to the new filament's afterwards (seen: ASA leftover,
# TPU loaded at 210C, purge only worked after heating by hand).
variable_flush_margin: 10 # C; smaller differences purge at the new temperature
variable_flush_restore: 0 # runtime: temperature to cool back to after a hot purge
gcode:
[gcode_macro BLOBIFIER_CHECKED]
@@ -77,6 +85,7 @@ gcode:
# the purge too, so a bdwidth that does not see the movement cannot
# pause the printer here; the pressure check judges the purge.
{% set runout_off = has_bdw and (bdw_on or not cfg.motion_check) %}
_PURGE_FLUSH_HEAT
{% if cfg.mode == "off" %}
BLOBIFIER {rawparams}
{% else %}
@@ -107,9 +116,41 @@ gcode:
SET_FILAMENT_SENSOR SENSOR={bdw} ENABLE={runout_was}
{% endif %}
{% endif %}
_PURGE_FLUSH_DONE
# Separate macros so the status is read when they run, not when
# BLOBIFIER_CHECKED is rendered
[gcode_macro _PURGE_FLUSH_HEAT]
description: Helper for BLOBIFIER_CHECKED: heat to the previous filament's temperature when it is hotter than the new one
gcode:
{% set cfg = printer["gcode_macro _PURGE_CHECK_CFG"] %}
{% set old = printer.save_variables.variables.nozzle_last_temp|default(0)|int %}
{% set new = printer.extruder.target|int %}
{% set top = printer.configfile.settings.extruder.max_temp|int - 15 %}
{% set hot = [old, top]|min %}
{% if new > 0 and hot > new + cfg.flush_margin %}
RESPOND MSG="Purge at {hot}C: the previous filament needs {old}C, back to {new}C after the purge"
SET_GCODE_VARIABLE MACRO=_PURGE_CHECK_CFG VARIABLE=flush_restore VALUE={new}
M104 S{hot}
TEMPERATURE_WAIT SENSOR=extruder MINIMUM={hot - 2}
{% else %}
SET_GCODE_VARIABLE MACRO=_PURGE_CHECK_CFG VARIABLE=flush_restore VALUE=0
{% endif %}
[gcode_macro _PURGE_FLUSH_DONE]
description: Helper for BLOBIFIER_CHECKED: cool back after a hot purge and remember the new filament's temperature
gcode:
{% set cfg = printer["gcode_macro _PURGE_CHECK_CFG"] %}
{% set new = cfg.flush_restore|int if cfg.flush_restore|int > 0 else printer.extruder.target|int %}
{% if cfg.flush_restore|int > 0 %}
M104 S{new}
TEMPERATURE_WAIT SENSOR=extruder MAXIMUM={new + 3}
SET_GCODE_VARIABLE MACRO=_PURGE_CHECK_CFG VARIABLE=flush_restore VALUE=0
{% endif %}
{% if new > 0 %}
SAVE_VARIABLE VARIABLE=nozzle_last_temp VALUE={new}
{% endif %}
[gcode_macro _PURGE_CHECK_START]
gcode:
SET_GCODE_VARIABLE MACRO=_PURGE_CHECK_CFG VARIABLE=start_counts VALUE={printer.bdwidth_status.total_move}