# Extruder PA synchronization with input shaping

**URL:** <https://klipper.discourse.group/t/extruder-pa-synchronization-with-input-shaping/3843>\
**Category:** Developers\
**Created:** [August 14, 2022, 5:42pm UTC](https://klipper.discourse.group/t/extruder-pa-synchronization-with-input-shaping/3843 "2022-08-14T17:42:19Z")\
**Posts on this page:** 1\
**Showing post:** 27

<div class="post-metadata">

**Author:** ![dmbutyugin](https://avatars.discourse-cdn.com/v4/letter/d/e0b2c6/32.png) [@dmbutyugin](https://klipper.discourse.group/u/dmbutyugin)\
**Post date:** [September 14, 2022, 9:53pm UTC](https://klipper.discourse.group/t/extruder-pa-synchronization-with-input-shaping/3843/27 "2022-09-14T21:53:41Z")

</div>

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`

```auto
[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`:

```auto
[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](https://github.com/dmbutyugin/klipper/tree/pa-tuning-script). Otherwise, I’ve updated the extruder pa input shaping branches to include this patch too.

---

_[View the full topic](https://klipper.discourse.group/t/extruder-pa-synchronization-with-input-shaping/3843)._
