From 50ed13ca598b0be8dce1225cac56fbe273dd826b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Boisselier?= Date: Thu, 20 Jun 2024 11:59:19 +0200 Subject: [PATCH] using Klipper reactor for file write process handling --- shaketune/commands/accelerometer.py | 28 +++++++++++++++++-- shaketune/commands/axes_map_calibration.py | 20 +++++++------ shaketune/commands/axes_shaper_calibration.py | 12 ++++---- shaketune/commands/compare_belts_responses.py | 12 ++++---- .../commands/create_vibrations_profile.py | 20 +++++++------ shaketune/commands/excitate_axis_at_freq.py | 2 +- 6 files changed, 62 insertions(+), 32 deletions(-) diff --git a/shaketune/commands/accelerometer.py b/shaketune/commands/accelerometer.py index 3fbde12..d00c0d2 100644 --- a/shaketune/commands/accelerometer.py +++ b/shaketune/commands/accelerometer.py @@ -13,10 +13,13 @@ import os import time from multiprocessing import Process, Queue +FILE_WRITE_TIMEOUT = 10 # seconds + class Accelerometer: - def __init__(self, klipper_accelerometer): + def __init__(self, reactor, klipper_accelerometer): self._k_accelerometer = klipper_accelerometer + self._reactor = reactor self._bg_client = None self._write_queue = Queue() @@ -70,16 +73,35 @@ class Accelerometer: os.nice(20) except Exception: pass + with open(filename, 'w') as f: f.write('#time,accel_x,accel_y,accel_z\n') samples = bg_client.samples or bg_client.get_samples() for t, accel_x, accel_y, accel_z in samples: f.write(f'{t:.6f},{accel_x:.6f},{accel_y:.6f},{accel_z:.6f}\n') + self._write_queue.get() def wait_for_file_writes(self): while not self._write_queue.empty(): - time.sleep(0.1) + eventtime = self._reactor.monotonic() + self._reactor.pause(eventtime + 0.1) + for proc in self._write_processes: - proc.join() + if proc is None: + continue + eventtime = self._reactor.monotonic() + endtime = eventtime + FILE_WRITE_TIMEOUT + complete = False + while eventtime < endtime: + eventtime = self._reactor.pause(eventtime + 0.05) + if not proc.is_alive(): + complete = True + break + if not complete: + raise TimeoutError( + 'Shake&Tune was not able to write the accelerometer data into the CSV file. ' + 'This might be due to a slow SD card or a busy or full filesystem.' + ) + self._write_processes = [] diff --git a/shaketune/commands/axes_map_calibration.py b/shaketune/commands/axes_map_calibration.py index b310949..9c8e433 100644 --- a/shaketune/commands/axes_map_calibration.py +++ b/shaketune/commands/axes_map_calibration.py @@ -37,7 +37,7 @@ def axes_map_calibration(gcmd, config, st_process: ShakeTuneProcess) -> None: 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")!' ) - accelerometer = Accelerometer(k_accelerometer) + accelerometer = Accelerometer(printer.get_reactor(), k_accelerometer) toolhead_info = toolhead.get_status(systime) old_accel = toolhead_info['max_accel'] @@ -45,9 +45,11 @@ def axes_map_calibration(gcmd, config, st_process: ShakeTuneProcess) -> None: # set the wanted acceleration values if 'minimum_cruise_ratio' in toolhead_info: - old_mcr = toolhead_info['minimum_cruise_ratio'] # minimum_cruise_ratio found: Klipper >= v0.12.0-239 - gcode.run_script_from_command(f'SET_VELOCITY_LIMIT ACCEL={accel} MINIMUM_CRUISE_RATIO=0 SQUARE_CORNER_VELOCITY=5.0') - else: # minimum_cruise_ratio not found: Klipper < v0.12.0-239 + old_mcr = toolhead_info['minimum_cruise_ratio'] # minimum_cruise_ratio found: Klipper >= v0.12.0-239 + gcode.run_script_from_command( + f'SET_VELOCITY_LIMIT ACCEL={accel} MINIMUM_CRUISE_RATIO=0 SQUARE_CORNER_VELOCITY=5.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={accel} SQUARE_CORNER_VELOCITY=5.0') @@ -93,11 +95,13 @@ def axes_map_calibration(gcmd, config, st_process: ShakeTuneProcess) -> None: input_shaper.enable_shaping() # 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_accel} MINIMUM_CRUISE_RATIO={old_mcr} SQUARE_CORNER_VELOCITY={old_sqv}') - else: # minimum_cruise_ratio not found: Klipper < v0.12.0-239 + 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_accel} MINIMUM_CRUISE_RATIO={old_mcr} SQUARE_CORNER_VELOCITY={old_sqv}' + ) + else: # minimum_cruise_ratio not found: Klipper < v0.12.0-239 gcode.run_script_from_command(f'SET_VELOCITY_LIMIT ACCEL={old_accel} SQUARE_CORNER_VELOCITY={old_sqv}') - + toolhead.wait_moves() # Run post-processing diff --git a/shaketune/commands/axes_shaper_calibration.py b/shaketune/commands/axes_shaper_calibration.py index 051f71b..8aab716 100644 --- a/shaketune/commands/axes_shaper_calibration.py +++ b/shaketune/commands/axes_shaper_calibration.py @@ -76,10 +76,10 @@ def axes_shaper_calibration(gcmd, config, st_process: ShakeTuneProcess) -> None: # set the needed acceleration values for the test toolhead_info = toolhead.get_status(systime) old_accel = toolhead_info['max_accel'] - if 'minimum_cruise_ratio' in toolhead_info: # minimum_cruise_ratio found: Klipper >= v0.12.0-239 + 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 + 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}') @@ -99,7 +99,7 @@ def axes_shaper_calibration(gcmd, config, st_process: ShakeTuneProcess) -> None: 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.lookup_object(accel_chip)) + accelerometer = Accelerometer(printer.get_reactor(), printer.lookup_object(accel_chip)) # Then do the actual measurements accelerometer.start_measurement() @@ -119,9 +119,9 @@ def axes_shaper_calibration(gcmd, config, st_process: ShakeTuneProcess) -> None: # Re-enable the input shaper if it was active if input_shaper is not None: input_shaper.enable_shaping() - + # Restore the previous acceleration values - if old_mcr is not None: # minimum_cruise_ratio found: Klipper >= v0.12.0-239 + 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_accel} MINIMUM_CRUISE_RATIO={old_mcr}') - else: # minimum_cruise_ratio not found: Klipper < v0.12.0-239 + else: # minimum_cruise_ratio not found: Klipper < v0.12.0-239 gcode.run_script_from_command(f'SET_VELOCITY_LIMIT ACCEL={old_accel}') diff --git a/shaketune/commands/compare_belts_responses.py b/shaketune/commands/compare_belts_responses.py index f5d578c..c114e99 100644 --- a/shaketune/commands/compare_belts_responses.py +++ b/shaketune/commands/compare_belts_responses.py @@ -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.lookup_object(accel_chip)) + accelerometer = Accelerometer(printer.get_reactor(), printer.lookup_object(accel_chip)) # Move to the starting point test_points = res_tester.test.get_start_test_points() @@ -88,11 +88,11 @@ def compare_belts_responses(gcmd, config, st_process: ShakeTuneProcess) -> None: # set the needed acceleration values for the test toolhead_info = toolhead.get_status(systime) - old_accel = toolhead_info['max_accel'] - if 'minimum_cruise_ratio' in toolhead_info: # minimum_cruise_ratio found: Klipper >= v0.12.0-239 + old_accel = toolhead_info['max_accel'] + 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 + 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}') @@ -116,9 +116,9 @@ def compare_belts_responses(gcmd, config, st_process: ShakeTuneProcess) -> None: input_shaper.enable_shaping() # Restore the previous acceleration values - if old_mcr is not None: # minimum_cruise_ratio found: Klipper >= v0.12.0-239 + 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_accel} MINIMUM_CRUISE_RATIO={old_mcr}') - else: # minimum_cruise_ratio not found: Klipper < v0.12.0-239 + else: # minimum_cruise_ratio not found: Klipper < v0.12.0-239 gcode.run_script_from_command(f'SET_VELOCITY_LIMIT ACCEL={old_accel}') # Run post-processing diff --git a/shaketune/commands/create_vibrations_profile.py b/shaketune/commands/create_vibrations_profile.py index 06bd5a7..84cd04f 100644 --- a/shaketune/commands/create_vibrations_profile.py +++ b/shaketune/commands/create_vibrations_profile.py @@ -62,10 +62,12 @@ def create_vibrations_profile(gcmd, config, st_process: ShakeTuneProcess) -> Non old_sqv = toolhead_info['square_corner_velocity'] # set the wanted acceleration values - 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={accel} MINIMUM_CRUISE_RATIO=0 SQUARE_CORNER_VELOCITY=5.0') - else: # minimum_cruise_ratio not found: Klipper < v0.12.0-239 + 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={accel} MINIMUM_CRUISE_RATIO=0 SQUARE_CORNER_VELOCITY=5.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={accel} SQUARE_CORNER_VELOCITY=5.0') @@ -95,7 +97,7 @@ def create_vibrations_profile(gcmd, config, st_process: ShakeTuneProcess) -> Non if k_accelerometer is None: raise gcmd.error(f'Accelerometer [{current_accel_chip}] not found!') ConsoleOutput.print(f'Accelerometer chip used for this angle: [{current_accel_chip}]') - accelerometer = Accelerometer(k_accelerometer) + accelerometer = Accelerometer(printer.get_reactor(), k_accelerometer) # Sweep the speed range to record the vibrations at different speeds for curr_speed_sample in range(nb_speed_samples): @@ -138,9 +140,11 @@ def create_vibrations_profile(gcmd, config, st_process: ShakeTuneProcess) -> Non accelerometer.wait_for_file_writes() # 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_accel} MINIMUM_CRUISE_RATIO={old_mcr} SQUARE_CORNER_VELOCITY={old_sqv}') - else: # minimum_cruise_ratio not found: Klipper < v0.12.0-239 + 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_accel} MINIMUM_CRUISE_RATIO={old_mcr} SQUARE_CORNER_VELOCITY={old_sqv}' + ) + else: # minimum_cruise_ratio not found: Klipper < v0.12.0-239 gcode.run_script_from_command(f'SET_VELOCITY_LIMIT ACCEL={old_accel} SQUARE_CORNER_VELOCITY={old_sqv}') toolhead.wait_moves() diff --git a/shaketune/commands/excitate_axis_at_freq.py b/shaketune/commands/excitate_axis_at_freq.py index c8aa1d6..6eae2d4 100644 --- a/shaketune/commands/excitate_axis_at_freq.py +++ b/shaketune/commands/excitate_axis_at_freq.py @@ -41,7 +41,7 @@ def excitate_axis_at_freq(gcmd, config, st_process: ShakeTuneProcess) -> None: k_accelerometer = printer.lookup_object(accel_chip, None) if k_accelerometer is None: raise gcmd.error(f'Accelerometer chip [{accel_chip}] was not found!') - accelerometer = Accelerometer(k_accelerometer) + accelerometer = Accelerometer(printer.get_reactor(), k_accelerometer) ConsoleOutput.print(f'Excitating {axis.upper()} axis at {freq}Hz for {duration} seconds')