From 2b400effe3bbe18b3a39b8ea1f6c5cc39ddba5c1 Mon Sep 17 00:00:00 2001 From: Dmitry Butyugin Date: Thu, 14 Nov 2024 21:57:24 +0100 Subject: [PATCH] resonance_tester: Made the new test a default 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 --- docs/Config_Changes.md | 8 +++++++ docs/Config_Reference.md | 22 ++++++------------- docs/Measuring_Resonances.md | 20 +++--------------- klippy/extras/resonance_tester.py | 35 ++++++++----------------------- 4 files changed, 26 insertions(+), 59 deletions(-) diff --git a/docs/Config_Changes.md b/docs/Config_Changes.md index 5535dc85a195..c30b84e5a25e 100644 --- a/docs/Config_Changes.md +++ b/docs/Config_Changes.md @@ -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=` 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`. diff --git a/docs/Config_Reference.md b/docs/Config_Reference.md index efdc7924b79d..7c3d96b6302c 100644 --- a/docs/Config_Reference.md +++ b/docs/Config_Reference.md @@ -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 @@ -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 @@ -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 diff --git a/docs/Measuring_Resonances.md b/docs/Measuring_Resonances.md index cc2b33da1d8c..313028db97b8 100644 --- a/docs/Measuring_Resonances.md +++ b/docs/Measuring_Resonances.md @@ -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 diff --git a/klippy/extras/resonance_tester.py b/klippy/extras/resonance_tester.py index b5e1d6ca5ca2..ef86d908c411 100644 --- a/klippy/extras/resonance_tester.py +++ b/klippy/extras/resonance_tester.py @@ -48,20 +48,19 @@ 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 = [] @@ -69,21 +68,14 @@ def gen_test(self): 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 @@ -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() @@ -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())]