Print start: contact homing, nozzle guard, Z check, purge before chamber heat

- HOME always homes Z with Beacon contact and recalibrates, also when the
  printer is already homed (home_method_when_homed = proximity used the
  model of an earlier print without touching the bed). PRINT_START homes
  Z again after QGL, before the brush takes the nozzle below Z0.
- _Z_CHECK: after the soak, compare Klipper's Z with a BEACON_QUERY
  reading at Z3 over the bed centre and stop the print above 1 mm.
  Warns and continues when BEACON_QUERY leaves no new
  printer.beacon.last_sample.
- Nozzle guard (extras/bdp_guard.py, print/nozzle_guard.cfg): reads the
  bd_pressure force over I2C every 20 ms while armed and, in stop mode,
  shuts Klipper down on a touch. Armed for HOME X/Y, QGL, Z homing, brush,
  mesh and the Z check; starts in log mode to collect peaks per phase.
- Chamber prints: load and purge the first tool before the chamber heats
  (_LOAD_FOR_CHAMBER replaces _UNLOAD_FOR_CHAMBER). A cut unload leaves a
  piece of PLA in the extruder that softened in the hot chamber and jammed
  the ASA load.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
mangavalkandClaude Opus 5.5 committed 2026-10-18 22:39:26 +02:00
1 parent 2100857846
commit 61fa8acb05
7 files changed
+374 -26

No files matched your search

