Skip to content

Commit

Permalink
resonance_tester: Made the new test a default
Browse files Browse the repository at this point in the history
This also removed the option to specify the test method directly,
and reworked the handling of the test parameters from GCode a bit.

Signed-off-by: Dmitry Butyugin <[email protected]>
  • Loading branch information
dmbutyugin committed Nov 14, 2024
1 parent adce95f commit 2b400ef
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 59 deletions.
8 changes: 8 additions & 0 deletions docs/Config_Changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@ All dates in this document are approximate.

## Changes

20241115: The resonance test has been changed to include slow sweeping
moves. This change requires that testing point(s) have some clearance
in X/Y plane (+/- 30 mm from the test point should suffice when using
the default settings). The new test should generally produce more
accurate and reliable test results. However, if required, the previous
test behavior can be restored by adding options `sweeping_period: 0` and
`accel_per_hz: 75` to the `[resonance_tester]` config section.

20241112: Option `CHIPS=<chip_name>` in `TEST_RESONANCES` and
`SHAPER_CALIBRATE` requires specifying the full name(s) of the accel
chip(s). For example, `adxl345 rpi` instead of short name - `rpi`.
Expand Down
22 changes: 6 additions & 16 deletions docs/Config_Reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -1785,15 +1785,6 @@ section of the measuring resonances guide for more information on
# and on the toolhead (for X axis). These parameters have the same
# format as 'accel_chip' parameter. Only 'accel_chip' or these two
# parameters must be provided.
#method: vibrations
# A test method to use for resonance testing. Valid choices are
# vibrations, sweeping_vibrations. The vibrations method tests
# different vibration frequencies at the designated test point.
# The sweeping_vibrations method tests different vibration frequencies
# while also moving the toolhead slowly around the test point, and
# thus may help, for example, if stiction of the toolhead (a force that
# must be be overcome to start toolhead motion) is too high.
# The default is vibrations, which is generally a recommended choice.
#max_smoothing:
# Maximum input shaper smoothing to allow for each axis during shaper
# auto-calibration (with 'SHAPER_CALIBRATE' command). By default no
Expand All @@ -1806,7 +1797,7 @@ section of the measuring resonances guide for more information on
# Minimum frequency to test for resonances. The default is 5 Hz.
#max_freq: 133.33
# Maximum frequency to test for resonances. The default is 133.33 Hz.
#accel_per_hz: 75
#accel_per_hz: 60
# This parameter is used to determine which acceleration to use to
# test a specific frequency: accel = accel_per_hz * freq. Higher the
# value, the higher is the energy of the oscillations. Can be set to
Expand All @@ -1821,13 +1812,12 @@ section of the measuring resonances guide for more information on
# will decrease the precision of the test. The default value is 1.0
# (Hz/sec == sec^-2).
#sweeping_accel: 400
# An acceleration of slow sweeping moves. Available only for
# sweeping_vibrations test method. The default is 400 mm/sec^2.
# An acceleration of slow sweeping moves. The default is 400 mm/sec^2.
#sweeping_period: 1.2
# A period of slow sweeping moves. Must not be set to a too small
# value in order to not poison the measurements. Available only for
# sweeping_vibrations test method. The default is 1.2 sec which is
# a good all-round choice.
# A period of slow sweeping moves. Setting this parameter to 0
# disables slow sweeping moves. Avoid setting it to a too small
# non-zero value in order to not poison the measurements.
# The default is 1.2 sec which is a good all-round choice.
```

## Config file helpers
Expand Down
20 changes: 3 additions & 17 deletions docs/Measuring_Resonances.md
Original file line number Diff line number Diff line change
Expand Up @@ -705,23 +705,9 @@ of the printer itself and not the carriage, and some people get better
results by mounting the accelerometer on the nozzle itself). As for
mechanical problems, the user should inspect if there is any fault that
can be fixed with a moving axis (e.g. linear guide rails cleaned up and
lubricated and V-slot wheels tension adjusted correctly). However, if
the axis has too high stiction (a force that must be be overcome to start
toolhead motion over that axis) and thus binds, or if the user gets
recommended shapers that do not eliminate the echo well on the prints
and troubleshooting did not help, the user may try to use a different
resonance test method that can be activated by adding
```
[resonance_tester]
method: sweeping_vibrations
```
option to the Klipper config, restarting Klipper, and reruning the resonance
test again. Note that this test moves the toolhead slowly around the test
point, thus requiring some clearance around the test point over the tested
axis. Since this method may produce higher amplitude vibrations compared to
the default method, it is avised to monitor the printer closely during the
test, and if the vibrations get too strong, the user may need to reduce
`accel_per_hz` value in `[resonance_tester]` section from its default value.
lubricated and V-slot wheels tension adjusted correctly). If none of that
helps, a user may try the other shapers from the produced list besides the
one recommended by default.

### Testing custom axes

Expand Down
35 changes: 9 additions & 26 deletions klippy/extras/resonance_tester.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,42 +48,34 @@ def _parse_axis(gcmd, raw_axis):
class VibrationPulseTestGenerator:
def __init__(self, config):
self.min_freq = config.getfloat('min_freq', 5., minval=1.)
# Defaults are such that max_freq * accel_per_hz == 10000 (max_accel)
self.max_freq = config.getfloat('max_freq', 10000. / 75.,
self.max_freq = config.getfloat('max_freq', 135.,
minval=self.min_freq, maxval=300.)
self.accel_per_hz = config.getfloat('accel_per_hz', 75., above=0.)
self.accel_per_hz = config.getfloat('accel_per_hz', 60., above=0.)
self.hz_per_sec = config.getfloat('hz_per_sec', 1.,
minval=0.1, maxval=2.)
def prepare_test(self, gcmd):
self.freq_start = gcmd.get_float("FREQ_START", self.min_freq, minval=1.)
self.freq_end = gcmd.get_float("FREQ_END", self.max_freq,
minval=self.freq_start, maxval=300.)
self.accel_per_hz = gcmd.get_float("ACCEL_PER_HZ",
self.accel_per_hz, above=0.)
self.hz_per_sec = gcmd.get_float("HZ_PER_SEC", self.hz_per_sec,
above=0., maxval=2.)
self.test_accel_per_hz = gcmd.get_float("ACCEL_PER_HZ",
self.accel_per_hz, above=0.)
self.test_hz_per_sec = gcmd.get_float("HZ_PER_SEC", self.hz_per_sec,
above=0., maxval=2.)
def gen_test(self):
freq = self.freq_start
res = []
sign = 1.
time = 0.
while freq <= self.freq_end + 0.000001:
t_seg = .25 / freq
accel = self.accel_per_hz * freq
accel = self.test_accel_per_hz * freq
time += t_seg
res.append((time, sign * accel))
time += t_seg
res.append((time, -sign * accel))
freq += 2. * t_seg * self.hz_per_sec
freq += 2. * t_seg * self.test_hz_per_sec
sign = -sign
return res
def get_params(self):
return {
'freq_start': self.freq_start,
'freq_end': self.freq_end,
'accel_per_hz': self.accel_per_hz,
'hz_per_sec': self.hz_per_sec,
}
def get_max_freq(self):
return self.freq_end

Expand Down Expand Up @@ -125,11 +117,6 @@ def gen_test(self):
res.append((next_t, accel + sweeping_accel * sig))
last_t = next_t
return res
def get_params(self):
params = self.vibration_generator.get_params()
params.update({'sweeping_accel': self.sweeping_accel,
'sweeping_period': self.sweeping_period})
return params
def get_max_freq(self):
return self.vibration_generator.get_max_freq()

Expand Down Expand Up @@ -210,11 +197,7 @@ class ResonanceTester:
def __init__(self, config):
self.printer = config.get_printer()
self.move_speed = config.getfloat('move_speed', 50., above=0.)
test_methods = {
'vibrations': VibrationPulseTestGenerator,
'sweeping_vibrations': SweepingVibrationsTestGenerator}
test_method = config.getchoice('method', test_methods, 'vibrations')
self.generator = test_method(config)
self.generator = SweepingVibrationsTestGenerator(config)
self.executor = ResonanceTestExecutor(config)
if not config.get('accel_chip_x', None):
self.accel_chip_names = [('xy', config.get('accel_chip').strip())]
Expand Down

0 comments on commit 2b400ef

Please sign in to comment.