Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Trying to fix Klipper TTC errors #168

Merged
merged 11 commits into from
Oct 20, 2024
42 changes: 31 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,38 @@ Follow these steps to install Shake&Tune on your printer:
```
[shaketune]
# result_folder: ~/printer_data/config/ShakeTune_results
# The folder where the results will be stored. It will be created if it doesn't exist.
# number_of_results_to_keep: 3
# The number of results to keep in the result_folder. The oldest results will
# be automatically deleted after each runs.
# keep_raw_csv: False
# If True, the raw CSV files will be kept in the result_folder alongside the
# PNG graphs. If False, they will be deleted and only the graphs will be kept.
# Path where the processed results will be stored. If the folder doesn't exist,
# it will be automatically created. You can change this if you'd like to store
# results in a different location.
# number_of_results_to_keep: 10
# This setting defines how many results you want to keep in the result folder.
# Once the specified number is exceeded, older results will be automatically deleted
# to free up space on the SD card and avoid cluttering the results folder.
# keep_raw_data: False
# If set to True, Shake&Tune will store both the processed graphs and the raw accelerometer
# .stdata files in the results folder. This can be useful for debugging or archiving purposes.
# Please always attach them when reporting any issues on GitHub or Discord.
# show_macros_in_webui: True
# Mainsail and Fluidd doesn't create buttons for "system" macros that are not in the
# printer.cfg file. If you want to see the macros in the webui, set this to True.
# timeout: 300
# The maximum time in seconds to let Shake&Tune process the CSV files and generate the graphs.
# Mainsail and Fluidd doesn't create buttons for system commands (macros that are not part
# of the printer.cfg file). This option allow Shake&Tune to inject them into the webui at runtime.
# If set to False, the macros will be hidden but still accessible from the console by typing
# their names manually, which can be useful if you prefer to encapsulate them into your own macros.
# timeout: 600
# This defines the maximum processing time (in seconds) to allow to Shake&Tune for generating
# graphs from a .stdata file. 10 minutes should be more than enough in most cases, but if you have
# slower hardware (e.g., older SD cards or low-performance devices), increase it to prevent timeouts.
# measurements_chunk_size: 2
# Each Shake&Tune command uses the accelerometer to take multiple measurements. By default,
# Shake&Tune will write a chunk of data to disk every two measurements, and at the end of the
# command will merge these chunks into the final .stdata file for processing. "2" is a very
# conservative setting to avoid Klipper Timer Too Close errors on lower end devices with little
# RAM, and should work for everyone. However, if you are using a powerful computer, you may
# wish to increase this value to keep more measurements in memory (e.g., 15-20) before writing
# the chunk and avoid stressing the filesystem too much.
# dpi: 300
# Controls the resolution of the generated graphs. The default value of 300 dpi was optimized
# and strikes a balance between performance and readability, ensuring that graphs are clear
# without using too much RAM to generate them. Usually, you shouldn't need to change this value.
```

Don't forget to check out **[Shake&Tune documentation here](./docs/README.md)**.
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ matplotlib==3.8.2
numpy==1.26.2
scipy==1.11.4
PyWavelets==1.6.0
zstandard==0.23.0
107 changes: 0 additions & 107 deletions shaketune/commands/accelerometer.py

This file was deleted.

29 changes: 17 additions & 12 deletions shaketune/commands/axes_map_calibration.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
# and performs post-processing to analyze the collected data.


from ..helpers.accelerometer import Accelerometer, MeasurementsManager
from ..helpers.console_output import ConsoleOutput
from ..shaketune_process import ShakeTuneProcess
from .accelerometer import Accelerometer

SEGMENT_LENGTH = 30 # mm

Expand All @@ -35,9 +35,9 @@ def axes_map_calibration(gcmd, config, st_process: ShakeTuneProcess) -> None:
current_axes_map = pconfig.status_raw_config[accel_chip].get('axes_map', None)
if current_axes_map is not None and current_axes_map.strip().replace(' ', '') != 'x,y,z':
raise gcmd.error(
f'The parameter axes_map is already set in your {accel_chip} configuration! Please remove it (or set it to "x,y,z")!'
f'The parameter axes_map is already set in your {accel_chip} configuration! Please remove it (or set it to "x,y,z") to be able to use this macro!'
)
accelerometer = Accelerometer(printer.get_reactor(), k_accelerometer)
accelerometer = Accelerometer(k_accelerometer, printer.get_reactor())

