Hi,
The current ringing_tower test isn’t too bad for input shaping calibration, but it has 1 severe defect: for each tested axis it, technically, changes the velocity for both axes, because it has diagonal moves that are pretty much impossible to avoid:
As a result, both axis can start to vibrate after the notch. If one is lucky, the vibrations of the axis that follows the motion of the toolhead are small enough, then perpendicular vibrations of the other axis will be most visible, and one can measure its resonance frequency. However, if the vibrations of the collinear axis are too large, e.g. if that axis is much heavier than the other one, then the vibrations may interfere with the vibrations of the axis of interest, leading to irregular waves on the side of the print that are hard to measure. Here one can see that there are some parasitic waves after the notch, and the period of the waves seems to change after some time:
Looking at the accelerometer data (obtained using motan tools):
one can see that even though this is the side of the test for X axis, Y axis actually resonates more and has higher amplitude of vibrations, and some vibrations are also present on Z axis.
In order to overcome this defect, I tried to create an alternative test that would affect one, the tested axis a time. Unfortunately, making such test required direct GCode generation. Here’s what I came up with:
In a nutshell, the test first accelerates both axes during a diagonal move, but then decelerates only one - tested axis - to a complete stop, while the other axis maintains its original speed, and the vibrations are excited only on one axis at a time:
The test has the embossed axes letters on the sides where the measurements are supposed to be performed. They can also be used to estimate the magnitude of smoothing after the input shaper has been calibrated, as they become less crisp with the increase of acceleration:
With the new test, I managed to more reliably calibrate the input shaper by measuring the distances and the number of waves in several places of the test and taking the averages:
axis | N | D, mm | F, hz |
---|---|---|---|
Y | 3 | 5.7 | 42.11 |
Y | 4 | 7.5 | 42.67 |
Y | 4 | 7.35 | 43.54 |
Y | 6 | 11 | 43.64 |
Y | 4 | 7.3 | 43.84 |
Y | 43.2 | ||
X | 3 | 5.65 | 42.48 |
X | 4 | 6.9 | 46.38 |
X | 5 | 8.5 | 47.06 |
X | 4 | 7.25 | 44.14 |
X | 3 | 5.2 | 46.15 |
X | 4 | 7.4 | 43.24 |
X | 44.9 |
These results were not in 100% correspondence with the data from the accelerometer calibration:
but this is likely because I have several resonances on each axis. And they were still quite good with EI input shaper.
At least, these were the results on my Ender 3 Pro, but it may work differently on, say, CoreXY or Delta printers. I also understand that the accelerometer-based calibration may be more robust. However, even then it is good to have an ability to confirm the results of the calibration. And some may not wish to purchase an accelerometer, and they may still benefit from the print-based test. So, if you want to give it a try, I made another module similar to a new proposed PA test available in the branch GitHub - dmbutyugin/klipper at pa-tuning-script (and also in this and this branch).
In order to enable it, I suggest to add the following snippet to the printer.cfg:
[ringing_test]
[delayed_gcode start_ringing_test]
gcode:
{% set vars = printer["gcode_macro RUN_RINGING_TEST"] %}
; Add your start GCode here, for example:
G28
M190 S{vars.bed_temp}
M109 S{vars.hotend_temp}
M106 S255
{% set flow_percent = vars.flow_rate|float * 100.0 %}
{% if flow_percent > 0 %}
M221 S{flow_percent}
{% endif %}
{% set layer_height = vars.nozzle * 0.5 %}
{% set first_layer_height = layer_height * 1.25 %}
PRINT_RINGING_TOWER {vars.rawparams} LAYER_HEIGHT={layer_height} FIRST_LAYER_HEIGHT={first_layer_height} FINAL_GCODE_ID=end_ringing_test
[delayed_gcode end_ringing_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=RINGING_TEST_STATE
[gcode_macro RUN_RINGING_TEST]
variable_bed_temp: -1
variable_hotend_temp: -1
variable_nozzle: -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_RINGING_TEST VARIABLE=bed_temp VALUE={params.BED_TEMP|default(60)}
SET_GCODE_VARIABLE MACRO=RUN_RINGING_TEST VARIABLE=hotend_temp VALUE={params.TARGET_TEMP}
SET_GCODE_VARIABLE MACRO=RUN_RINGING_TEST VARIABLE=nozzle VALUE={params.NOZZLE}
SET_GCODE_VARIABLE MACRO=RUN_RINGING_TEST VARIABLE=flow_rate VALUE={params.FLOW_RATE|default(-1)}
SET_GCODE_VARIABLE MACRO=RUN_RINGING_TEST VARIABLE=rawparams VALUE="'{rawparams}'"
SAVE_GCODE_STATE NAME=RINGING_TEST_STATE
UPDATE_DELAYED_GCODE ID=start_ringing_test DURATION=0.01
Then the ringing tower test can be triggered via a command like RUN_RINGING_TEST NOZZLE=0.4 TARGET_TEMP=210 BED_TEMP=55
.
[ringing_tower]
module has the following parameters that can be altered (and these are their default values):
[ringing_tower]
# Interesting parameters that may require adjustment
size: 100
height: 60
band: 5
perimeters: 2
velocity: 80
brim_velocity: 30
accel_start: 1500 # the acceleration of the start of the test
accel_step: 500 # the increment of the acceleration every `band` mm
layer_height: 0.2
first_layer_height: 0.2
filament_diameter: 1.75
# Parameters that are computed automatically, but may be adjusted if necessary
center_x: ... # Center of the bed by default (if detected correctly)
center_y: ... # Center of the bed by default (if detected correctly)
brim_width: ... # computed based on the model size, but may be increased
# Parameters that are better left at their default values
# notch: 1 # size of the notch in mm
# notch_offset: ... # 0.275 * size by default
# deceleration_points: 100