Extruder PA synchronization with input shaping

OK, so I put together a module to print that PA tower from within Klipper. It works as follows. You can add the following configuration to printer.cfg

[pa_test]
# size_x: 100
# size_y: 50
# height: 50
# origin_x: #bed_center_x
# origin_y: #bed_center_y
# layer_height: 0.2
# first_layer_height: 0.3
# perimeters: 2
# brim_width: 10
# slow_velocity: 20
# fast_velocity: 80
# filament_diameter: 1.75

Basically, as you can see, all parameters have their default values, so just adding [pa_test] may suffice. However, automatic tower placement (and determining max size) on some exotic kinematics like polar, delta, etc. may not work very well, in which case it may be necessary to manually specify origin_x, origin_y (and perhaps size_x and size_y). Then you can initiate a tower print by issuing a PRINT_PA_TOWER command. It also lets you override any of the parameters from printer.cfg (e.g. as PRINT_PA_TOWER BRIM_WIDTH=5), and it also has 2 other required parameters NOZZLE and TARGET_TEMP (e.g. PRINT_PA_TOWER NOZZLE=0.4 TARGET_TEMP=205) that cannot be set in the config. This is because both have critical impact on PA testing, so you must make sure that you are providing the correct values. However, PRINT_PA_TOWER does not heat the extruder, and TARGET_TEMP is only used for sanity-checking the currently configured extruder temp; you must pre-heat the extruder separately.

Now, to the GCode prologue/epilogue and other features. I do not recommend using PRINT_PA_TOWER directly. Instead, I suggest to add the following macros to your printer.cfg:

[delayed_gcode start_pa_test]
gcode:
    {% set vars = printer["gcode_macro RUN_PA_TEST"] %}
    ; Add your start GCode here, for example:
    G28
    M190 S{vars.bed_temp}
    M109 S{vars.hotend_temp}
    {% set flow_percent = vars.flow_rate|float * 100.0 %}
    {% if flow_percent > 0 %}
    M221 S{flow_percent}
    {% endif %}
    TUNING_TOWER COMMAND=SET_PRESSURE_ADVANCE PARAMETER=ADVANCE START=0 FACTOR=.005
    ; PRINT_PA_TOWER must be the last command in the start_pa_test script:
    ; it starts a print and then immediately returns without waiting for the print to finish
    PRINT_PA_TOWER {vars.rawparams} FINAL_GCODE_ID=end_pa_test

[delayed_gcode end_pa_test]
gcode:
    ; Add your end GCode here, for example:
    M104 S0 ; turn off temperature
    M140 S0 ; turn off heatbed
    M107 ; turn off fan
    G91 ; relative positioning
    G1 Z5 ; raise Z
    G90 ; absolute positioning
    G1 X0 Y200 ; present print
    M84 ; disable steppers
    RESTORE_GCODE_STATE NAME=PA_TEST_STATE

[gcode_macro RUN_PA_TEST]
variable_bed_temp: -1
variable_hotend_temp: -1
variable_flow_rate: -1
variable_rawparams: ''
gcode:
    # Fail early if the required parameters are not provided
    {% if params.NOZZLE is not defined %}
    {action_raise_error('NOZZLE= parameter must be provided')}
    {% endif %}
    {% if params.TARGET_TEMP is not defined %}
    {action_raise_error('TARGET_TEMP= parameter must be provided')}
    {% endif %}
    SET_GCODE_VARIABLE MACRO=RUN_PA_TEST VARIABLE=bed_temp VALUE={params.BED_TEMP|default(60)}
    SET_GCODE_VARIABLE MACRO=RUN_PA_TEST VARIABLE=hotend_temp VALUE={params.TARGET_TEMP}
    SET_GCODE_VARIABLE MACRO=RUN_PA_TEST VARIABLE=flow_rate VALUE={params.FLOW_RATE|default(-1)}
    SET_GCODE_VARIABLE MACRO=RUN_PA_TEST VARIABLE=rawparams VALUE="'{rawparams}'"
    SAVE_GCODE_STATE NAME=PA_TEST_STATE
    UPDATE_DELAYED_GCODE ID=start_pa_test DURATION=0.01

Of course, you can adjust the scripts to your liking and add more parameters, for example. Then you can just call as RUN_PA_TEST NOZZLE=0.4 TARGET_TEMP=205 [other params as necessary].

Note the use of FINAL_GCODE_ID parameter of PRINT_PA_TOWER to trigger a delayed_gcode upon print completion, and also passing all parameters as-is to it via {vars.rawparams}. The latter uses the fact that Klipper ignores unknown GCode command parameters, so you can safely pass additional parameters to RUN_PA_TEST (e.g. FLOW_RATE) that are only handled by the macro itself and which are not recognized by PRINT_PA_TOWER.

For this to work nicely I also modified virtual_sdcard module to support printing from other GCode sources rather than the virtual sdcard itself. So, the PA tower prints somewhat similar to as if it was printed from sdcard, e.g. there is progress tracking and you can call PAUSE/RESUME and CANCEL_PRINT if you enable [pause_resume] module to pause/unpause and cancel the print. Alas, I could have broken [virtual_sdcard] module in some non-obvious way, so if you run into issues, please report.

If you wish to test just this new script with the current Klipper PA implementation, you can use this branch. Otherwise, I’ve updated the extruder pa input shaping branches to include this patch too.