macros.cfg
🧩 Syntax:
#####################################################################
# Macros
#####################################################################
[gcode_macro PRINT_START]
# This variable will set the Z offset for your first layer.
variable_z_offset: 0.06
# This variable will set the temp used for probing and homing.
variable_probe_temp: 150
gcode:
# Check if BED and HOTEND parameters are given.
{% if not params.BED %}
{action_raise_error("Parameter 'BED' is missing.")}
{% elif not params.HOTEND %}
{action_raise_error("Parameter 'HOTEND' is missing.")}
{% else %}
# Grab the parameters and cast them as int.
{% set bed_temp = params.BED | int %}
{% set hotend_temp = params.HOTEND | int %}
{% set probe_temp = printer["gcode_macro PRINT_START"].probe_temp %}
{% set z_offset = printer["gcode_macro PRINT_START"].z_offset %}
# Get max X, Y, and speeds.
{% set max_x = printer.toolhead.axis_maximum.x %}
{% set max_y = printer.toolhead.axis_maximum.y %}
{% set max_accel = printer.configfile.settings.printer.max_accel %}
{% set max_speed = (printer.configfile.settings.printer.max_velocity * 60) %}
# Perform initial homing if needed.
{% if "xyz" not in printer.toolhead.homed_axes %}
M117 Homing all axes..
G28
{% endif %}
# Turn off fans, clear existing mesh, and set Z offset to 0.
M107
BED_MESH_CLEAR
SET_GCODE_OFFSET Z=0
# Set absolute positioning and move the toolhead to center and close to bed for heat soaking the beacon probe.
G90
G0 X{max_x//2} Y{max_y//2} F{80 * 60}
G0 Z3 F{50 * 60}
# Heat the bed and then heat hotend to probe temp.
M117 {"Waiting for bed temperature to reach %dC.." % (bed_temp)}
M190 S{bed_temp}
TOOL_LEDS STATE=PRINT
M117 {"Waiting for hotend to reach %dC.." % (probe_temp)}
M109 S{probe_temp}
# Perform beacon model calibration, bed mesh, and then z-offset calibration.
M117 Performing Z offset and Bed Mesh calibration..
G28 Z METHOD=CONTACT CALIBRATE=1 # Z offset + beacon model calibrate
BED_MESH_CALIBRATE PROBE_METHOD=proximity ADAPTIVE=1 RUNS=2
G28 Z METHOD=CONTACT CALIBRATE=0 # Z offset only
# Move toolhead to center of bed and heat to printing temp.
G0 X{max_x//2} Y{max_y//2} F{80 * 60}
G0 Z5 F{50 * 60}
M117 {"Waiting for hotend to reach %dC.." % (hotend_temp)}
M109 S{hotend_temp}
# Move toolhead to edge of part location and perform Voron Purge and begin print.
M117 Starting print..
SET_GCODE_OFFSET Z={z_offset}
PARK
VORON_PURGE
{% endif %}
[gcode_macro PRINT_END]
gcode:
# Get Boundaries
{% set max_x = printer.configfile.config["stepper_x"]["position_max"]|float %}
{% set max_y = printer.configfile.config["stepper_y"]["position_max"]|float %}
{% set max_z = printer.configfile.config["stepper_z"]["position_max"]|float %}
# Check end position to determine safe directions to move
{% if printer.toolhead.position.x < (max_x - 20) %}
{% set x_safe = 20.0 %}
{% else %}
{% set x_safe = -20.0 %}
{% endif %}
{% if printer.toolhead.position.y < (max_y - 20) %}
{% set y_safe = 20.0 %}
{% else %}
{% set y_safe = -20.0 %}
{% endif %}
{% if printer.toolhead.position.z < (max_z - 2) %}
{% set z_safe = 2.0 %}
{% else %}
{% set z_safe = max_z - printer.toolhead.position.z %}
{% endif %}
# Commence PRINT_END
M400 ; wait for buffer to clear
G92 E0 ; zero the extruder
G1 E-4.0 F3600 ; retract
G91 ; relative positioning
G0 Z{z_safe} F3600 ; move nozzle up
G0 X{x_safe} Y{y_safe} F20000 ; move nozzle to remove stringing
G1 E{printer["gcode_macro VORON_PURGE"].tip_distance * -1} F{60 * 5}
M104 S0 ; turn off hotend
M140 S0 ; turn off bed
M106 S0 ; turn off fan
TOOL_LEDS STATE=START
G90 ; absolute positioning
G0 X{max_x / 2} Y{max_y} F3600 ; park nozzle at rear
M117 Finished!
[gcode_macro VORON_PURGE]
description: Pre-print purge in the shape of Voron logo.
# Configurable variables.
variable_purge_height: 0.8 # Z position of nozzle during purge, default is 0.8.
variable_tip_distance: 15 # Distance between tip of filament and nozzle before purge. Should be similar to PRINT_END final retract amount.
variable_purge_margin: 10 # Distance the purge will be in front of the print area, default is 10.
variable_purge_amount: 30 # Amount of filament to be purged prior to printing. Default 30
variable_flow_rate: 16 # Flow rate of purge in mm3/s. Default is 12.
variable_retract_length: 1 # Length in mm for retractions.
variable_retract_speed: 30 # Speed in mm/s for retractions.
gcode:
# Check if printer has been homed first.
{% if "xyz" not in printer.toolhead.homed_axes %}
{action_raise_error("Must home all axes first.")}
{% else %}
# Get relevant printer params
{% set travel_speed = (printer.toolhead.max_velocity) * 60 | float %}
{% set cross_section = printer.configfile.settings.extruder.max_extrude_cross_section | float %}
# Get purge settings.
{% set purge_height = printer["gcode_macro VORON_PURGE"].purge_height | float %}
{% set tip_distance = printer["gcode_macro VORON_PURGE"].tip_distance | float %}
{% set purge_margin = printer["gcode_macro VORON_PURGE"].purge_margin | float %}
{% set purge_amount = printer["gcode_macro VORON_PURGE"].purge_amount | float %}
{% set flow_rate = params.FLOW | default(printer["gcode_macro VORON_PURGE"].flow_rate) | float %}
{% set size = 10 | float %}
{% set retract_length = printer["gcode_macro VORON_PURGE"].retract_length %}
{% set retract_speed = printer["gcode_macro VORON_PURGE"].retract_speed * 60 %}
# Calculate purge origins and centers from objects
{% set all_points = printer.exclude_object.objects | map(attribute='polygon') | sum(start=[]) %} # Get all object points
{% set purge_x_min = (all_points | map(attribute=0) | min | default(0)) %} # Object x min
{% set purge_x_max = (all_points | map(attribute=0) | max | default(0)) %} # Object x max
{% set purge_y_min = (all_points | map(attribute=1) | min | default(0)) %} # Object y min
{% set purge_y_max = (all_points | map(attribute=1) | max | default(0)) %} # Object y max
{% set purge_x_center = ([((purge_x_max + purge_x_min) / 2) - (purge_amount / 2), 0] | max) %} # Create center point of purge line relative to print on X axis
{% set purge_y_center = ([((purge_y_max + purge_y_min) / 2) - (purge_amount / 2), 0] | max) %} # Create center point of purge line relative to print on Y axis
{% set purge_x_origin = ([purge_x_min - purge_margin, 0] | max) %} # Add margin to x min, compare to 0, and choose the larger
{% set purge_y_origin = ([purge_y_min - purge_margin, 0] | max) %} # Add margin to y min, compare to 0, and choose the larger
# Calculate purge speed
{% set purge_move_speed = (flow_rate / 5.0) * 60 | float %}
{% if cross_section < 5 %}
{action_respond_info("[Extruder] max_extrude_cross_section is insufficient for purge, please set it to 5 or greater. Purge skipped.")}
{% else %}
# Perform the purge.
SAVE_GCODE_STATE NAME=Prepurge_State # Create gcode state
G92 E0 # Reset extruder
G0 F{travel_speed} # Set travel speed
G90 # Absolute positioning
G0 X{purge_x_origin} Y{purge_y_origin+size/2} # Move to purge position
G0 Z{purge_height} # Move to purge Z height
M83 # Relative extrusion mode
G1 E{tip_distance} F{purge_move_speed} # Move tip of filament to nozzle
G1 X{purge_x_origin+size*0.289} Y{purge_y_origin+size} E{purge_amount/4} F{purge_move_speed} # Purge first line of logo
G1 E-{retract_length} F{retract_speed} # Retract
G0 Z{purge_height*2} # Z hop
G0 X{purge_x_origin+size*0.789} Y{purge_y_origin+size} # Move to second purge line origin
G0 Z{purge_height} # Move to purge Z height
G1 E{retract_length} F{retract_speed} # Recover
G1 X{purge_x_origin+size*0.211} Y{purge_y_origin} E{purge_amount/2} F{purge_move_speed} # Purge second line of logo
G1 E-{retract_length} F{retract_speed} # Retract
G0 Z{purge_height*2} # Z hop
G0 X{purge_x_origin+size*0.711} Y{purge_y_origin} # Move to third purge line origin
G0 Z{purge_height} # Move to purge Z height
G1 E{retract_length} F{retract_speed} # Recover
G1 X{purge_x_origin+size} Y{purge_y_origin+size/2} E{purge_amount/4} F{purge_move_speed} # Purge third line of logo
G1 E-{retract_length} F{retract_speed} # Retract.
G0 Z{purge_height*2} F{travel_speed} # Z hop
M82
G92 E0 # Reset extruder distance
RESTORE_GCODE_STATE NAME=Prepurge_State # Restore gcode state
{% endif %}
{% endif %}
[gcode_macro PARK]
# Z height for center and smart parking. Default: Voron 30, KAMP 10.
variable_default_z_height: 10
# Minimum allowed Z height.
variable_min_z_height: 5
gcode:
{% set position = params.POS | default('CENTER') | upper %}
{% set speed = (printer.configfile.settings.printer.max_velocity * 60) %}
{% set z_height = params.Z | default(printer["gcode_macro PARK"].default_z_height) | int %}
{% set min_z_meight = printer["gcode_macro PARK"].min_z_height %}
{% set max_x = printer.toolhead.axis_maximum.x %}
{% set max_y = printer.toolhead.axis_maximum.y %}
{% set purge_margin = printer["gcode_macro VORON_PURGE"].purge_margin | float %} # Set purge margin variable
{% set center_x = max_x / 2 | float %} # Create center point of x for fallback
{% set center_y = max_y / 2 | float %} # Create center point of y for fallback
{% set all_points = printer.exclude_object.objects | map(attribute='polygon') | sum(start=[]) %} # Gather all object points
{% set x_min = all_points | map(attribute=0) | min | default(center_x) %} # Set x_min from smallest object x point
{% set y_min = all_points | map(attribute=1) | min | default(center_y) %} # Set y_min from smallest object y point
# If objects are detected apply purge_margin if > 0.
{% if purge_margin > 0 and x_min != center_x and y_min != center_y %}
{% set x_min = [ x_min - purge_margin , x_min ] | max %}
{% set y_min = [ y_min - purge_margin , y_min ] | max %}
{% endif %}
# Park toolhead near object area.
G0 X{x_min} Y{y_min} F{speed}
G0 Z{z_height}
[gcode_macro LOAD_FILAMENT]
# Distance from extruder to the tip of nozzle.
variable_load_distance: 70
# Purge amount.
variable_purge_distance: 30
# Default hotend temp
variable_hotend_temp: 220
gcode:
{% set speed = params.SPEED|default(5) %}
{% set max_velocity = params.MAX|default(30) %}
{% set hotend_temp = params.TEMP|default(printer["gcode_macro LOAD_FILAMENT"].hotend_temp) %}
SAVE_GCODE_STATE NAME=load_state
M107 # Part cooling fan off.
M109 S{hotend_temp} # Heat hotend.
M106 S255 # Part cooling fan to full.
G91 # Relative positioning.
G92 E0 # Zero extruder.
G1 E{load_distance} F{max_velocity * 60} # Fast move extruder.
G1 E{purge_distance} F{speed * 60} # Purge move
RESTORE_GCODE_STATE NAME=load_state
[gcode_macro UNLOAD_FILAMENT]
# Distance from extruder to the tip of nozzle.
variable_unload_distance: 100
# Purge amount.
variable_purge_distance: 30
# Default hotend temp
variable_hotend_temp: 220
gcode:
{% set speed = params.SPEED|default(5) %}
{% set max_velocity = params.MAX|default(30) %}
{% set hotend_temp = params.TEMP|default(printer["gcode_macro UNLOAD_FILAMENT"].hotend_temp) %}
SAVE_GCODE_STATE NAME=unload_state
M107 # Part cooling fan off.
M109 S{hotend_temp} # Heat hotend.
G91 # Relative positioning.
G92 E0 # Zero extruders
G1 E{purge_distance} F{speed * 60} # Purge move
G1 E-{unload_distance} F{max_velocity * 60} # Fast unload.
RESTORE_GCODE_STATE NAME=unload_state
[gcode macro TOOL_LEDS]
description: Macro for control of the toolhead LEDs.
gcode:
{% if params.STATE == 'START'%}
SET_LED LED=headlight RED=1 GREEN=0 BLUE=0 WHITE=0 INDEX=1
SET_LED LED=headlight RED=0 GREEN=0 BLUE=0 WHITE=0 INDEX=2
SET_LED LED=headlight RED=0 GREEN=0 BLUE=0 WHITE=0 INDEX=3
{% elif params.STATE == 'PRINT' %}
SET_LED LED=headlight RED=1 GREEN=0 BLUE=0 WHITE=0 INDEX=1
SET_LED LED=headlight RED=0 GREEN=0 BLUE=0 WHITE=1 INDEX=2
SET_LED LED=headlight RED=0 GREEN=0 BLUE=0 WHITE=1 INDEX=3
{% else}
{action_raise_error("TOOL_LEDS state invalid.")}
{% endif %}
[delayed_gcode SET_LED_START]
duration: 1
description: Set LEDs at startup.
gcode:
TOOL_LEDS STATE=START
[gcode_macro TEST_SPEED]
description: Tool for testing maximum speeds and accelerations.
gcode:
# Speed
{% set speed = params.SPEED|default(printer.configfile.settings.printer.max_velocity)|int %}
# Iterations
{% set iterations = params.ITERATIONS|default(5)|int %}
# Acceleration
{% set accel = params.ACCEL|default(printer.configfile.settings.printer.max_accel)|int %}
# Bounding inset for large pattern (helps prevent slamming the toolhead into the sides after small skips, and helps to account for machines with imperfectly set dimensions)
{% set bound = params.BOUND|default(20)|int %}
# Size for small pattern box
{% set smallpatternsize = SMALLPATTERNSIZE|default(20)|int %}
# Large pattern
# Max positions, inset by BOUND
{% set x_min = printer.toolhead.axis_minimum.x + bound %}
{% set x_max = printer.toolhead.axis_maximum.x - bound %}
{% set y_min = printer.toolhead.axis_minimum.y + bound %}
{% set y_max = printer.toolhead.axis_maximum.y - bound %}
# Small pattern at center
# Find X/Y center point
{% set x_center = (printer.toolhead.axis_minimum.x|float + printer.toolhead.axis_maximum.x|float ) / 2 %}
{% set y_center = (printer.toolhead.axis_minimum.y|float + printer.toolhead.axis_maximum.y|float ) / 2 %}
# Set small pattern box around center point
{% set x_center_min = x_center - (smallpatternsize/2) %}
{% set x_center_max = x_center + (smallpatternsize/2) %}
{% set y_center_min = y_center - (smallpatternsize/2) %}
{% set y_center_max = y_center + (smallpatternsize/2) %}
# Save current gcode state (absolute/relative, etc)
SAVE_GCODE_STATE NAME=TEST_SPEED
# Output parameters to g-code terminal
{ action_respond_info("TEST_SPEED: starting %d iterations at speed %d, accel %d" % (iterations, speed, accel)) }
# Home and get position for comparison later:
M400 # Finish moves - https://github.com/AndrewEllis93/Print-Tuning-Guide/issues/66
G28
# QGL if not already QGLd (only if QGL section exists in config)
{% if printer.configfile.settings.quad_gantry_level %}
{% if printer.quad_gantry_level.applied == False %}
QUAD_GANTRY_LEVEL
G28 Z
{% endif %}
{% endif %}
# Move 50mm away from max position and home again (to help with hall effect endstop accuracy - https://github.com/AndrewEllis93/Print-Tuning-Guide/issues/24)
G90
G1 X{printer.toolhead.axis_maximum.x-50} Y{printer.toolhead.axis_maximum.y-50} F{30*60}
M400 # Finish moves - https://github.com/AndrewEllis93/Print-Tuning-Guide/issues/66
G28 X Y
G0 X{printer.toolhead.axis_maximum.x-1} Y{printer.toolhead.axis_maximum.y-1} F{30*60}
G4 P1000
GET_POSITION
# Go to starting position
G0 X{x_min} Y{y_min} Z{bound + 10} F{speed*60}
# Set new limits
SET_VELOCITY_LIMIT VELOCITY={speed} ACCEL={accel}
{% for i in range(iterations) %}
# Large pattern diagonals
G0 X{x_min} Y{y_min} F{speed*60}
G0 X{x_max} Y{y_max} F{speed*60}
G0 X{x_min} Y{y_min} F{speed*60}
G0 X{x_max} Y{y_min} F{speed*60}
G0 X{x_min} Y{y_max} F{speed*60}
G0 X{x_max} Y{y_min} F{speed*60}
# Large pattern box
G0 X{x_min} Y{y_min} F{speed*60}
G0 X{x_min} Y{y_max} F{speed*60}
G0 X{x_max} Y{y_max} F{speed*60}
G0 X{x_max} Y{y_min} F{speed*60}
# Small pattern diagonals
G0 X{x_center_min} Y{y_center_min} F{speed*60}
G0 X{x_center_max} Y{y_center_max} F{speed*60}
G0 X{x_center_min} Y{y_center_min} F{speed*60}
G0 X{x_center_max} Y{y_center_min} F{speed*60}
G0 X{x_center_min} Y{y_center_max} F{speed*60}
G0 X{x_center_max} Y{y_center_min} F{speed*60}
# Small patternbox
G0 X{x_center_min} Y{y_center_min} F{speed*60}
G0 X{x_center_min} Y{y_center_max} F{speed*60}
G0 X{x_center_max} Y{y_center_max} F{speed*60}
G0 X{x_center_max} Y{y_center_min} F{speed*60}
{% endfor %}
# Restore max speed/accel/accel_to_decel to their configured values
SET_VELOCITY_LIMIT VELOCITY={printer.configfile.settings.printer.max_velocity} ACCEL={printer.configfile.settings.printer.max_accel}
# Re-home and get position again for comparison:
M400 # Finish moves - https://github.com/AndrewEllis93/Print-Tuning-Guide/issues/66
G28 # This is a full G28 to fix an issue with CoreXZ - https://github.com/AndrewEllis93/Print-Tuning-Guide/issues/12
# Go to XY home positions (in case your homing override leaves it elsewhere)
G90
G0 X{printer.toolhead.axis_maximum.x-1} Y{printer.toolhead.axis_maximum.y-1} F{30*60}
G4 P1000
GET_POSITION
# Restore previous gcode state (absolute/relative, etc)
RESTORE_GCODE_STATE NAME=TEST_SPEED