toolhead_info = toolhead.get_status(systime)
old_accel = toolhead_info['max_accel']
Expand Down Expand Up @@ -69,26 +69,30 @@ def axes_map_calibration(gcmd, config, st_process: ShakeTuneProcess) -> None:
toolhead.move([mid_x - SEGMENT_LENGTH / 2, mid_y - SEGMENT_LENGTH / 2, z_height, E], feedrate_travel)
toolhead.dwell(0.5)

measurements_manager = MeasurementsManager(st_process.get_st_config().chunk_size)

# Start the measurements and do the movements (+X, +Y and then +Z)
accelerometer.start_measurement()
accelerometer.start_recording(measurements_manager, name='axesmap_X', append_time=True)
toolhead.dwell(0.5)
toolhead.move([mid_x + SEGMENT_LENGTH / 2, mid_y - SEGMENT_LENGTH / 2, z_height, E], speed)
toolhead.dwell(0.5)
accelerometer.stop_measurement('axesmap_X', append_time=True)
accelerometer.stop_recording()
accelerometer.wait_for_samples()
toolhead.dwell(0.5)
accelerometer.start_measurement()
accelerometer.start_recording(measurements_manager, name='axesmap_Y', append_time=True)
toolhead.dwell(0.5)
toolhead.move([mid_x + SEGMENT_LENGTH / 2, mid_y + SEGMENT_LENGTH / 2, z_height, E], speed)
toolhead.dwell(0.5)
accelerometer.stop_measurement('axesmap_Y', append_time=True)
accelerometer.stop_recording()
accelerometer.wait_for_samples()
toolhead.dwell(0.5)
accelerometer.start_measurement()
accelerometer.start_recording(measurements_manager, name='axesmap_Z', append_time=True)
toolhead.dwell(0.5)
toolhead.move([mid_x + SEGMENT_LENGTH / 2, mid_y + SEGMENT_LENGTH / 2, z_height + SEGMENT_LENGTH, E], speed)
toolhead.dwell(0.5)
accelerometer.stop_measurement('axesmap_Z', append_time=True)

accelerometer.wait_for_file_writes()
accelerometer.stop_recording()
accelerometer.wait_for_samples()
toolhead.dwell(0.5)

# Re-enable the input shaper if it was active
if input_shaper is not None:
Expand All @@ -109,5 +113,6 @@ def axes_map_calibration(gcmd, config, st_process: ShakeTuneProcess) -> None:
ConsoleOutput.print('This may take some time (1-3min)')
creator = st_process.get_graph_creator()
creator.configure(accel, SEGMENT_LENGTH)
st_process.run()
measurements_manager.wait_for_data_transfers(printer.get_reactor())
st_process.run(measurements_manager)
st_process.wait_for_completion()
20 changes: 12 additions & 8 deletions shaketune/commands/axes_shaper_calibration.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@
# and generates graphs for each axis to analyze the collected data.


from ..helpers.accelerometer import Accelerometer, MeasurementsManager
from ..helpers.common_func import AXIS_CONFIG
from ..helpers.console_output import ConsoleOutput
from ..helpers.resonance_test import vibrate_axis
from ..shaketune_process import ShakeTuneProcess
from .accelerometer import Accelerometer


def axes_shaper_calibration(gcmd, config, st_process: ShakeTuneProcess) -> None:
Expand Down Expand Up @@ -95,26 +95,30 @@ def axes_shaper_calibration(gcmd, config, st_process: ShakeTuneProcess) -> None:
a for a in AXIS_CONFIG if a['axis'] == axis_input or (axis_input == 'all' and a['axis'] in ('x', 'y'))
]
for config in filtered_config:
measurements_manager = MeasurementsManager(st_process.get_st_config().chunk_size)

