Print start: soak before QGL and Z, load after Z, PA per lane temperature

PRINT_WARMUP: bed heats during the warmup, the nozzle only waits while it
is above 170C (Beacon contact limit 180C), one HOME to get over the bed,
then M190 and HEAT_SOAK. No more filament load and 220->150C cycle there.

PRINT_START (on the soaked bed): one QGL, one contact Z calibration, mesh,
heat over the bucket, load the initial tool, PA for all lanes, load the
initial tool again if a calibration changed lanes, G28 X Y reference.
Loading after the contact keeps ooze off the nozzle for the calibration.

PA: calibrate each lane at its own filament temperature (was the
temperature from before CHANGE_TOOL), and apply the loaded lane's PA
after PA_CALIBRATE_ALL_LANES (the last cached lane's PA won before).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
mangavalkandClaude Opus 5.5 committed 2026-10-17 19:46:05 +02:00
1 parent e5be65834e
commit 6cc43f951d
2 files changed
+84 -124

No files matched your search

+20 -4
View File
@@ -422,11 +422,14 @@ gcode:
{% else %} {% else %}
CHANGE_TOOL LANE={lane} CHANGE_TOOL LANE={lane}
# Nozzle temp: use the extruder's current target, which AFC # Nozzle temp: the lane's own filament temperature (AFC, from
# already sets from Spoolman when the lane was loaded. Fall # Spoolman). Not printer.extruder.target: the template is rendered
# back to the configured default if nothing is set yet. # before CHANGE_TOOL runs, so that is still the previous lane's
# (or the print's) temperature. PA_CALIBRATE heats to it (M109).
{% set lane_obj = printer["AFC_stepper " ~ lane] if ("AFC_stepper " ~ lane) in printer else {} %}
{% set lane_temp = lane_obj.extruder_temp|default(0, true)|float %}
{% set target = printer.extruder.target|default(0)|float %} {% set target = printer.extruder.target|default(0)|float %}
{% set nozzle_temp = target if target > 0 else cfg.fallback_nozzle_temp|float %} {% set nozzle_temp = lane_temp if lane_temp > 0 else (target if target > 0 else cfg.fallback_nozzle_temp|float) %}
{action_respond_info("Calibrating PA for %s (spool %d) at %.0fC..." % (lane, spool_id, nozzle_temp))} {action_respond_info("Calibrating PA for %s (spool %d) at %.0fC..." % (lane, spool_id, nozzle_temp))}
M117 Calibrating PA: {lane} M117 Calibrating PA: {lane}
@@ -619,6 +622,19 @@ gcode:
UPDATE_DELAYED_GCODE ID=_PA_POLL_LANE_CHANGE DURATION=2 UPDATE_DELAYED_GCODE ID=_PA_POLL_LANE_CHANGE DURATION=2
# PA_CALIBRATE_ALL_LANES sets the PA of every lane in turn (the last one
# wins), and the lane-change poll only reacts to a change of the loaded lane.
# Run this after it so the PA matches the lane that is actually loaded.
[gcode_macro _PA_APPLY_LOADED_LANE]
description: Apply the cached PA of the lane loaded in the toolhead
gcode:
{% set lane = printer.AFC.current_load|default(none) if "AFC" in printer else none %}
{% if lane %}
_PA_APPLY_FOR_LANE LANE={lane}
{% else %}
RESPOND MSG="_PA_APPLY_LOADED_LANE: no lane loaded, PA unchanged"
{% endif %}
[gcode_macro _PA_APPLY_FOR_LANE] [gcode_macro _PA_APPLY_FOR_LANE]
description: Internal -- applies cached PA for a lane without calibrating description: Internal -- applies cached PA for a lane without calibrating
# LANE=<lane_name> # LANE=<lane_name>
+64 -120
View File
@@ -1,28 +1,24 @@
# Print start and end: PRINT_WARMUP, PRINT_START, PRINT_END # Print start and end: PRINT_WARMUP, PRINT_START, PRINT_END
# Idle time (in seconds) to wait before running the above G-Code
# commands. The default is 600 seconds.
##################################################################### #####################################################################
# Macros # Macros
##################################################################### #####################################################################
# [gcode_macro PRINT_START] # OrcaSlicer calls PRINT_WARMUP and then PRINT_START. HEAT_SOAK at the end of
# gcode: # PRINT_WARMUP pauses the print file and resumes it when the soak is done, so
# PRINT_WARMUP BED={params.BED} EXTRUDER={params.EXTRUDER} CHAMBER={params.CHAMBER|default("0")} TOOL={params.TOOL|default("0")} # PRINT_START runs on a soaked bed:
# PRINT_START_2 EXTRUDER={params.EXTRUDER} # 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,
# 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.
[gcode_macro PRINT_WARMUP] [gcode_macro PRINT_WARMUP]
description: Perform initial homing and heating tasks description: Print start before HEAT_SOAK: home while the bed heats, wait for the bed, soak
gcode: gcode:
{% set target_bed = params.BED|int %} {% set target_bed = params.BED|int %}
{% set target_extruder = params.EXTRUDER|int %}
{% set target_chamber = params.CHAMBER|default("0")|int %} {% set target_chamber = params.CHAMBER|default("0")|int %}
# {% set x_wait = printer.toolhead.axis_maximum.x|float / 2 %}
# {% set y_wait = printer.toolhead.axis_maximum.y|float / 2 %}
{% set initial_tool = params.TOOL|default("0")|int %}
{% set chamber_temp = printer["temperature_sensor chamber"].temperature|float %}
RESET_FAILURE RESET_FAILURE
CLEAR_PAUSE CLEAR_PAUSE
@@ -31,29 +27,13 @@ gcode:
_LIGHTS_ON _LIGHTS_ON
#SET_PIN PIN=caselight VALUE=1.00
UPDATE_DELAYED_GCODE ID=_delayed_motors_off DURATION=0 UPDATE_DELAYED_GCODE ID=_delayed_motors_off DURATION=0
BED_MESH_CLEAR BED_MESH_CLEAR
SET_GCODE_OFFSET Z=0 SET_GCODE_OFFSET Z=0
CLEAR_PAUSE
SKEW_PROFILE LOAD=Califlower SKEW_PROFILE LOAD=Califlower
M106 S0
{% set current_temp = printer.extruder.temperature %} # Bed first, so it heats during the rest of the warmup
{% if current_temp > 150 %}
RESPOND MSG="nozzle to hot, lowering to 150"
M104 S150 ; set nozzle temp to 150
M109 S150 ; wait until nozzle reaches 150 ; wait until nozzle reaches 0
{% endif %}
_STATUS STATE=homing
RESPOND MSG="homing"
HOME
RESPOND MSG="homing finished"
# G0 Z2 ; position beacon at 2mm for heat soak
{% if target_bed < 60 %} {% if target_bed < 60 %}
RESPOND MSG="Using PID for <60°C bed" RESPOND MSG="Using PID for <60°C bed"
SET_HEATER_TEMPERATURE HEATER=heater_bed TARGET={target_bed} PID_KP=33.606 PID_KI=0.694 PID_KD=407.058 SET_HEATER_TEMPERATURE HEATER=heater_bed TARGET={target_bed} PID_KP=33.606 PID_KI=0.694 PID_KD=407.058
@@ -62,52 +42,43 @@ gcode:
SET_HEATER_TEMPERATURE HEATER=heater_bed TARGET={target_bed} pid_Kp=46.843 pid_Ki=2.002 pid_Kd=274.034 SET_HEATER_TEMPERATURE HEATER=heater_bed TARGET={target_bed} pid_Kp=46.843 pid_Ki=2.002 pid_Kd=274.034
{% endif %} {% endif %}
G1 X175 Y175 Z2 F1200 # Only to get the toolhead over the bed for the soak; the Z that counts
# is the contact calibration in PRINT_START on the soaked bed
_STATUS STATE=homing
_NOZZLE_CONTACT_TEMP
RESPOND MSG="homing"
HOME
G1 X175 Y175 Z5 F1200
_STATUS STATE=heating_bed _STATUS STATE=heating_bed
RESPOND MSG="heating"
{% if target_bed > 0 %} {% if target_bed > 0 %}
M140 S{target_bed} ; start bed heater RESPOND MSG="heating"
M104 S150 ; set nozzle temp to 150 M190 S{target_bed}
M109 S150 ; wait until nozzle reaches 150 ; wait until nozzle reaches 0
M190 S{target_bed} ; wait on bed temperature
{% endif %} {% endif %}
_STATUS STATE=homing
HOME
_STATUS STATE=leveling
QUAD_GANTRY_LEVEL
BLOBIFIER_CLEAN ; call another macro to wipe nozzle if available
G1 X175 Y175 Z5 F1200
_STATUS STATE=heating_extruder
_HEAT_FOR_LOADED_LANE TOOL={initial_tool} ; unload needs the loaded filament's temperature
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
_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
BLOBIFIER_CLEAN ; call another macro to wipe nozzle if available
G1 X175 Y175 Z5 F1200
_STATUS STATE=heating_bed
{% if target_chamber > 30 %} {% if target_chamber > 30 %}
RESPOND MSG="waiting for chamber temperature" RESPOND MSG="waiting for chamber temperature"
M141 S{target_chamber} M141 S{target_chamber}
# M191 S{target_chamber} ; Waits until the chamber temperature reaches 60°C
# TEMPERATURE_WAIT SENSOR="temperature_sensor chamber" MINIMUM={target_chamber}
M106 S255 M106 S255
# HEAT_SOAK HEATER='heater_bed' TARGET={BED_TEMP} SOAKER='temperature_sensor iHeater_S' SOAK_TEMP={target_chamber} TIMEOUT=60 CANCEL='_NOTHING' # Unreachable SOAK_TEMP + CANCEL='_NOTHING': soaks until the TIMEOUT, then continues the print
HEAT_SOAK HEATER='heater_bed' TARGET={target_bed} SOAKER='temperature_sensor chamber' SOAK_TEMP={target_chamber} TIMEOUT=60 CANCEL='_NOTHING' HEAT_SOAK HEATER='heater_bed' TARGET={target_bed} SOAKER='temperature_sensor chamber' SOAK_TEMP={target_chamber} TIMEOUT=60 CANCEL='_NOTHING'
# (CANCEL='_NOTHING') and having unreachable SOAK_TEMP makes it run till the TIMEOUT and continue without canceling the print.
{% else %} {% else %}
RESPOND MSG="waiting for bed core temperature" RESPOND MSG="waiting for bed core temperature"
HEAT_SOAK HEATER='heater_bed' TARGET={target_bed} SOAKER='temperature_sensor bed_core' SOAK_TEMP={target_bed - 5} TIMEOUT=30 CANCEL='_NOTHING' HEAT_SOAK HEATER='heater_bed' TARGET={target_bed} SOAKER='temperature_sensor bed_core' SOAK_TEMP={target_bed - 5} TIMEOUT=30 CANCEL='_NOTHING'
# (CANCEL='_NOTHING') and having unreachable SOAK_TEMP makes it run till the TIMEOUT and continue without canceling the print. {% endif %}
# Beacon contact refuses a nozzle above contact_max_hotend_temperature (180C)
[gcode_macro _NOZZLE_CONTACT_TEMP]
description: Nozzle to 150C for Beacon contact; wait only while it is above MAXIMUM (default 170C), WAIT=1 also waits until it is at least 145C
gcode:
{% set max = params.MAXIMUM|default(170)|float %}
{% set heat = params.WAIT|default(0)|int == 1 %}
M104 S150
{% if heat %}
TEMPERATURE_WAIT SENSOR=extruder MINIMUM=145 MAXIMUM={max}
{% elif printer.extruder.temperature > max %}
RESPOND MSG="Nozzle at {printer.extruder.temperature|round|int}C, waiting until it is below {max|int}C"
TEMPERATURE_WAIT SENSOR=extruder MAXIMUM={max}
{% endif %} {% endif %}
# AFC heats for a tool change from the print file's per-tool temperatures. # AFC heats for a tool change from the print file's per-tool temperatures.
@@ -134,85 +105,58 @@ gcode:
RESUME_BASE RESUME_BASE
[gcode_macro PRINT_START] [gcode_macro PRINT_START]
description: Print start after HEAT_SOAK: QGL, Z calibration, mesh, load the initial tool, PA
gcode: gcode:
RESPOND MSG="print start macro continued"
_LIGHTS_ON
{% set target_extruder = params.EXTRUDER|int %} {% set target_extruder = params.EXTRUDER|int %}
{% set initial_tool = params.TOOL|default("0")|int %}
RESPOND MSG="print start macro continued"
_LIGHTS_ON
M106 S0 M106 S0
M104 S150 ; set nozzle temp to 150 # The bed is soaked now: level and calibrate Z on the final geometry
M109 S150 ; wait until nozzle reaches 150 ; wait until nozzle reaches 0
HOME
BLOBIFIER_CLEAN ; call another macro to wipe nozzle if available
_STATUS STATE=calibrating_z
G28 Z METHOD=CONTACT CALIBRATE=1 ; calibrate z offset and beacon model hot
_STATUS STATE=leveling _STATUS STATE=leveling
RESPOND MSG="quad ganrty level" RESPOND MSG="quad gantry level"
QUAD_GANTRY_LEVEL QUAD_GANTRY_LEVEL
BLOBIFIER_CLEAN
_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 _STATUS STATE=meshing
RESPOND MSG="meshing" RESPOND MSG="meshing"
BED_MESH_CALIBRATE RUNS=2 ; bed mesh in scan mode BED_MESH_CALIBRATE RUNS=2 ; bed mesh in scan mode
BLOBIFIER_CLEAN ; call another macro to wipe nozzle if available # Heat over the bucket, then undo the retracts of the previous PRINT_END
M104 S150 ; set nozzle temp to 150
M109 S150 ; wait until nozzle reaches 150 ; wait until nozzle reaches 0
_STATUS STATE=calibrating_z
G28 Z METHOD=CONTACT CALIBRATE=1 ; calibrate z offset and beacon model hot
_STATUS STATE=heating_extruder _STATUS STATE=heating_extruder
M104 S{target_extruder} ; set extruder to print temp BLOBIFIER_PARK
M109 S{target_extruder} ; wait for extruder temp M109 S{target_extruder}
BLOBIFIER_PARK ; over the bucket, then undo the retracts _NOZZLE_UNRETRACT
_NOZZLE_UNRETRACT ; of PRINT_WARMUP and the previous PRINT_END
# ; needs fine tuning, long meltzones require more # Load the initial tool (unloading another lane needs that lane's temperature)
# SET_GCODE_OFFSET Z_ADJUST={OFFSET} ; apply optional material squish via slicer _HEAT_FOR_LOADED_LANE TOOL={initial_tool}
#SET_GCODE_OFFSET Z=-0.06 ; squish T{initial_tool}
# SET_GCODE_OFFSET Z=0.02 ; squish # worked before but a bit to high now
# SET_GCODE_OFFSET Z=-0.05 ; squish
SET_GCODE_OFFSET Z=-0.00 ; squish
RESPOND MSG="starting"
;PRIME_NOZZLE ; call another macro to purge or prime nozzle
# WIPE_NOZZLE ; call another macro to wipe nozzle if available
# Line_Purge
# AFC_POOP PURGE_LENGTH=100
# AFC_KICK
BLOBIFIER_CLEAN
PA_CALIBRATE_ALL_LANES LANES="lane1,lane2,lane3,lane4,lane5" PA_CALIBRATE_ALL_LANES LANES="lane1,lane2,lane3,lane4,lane5"
# A calibration can leave another lane loaded, and every cached lane
# sets its PA: load the initial tool again and apply its PA
T{initial_tool}
_PA_APPLY_LOADED_LANE
M104 S{target_extruder} ; set extruder to print temp M109 S{target_extruder}
M109 S{target_extruder} ; wait for extruder temp SET_GCODE_OFFSET Z=-0.00 ; squish
BLOBIFIER_CLEAN BLOBIFIER_CLEAN
; start printing # XY reference for AFC_XY_SAFETY_CHECK (homes X and Y; Z stays from the
# contact calibration)
G90 ; absolute positioning
G1 Z20 F30000 ; move nozzle away from bed
G1 X175 Y175 F30000 ; move nozzle away from bed
G28 XYZ
#G11 ; unretract
_AFC_STORE_HOME_REFERENCE _AFC_STORE_HOME_REFERENCE
# bdwidth is not used while printing: its motion reading stays at 0 and its # bdwidth is not used while printing: its motion reading stays at 0 and its
# per-reading width compensation made the flow jump between 77 and 119%. # per-reading width compensation made the flow jump between 77 and 119%.
# To use it again: SET_BDWIDTH NAME=fila_width_0 COMMAND=ENABLE_WIDTH # To use it again: SET_BDWIDTH NAME=fila_width_0 COMMAND=ENABLE_WIDTH
RESPOND MSG="starting"
_STATUS STATE=printing _STATUS STATE=printing