# calibrate-offsets.cfg
################################################################################# ################## ProForge 5 Print Head Calibration Config #################### #################################################################################
#config file version v1.0.1 #release date: 03.06.2026
[tools_calibrate] pin: ^PG10 travel_speed: 20 # mm/s to travel sideways for XY probing spread: 7 # mm to travel down from top for XY probing lower_z: 0.50 # mm/s to move tools down onto the probe speed: 2 # mm/s to retract between probes lift_speed: 4 # Z lift after probing; should exceed any Z variance final_lift_z: 6 # final lift height after calibration
# --- nozzle-probe sampling settings --- sample_retract_dist: 2 # mm to retract between sample probes samples_tolerance: 0.1 # allowable spread before re-sampling samples: 2 # number of raw probe samples to take samples_result: median # how to collapse samples: median or average
# Optional nozzle-probe calibration: probe: probe # name of the nozzle probe to use trigger_to_bottom_z: 1.0 # offset from probe trigger to nozzle bottom # decrease if nozzle reads too high, increase if too low
[gcode_macro _CALIBRATE_MOVE_OVER_PROBE] gcode: BED_MESH_CLEAR G0 Z26 F10000 # safe Z; G0 X314 Y379 F10000 # PROBE LOCATION - Default X314 Y379
[gcode_macro CALIBRATE_TOOL_OFFSETS] gcode: {% set svv = printer.save_variables.variables %} {% set tool_count = svv.active_tools %}
{% if tool_count == 0 %} RESPOND MSG="No print heads detected. Check configuration." {% elif tool_count == 1 %} RESPOND MSG="Only one print head installed. Calibration requires more than one." {% elif tool_count == 2 %} RESPOND MSG="Detected 2 print heads. Heating both to 150°C before calibration." T0 M104 S150 # Heat Tool 0 to 150°C T1 M104 S150 # Heat Tool 1 to 150°C T0 M109 S150 # Wait until Tool 0 is 150°C T1 M109 S150 # Wait until Tool 1 is 150°C RESPOND MSG="Starting calibration for 2 print heads." G28 DOCK _CAL_SELECT_T0 _CALIBRATE_MOVE_OVER_PROBE TOOL_LOCATE_SENSOR M104 S0 SAVE_GCODE_STATE NAME=SENSOR_LOCATION _CAL_DOCK_T0 {% for tool in [1] %} _CAL_SELECT_T{tool} RESTORE_GCODE_STATE NAME=SENSOR_LOCATION MOVE=1 MOVE_SPEED=150 TOOL_CALIBRATE_TOOL_OFFSET_{tool} M104 S0 _CAL_DOCK_T{tool} {% endfor %} SAVE_CONFIG
{% elif tool_count == 3 %} RESPOND MSG="Detected 3 print heads. Heating all to 150°C before calibration." T0 M104 S150 T1 M104 S150 T2 M104 S150 T0 M109 S150 T1 M109 S150 T2 M109 S150 RESPOND MSG="Starting calibration for 3 print heads." G28 DOCK _CAL_SELECT_T0 _CALIBRATE_MOVE_OVER_PROBE TOOL_LOCATE_SENSOR M104 S0 SAVE_GCODE_STATE NAME=SENSOR_LOCATION _CAL_DOCK_T0 {% for tool in [1, 2] %} _CAL_SELECT_T{tool} RESTORE_GCODE_STATE NAME=SENSOR_LOCATION MOVE=1 MOVE_SPEED=150 TOOL_CALIBRATE_TOOL_OFFSET_{tool} M104 S0 _CAL_DOCK_T{tool} {% endfor %} SAVE_CONFIG
{% elif tool_count == 4 %} RESPOND MSG="Detected 4 print heads. Heating all to 150°C before calibration." T0 M104 S150 T1 M104 S150 T2 M104 S150 T3 M104 S150 T0 M109 S150 T1 M109 S150 T2 M109 S150 T3 M109 S150 RESPOND MSG="Starting calibration for 4 print heads." G28 DOCK _CAL_SELECT_T0 _CALIBRATE_MOVE_OVER_PROBE TOOL_LOCATE_SENSOR M104 S0 SAVE_GCODE_STATE NAME=SENSOR_LOCATION _CAL_DOCK_T0 {% for tool in [1, 2, 3] %} _CAL_SELECT_T{tool} RESTORE_GCODE_STATE NAME=SENSOR_LOCATION MOVE=1 MOVE_SPEED=150 TOOL_CALIBRATE_TOOL_OFFSET_{tool} M104 S0 _CAL_DOCK_T{tool} {% endfor %} SAVE_CONFIG
{% elif tool_count == 5 %} RESPOND MSG="Detected 5 print heads. Heating all to 150°C before calibration." T0 M104 S150 T1 M104 S150 T2 M104 S150 T3 M104 S150 T4 M104 S150 T0 M109 S150 T1 M109 S150 T2 M109 S150 T3 M109 S150 T4 M109 S150 RESPOND MSG="Starting calibration for 5 print heads." G28 DOCK _CAL_SELECT_T0 _CALIBRATE_MOVE_OVER_PROBE TOOL_LOCATE_SENSOR M104 S0 SAVE_GCODE_STATE NAME=SENSOR_LOCATION _CAL_DOCK_T0 {% for tool in [1, 2, 3, 4] %} _CAL_SELECT_T{tool} RESTORE_GCODE_STATE NAME=SENSOR_LOCATION MOVE=1 MOVE_SPEED=150 TOOL_CALIBRATE_TOOL_OFFSET_{tool} M104 S0 _CAL_DOCK_T{tool} {% endfor %} SAVE_CONFIG
{% else %} RESPOND MSG="Error: Unexpected tool count. Check configuration." {% endif %}
### Toolhead Select and Dock Macros ###
[gcode_macro _CAL_SELECT_T0] gcode: {% set svv = printer.save_variables.variables %} T0 G90 G0 Y{svv.zero_select_y} F12000 G0 X{svv.zero_select_x + 7} F12000 G0 X{svv.zero_select_x} F1000 G0 Y{svv.zero_dock_y} F1000 _SERVO_SELECT G0 X{svv.zero_select_x + 8} F9000 _WIPE G0 X0 F9000 G4 P1000
[gcode_macro _CAL_DOCK_T0] gcode: {% set svv = printer.save_variables.variables %} _OFFSET_RESET G90 G0 Y{svv.zero_dock_y} F12000 G0 X{svv.zero_dock_x + 31} F12000 G0 X{svv.zero_dock_x} F8000 _SERVO_DOCK G0 Y{svv.zero_select_y} F4000 G0 X{svv.zero_dock_x + 10} F12000 G0 X15 F20000
[gcode_macro _CAL_SELECT_T1] gcode: {% set svv = printer.save_variables.variables %} T1 G90 G0 Y{svv.one_select_y} F12000 G0 X{svv.one_select_x + 7} F12000 G0 X{svv.one_select_x} F1000 G0 Y{svv.one_dock_y} F1000 _SERVO_SELECT G0 X{svv.one_select_x + 8} F9000 _WIPE G0 X0 F9000 G4 P1000
[gcode_macro _CAL_DOCK_T1] gcode: {% set svv = printer.save_variables.variables %} _OFFSET_RESET G90 G0 Y{svv.one_dock_y} F12000 G0 X{svv.one_dock_x + 31} F12000 G0 X{svv.one_dock_x} F8000 _SERVO_DOCK G0 Y{svv.one_select_y} F4000 G0 X{svv.one_dock_x + 10} F12000 G0 X15 F20000
[gcode_macro _CAL_SELECT_T2] gcode: {% set svv = printer.save_variables.variables %} T2 G90 G0 Y{svv.two_select_y} F12000 G0 X{svv.two_select_x + 7} F12000 G0 X{svv.two_select_x} F1000 G0 Y{svv.two_dock_y} F1000 _SERVO_SELECT G0 X{svv.two_select_x + 8} F9000 _WIPE G0 X0 F9000 G4 P1000
[gcode_macro _CAL_DOCK_T2] gcode: {% set svv = printer.save_variables.variables %} _OFFSET_RESET G90 G0 Y{svv.two_dock_y} F12000 G0 X{svv.two_dock_x + 31} F12000 G0 X{svv.two_dock_x} F8000 _SERVO_DOCK G0 Y{svv.two_select_y} F4000 G0 X{svv.two_dock_x + 10} F12000 G0 X15 F20000
[gcode_macro _CAL_SELECT_T3] gcode: {% set svv = printer.save_variables.variables %} T3 G90 G0 Y{svv.three_select_y} F12000 G0 X{svv.three_select_x + 7} F12000 G0 X{svv.three_select_x} F1000 G0 Y{svv.three_dock_y} F1000 _SERVO_SELECT G0 X{svv.three_select_x + 8} F9000 _WIPE G0 X0 F9000 G4 P1000
[gcode_macro _CAL_DOCK_T3] gcode: {% set svv = printer.save_variables.variables %} _OFFSET_RESET G90 G0 Y{svv.three_dock_y} F12000 G0 X{svv.three_dock_x + 31} F12000 G0 X{svv.three_dock_x} F8000 _SERVO_DOCK G0 Y{svv.three_select_y} F4000 G0 X{svv.three_dock_x + 10} F12000 G0 X15 F20000
[gcode_macro _CAL_SELECT_T4] gcode: {% set svv = printer.save_variables.variables %} T4 G90 G0 Y{svv.four_select_y} F12000 G0 X{svv.four_select_x + 7} F12000 G0 X{svv.four_select_x} F1000 G0 Y{svv.four_dock_y} F1000 _SERVO_SELECT G0 X{svv.four_select_x + 8} F9000 _WIPE G0 X0 F9000 G4 P1000
[gcode_macro _CAL_DOCK_T4] gcode: {% set svv = printer.save_variables.variables %} _OFFSET_RESET G90 G0 Y{svv.four_dock_y} F12000 G0 X{svv.four_dock_x + 31} F12000 G0 X{svv.four_dock_x} F8000 _SERVO_DOCK G0 Y{svv.four_select_y} F4000 G0 X{svv.four_dock_x + 10} F12000 G0 X15 F20000