# First we need to find the accelerometer chip suited for the axis
accel_chip = Accelerometer.find_axis_accelerometer(printer, config['axis'])
if accel_chip is None:
raise gcmd.error('No suitable accelerometer found for measurement!')
accelerometer = Accelerometer(printer.get_reactor(), printer.lookup_object(accel_chip))
accelerometer = Accelerometer(printer.lookup_object(accel_chip), printer.get_reactor())

# Then do the actual measurements
accelerometer.start_measurement()
ConsoleOutput.print(f'Measuring {config["label"]}...')
accelerometer.start_recording(measurements_manager, name=config['label'], append_time=True)
vibrate_axis(toolhead, gcode, config['direction'], min_freq, max_freq, hz_per_sec, accel_per_hz)
accelerometer.stop_measurement(config['label'], append_time=True)

accelerometer.wait_for_file_writes()
accelerometer.stop_recording()
accelerometer.wait_for_samples()
toolhead.dwell(0.5)
toolhead.wait_moves()

# And finally generate the graph for each measured axis
ConsoleOutput.print(f'{config["axis"].upper()} axis frequency profile generation...')
ConsoleOutput.print('This may take some time (1-3min)')
st_process.run()
measurements_manager.wait_for_data_transfers(printer.get_reactor())
st_process.run(measurements_manager)
st_process.wait_for_completion()
toolhead.dwell(1)
toolhead.wait_moves()

# Re-enable the input shaper if it was active
if input_shaper is not None:
Expand Down
19 changes: 12 additions & 7 deletions shaketune/commands/compare_belts_responses.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@
# for each axis to analyze the collected data.


from ..helpers.accelerometer import Accelerometer, MeasurementsManager
from ..helpers.common_func import AXIS_CONFIG
from ..helpers.console_output import ConsoleOutput
from ..helpers.motors_config_parser import MotorsConfigParser
from ..helpers.resonance_test import vibrate_axis
from ..shaketune_process import ShakeTuneProcess
from .accelerometer import Accelerometer


def compare_belts_responses(gcmd, config, st_process: ShakeTuneProcess) -> None:
Expand Down Expand Up @@ -60,7 +60,7 @@ def compare_belts_responses(gcmd, config, st_process: ShakeTuneProcess) -> None:
raise gcmd.error(
'No suitable accelerometer found for measurement! Multi-accelerometer configurations are not supported for this macro.'
)
accelerometer = Accelerometer(printer.get_reactor(), printer.lookup_object(accel_chip))
accelerometer = Accelerometer(printer.lookup_object(accel_chip), printer.get_reactor())

# Move to the starting point
test_points = res_tester.test.get_start_test_points()
Expand Down Expand Up @@ -103,13 +103,17 @@ def compare_belts_responses(gcmd, config, st_process: ShakeTuneProcess) -> None:
else:
input_shaper = None

measurements_manager = MeasurementsManager(st_process.get_st_config().chunk_size)

# Run the test for each axis
for config in filtered_config:
accelerometer.start_measurement()
ConsoleOutput.print(f'Measuring {config["label"]}...')
accelerometer.start_recording(measurements_manager, name=config['label'], append_time=True)
vibrate_axis(toolhead, gcode, config['direction'], min_freq, max_freq, hz_per_sec, accel_per_hz)
accelerometer.stop_measurement(config['label'], append_time=True)

accelerometer.wait_for_file_writes()
accelerometer.stop_recording()
accelerometer.wait_for_samples()
toolhead.dwell(0.5)
toolhead.wait_moves()

# Re-enable the input shaper if it was active
if input_shaper is not None:
Expand All @@ -124,5 +128,6 @@ def compare_belts_responses(gcmd, config, st_process: ShakeTuneProcess) -> None:
# Run post-processing
ConsoleOutput.print('Belts comparative frequency profile generation...')
ConsoleOutput.print('This may take some time (1-3min)')
st_process.run()
measurements_manager.wait_for_data_transfers(printer.get_reactor())
st_process.run(measurements_manager)
st_process.wait_for_completion()
Loading
Loading