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