+69 -24
View File
@@ -9,10 +9,13 @@
# PRINT_START runs on a soaked bed:
# PRINT_WARMUP bed heats while the nozzle cools and the printer homes,
# wait for the bed, HEAT_SOAK
# PRINT_START QGL, contact Z calibration, mesh, load the initial tool,
# PRINT_START QGL, Z, contact Z calibration, mesh, load the initial tool,
# PA for all lanes, XY reference
# The filament is loaded after the Z calibration, so the contact always
# touches a clean nozzle that has not been oozing at 150C for minutes.
# Chamber prints are the exception: PRINT_WARMUP loads and purges the first
# tool before the chamber heats (_LOAD_FOR_CHAMBER), retracted for the soak;
# BLOBIFIER_CLEAN cleans the nozzle before the contact.
[gcode_macro PRINT_WARMUP]
description: Print start before HEAT_SOAK: home while the bed heats, wait for the bed, soak
@@ -50,9 +53,11 @@ gcode:
RESPOND MSG="homing"
HOME
{% if target_chamber > 30 %}
_UNLOAD_FOR_CHAMBER TOOL={initial_tool}
_LOAD_FOR_CHAMBER TOOL={initial_tool}
{% endif %}
_GUARD_ON PHASE=warmup_park
G1 X175 Y175 Z5 F1200
_GUARD_OFF
_STATUS STATE=heating_bed
{% if target_bed > 0 %}
@@ -71,35 +76,56 @@ gcode:
HEAT_SOAK HEATER='heater_bed' TARGET={target_bed} SOAKER='temperature_sensor bed_core' SOAK_TEMP={target_bed - 5} TIMEOUT=30 CANCEL='_NOTHING'
{% endif %}
# With the chamber heated, a filament that stays in the toolhead path softens
# in the PTFE tube (PLA loaded, ASA print). PRINT_START would swap a lane that
# is not the first tool's anyway, so unload it now, before the chamber heats.
# AFC moves the filament back into the Box Turtle, outside the chamber.
[gcode_macro _UNLOAD_FOR_CHAMBER]
description: Before a chamber soak: unload the toolhead when its lane is not mapped to TOOL (the print's first tool)
# With the chamber heated, filament in the toolhead path softens: a PLA lane
# still loaded softens in the PTFE tube, and the piece of PLA that a cut
# unload leaves below the cutter softens in the extruder and jams the next
# load (seen: PLA unloaded, ASA jammed after the soak). The piece stays until
# the next load, so an empty toolhead can have it too. For a chamber print,
# load the print's first tool and purge it now, before the chamber heats:
# the purge at the new filament's temperature pushes the leftover out.
# AFC unloads a loaded lane back into the Box Turtle, outside the chamber.
[gcode_macro _LOAD_FOR_CHAMBER]
description: Before a chamber soak: load and purge TOOL (the print's first tool) unless its lane is already loaded
gcode:
{% set tool = 'T' ~ params.TOOL|default(0)|int %}
{% set cur = printer.AFC.current_load if 'AFC' in printer else none %}
{% if cur and ('AFC_stepper ' ~ cur) in printer %}
{% set lane = printer['AFC_stepper ' ~ cur] %}
{% if lane.map != tool %}
RESPOND MSG="Chamber heating: unloading {cur} ({lane.material}, {lane.map}), the print starts with {tool}"
_HEAT_FOR_LOADED_LANE TOOL={params.TOOL|default(0)|int}
TOOL_UNLOAD LANE={cur}
_UNLOAD_FOR_CHAMBER_VERIFY LANE={cur}
{% if 'AFC' in printer %}
{% set cur = printer.AFC.current_load %}
{% set ns = namespace(lane=none) %}
{% for l in printer.AFC.lanes if ('AFC_stepper ' ~ l) in printer and printer['AFC_stepper ' ~ l].map == tool %}
{% set ns.lane = l %}
{% endfor %}
{% if ns.lane is none %}
_ERROR MSG="Chamber heating: no AFC lane is mapped to {tool}, print stopped before the chamber heats" DISPLAY="No lane for {tool}, print stopped"
{% elif cur != ns.lane %}
{% set new = printer['AFC_stepper ' ~ ns.lane] %}
# Hot enough to unload the old filament and to purge the new one
{% set temps = [new.extruder_temp|default(0, true)|int, printer.configfile.settings.extruder.min_extrude_temp|int + 20] %}
{% if cur and ('AFC_stepper ' ~ cur) in printer %}
{% set temps = temps + [printer['AFC_stepper ' ~ cur].extruder_temp|default(0, true)|int] %}
RESPOND MSG="Chamber heating: unloading {cur} ({printer['AFC_stepper ' ~ cur].material}), loading and purging {ns.lane} ({new.material}, {tool}) before the chamber heats"
{% else %}
RESPOND MSG="Chamber heating: loading and purging {ns.lane} ({new.material}, {tool}) before the chamber heats"
{% endif %}
M109 S{temps|max}
{tool}
_LOAD_FOR_CHAMBER_VERIFY LANE={ns.lane}
{% endif %}
{% endif %}
# Separate macro: rendered after TOOL_UNLOAD has run. A failed unload stops
# the print before the chamber heats.
[gcode_macro _UNLOAD_FOR_CHAMBER_VERIFY]
description: Helper for _UNLOAD_FOR_CHAMBER: stop the print when the lane is still loaded
# Separate macro: rendered after the tool change has run. AFC pauses on a
# failed load instead of raising an error, so check the result here: a
# failed load stops the print before the chamber heats.
[gcode_macro _LOAD_FOR_CHAMBER_VERIFY]
description: Helper for _LOAD_FOR_CHAMBER: stop the print when LANE is not loaded, else retract and cool the nozzle for the soak
gcode:
{% if printer.AFC.current_load %}
_ERROR MSG="Chamber heating: {params.LANE} could not be unloaded ({printer.AFC.current_load} still in the toolhead), print stopped before the chamber heats" DISPLAY="Unload failed, print stopped"
{% if printer.AFC.current_load != params.LANE %}
_ERROR MSG="Chamber heating: {params.LANE} could not be loaded ({printer.AFC.current_load or 'nothing'} in the toolhead), print stopped before the chamber heats" DISPLAY="Load failed, print stopped"
{% else %}
# The filament the retract was remembered for is gone
# New filament, just purged: a retract remembered for the old one is
# gone. Retract so it does not ooze during the soak; PRINT_START
# undoes it over the bucket.
SAVE_VARIABLE VARIABLE=nozzle_retract VALUE=0
_NOZZLE_RETRACT
M104 S150
{% endif %}
@@ -150,19 +176,37 @@ gcode:
_LIGHTS_ON
M106 S0
# The last homing was before the soak: check that Z still matches the
# Beacon before the gantry goes low. MAX=1.0: the soak itself drifts Z
# a few tenths; the console line shows how much.
_Z_CHECK MAX=1.0
# The bed is soaked now: level and calibrate Z on the final geometry
_STATUS STATE=leveling
RESPOND MSG="quad gantry level"
# Nozzle guard (bd_pressure) on while nothing should touch the nozzle
_GUARD_ON PHASE=qgl
QUAD_GANTRY_LEVEL
# QGL moved the Z steppers and the frame drifted during the soak: home Z
# again (proximity, on the model of the contact homing in PRINT_WARMUP)
# before the brush takes the nozzle below Z0
_GUARD_ON PHASE=z_home
G28 Z
# Own phase: the bristles press on the nozzle too
_GUARD_ON PHASE=brush
BLOBIFIER_CLEAN
_GUARD_OFF
_STATUS STATE=calibrating_z
_NOZZLE_CONTACT_TEMP WAIT=1
G28 Z METHOD=CONTACT CALIBRATE=1 ; calibrate z offset and beacon model hot
_STATUS STATE=meshing
RESPOND MSG="meshing"
_GUARD_ON PHASE=mesh
BED_MESH_CALIBRATE RUNS=2 ; bed mesh in scan mode
# From here on the nozzle extrudes and AFC cuts and loads: guard off
_GUARD_OFF
# Heat over the bucket, then undo the retracts of the previous PRINT_END
_STATUS STATE=heating_extruder
@@ -232,8 +276,9 @@ gcode:
# End-of-print cleanup shared by PRINT_END and CANCEL_PRINT
[gcode_macro _PRINT_CLEANUP]
description: Heaters (incl. chamber heater) and part fan off, flow back to 100%, bdwidth off, mesh and skew cleared
description: Heaters (incl. chamber heater) and part fan off, flow back to 100%, bdwidth off, mesh and skew cleared, nozzle guard off
gcode:
_GUARD_OFF ; a print start that failed while it was armed
TURN_OFF_HEATERS
iHEATER_OFF ; stops the chamber heater control loop too
M107