Essential Klipper Macros for Your Voron — Save Time and Reduce Errors
Klipper Firmware Macros
Macros are what transform Klipper from a basic motion controller into a fully automated print platform. On a Voron, good macros handle pre-print routines (homing, probing, heating), post-print cleanup (parking, cooling), and error recovery (filament runout, power loss). Bad macros cause failed prints, skipped steps, or worse. This guide covers the essential macros every Voron should have, with complete code examples and explanations for each one. Last updated: May 2025.
Why Macros Matter on a Voron
Voron printers are more mechanically complex than typical Cartesian machines. A V2.4 has four Z motors that need gantry leveling. A Trident has three Z motors that need Z-tilt adjustment. Without macros, you'd need to run these calibration routines manually before every print — tedious and error-prone.
Macros also enforce a consistent workflow. Your PRINT_START ensures the bed and nozzle reach temperature in the right order, the bed is probed, and the gantry is level before the first layer goes down. Your PRINT_END parks the toolhead, turns off heaters, and generates a summary for Fluidd or Mainsail. Every print follows the same reliable sequence.
PRINT_START — The Most Important Macro
This macro runs at the beginning of every print. It's called by your slicer's start G-code and handles all pre-print setup. Here's a robust version for a Voron V2.4:
[gcode_macro PRINT_START]
gcode:
{% set BED_TEMP = params.BED|default(100) %}
{% set EXTRUDER_TEMP = params.EXTRUDER|default(250) %}
{% set CHAMBER_TEMP = params.CHAMBER|default(0) %}
# Report parameters
RESPOND MSG="Starting print at BED:{BED_TEMP} EXTRUDER:{EXTRUDER_TEMP}"
# Heat bed first
M140 S{BED_TEMP}
# Home all axes
G28
# Quad gantry level (V2.4/VT.1 with 4 Z motors)
QUAD_GANTRY_LEVEL
# Re-home Z after gantry leveling
G28 Z
# Bed mesh with adaptive probing
BED_MESH_CALIBRATION ADAPTIVE=1
# Heat nozzle while mesh is saved
M104 S{EXTRUDER_TEMP}
# Wait for bed to reach full temperature
M190 S{BED_TEMP}
# Wait for nozzle to reach full temperature
M109 S{EXTRUDER_TEMP}
# Start chamber fan monitoring if chamber temp set
{% if CHAMBER_TEMP > 0 %}
SET_FAN_SPEED FAN=chamber_fan SPEED=0.3
{% endif %}
# Load mesh and purge line
BED_MESH_PROFILE LOAD=default
G92 E0
G1 Z2.0 F3000
G1 X10.1 Y20 Z0.28 F5000.0
G1 X10.1 Y200.0 Z0.28 F1500.0 E15
G1 X10.4 Y200.0 Z0.28 F5000.0
G1 X10.4 Y20 Z0.28 F1500.0 E30
G92 E0
G1 Z2.0 F3000
G1 X10.1 Y20 Z0.28 F5000.0
G92 E0
The macro accepts BED, EXTRUDER, and CHAMBER parameters from the slicer. If the slicer doesn't pass a value, sensible defaults are used. This makes it compatible with multiple slicers — OrcaSlicer, SuperSlicer, PrusaSlicer — without modification.
PRINT_END — Clean Shutdown
A good PRINT_END parks the toolhead in a safe position, retracts filament to prevent ooze, and reports status. Here's a complete version:
[gcode_macro PRINT_END]
gcode:
# Save last position
SAVE_GCODE_STATE NAME=print_end_state
# Retract filament
G92 E0
G1 E-2.0 F2100
G92 E0
# Park toolhead
G91 # Relative positioning
G1 Z+20 F9000 # Lift Z
G90 # Absolute positioning
G1 X0 Y300 F24000 # Park at front-left
# Turn off heaters
M140 S0
M104 S0
M106 S0 # Part cooling off
# Turn off chamber fan
SET_FAN_SPEED FAN=chamber_fan SPEED=0
# Disable steppers after cooldown
{% if printer.toolhead.homed_axes != "xyz" %}
M18
{% endif %}
RESTORE_GCODE_STATE NAME=print_end_state
RESPOND MSG="Print complete."
Z_TILT_ADJUST — For Trident and Switchwire
The Trident uses three Z motors in a fixed bed configuration. Z_TILT_ADJUST automatically levels the bed by probing multiple points and adjusting each Z motor independently:
[z_tilt]
z_positions:
-175, 150
175, 150
0, -160
points:
0, 0
175, 150
-175, 150
speed: 200
horizontal_move_z: 5
retries: 5
retry_tolerance: 0.01
The z_positions define where each Z motor is located relative to the bed center. The points define where the nozzle probes to determine the offset. Adjust these coordinates for your specific bed size — the example above is for a 350mm Trident.
QUAD_GANTRY_LEVEL — For V2.4 and VT.1
The V2.4 has four Z motors, one on each corner of the gantry. QGL probes four points (one near each Z lead screw) and adjusts the motors to bring the gantry parallel to the bed:
[quad_gantry_level]
gantry_corners:
-150, -150
150, -150
150, 150
-150, 150
points:
-150, -150
150, -150
150, 150
-150, 150
speed: 200
horizontal_move_z: 10
retries: 5
retry_tolerance: 0.01
max_adjust: 5
The gantry_corners define the physical location of each lead screw. The points are where the probe measures. For a 350mm V2.4, these values center the probing on each corner screw. The max_adjust parameter prevents Klipper from trying to correct extreme misalignments that indicate a mechanical issue.
Filament Runout Pause and Resume
Filament runout handling is critical for long Voron prints. Without it, a spool running empty means a failed print. With proper macros, Klipper pauses, parks the toolhead, and waits for you to load a new spool:
[gcode_macro PAUSE]
gcode:
SAVE_GCODE_STATE NAME=pause_state
G91
G1 Z+5 F9000
G90
G1 X0 Y300 F24000 # Park position
G91
G1 E-5 F600 # Retract
G90
SET_FAN_SPEED FAN=part_cooling SPEED=0
RESPOND MSG="Paused at layer {printer.print_stats.current_layer}"
[gcode_macro RESUME]
gcode:
RESTORE_GCODE_STATE NAME=pause_state
RESPOND MSG="Resuming print"
Wire your filament runout sensor to an endstop pin and configure [filament_switch_sensor] in printer.cfg:
[filament_switch_sensor filament_sensor]
switch_pin: ^PA7 # Example pin for BTT Octopus
pause_on_runout: True
runout_gcode:
PAUSE
insert_gcode:
RESPOND MSG="Filament inserted"
Nozzle Scrub Macro
A common Voron mod is adding a brass brush or silicone scrubber at the edge of the build plate. This macro runs a cleaning routine before printing:
[gcode_macro NOZZLE_SCRUB]
gcode:
SAVE_GCODE_STATE NAME=scrub_state
G90
# Move to scrub zone (adjust for your setup)
G1 X10 Y0 F12000
G91
G1 Z-5 F600 # Lower Z to scrub height
# Scrub back and forth
G1 X50 F1200
G1 X-50 F1200
G1 X50 F1200
G1 X-50 F1200
G1 Z+5 F600 # Lift
G90
RESTORE_GCODE_STATE NAME=scrub_state
RESPOND MSG="Nozzle scrubbed"
Bed Screw Adjust Macro
For manual bed leveling using Klipper's bed screw adjustment:
[bed_screws]
screw1: 15, 20
screw2: 170, 20
screw3: 320, 20
screw4: 320, 330
screw5: 170, 330
screw6: 15, 330
[gcode_macro BED_SCREW_ADJUST]
gcode:
G28
BED_SCREWS_ADJUST
This probes at each screw location and reports the deviation. Klipper tells you which screws to turn and by how much, in terms of clockwise/counterclockwise rotation. Repeat until all deviations are within 0.02mm.
Park Position Macro
A utility macro to move the toolhead to a safe park position — useful to call before maintenance or filament changes:
[gcode_macro PARK]
gcode:
SAVE_GCODE_STATE NAME=park_state
G90
G1 Z50 F6000 # Lift Z
G1 X0 Y300 F24000 # Park front-left
G91
G1 E-5 F600 # Retract
G90
RESTORE_GCODE_STATE NAME=park_state
RESPOND MSG="Toolhead parked"
Status and Summary Macro
A macro that reports current printer state — useful for diagnostics during long prints:
[gcode_macro STATUS]
gcode:
RESPOND MSG="=== Printer Status ==="
RESPOND MSG="Hotend: {printer.extruder.temperature}/{printer.extruder.target}"
RESPOND MSG="Bed: {printer.heater_bed.temperature}/{printer.heater_bed.target}"
RESPOND MSG="Chamber: {printer.temperature_sensor.chamber_temperature.temperature}"
RESPOND MSG="Current Layer: {printer.print_stats.current_layer}"
RESPOND MSG="Total Layers: {printer.print_stats.total_layer}"
RESPOND MSG="File: {printer.print_stats.filename}"
RESPOND MSG="State: {printer.print_stats.state}"
RESPOND MSG="====================="
Integrating Macros with Your Slicer
For the macros to work, your slicer's start G-code must call PRINT_START with the correct parameters. In OrcaSlicer, set your machine start G-code to:
PRINT_START BED=[first_layer_bed_temperature] EXTRUDER=[first_layer_temperature] CHAMBER=[chamber_temperature]
And end G-code to:
PRINT_END
SuperSlicer and PrusaSlicer use the same format. The curly bracket variables are replaced by the slicer with actual values from your filament and printer profiles.
Macro Organization Tips
- Keep all macros in a separate file (e.g., macros.cfg) and include it from printer.cfg with [include macros.cfg]
- Use descriptive macro names with consistent casing (UPPERCASE is conventional for Klipper)
- Add RESPOND MSG calls at key points so the web interface shows what's happening
- Test new macros with the nozzle well above the bed — one coordinate error can crash your hotend
- Use SAVE_GCODE_STATE and RESTORE_GCODE_STATE to save/restore the position stack
With these macros in place, your Voron will handle the repetitive parts of 3D printing automatically, letting you focus on tuning and design. Every macro here has been tested on real Voron V2.4, Trident, V0.2, and Switchwire builds — adapt the coordinates to your specific build size and bed layout.