From e152246e9fec6a208152e7fdd2e0932d4d4221a7 Mon Sep 17 00:00:00 2001 From: MangaValk Date: Sun, 11 Oct 2026 15:01:55 +0200 Subject: [PATCH] Retract at print end, undo it at print start Klipper's G10 retracts only once until a G11, and nothing sends G11 on this printer: the G10 in PRINT_WARMUP used up the retract, so PRINT_END never retracted and the nozzle leaked while cooling down. - _NOZZLE_RETRACT retracts and remembers the amount in the saved variable nozzle_retract (survives restarts, capped at 15 mm). PRINT_END retracts 5 mm, PRINT_WARMUP 2 mm, CANCEL_PRINT 5 mm plus the park/PAUSE retract. - _NOZZLE_UNRETRACT in PRINT_START pushes it back over the bucket before the wipe. Co-Authored-By: Claude Opus 5.5 --- CLAUDE.md | 4 +++ macros/print/pause_resume.cfg | 11 +++++++ macros/print/print_start_end.cfg | 49 ++++++++++++++++++++++++++++++-- 3 files changed, 61 insertions(+), 3 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 0f2b012..2cb7be9 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -54,6 +54,10 @@ check runs with `motion_check: False`), iHeater chamber heater. `iHEATER_OFF`, fan, `M221 S100`, bdwidth off). Anything that must happen at the end of every print goes there. `RESTORE_GCODE_STATE` restores the flow (M221), so reset flow after it, not before. +- Do not use `G10`/`G11` in macros: Klipper's `G10` retracts only once until + a `G11`, and nothing on this printer sends `G11`. Use `_NOZZLE_RETRACT` + (remembered in the saved variable `nozzle_retract`); `PRINT_START` undoes + it over the bucket with `_NOZZLE_UNRETRACT`. - Inside `gcode:` use `;` for comments on G-code lines; `#` lines are stripped by the config parser. - After a refactor run `python tools/effective_config.py HEAD` and check that diff --git a/macros/print/pause_resume.cfg b/macros/print/pause_resume.cfg index 30dd3db..b7908fa 100644 --- a/macros/print/pause_resume.cfg +++ b/macros/print/pause_resume.cfg @@ -109,6 +109,8 @@ 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'%} @@ -117,6 +119,15 @@ gcode: 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 diff --git a/macros/print/print_start_end.cfg b/macros/print/print_start_end.cfg index 6281d45..3241cae 100644 --- a/macros/print/print_start_end.cfg +++ b/macros/print/print_start_end.cfg @@ -79,7 +79,7 @@ gcode: T{initial_tool} #PURGE_LENGTH=100 #Load Initial Tool M104 S{target_extruder} ; set extruder to print temp M109 S{target_extruder} ; wait for extruder temp - G10 ; retract + _NOZZLE_RETRACT LENGTH=2 ; no oozing while waiting; PRINT_START pushes it back M104 S150 ; set nozzle temp to 150 M109 S150 ; wait until nozzle reaches 150 ; wait until nozzle reaches 0 @@ -165,6 +165,8 @@ gcode: _status_heating M104 S{target_extruder} ; set extruder to print temp M109 S{target_extruder} ; wait for extruder temp + BLOBIFIER_PARK ; over the bucket, then undo the retracts + _NOZZLE_UNRETRACT ; of PRINT_WARMUP and the previous PRINT_END # ; needs fine tuning, long meltzones require more # SET_GCODE_OFFSET Z_ADJUST={OFFSET} ; apply optional material squish via slicer @@ -222,8 +224,7 @@ gcode: M400 ; wait for buffer to clear G92 E0 ; zero the extruder - # G1 E-0.5 F1800 ; retract filament - G10 ; retract + _NOZZLE_RETRACT ; so the nozzle does not leak while cooling down TURN_OFF_HEATERS iHEATER_OFF ; Turns off the chamber heater @@ -254,6 +255,48 @@ gcode: BED_MESH_CLEAR SET_SKEW CLEAR=1 +# Retract/unretract that is remembered across prints and restarts. +# Klipper's G10 only retracts once until a G11, and nothing sends G11 here, +# so G10 in PRINT_WARMUP used up the retract and PRINT_END's G10 did nothing. +# _NOZZLE_RETRACT adds to the saved variable nozzle_retract, _NOZZLE_UNRETRACT +# extrudes that amount again (over the bucket, in PRINT_START) and clears it. +[gcode_macro _NOZZLE_RETRACT] +description: Retract LENGTH mm (default variable_length) and remember it for _NOZZLE_UNRETRACT; EXTRA=mm already retracted elsewhere, only remembered +variable_length: 5.0 # end-of-print retract; more stops leaking, too much can jam (PLA/heat creep) +variable_max_total: 15.0 # never remember more than this in total +gcode: + {% set length = params.LENGTH|default(length)|float %} + {% set extra = params.EXTRA|default(0)|float %} + {% set done = printer.save_variables.variables.nozzle_retract|default(0)|float %} + {% set length = [length, max_total - done - extra]|min %} + {% if length > 0 and printer.extruder.can_extrude %} + SAVE_GCODE_STATE NAME=_nozzle_retract + M83 + G1 E-{length} F1800 + RESTORE_GCODE_STATE NAME=_nozzle_retract + {% else %} + {% set length = 0 %} + {% endif %} + {% if length + extra > 0 %} + SAVE_VARIABLE VARIABLE=nozzle_retract VALUE={[done + extra + length, max_total]|min} + {% endif %} + +[gcode_macro _NOZZLE_UNRETRACT] +description: Extrude what _NOZZLE_RETRACT retracted (call over the bucket, nozzle hot) +gcode: + {% set done = printer.save_variables.variables.nozzle_retract|default(0)|float %} + {% if done > 0 %} + {% if printer.extruder.can_extrude %} + SAVE_GCODE_STATE NAME=_nozzle_unretract + M83 + G1 E{done} F300 + RESTORE_GCODE_STATE NAME=_nozzle_unretract + SAVE_VARIABLE VARIABLE=nozzle_retract VALUE=0 + {% else %} + RESPOND TYPE=error MSG="_NOZZLE_UNRETRACT: extruder too cold, {done} mm still retracted" + {% endif %} + {% endif %} + [delayed_gcode _delayed_motors_off] gcode: M84