Skip to content

Commit

Permalink
fixed compatibility with Klipper < v0.12.0-239
Browse files Browse the repository at this point in the history
  • Loading branch information
Frix-x committed Dec 22, 2024
1 parent 6376c84 commit c6a57c9
Showing 1 changed file with 41 additions and 12 deletions.
53 changes: 41 additions & 12 deletions shaketune/helpers/resonance_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,28 @@

from ..helpers.console_output import ConsoleOutput

# Shake&Tune: 3D printer analysis tools
#
# Adapted from Klipper's original resonance_tester.py file by Dmitry Butyugin <[email protected]>
# Copyright (C) 2024 Félix Boisselier <[email protected]> (Frix_x on Discord)
# Licensed under the GNU General Public License v3.0 (GPL-3.0)
#
# File: resonance_test.py
# Description: Contains functions to test the resonance frequency of the printer and its components
# by vibrating the toolhead in specific axis directions. This derive a bit from Klipper's
# implementation as there are a couple of changes:
# 1. Original code doesn't use euclidean distance with projection for the coordinates calculation.
# The new approach implemented here ensures that the vector's total length remains constant (= L),
# regardless of the direction components. It's especially important when the direction vector
# involves combinations of movements along multiple axes like for the diagonal belt tests.
# 2. Original code doesn't allow Z axis movements that was added in order to test the Z axis resonance
# or CoreXZ belts frequency profiles as well.
# 3. There is the possibility to do a real static frequency test by specifying a duration and a
# fixed frequency to maintain.


# This class is used to generate the base vibration test sequences
# Note: it's almost untouched from the original Klipper code from Dmitry Butyugin
class BaseVibrationGenerator:
def __init__(self, min_freq, max_freq, accel_per_hz, hz_per_sec):
self.min_freq = min_freq
Expand Down Expand Up @@ -66,6 +86,7 @@ def gen_test(self):


# This class is a derivative of BaseVibrationGenerator that adds slow sweeping acceleration to the test sequences (new style)
# Note: it's almost untouched from the original Klipper code from Dmitry Butyugin
class SweepingVibrationGenerator(BaseVibrationGenerator):
def __init__(self, min_freq, max_freq, accel_per_hz, hz_per_sec, sweeping_accel=400.0, sweeping_period=1.2):
super().__init__(min_freq, max_freq, accel_per_hz, hz_per_sec)
Expand Down Expand Up @@ -192,10 +213,12 @@ def vibrate_axis(self, axis_direction, min_freq=None, max_freq=None, hz_per_sec=
s_period = base_s_period
s_accel = base_s_accel

if s_period > 0:
gen = SweepingVibrationGenerator(final_min_f, final_max_f, final_aph, final_hps, s_accel, s_period)
else:
if s_period == 0 or self.is_old_klipper:
ConsoleOutput.print('Using pulse-only test')
gen = BaseVibrationGenerator(final_min_f, final_max_f, final_aph, final_hps)
else:
ConsoleOutput.print('Using pulse test with additional sweeping')
gen = SweepingVibrationGenerator(final_min_f, final_max_f, final_aph, final_hps, s_accel, s_period)

test_seq = gen.gen_test()
self._run_test_sequence(axis_direction, test_seq)
Expand All @@ -216,15 +239,19 @@ def _run_test_sequence(self, axis_direction, test_seq):
X, Y, Z, E = toolhead.get_position()

old_max_accel = toolhead_info['max_accel']
old_mcr = toolhead_info.get('minimum_cruise_ratio', 1.0)

# Set velocity limits
if test_seq:
max_accel = max(abs(a) for _, a, _ in test_seq)
else:
max_accel = old_max_accel # no moves, just default

gcode.run_script_from_command(f'SET_VELOCITY_LIMIT ACCEL={max_accel:.3f} MINIMUM_CRUISE_RATIO=0')
if 'minimum_cruise_ratio' in toolhead_info: # minimum_cruise_ratio found: Klipper >= v0.12.0-239
old_mcr = toolhead_info['minimum_cruise_ratio']
gcode.run_script_from_command(f'SET_VELOCITY_LIMIT ACCEL={max_accel} MINIMUM_CRUISE_RATIO=0')
else: # minimum_cruise_ratio not found: Klipper < v0.12.0-239
old_mcr = None
gcode.run_script_from_command(f'SET_VELOCITY_LIMIT ACCEL={max_accel}')

# Disable input shaper if present
input_shaper = self.toolhead.printer.lookup_object('input_shaper', None)
Expand All @@ -240,7 +267,7 @@ def _run_test_sequence(self, axis_direction, test_seq):

for next_t, accel, freq in test_seq:
t_seg = next_t - last_t
gcode.run_script_from_command(f'M204 S={abs(accel):.3f}')
toolhead.cmd_M204(gcode.create_gcode_command('M204', 'M204', {'S': abs(accel)}))
v = last_v + accel * t_seg
abs_v = abs(v)
if abs_v < 1e-6:
Expand All @@ -253,7 +280,8 @@ def _run_test_sequence(self, axis_direction, test_seq):
dX, dY, dZ = self._project_distance(d, normalized_direction)
nX, nY, nZ = X + dX, Y + dY, Z + dZ

toolhead.limit_next_junction_speed(abs_last_v)
if not self.is_old_klipper:
toolhead.limit_next_junction_speed(abs_last_v)

# If direction changed sign, must pass through zero velocity
if v * last_v < 0:
Expand All @@ -278,13 +306,14 @@ def _run_test_sequence(self, axis_direction, test_seq):
if last_v != 0.0:
d_decel = -0.5 * last_v2 / old_max_accel if old_max_accel != 0 else 0
ddX, ddY, ddZ = self._project_distance(d_decel, normalized_direction)
gcode.run_script_from_command(f'M204 S={old_max_accel:.3f}')
toolhead.cmd_M204(gcode.create_gcode_command('M204', 'M204', {'S': old_max_accel}))
toolhead.move([X + ddX, Y + ddY, Z + ddZ, E], abs(last_v))

# Restore original limits
gcode.run_script_from_command(
f'SET_VELOCITY_LIMIT ACCEL={old_max_accel:.3f} MINIMUM_CRUISE_RATIO={old_mcr:.3f}'
)
# Restore the previous acceleration values
if old_mcr is not None: # minimum_cruise_ratio found: Klipper >= v0.12.0-239
gcode.run_script_from_command(f'SET_VELOCITY_LIMIT ACCEL={old_max_accel} MINIMUM_CRUISE_RATIO={old_mcr}')
else: # minimum_cruise_ratio not found: Klipper < v0.12.0-239
gcode.run_script_from_command(f'SET_VELOCITY_LIMIT ACCEL={old_max_accel}')

# Re-enable input shaper if disabled
if input_shaper is not None:
Expand Down

0 comments on commit c6a57c9

Please sign in to comment.