Files
3dprinters/DNV-TPU-Ender3/klipper_config/klipper-macros-main/start_end.cfg
2024-05-28 21:10:07 +02:00

485 lines
20 KiB
INI

# Copyright (C) 2022 Justin Schuh <code@justinschuh.com>
#
# This file may be distributed under the terms of the GNU GPLv3 license.
[gcode_macro print_start]
description: Inserted by slicer at start of print. Rather than using this macro
directly you should configure your slicer as instructed in the readme.
Usage: PRINT_START BED=<temp> EXTRUDER=<temp> [CHAMBER=<temp>]
[MESH_MIN=<x,y>] [MESH_MAX=<x,y>] [LAYERS=<num>]
[NOZZLE_SIZE=<mm>]
gcode:
{action_respond_info(
"This file is using an old The PRINT_START format. This print will run "
"fine, but you should update your slicer config to take advantage of the "
"phased PRINT_START macros. The slicer documentation is here:\n"
"https://github.com/jschuh/klipper-macros\x23slicer-configuration"
)}
_PRINT_START_PHASE_INIT {rawparams}
_PRINT_START_PHASE_PREHEAT
_PRINT_START_PHASE_PROBING
_PRINT_START_PHASE_EXTRUDER
_PRINT_START_PHASE_PURGE
[gcode_macro _print_start_phase_init]
description: Inserted by slicer at start of print. Initializes PRINT_START
phases.
Usage: See PRINT_START.
gcode:
CHECK_KM_CONFIG # Need this in case startup errors were missed.
SET_GCODE_VARIABLE MACRO=_print_end_inner VARIABLE=cancelled VALUE="{False}"
_KM_APPLY_PRINT_OFFSET RESET=1
_PRINT_START_PHASE_CHECK PHASE=none
{% set km = printer["gcode_macro _km_globals"] %}
{% if not params.BED %}
{% set dummy = params.__setitem__('BED', params.BED_TEMP|int) %}
{% endif %}
{% if not params.EXTRUDER %}
{% set dummy = params.__setitem__('EXTRUDER', params.EXTRUDER_TEMP|int) %}
{% endif %}
# Stash all the params for use by the other phases.
PRINT_START_SET PRINT_START_PHASE="init" {% for k in params %}{' %s=\"%s\"' %
(k,params[k]|replace('\\','\\\\')|replace('\'','\\\'')|replace('\"','\\\"'))
}{% endfor %}
# Check and propogate the printable bounds.'
_km_check_and_set_print_bounds
M107 # Turn off part cooling fan in case it was on.
CLEAR_PAUSE
# Kick off the longest preheats in the init.
M140 S{params.BED}
{% if params.CHAMBER %}M141 S{params.CHAMBER|int}{% endif %}
{% if printer.bed_mesh %}BED_MESH_CLEAR{% endif %}
# Load a saved mesh if configured.
{% if km.start_try_saved_surface_mesh and printer.bed_mesh %}
LOAD_SURFACE_MESH
{% endif %}
PRINT_START_SET PRINT_START_PHASE="preheat"
[gcode_macro _print_start_phase_preheat]
description: Inserted by slicer at start of print. Handles the bed and chamber
heating phases and ends when both are stabilized at their target temperatures.
Usage: See PRINT_START.
gcode:
_PRINT_START_PHASE_CHECK PHASE=preheat
{% set print = printer["gcode_macro print_start_set"].print %}
{% set BED = print.BED|int %}
{% set EXTRUDER = print.EXTRUDER|int %}
{% set CHAMBER = print.CHAMBER|default(0)|int %}
{% set LAYERS = print.LAYERS|default(0)|int %}
{% set km = printer["gcode_macro _km_globals"] %}
# The bed started at no more than 0.2C below and 1.0C above the target temp.
{% set bed_at_target = (BED + 0.4 - printer.heater_bed.temperature) |
abs <= 0.6 %}
PRINT_START_SET BED_AT_TARGET={1 if bed_at_target else 0}
{% set start_level_bed_at_temp = km.start_level_bed_at_temp and
not printer.bed_mesh.profile_name %}
{% set actions_at_temp = start_level_bed_at_temp or
km.start_quad_gantry_level_at_temp or
km.start_z_tilt_adjust_at_temp or
(km.start_home_z_at_temp and not bed_at_target) %}
{% set bed_overshoot = (BED + (km.start_bed_heat_overshoot if
(BED and not bed_at_target) else 0.0),
printer.configfile.settings.heater_bed.max_temp ) | min %}
INIT_LAYER_GCODE LAYERS="{LAYERS}"
{% if CHAMBER > 0.0 %}
M141 S{CHAMBER}
{% endif %}
# Start bed heating
M140 S{bed_overshoot}
{% if actions_at_temp %}
# If we're going to run a bed level we either have a probing temp specified
# or we heat the extruder part way to avoid oozing while probing.
M104 S{km.start_extruder_probing_temp if km.start_extruder_probing_temp > 0
else (km.start_extruder_preheat_scale * EXTRUDER)|round(0,'ceil')|int}
{% else %}
# Honor the extruder probing temp, in case we just want to delay extruder
# heating until after the bed is ready.
M104 S{km.start_extruder_probing_temp if km.start_extruder_probing_temp > 0
else EXTRUDER}
{% endif %}
# home all axes
_KM_PRINT_STATUS ACTION=CHANGE STATUS=homing RESET_STACK=1
G28
G90
{% if BED > 0.0 %}
_KM_PRINT_STATUS ACTION=CHANGE STATUS=bed_heating RESET_STACK=1
# Skip this if the bed was already at target when START_PRINT was called.
{% if not bed_at_target %}
PARK
# Overshoot the target a bit.
M190 S{bed_overshoot}
G4 P{km.start_bed_heat_delay / 2}
M190 R{BED} # Settle down after the overshoot.
G4 P{km.start_bed_heat_delay / 2}
{% endif %}
{% endif %}
{% if CHAMBER > 0.0 %}
_KM_PRINT_STATUS ACTION=CHANGE STATUS=chamber_heating RESET_STACK=1
_KM_PARK_IF_NEEDED HEATER="chamber" RANGE=ABOVE
M191 S{CHAMBER}
{% endif %}
{% if BED > 0.0 and bed_at_target%}
M190 R{BED} # Extra bed stabilization if we skipped it earlier.
{% endif %}
PRINT_START_SET PRINT_START_PHASE="probing"
[gcode_macro _print_start_phase_probing]
description: Inserted by slicer at start of print. Performs probing (including
mesh bed level) and other operations that should be run when the bed and
chamber are stabilized at their target temps.
Usage: See PRINT_START.
gcode:
_PRINT_START_PHASE_CHECK PHASE=probing
{% set print = printer["gcode_macro print_start_set"].print %}
{% set km = printer["gcode_macro _km_globals"] %}
{% set MESH_MIN = print.MESH_MIN|default(None) %}
{% set MESH_MAX = print.MESH_MAX|default(None) %}
# Randomize the placement of the print on the bed.
{% if km.start_random_placement_max > 0 and print.PRINT_MIN and MESH_MIN %}
{% set PRINT_MIN = print.PRINT_MIN.split(",")|map('float')|list %}
{% set PRINT_MAX = print.PRINT_MAX.split(",")|map('float')|list %}
{% set x_offset = (((km.print_max[0] - km.print_min[0] - PRINT_MAX[0] +
PRINT_MIN[0] - 2 * km.start_random_placement_padding)|int,
km.start_random_placement_max * 2)|min, 0)|max %}
{% set y_offset = (((km.print_max[1] - km.print_min[1] - PRINT_MAX[1] +
PRINT_MIN[1] - 2 * km.start_random_placement_padding)|int,
km.start_random_placement_max * 2)|min, 0)|max %}
{% if x_offset > 0 %}
{% set x_offset = range(x_offset)|random + km.print_min[0] -
PRINT_MIN[0] + km.start_random_placement_padding %}
{% endif %}
{% if y_offset > 0 %}
{% set y_offset = range(y_offset)|random + km.print_min[1] -
PRINT_MIN[1] + km.start_random_placement_padding %}
{% endif %}
# This MESH_MIN/MESH_MAX gets passed to BED_MESH_CALIBRATE below, but the
# rest of the macros rely on SET_GCODE_OFFSET performing the adjustment.
{% set MESH_MIN = MESH_MIN.split(",")|map('float')|list %}
{% set MESH_MAX = MESH_MAX.split(",")|map('float')|list %}
{% set MESH_MIN_NEW = (MESH_MIN[0] + x_offset, MESH_MIN[1] + y_offset) %}
{% set MESH_MAX_NEW = (MESH_MAX[0] + x_offset, MESH_MAX[1] + y_offset) %}
{action_respond_info(
"Relocating print origin from (%.3f,%.3f) "|format(*MESH_MIN) +
"to (%.3f,%.3f)"|format(*MESH_MIN_NEW))}
{% set MESH_MIN = (MESH_MIN_NEW[0], MESH_MIN_NEW[1])|join(',') %}
{% set MESH_MAX = (MESH_MAX_NEW[0], MESH_MAX_NEW[1])|join(',') %}
PRINT_START_SET PRINT_OFFSET={"%d,%d" % (x_offset,y_offset)}
{% endif %}
{% set EXTRUDER = print.EXTRUDER|int %}
{% set km = printer["gcode_macro _km_globals"] %}
{% set start_level_bed_at_temp = km.start_level_bed_at_temp and
not printer.bed_mesh.profile_name %}
{% set start_home_z_at_temp = km.start_home_z_at_temp and
not print.BED_AT_TARGET|int %}
{% set actions_at_temp = start_level_bed_at_temp or
km.start_quad_gantry_level_at_temp or
km.start_z_tilt_adjust_at_temp or
start_home_z_at_temp %}
{% if actions_at_temp %}
{% if km.start_extruder_probing_temp > 0 %}
_KM_PRINT_STATUS ACTION=CHANGE STATUS=extruder_heating RESET_STACK=1
_KM_PARK_IF_NEEDED HEATER={printer.toolhead.extruder} RANGE=2
M109 R{km.start_extruder_probing_temp}
{% else %}
M104 S{EXTRUDER} # set the final extruder target temperature
{% endif %}
{% if km.start_z_tilt_adjust_at_temp %}
_KM_PRINT_STATUS ACTION=CHANGE STATUS=calibrating_z RESET_STACK=1
Z_TILT_ADJUST
{% endif %}
{% if km.start_quad_gantry_level_at_temp %}
_KM_PRINT_STATUS ACTION=CHANGE STATUS=leveling_gantry RESET_STACK=1
QUAD_GANTRY_LEVEL
{% endif %}
{% if start_home_z_at_temp %}
_KM_PRINT_STATUS ACTION=CHANGE STATUS=homing RESET_STACK=1
G28 Z # Re-home only the Z axis now that the bed has stabilized.
{% endif %}
{% if start_level_bed_at_temp %}
_KM_PRINT_STATUS ACTION=CHANGE STATUS=meshing RESET_STACK=1
_km_mesh_if_needed {% if MESH_MIN %} MESH_MIN={MESH_MIN}{% endif
%}{% if MESH_MAX %} MESH_MAX={MESH_MAX}{% endif %}
{% endif %}
{% if km.start_extruder_probing_temp > 0 %}
M104 S{EXTRUDER} # set the final extruder target temperature
{% endif %}
G4
{% endif %}
PRINT_START_SET PRINT_START_PHASE="extruder"
[gcode_macro _print_start_phase_extruder]
description: Inserted by slicer at start of print. Preheats the extruder.
Usage: See PRINT_START.
gcode:
_PRINT_START_PHASE_CHECK PHASE=extruder
{% set print = printer["gcode_macro print_start_set"].print %}
{% set EXTRUDER = print.EXTRUDER|default(print.EXTRUDER_TEMP)|float %}
{% set km = printer["gcode_macro _km_globals"] %}
# Wait for extruder to reach temperature
{% if EXTRUDER > 0 %}
_KM_PRINT_STATUS ACTION=CHANGE STATUS=extruder_heating RESET_STACK=1
_KM_PARK_IF_NEEDED HEATER={printer.toolhead.extruder} RANGE=ABOVE
M109 S{EXTRUDER}
{% endif %}
PRINT_START_SET PRINT_START_PHASE="purge"
[gcode_macro _print_start_phase_purge]
description: Inserted by slicer at start of print. Generates purge lines.
Usage: See PRINT_START.
gcode:
_PRINT_START_PHASE_CHECK PHASE=purge
# Apply the offset for bed placement randomization.
_KM_APPLY_PRINT_OFFSET
# apply Z offset for bed surface (just in case it was reset).
_APPLY_BED_SURFACE_OFFSET
{% set print = printer["gcode_macro print_start_set"].print %}
{% set MESH_MIN = print.MESH_MIN|default(None) %}
{% set MESH_MAX = print.MESH_MAX|default(None) %}
{% set NOZZLE_SIZE = print.NOZZLE_SIZE|default(print.NOZZLE_SIZE)|
default(printer.configfile.settings.extruder.nozzle_diameter)|float %}
{% set km = printer["gcode_macro _km_globals"] %}
{% if km.start_purge_length > 0.0 and printer.extruder.can_extrude %}
_KM_PRINT_STATUS ACTION=CHANGE STATUS=purging RESET_STACK=1
DRAW_PURGE_LINE WIDTH="{NOZZLE_SIZE * 1.25}" HEIGHT="{NOZZLE_SIZE * 0.625
}"{% if MESH_MIN %} PRINT_MIN={MESH_MIN}{% endif
%}{% if MESH_MAX %} PRINT_MAX={MESH_MAX}{% endif %}
{% endif %}
PRINT_START_SET PRINT_START_PHASE="printing"
_KM_PRINT_STATUS ACTION=CHANGE STATUS=printing RESET_STACK=1
[gcode_macro _km_park_if_needed]
description: Parks the extruder if the current temperature of the supplied
heater is not within the specified target range.
Usage: _KM_PARK_IF_NEEDED HEATER=<heater> RANGE=[<percentage>|ABOVE|BELOW]
gcode:
# This needs to get called as its own macro to get the current temp evaluated.
{% set HEATER = params.HEATER if params.HEATER in
printer.heaters.available_heaters else
("heater_generic " ~ params.HEATER) %}
{% set RANGE = (params.RANGE|default(1))|string|upper %}
{% if printer[HEATER].target %}
{% if RANGE == "ABOVE" %}
{% if printer[HEATER].temperature < printer[HEATER].target %}
PARK
{% endif %}
{% elif RANGE == "BELOW" %}
{% if printer[HEATER].temperature > printer[HEATER].target %}
PARK
{% endif %}
{% elif (printer[HEATER].temperature - printer[HEATER].target)|abs >
(printer[HEATER].target * RANGE|float * 0.01)|abs %}
PARK
{% endif %}
{% endif %}
[gcode_macro _km_apply_print_offset]
variable_offset: []
gcode:
{% set print = printer["gcode_macro print_start_set"].print %}
{% if params.RESET|default(0)|int and offset and
not printer["gcode_macro _km_save_state"].is_ephemeral%}
{% set PRINT_OFFSET = [offset.pop(0) * -1, offset.pop() * -1] %}
{% elif print.PRINT_OFFSET and not offset and
not printer["gcode_macro _km_save_state"].is_ephemeral %}
{% set PRINT_OFFSET = print.PRINT_OFFSET.split(",")|map('float')|list %}
{% set dummy = offset.extend(PRINT_OFFSET) %}
{% endif %}
{% if PRINT_OFFSET %}
_KM_SET_GCODE_OFFSET_BASE {"X_ADJUST=%.2f Y_ADJUST=%.2f"|
format(*PRINT_OFFSET)}
{% endif %}
[gcode_macro _km_mesh_if_needed]
gcode:
# TODO: Instead of blindly using the loaded mesh we could probe a few key
# points on the saved grid. If those probes show that the saved grid is no
# longer in tolerance we could just run BED_MESH_CALIBRATE_FAST anyway.
{% if not printer.bed_mesh.profile_name %}
BED_MESH_CALIBRATE_FAST {rawparams}
{% endif %}
[gcode_macro print_start_set]
description: Inserted by slicer to set values used by PRINT_START.
Usage: PRINT_START_SET <VARIABLE>=<value>
variable_print: {}
gcode:
{%for k in params %}
{% set dummy = print.__setitem__(k|upper, params[k]) %}
{% endfor %}
[gcode_macro _print_start_phase_check]
gcode:
{% set print = printer["gcode_macro print_start_set"].print %}
{% set PRINT_START_PHASE = print.PRINT_START_PHASE|default("none") %}
{% if PRINT_START_PHASE != params.PHASE %}
# Reset the phases manually just to be sure.
SET_GCODE_VARIABLE MACRO=print_start_set VARIABLE=print VALUE="{{}}"
{% if params.PHASE != 'none' %}
{% set error = "PRINT_START phase error. Expected '%s' but found '%s'" %
(params.PHASE, PRINT_START_PHASE) %}
# Do the cancel manually if we're not confident it will fire.
{% if not 'virtual_sdcard' in printer or
not printer.virtual_sdcard.is_active or 'CANCEL_PRINT' not in
printer.configfile.settings.virtual_sdcard.on_error_gcode|
default("")|upper %}
{action_respond_info(error)}
CANCEL_PRINT
{% else %}
{action_raise_error(error)}
{% endif %}
{% else %}
{ action_respond_info("Expected phase '%s' but found '%s'. Resetting."
% (params.PHASE, PRINT_START_PHASE)) }
{% endif %}
{% endif %}
[gcode_macro print_end]
description: Inserted by slicer at end of print.
Usage: PRINT_END
gcode:
_KM_CHECK_IS_PRINTING
M400
_PRINT_END_INNER
{% set km = printer["gcode_macro _km_globals"] %}
{% if km.start_clear_adjustments_at_end != 0 %}
RESET_HEATER_SCALING
RESET_FAN_SCALING
M220 S100
M221 S100
{% endif %}
_RESET_LAYER_GCODE
_RESET_VELOCITY_LIMITS
TURN_OFF_HEATERS
M107; turn off fan
{% if printer.bed_mesh %}BED_MESH_CLEAR{% endif %}
# Park the toolhead and present the bed
{% if printer.toolhead.homed_axes|lower == "xyz" %}
PARK Y="{km.start_end_park_y}"
{% endif %}
M84 ; disable steppers
CLEAR_PAUSE
SET_GCODE_VARIABLE MACRO=print_start_set VARIABLE=print VALUE="{{}}"
_KM_PRINT_STATUS ACTION=CHANGE STATUS=ready RESET_STACK=1
[gcode_macro _print_end_inner]
variable_cancelled: False
gcode:
SET_GCODE_VARIABLE MACRO=_print_end_inner VARIABLE=cancelled VALUE="{False}"
{% set km = printer["gcode_macro _km_globals"] %}
{% set toolhead = printer.toolhead %}
{% set origin = printer.gcode_move.homing_origin%}
{% set max_x = km.print_max[0] - origin.x %}
{% set max_y = km.print_max[1] - origin.y %}
{% set max_z = toolhead.axis_maximum.z - origin.z %}
{% if not cancelled %}
_KM_PRINT_STATUS ACTION=CHANGE STATUS=completing
{% endif %}
{% if printer.extruder.can_extrude %}
# Wipe if we're not cancelling a paused print.
{% if not printer.pause_resume.is_paused and not cancelled and
toolhead.homed_axes|lower == "xyz" %}
{% set x_safe = (max_x - toolhead.position.x, 2.0)|min %}
{% set y_safe = (max_y - toolhead.position.y, 2.0)|min %}
{% set z_safe = (max_z - toolhead.position.z, 2.0)|min %}
G91
G0 Z{z_safe} E-1.0 F{km.travel_speed_z * 2} ; move nozzle up
G0 X{x_safe} Y{y_safe} E-1.0 F{km.travel_speed_xy} ; remove stringing
# Remove the offset now that we're done.
_KM_APPLY_PRINT_OFFSET RESET=1
{% endif %}
# Small retract to prevent ooze
G92 E0
G1 E{"%.2f" % ((0, 2 - km.load_priming_length / 4)|min)} F1200
M400
{% endif %}
[gcode_macro _km_check_is_printing]
variable_debug_state: False # Disables print state check for debugging.
description: Throws an error if print is not currently in progress.
gcode:
{% if not debug_state and
printer.idle_timeout.state|string != "Printing" and
not (printer.virtual_sdcard|default({})).is_active|default(False) and
not printer.pause_resume.is_paused %}
{ action_raise_error("No active print.") }
{% endif %}
[gcode_macro _km_check_and_set_print_bounds]
description: Validates all print bounds and caches their values.
gcode:
{% set km = printer["gcode_macro _km_globals"] %}
{% set print = printer["gcode_macro print_start_set"].print %}
# Check the mesh bounds.
{% if print.MESH_MIN %}
{% set MESH_MIN = print.MESH_MIN.split(",")|map('float')|list %}
{% set MESH_MAX = print.MESH_MAX.split(",")|map('float')|list %}
{%if MESH_MIN[0] < km.print_min[0] or MESH_MIN[1] < km.print_min[1] %}
{action_raise_error("MESH_MIN %s is outside the printable bounds %s" %
(MESH_MIN|string, km.print_min|string))}
{%elif MESH_MAX[0] > km.print_max[0] or MESH_MAX[1] > km.print_max[1] %}
{action_raise_error("MESH_MAX %s is outside the printable bounds %s" %
(MESH_MAX|string, km.print_max|string))}
{% endif %}
{% endif %}
# Find all the model bounds (including any bounds passed in).
{% set points = [] %}
{% if print.MODEL_MIN or print.MODEL_MAX %}
{% set MODEL_MIN = print.MODEL_MIN.split(",")|map('float')|list %}
{% set MODEL_MAX = print.MODEL_MAX.split(",")|map('float')|list %}
{% set points = [MODEL_MIN, MODEL_MAX] %}
{% endif %}
{% if (printer.exclude_object|default({})).objects %}
{% set points = printer.exclude_object.objects|selectattr('polygon')|
map(attribute='polygon')|sum(start=points) %}
{% set points_len = points|length %}
{% if points_len >= 2 %}
{% set x_coords = (points|map(attribute=0)|sort|list)[0::points_len-1] %}
{% set y_coords = (points|map(attribute=1)|sort|list)[0::points_len-1] %}
{% set MODEL_MIN = (x_coords[0],y_coords[0])|map('float')|list %}
{% set MODEL_MAX = (x_coords[1],y_coords[1])|map('float')|list %}
PRINT_START_SET MODEL_MIN="{MODEL_MIN|join(',')
}" MODEL_MAX="{MODEL_MAX|join(',')}"
{% endif %}
{% endif %}
{% if MODEL_MIN %}
# Check the model bounds.
{% if MODEL_MIN[0] < km.print_min[0] or MODEL_MIN[1] < km.print_min[1] %}
{action_raise_error("MODEL_MIN %s is outside the printable bounds %s" %
(MODEL_MIN|string, km.print_min|string))}
{% elif MODEL_MAX[0] > km.print_max[0] or MODEL_MAX[1] > km.print_max[1] %}
{action_raise_error("MODEL_MAX %s is outside the printable bounds %s" %
(MODEL_MAX|string, km.print_max|string))}
{% endif %}
{% endif %}
# Set the PRINT_LIMITS
{% if MESH_MIN and MODEL_MIN %}
PRINT_START_SET PRINT_MIN="{((MODEL_MIN[0],MESH_MIN[0])|min,
(MODEL_MIN[1],MESH_MIN[1])|min)|join(',')
}" PRINT_MAX="{((MODEL_MAX[0],MESH_MAX[0])|max,
(MODEL_MAX[1],MESH_MAX[1])|max)|join(',')}"
{% else %}
PRINT_START_SET PRINT_MIN="{km.print_min|join(',')
}" PRINT_MAX="{km.print_max|join(',')}"
{% endif %}