Skip to content

Instantly share code, notes, and snippets.

@bistory
Created July 24, 2022 09:34
Show Gist options
  • Save bistory/f21b8ebca543f48e21efd83714c4e4b0 to your computer and use it in GitHub Desktop.
Save bistory/f21b8ebca543f48e21efd83714c4e4b0 to your computer and use it in GitHub Desktop.
Klipper Macro for easy Pressure Advance calibration
#
# This macro comes from VoronFR Discord : https://discord.gg/nmAdtqX6
# Pressure Advance calibration test.
#
# The main reason for this test is that the standard tuning tower provides ambigious, open to interpretation readings with a broad margin for error.
# This test provides control values next to the values being tested, so differences are easier to notice at a glance.
#
# Prints a series of bands, 6 lines per each, with the first 3 lines printed slowly and used as baseline/control and the other 3
# at two different speeds in the following sequence: 25% at 40mm/sec, 50% at 120mm/sec, 25% at 40mm/sec.
# Pressure Advance value is being increased for every band starting from 0.01 with 0.002 increments.
#
# The printed model should be inspected by looking at the top and bottom lines in each band, on the right side of the two vertical raft bars (where the print speeds change).
# Find the highest band from the bottom where the lines at its top still resemble the lines at its bottom, with no visible extrusion width irregularities.
# Then the pressure advance value is calculated as follows:
# PA = START + (INCREMENT * band_number)
# Which in case of using default values, would be:
# PA = 0.01 + (0.002 * band_number)
#
# You might also want to repeat the test using a START value that is slightly less that your calculated PA value, and smaller INCREMENTs
# to narrow down and refine your PA value further.
#
# This macro is parametric and most of the values can be adjusted with their respective input parameters.
# It can be called without any input parameters - in which case the default values would be used - or with any combination of parameters as desired.
#
# Make sure your axis are homed, your bed mesh is loaded (if you are using one) and both the hotend and the bed are at the temperature required for your filament.
# Usage:
# PRESSURE_ADVANCE_CALIBRATION START=0.01 INCREMENT=0.002 RAFT=1
#
# Primary input parameters:
# START : default(0.01) PA value to start with
# INCREMENT : default(0.002) PA value to increment for each subsequent band
# RAFT : default(1) whether to print a raft or not. printing one makes the finished test east to remove from the bed
# EXTRUSION_MULTIPLIER: default(1.25 if raft enabled, 1.5 if disabled) extrusion multiplier to apply to printing lines in the band
#
# Other tunable parameters:
# SIZE : default(120) maximum width/height, in mm, that the test can make use of. the model will be printed in the middle of the bed
# BANDS_LIMIT : default(999) optionally the number of bands can be limited this way. otherwise as many bands that fit in the given SIZE will be printed
# CONTROL_SPEED : default(30) speed at which the control lines in a band are printed at, mm/sec
# OUTER_SPEED : default(40) speed of printing the outer parts of the test lines in a band, mm/sec
# INNER_SPEED : default(120) speed of printing the middle part of the test lines in a band, mm/sec
# TRAVEL_SPEED : default(200) speed of travel moves, mm/sec
# RAFT_SPEED : default(120) speed of printing the raft, if enabled, mm/sec
# LINES_PER_BAND: default(6) number of lines per band. half of these will be control, another half the test lines
# RETRACT : default(0.6) retraction, in mm, to perform when traveling
# PURGE_MM : default(8) purge this amount of mm of filament before starting the print
# LINE_SPACING : default(0.4) spacing between individual lines in a band
#
# Play wround with enabling or disabling rafts, changing extrusion multiplier to get thicker lines where Pa changes would be easier to notice, or using
# OUTER and INNER speeds that are more realistic and closer to actual printing conditions: such as the speeds used for external and internal perimeters,
# or internal perimeters and infill. The default values for SLOW and FAST speeds are taken from Stephan's PIF profile for external and internal perimeters.
#
# @version: 1.2
#
# Based on the idea from a post by DonStauffer on https://forum.duet3d.com/topic/25161/my-pressure-advance-calibration
#
[gcode_macro PRESSURE_ADVANCE_CALIBRATION]
gcode:
#
# input and tunables
#
{% set pa_start = params.START|default(0.01)|float %} # starting PA value
{% set pa_increment = params.INCREMENT|default(0.002)|float %} # how much to increment PA per band
{% set do_raft = params.RAFT|default(1)|int %} # whether to print a raft or not
{% set print_size = params.SIZE|default(120)|int %} # width/height of the printed test
{% set num_bands = params.BANDS_LIMIT|default(999)|int %} # limit the number of bands to print. othwerwise print as many as would fit within a given size
{% set lines_per_band = params.LINES_PER_BAND|default(6)|int %} # number of lines per band. half are control, another half the test
{% set e_multiplier = params.EXTRUSION_MULTIPLIER|default(1.25 if do_raft == 1 else 1.5)|float %}, # extrusion multiplier for line print moves
{% set retract_length = params.RETRACT|default(0.6)|float %} # how much to retract when traveling between print moves
{% set initial_purge = params.PURGE_MM|default(8)|int %} # mm of filament to purge before printing. set to 0 to disable
{% set feedrate_control = params.CONTROL_SPEED|default(30)|int * 60 %} # print feedrate of the line in the middle of the band
{% set feedrate_outer = params.OUTER_SPEED|default(40)|int * 60 %} # print feedrate of the lines on the sides of the band
{% set feedrate_inner = params.INNER_SPEED|default(120)|int * 60 %} # print feedrate of the line in the middle of the band
{% set feedrate_travel = params.TRAVEL_SPEED|default(200)|int * 60 %} # travel feedrate between print moves
{% set feedrate_raft = params.RAFT_SPEED|default(120)|int * 60 %} # print feedrate for printing raft
{% set feedrate_z = 5 * 60 %} # z axis travel feedrate
{% set feedrate_retract = 50 * 60 %} # retract and deretract feedrate
{% set spacing_line = params.LINE_SPACING|default(0.4)|float %} # distance between lines in a band
{% set spacing_band = 2 %} # distance between individual bands
{% set spacing_raft = 2 %} # distance between raft lines
{% set fast_line_ratio_percent = 50 %}
# sanity check
{% set lines_per_band = [2, lines_per_band]|max %}
{% set e_multiplier = [1, e_multiplier]|max %}
{% set num_lines_control = (lines_per_band / 2)|round(0, 'floor')|int %}
{% set num_lines_test = (lines_per_band / 2)|round(0, 'ceil')|int %}
{% set spacing_line = spacing_line * (1 + e_multiplier - 1.25) %} # the higher the extrusion multiplier the wider the spacing
# computed values
{% set max_x = printer.toolhead.axis_maximum.x|float %}
{% set max_y = printer.toolhead.axis_maximum.y|float %}
{% set nozzle_diameter = printer.configfile.config['extruder'].nozzle_diameter|float %}
{% set line_width = nozzle_diameter * 1.25 %}
{% set line_height = nozzle_diameter / 2 %}
{% set z_hop_height = 2 * line_height %}
{% set e_per_mm = (line_width * line_height) / (3.1415 * (1.75/2)**2) %}
{% set spacing_purge = line_height * 0.8 %} # distance between purge lines and raft
# set print width to align with the raft grid
{% set spacing_raft = (spacing_raft / line_width)|round * line_width %} # align raft spacing to multiples of line width
{% set num_raft_lines = ([print_size, max_x]|min / spacing_raft)|round(0, 'floor')|int %}
{% set print_width = num_raft_lines * spacing_raft %}
# adjust print height to align with the band grid
{% set band_height = lines_per_band * line_width + (lines_per_band - 1) * spacing_line + spacing_band %}
{% set bands_per_height = (([print_size, max_y]|min - spacing_purge) / band_height)|round(0, 'floor')|int %}
{% set num_bands = [num_bands, bands_per_height]|min %}
{% set print_height = num_bands * band_height - spacing_band - spacing_purge %}
# adjust slow and fast line lengths to align with raft grid
{% set slow_line_length = ((print_width * (1 - fast_line_ratio_percent / 100) / 2) / spacing_raft)|round * spacing_raft + spacing_raft / 2 %} # ends between raft lines
{% set fast_line_length = print_width - slow_line_length * 2 %}
{% set thick_raft_num1 = (slow_line_length / spacing_raft)|round|int %}
{% set thick_raft_num2 = num_raft_lines - thick_raft_num1 + 1 %}
# find start position
{% set x_start = max_x / 2 - print_width / 2 %}
{% set y_start = max_y / 2 - print_height / 2 %}
{action_respond_info("")}
{action_respond_info("Starting Pressure Advance calibration print.")}
{action_respond_info("")}
{action_respond_info("This operation can not be interrupted by normal means. Hit the \"emergency stop\" button once the print starts exhibiting PA values that are obviously too high.")}
{action_respond_info("")}
{action_respond_info("PA of first band: %.4f" % pa_start)}
{action_respond_info("PA of last band: %.4f" % (num_bands * pa_increment))}
{action_respond_info("PA increment per band: %.4f" % pa_increment)}
{action_respond_info("Number of bands: %d" % num_bands)}
{action_respond_info("")}
{action_respond_info("Inspect the printed model. "
"Look at the top and bottom lines in each band, on the right side of the two vertical raft bars (where the print speeds change). "
"Find the highest band from the bottom where the lines at its top still resemble the lines at its bottom, with no visible extrusion width irregularities. "
"Your final Pressure Advance value would then be:"
)}
{action_respond_info("")}
{action_respond_info("PA = %.4f + (%.4f * band_number)" % (pa_start, pa_increment))}
{action_respond_info("")}
{action_respond_info("Update your [extruder] config section and set \"pressure_advance\" to the value you calculated.")}
{action_respond_info("")}
# The printed model should be inspected by
#
# Then the pressure advance value is calculated as follows:
# PA = START + (INCREMENT * band_number)
# Which in case of using default values, would be:
# PA = 0.01 + (0.002 * band_number)
#
SAVE_GCODE_STATE NAME=STATE_PRESSURE_ADVANCE_CALIBRATION
{% set pa_saved = printer.configfile.settings['extruder'].pressure_advance %}
SET_PRESSURE_ADVANCE ADVANCE={pa_start} # start with a given PA
#
# purging before raft
#
M117 Priming
G90 # absolute coords
G0 X{x_start} Y{y_start} Z{line_height} F{feedrate_travel} # move to start position
G91 # relative positioning
G1 E{initial_purge} F{5 * 60} # extrude at ~12mm3/sec
G1 X{print_width} E{print_width * e_per_mm} F{feedrate_raft / 2} # print prime line
G1 Y{line_width} E{line_width * e_per_mm} F{feedrate_raft / 2} # move to next line
G1 X-{print_width} E{print_width * e_per_mm} F{feedrate_raft / 2} # print prime line
#
# print the raft
#
{% if do_raft == 1 %}
G0 F{feedrate_raft} # set print speed
{% for curr_raft_line in range(1, num_raft_lines + 2) %} # rafts need to be on both sides
# see if we need to print thick raft on slow/fast line boundary
{% if curr_raft_line == thick_raft_num1 or curr_raft_line == thick_raft_num2 %}
G1 Y{loop.cycle(1.0, -1.0) * print_height} E{print_height * e_per_mm}
G1 X{line_width} E{line_width * e_per_mm}
G1 Y{loop.cycle(-1.0, 1.0) * print_height} E{print_height * e_per_mm}
G1 X{line_width} E{line_width * e_per_mm}
{% endif %}
G1 Y{loop.cycle(1.0, -1.0) * print_height} E{print_height * e_per_mm} # print the vertical raft line
# move over to next column
{% if not loop.last %}
{% set horizontal_move = spacing_raft - (2 * line_width if curr_raft_line == thick_raft_num1 - 1 or curr_raft_line == thick_raft_num2 - 1 else 0) %}
G1 X{horizontal_move} E{horizontal_move * e_per_mm}
{% endif %}
{% endfor %}
G1 E-{retract_length} F{feedrate_retract} # retract
G0 Z{z_hop_height} F{feedrate_z} # z-hop
{% endif %}
#
# print the bands
#
M117 Printing bands
G90 # absolute coords
G0 X{x_start} Y{y_start + 2 * line_width + spacing_purge} F{feedrate_travel} # move to XY start position
G0 Z{line_height + (line_height if do_raft == 1 else 0)} F{feedrate_z} # move to Z start position
G91 # relative positioning
G1 E{retract_length} F{feedrate_retract} # unretract
# print bands
{% for curr_band_num in range(1, num_bands + 1) %}
{% set outer_loop = loop %}
{% set curr_pa_value = pa_start + (curr_band_num - 1) * pa_increment %}
SET_PRESSURE_ADVANCE ADVANCE={curr_pa_value} # set PA
M117 Band {curr_band_num} PA {curr_pa_value|round(4)}
# print control lines
{% for _ in range(num_lines_control) %}
G1 X{print_width} E{print_width * e_per_mm * e_multiplier} F{feedrate_control} # print line
G1 E-{retract_length} F{feedrate_retract} # retract
G0 Z{z_hop_height} F{feedrate_z} # z-hop
G0 X-{print_width} Y{spacing_line + line_width} F{feedrate_travel} # move to start of next line
G0 Z-{z_hop_height} F{feedrate_z} # unz-hop
G1 E{retract_length} F{feedrate_retract} # unretract
{% endfor %}
# print test lines
{% for _ in range(num_lines_test) %}
{% for data in [{'mm': slow_line_length, 'f': feedrate_outer}, {'mm': fast_line_length, 'f': feedrate_inner}, {'mm': slow_line_length, 'f': feedrate_outer}] %}
G1 X{data.mm} E{data.mm * e_per_mm * e_multiplier} F{data.f} # print line
{% endfor %}
G1 E-{retract_length} F{feedrate_retract} # retract
G0 Z{z_hop_height} F{feedrate_z} # z-hop
{% if not (outer_loop.last and loop.last) %}
G0 X-{print_width} Y{(spacing_line if not loop.last else spacing_band) + line_width} F{feedrate_travel} # move to start of next line
G0 Z-{z_hop_height} F{feedrate_z} # unz-hop
G1 E{retract_length} F{feedrate_retract} # unretract
{% endif %}
{% endfor %}
{% endfor %}
#
# retract and move away
#
G1 E-{retract_length} F{feedrate_retract} # retract
G0 Z20 F{feedrate_z} # up
G0 X-{print_width / 2} Y{[50, max_y - (y_start + print_height)]|min} F{feedrate_travel} # center back
M117 # clear the LCD
SET_PRESSURE_ADVANCE ADVANCE={pa_saved} # restore original PA
RESTORE_GCODE_STATE NAME=STATE_PRESSURE_ADVANCE_CALIBRATION
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment