From 8721488d8c783f817f23c08ef26c43c731a79663 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Boisselier?= Date: Fri, 1 Dec 2023 00:08:32 +0100 Subject: [PATCH] added axes_map computation --- K-ShakeTune/K-SnT_axes_map.cfg | 60 +++++++++ K-ShakeTune/K-SnT_axis.cfg | 13 +- K-ShakeTune/K-SnT_belts.cfg | 7 +- K-ShakeTune/K-SnT_vibrations.cfg | 19 +-- K-ShakeTune/scripts/analyze_axesmap.py | 171 ++++++++++++++++++++++++ K-ShakeTune/scripts/graph_vibrations.py | 4 +- K-ShakeTune/scripts/is_workflow.py | 60 +++++++-- K-ShakeTune/shaketune_cmd.cfg | 2 + docs/README.md | 5 +- docs/macros/axis_tuning.md | 1 - docs/macros/belts_tuning.md | 1 - docs/macros/vibrations_tuning.md | 1 - requirements.txt | 1 + 13 files changed, 298 insertions(+), 47 deletions(-) create mode 100644 K-ShakeTune/K-SnT_axes_map.cfg create mode 100755 K-ShakeTune/scripts/analyze_axesmap.py diff --git a/K-ShakeTune/K-SnT_axes_map.cfg b/K-ShakeTune/K-SnT_axes_map.cfg new file mode 100644 index 0000000..81bcfeb --- /dev/null +++ b/K-ShakeTune/K-SnT_axes_map.cfg @@ -0,0 +1,60 @@ +############################################################ +###### AXE_MAP DETECTION AND ACCELEROMETER VALIDATION ###### +############################################################ +# Written by Frix_x#0161 # + +[gcode_macro AXES_MAP_CALIBRATION] +gcode: + {% set z_height = params.Z_HEIGHT|default(20)|int %} # z height to put the toolhead before starting the movements + {% set speed = params.SPEED|default(80)|float * 60 %} # feedrate for the movements + {% set accel = params.ACCEL|default(1500)|int %} # accel value used to move on the pattern + {% set feedrate_travel = params.TRAVEL_SPEED|default(120)|int * 60 %} # travel feedrate between moves + {% set accel_chip = params.ACCEL_CHIP|default("adxl345") %} # ADXL chip name in the config + + {% set mid_x = printer.toolhead.axis_maximum.x|float / 2 %} + {% set mid_y = printer.toolhead.axis_maximum.y|float / 2 %} + + {% set accel = [accel, printer.configfile.settings.printer.max_accel]|min %} + {% set old_accel = printer.toolhead.max_accel %} + {% set old_accel_to_decel = printer.toolhead.max_accel_to_decel %} + {% set old_sqv = printer.toolhead.square_corner_velocity %} + + + {% if not 'xyz' in printer.toolhead.homed_axes %} + { action_raise_error("Must Home printer first!") } + {% endif %} + + {action_respond_info("")} + {action_respond_info("Starting accelerometer axe_map calibration")} + {action_respond_info("This operation can not be interrupted by normal means. Hit the \"emergency stop\" button to stop it if needed")} + {action_respond_info("")} + + SAVE_GCODE_STATE NAME=STATE_AXESMAP_CALIBRATION + + G90 + + # Set the wanted acceleration values (not too high to avoid oscillation, not too low to be able to reach constant speed on each segments) + SET_VELOCITY_LIMIT ACCEL={accel} ACCEL_TO_DECEL={accel} SQUARE_CORNER_VELOCITY={[(accel / 1000), 5.0]|max} + + # Going to the start position + G1 Z{z_height} F{feedrate_travel / 8} + G1 X{mid_x - 15} Y{mid_y - 15} F{feedrate_travel} + G4 P500 + + ACCELEROMETER_MEASURE CHIP={accel_chip} + G4 P1000 # This first waiting time is to record the background accelerometer noise before moving + G1 X{mid_x + 15} F{speed} + G4 P1000 + G1 Y{mid_y + 15} F{speed} + G4 P1000 + G1 Z{z_height + 15} F{speed} + G4 P1000 + ACCELEROMETER_MEASURE CHIP={accel_chip} NAME=axemap + + RESPOND MSG="Analysis of the movements..." + RUN_SHELL_COMMAND CMD=shaketune PARAMS="AXESMAP {accel}" + + # Restore the previous acceleration values + SET_VELOCITY_LIMIT ACCEL={old_accel} ACCEL_TO_DECEL={old_accel_to_decel} SQUARE_CORNER_VELOCITY={old_sqv} + + RESTORE_GCODE_STATE NAME=STATE_AXESMAP_CALIBRATION diff --git a/K-ShakeTune/K-SnT_axis.cfg b/K-ShakeTune/K-SnT_axis.cfg index 69da343..5fbb589 100644 --- a/K-ShakeTune/K-SnT_axis.cfg +++ b/K-ShakeTune/K-SnT_axis.cfg @@ -6,7 +6,6 @@ [gcode_macro AXES_SHAPER_CALIBRATION] description: Perform standard axis input shaper tests on one or both XY axes to select the best input shaper filter gcode: - {% set verbose = params.VERBOSE|default(true) %} {% set min_freq = params.FREQ_START|default(5)|float %} {% set max_freq = params.FREQ_END|default(133.3)|float %} {% set hz_per_sec = params.HZ_PER_SEC|default(1)|float %} @@ -28,10 +27,8 @@ gcode: TEST_RESONANCES AXIS=X OUTPUT=raw_data NAME=x FREQ_START={min_freq} FREQ_END={max_freq} HZ_PER_SEC={hz_per_sec} M400 - {% if verbose %} - RESPOND MSG="X axis frequency profile generation..." - RESPOND MSG="This may take some time (1-3min)" - {% endif %} + RESPOND MSG="X axis frequency profile generation..." + RESPOND MSG="This may take some time (1-3min)" RUN_SHELL_COMMAND CMD=shaketune PARAMS=SHAPER {% endif %} @@ -39,9 +36,7 @@ gcode: TEST_RESONANCES AXIS=Y OUTPUT=raw_data NAME=y FREQ_START={min_freq} FREQ_END={max_freq} HZ_PER_SEC={hz_per_sec} M400 - {% if verbose %} - RESPOND MSG="Y axis frequency profile generation..." - RESPOND MSG="This may take some time (1-3min)" - {% endif %} + RESPOND MSG="Y axis frequency profile generation..." + RESPOND MSG="This may take some time (1-3min)" RUN_SHELL_COMMAND CMD=shaketune PARAMS=SHAPER {% endif %} diff --git a/K-ShakeTune/K-SnT_belts.cfg b/K-ShakeTune/K-SnT_belts.cfg index 4ee8e88..059efea 100644 --- a/K-ShakeTune/K-SnT_belts.cfg +++ b/K-ShakeTune/K-SnT_belts.cfg @@ -6,7 +6,6 @@ [gcode_macro BELTS_SHAPER_CALIBRATION] description: Perform a custom half-axis test to analyze and compare the frequency profiles of individual belts on CoreXY printers gcode: - {% set verbose = params.VERBOSE|default(true) %} {% set min_freq = params.FREQ_START|default(5)|float %} {% set max_freq = params.FREQ_END|default(133.33)|float %} {% set hz_per_sec = params.HZ_PER_SEC|default(1)|float %} @@ -17,8 +16,6 @@ gcode: TEST_RESONANCES AXIS=1,-1 OUTPUT=raw_data NAME=a FREQ_START={min_freq} FREQ_END={max_freq} HZ_PER_SEC={hz_per_sec} M400 - {% if verbose %} - RESPOND MSG="Belts comparative frequency profile generation..." - RESPOND MSG="This may take some time (3-5min)" - {% endif %} + RESPOND MSG="Belts comparative frequency profile generation..." + RESPOND MSG="This may take some time (3-5min)" RUN_SHELL_COMMAND CMD=shaketune PARAMS=BELTS diff --git a/K-ShakeTune/K-SnT_vibrations.cfg b/K-ShakeTune/K-SnT_vibrations.cfg index 76e3452..1598a2b 100644 --- a/K-ShakeTune/K-SnT_vibrations.cfg +++ b/K-ShakeTune/K-SnT_vibrations.cfg @@ -8,7 +8,6 @@ gcode: {% set size = params.SIZE|default(60)|int %} # size of the area where the movements are done {% set direction = params.DIRECTION|default('XY') %} # can be set to either XY, AB, ABXY, A, B, X, Y, Z {% set z_height = params.Z_HEIGHT|default(20)|int %} # z height to put the toolhead before starting the movements - {% set verbose = params.VERBOSE|default(true) %} # Wether to log the current speed in the console {% set min_speed = params.MIN_SPEED|default(20)|float * 60 %} # minimum feedrate for the movements {% set max_speed = params.MAX_SPEED|default(200)|float * 60 %} # maximum feedrate for the movements @@ -100,9 +99,7 @@ gcode: } %} - # - # STARTING... - # + {% if not 'xyz' in printer.toolhead.homed_axes %} { action_raise_error("Must Home printer first!") } {% endif %} @@ -126,22 +123,19 @@ gcode: SAVE_GCODE_STATE NAME=STATE_VIBRATIONS_CALIBRATION - M83 G90 # Set the wanted acceleration values (not too high to avoid oscillation, not too low to be able to reach constant speed on each segments) SET_VELOCITY_LIMIT ACCEL={accel} ACCEL_TO_DECEL={accel} SQUARE_CORNER_VELOCITY={[(accel / 1000), 5.0]|max} # Going to the start position - G1 Z{z_height} + G1 Z{z_height} F{feedrate_travel / 10} G1 X{mid_x + (size * direction_factor[direction].start.x) } Y{mid_y + (size * direction_factor[direction].start.y)} F{feedrate_travel} # vibration pattern for each frequency {% for curr_sample in range(0, nb_samples) %} {% set curr_speed = min_speed + curr_sample * speed_increment %} - {% if verbose %} - RESPOND MSG="{"Current speed: %.2f mm/s" % (curr_speed / 60)|float}" - {% endif %} + RESPOND MSG="{"Current speed: %.2f mm/s" % (curr_speed / 60)|float}" ACCELEROMETER_MEASURE CHIP={accel_chip} {% if direction == 'E' %} @@ -152,14 +146,13 @@ gcode: {% endfor %} {% endif %} ACCELEROMETER_MEASURE CHIP={accel_chip} NAME=sp{("%.2f" % (curr_speed / 60)|float)|replace('.','_')}n1 - G4 P300 + M400 {% endfor %} - {% if verbose %} - RESPOND MSG="Graphs generation... Please wait a minute or two and look in the configured folder." - {% endif %} + RESPOND MSG="Machine and motors vibration graph generation..." + RESPOND MSG="This may take some time (3-5min)" RUN_SHELL_COMMAND CMD=shaketune PARAMS="VIBRATIONS {direction}" # Restore the previous acceleration values diff --git a/K-ShakeTune/scripts/analyze_axesmap.py b/K-ShakeTune/scripts/analyze_axesmap.py new file mode 100755 index 0000000..370225d --- /dev/null +++ b/K-ShakeTune/scripts/analyze_axesmap.py @@ -0,0 +1,171 @@ +#!/usr/bin/env python3 + +###################################### +###### AXE_MAP DETECTION SCRIPT ###### +###################################### +# Written by Frix_x#0161 # + +# Be sure to make this script executable using SSH: type 'chmod +x ./analyze_axesmap.py' when in the folder ! + +##################################################################### +################ !!! DO NOT EDIT BELOW THIS LINE !!! ################ +##################################################################### + +import optparse +import numpy as np +import locale +from scipy.signal import butter, filtfilt + + +NUM_POINTS = 500 + + +# Set the best locale for time and date formating (generation of the titles) +try: + locale.setlocale(locale.LC_TIME, locale.getdefaultlocale()) +except locale.Error: + locale.setlocale(locale.LC_TIME, 'C') + +# Override the built-in print function to avoid problem in Klipper due to locale settings +original_print = print +def print_with_c_locale(*args, **kwargs): + original_locale = locale.setlocale(locale.LC_ALL, None) + locale.setlocale(locale.LC_ALL, 'C') + original_print(*args, **kwargs) + locale.setlocale(locale.LC_ALL, original_locale) +print = print_with_c_locale + + +###################################################################### +# Computation +###################################################################### + +def accel_signal_filter(data, cutoff=2, fs=100, order=5): + nyq = 0.5 * fs + normal_cutoff = cutoff / nyq + b, a = butter(order, normal_cutoff, btype='low', analog=False) + filtered_data = filtfilt(b, a, data) + filtered_data -= np.mean(filtered_data) + return filtered_data + +def find_first_spike(data): + min_index, max_index = np.argmin(data), np.argmax(data) + return ('-', min_index) if min_index < max_index else ('', max_index) + +def get_movement_vector(data, start_idx, end_idx): + if start_idx < end_idx: + vector = [] + for i in range(3): + vector.append(np.mean(data[i][start_idx:end_idx], axis=0)) + return vector + else: + return np.zeros(3) + +def angle_between(v1, v2): + v1_u = v1 / np.linalg.norm(v1) + v2_u = v2 / np.linalg.norm(v2) + return np.arccos(np.clip(np.dot(v1_u, v2_u), -1.0, 1.0)) + +def compute_errors(filtered_data, spikes_sorted, accel_value, num_points): + # Get the movement start points in the correct order from the sorted bag of spikes + movement_starts = [spike[0][1] for spike in spikes_sorted] + + # Theoretical unit vectors for X, Y, Z printer axes + printer_axes = { + 'x': np.array([1, 0, 0]), + 'y': np.array([0, 1, 0]), + 'z': np.array([0, 0, 1]) + } + + alignment_errors = {} + sensitivity_errors = {} + for i, axis in enumerate(['x', 'y', 'z']): + movement_start = movement_starts[i] + movement_end = movement_start + num_points + movement_vector = get_movement_vector(filtered_data, movement_start, movement_end) + alignment_errors[axis] = angle_between(movement_vector, printer_axes[axis]) + + measured_accel_magnitude = np.linalg.norm(movement_vector) + if accel_value != 0: + sensitivity_errors[axis] = abs(measured_accel_magnitude - accel_value) / accel_value * 100 + else: + sensitivity_errors[axis] = None + + return alignment_errors, sensitivity_errors + + +###################################################################### +# Startup and main routines +###################################################################### + +def parse_log(logname): + with open(logname) as f: + for header in f: + if not header.startswith('#'): + break + if not header.startswith('freq,psd_x,psd_y,psd_z,psd_xyz'): + # Raw accelerometer data + return np.loadtxt(logname, comments='#', delimiter=',') + # Power spectral density data or shaper calibration data + raise ValueError("File %s does not contain raw accelerometer data and therefore " + "is not supported by this script. Please use the official Klipper " + "calibrate_shaper.py script to process it instead." % (logname,)) + + +def axesmap_calibration(lognames, accel=None): + # Parse the raw data and get them ready for analysis + raw_datas = [parse_log(filename) for filename in lognames] + if len(raw_datas) > 1: + raise ValueError("Analysis of multiple CSV files at once is not possible with this script") + + filtered_data = [accel_signal_filter(raw_datas[0][:, i+1]) for i in range(3)] + spikes = [find_first_spike(filtered_data[i]) for i in range(3)] + spikes_sorted = sorted([(spikes[0], 'x'), (spikes[1], 'y'), (spikes[2], 'z')], key=lambda x: x[0][1]) + + # Using the previous variables to get the axes_map and errors + axes_map = ','.join([f"{spike[0][0]}{spike[1]}" for spike in spikes_sorted]) + # alignment_error, sensitivity_error = compute_errors(filtered_data, spikes_sorted, accel, NUM_POINTS) + + results = f"Detected axes_map:\n {axes_map}\n" + + # TODO: work on this function that is currently not giving good results... + # results += "Accelerometer angle deviation:\n" + # for axis, angle in alignment_error.items(): + # angle_degrees = np.degrees(angle) # Convert radians to degrees + # results += f" {axis.upper()} axis: {angle_degrees:.2f} degrees\n" + + # results += "Accelerometer sensitivity error:\n" + # for axis, error in sensitivity_error.items(): + # results += f" {axis.upper()} axis: {error:.2f}%\n" + + return results + + +def main(): + # Parse command-line arguments + usage = "%prog [options] " + opts = optparse.OptionParser(usage) + opts.add_option("-o", "--output", type="string", dest="output", + default=None, help="filename of output graph") + opts.add_option("-a", "--accel", type="string", dest="accel", + default=None, help="acceleration value used to do the movements") + options, args = opts.parse_args() + if len(args) < 1: + opts.error("No CSV file(s) to analyse") + if options.accel is None: + opts.error("You must specify the acceleration value used when generating the CSV file (option -a)") + try: + accel_value = float(options.accel) + except ValueError: + opts.error("Invalid acceleration value. It should be a numeric value.") + + results = axesmap_calibration(args, accel_value) + print(results) + + if options.output is not None: + with open(options.output, 'w') as f: + f.write(results) + + +if __name__ == '__main__': + main() diff --git a/K-ShakeTune/scripts/graph_vibrations.py b/K-ShakeTune/scripts/graph_vibrations.py index 450a4cc..4ca466d 100755 --- a/K-ShakeTune/scripts/graph_vibrations.py +++ b/K-ShakeTune/scripts/graph_vibrations.py @@ -317,7 +317,7 @@ def parse_log(logname): return np.loadtxt(logname, comments='#', delimiter=',') # Power spectral density data or shaper calibration data raise ValueError("File %s does not contain raw accelerometer data and therefore " - "is not supported by graph_vibrations.py script. Please use " + "is not supported by this script. Please use the official Klipper" "calibrate_shaper.py script to process it instead." % (logname,)) @@ -326,7 +326,7 @@ def extract_speed(logname): speed = re.search('sp(.+?)n', os.path.basename(logname)).group(1).replace('_','.') except AttributeError: raise ValueError("File %s does not contain speed in its name and therefore " - "is not supported by graph_vibrations.py script." % (logname,)) + "is not supported by this script." % (logname,)) return float(speed) diff --git a/K-ShakeTune/scripts/is_workflow.py b/K-ShakeTune/scripts/is_workflow.py index 762cf42..998b7d6 100755 --- a/K-ShakeTune/scripts/is_workflow.py +++ b/K-ShakeTune/scripts/is_workflow.py @@ -30,6 +30,7 @@ from graph_belts import belts_calibration from graph_shaper import shaper_calibration from graph_vibrations import vibrations_calibration +from analyze_axesmap import axesmap_calibration RESULTS_SUBFOLDERS = ['belts', 'inputshaper', 'vibrations'] @@ -50,7 +51,7 @@ def is_file_open(filepath): return False -def get_belts_graph(): +def create_belts_graph(): current_date = datetime.now().strftime('%Y%m%d_%H%M%S') lognames = [] @@ -61,6 +62,7 @@ def get_belts_graph(): if len(globbed_files) < 2: print("Not enough CSV files found in the /tmp folder. Two files are required for the belt graphs!") sys.exit(1) + sorted_files = sorted(globbed_files, key=os.path.getmtime, reverse=True) for filename in sorted_files[:2]: @@ -84,11 +86,12 @@ def get_belts_graph(): # Generate the belts graph and its name fig = belts_calibration(lognames, KLIPPER_FOLDER) png_filename = os.path.join(RESULTS_FOLDER, RESULTS_SUBFOLDERS[0], f'belts_{current_date}.png') - - return fig, png_filename + + fig.savefig(png_filename) + return -def get_shaper_graph(): +def create_shaper_graph(): current_date = datetime.now().strftime('%Y%m%d_%H%M%S') # Get all the files and sort them based on last modified time to select the most recent one @@ -96,6 +99,7 @@ def get_shaper_graph(): if not globbed_files: print("No CSV files found in the /tmp folder to create the input shaper graphs!") sys.exit(1) + sorted_files = sorted(globbed_files, key=os.path.getmtime, reverse=True) filename = sorted_files[0] @@ -117,10 +121,11 @@ def get_shaper_graph(): fig = shaper_calibration([new_file], KLIPPER_FOLDER) png_filename = os.path.join(RESULTS_FOLDER, RESULTS_SUBFOLDERS[1], f'resonances_{current_date}_{axis}.png') - return fig, png_filename + fig.savefig(png_filename) + return -def get_vibrations_graph(axis_name): +def create_vibrations_graph(axis_name): current_date = datetime.now().strftime('%Y%m%d_%H%M%S') lognames = [] @@ -159,7 +164,35 @@ def get_vibrations_graph(axis_name): tar.add(csv_file, recursive=False) os.remove(csv_file) - return fig, png_filename + fig.savefig(png_filename) + return + + +def find_axesmap(accel): + current_date = datetime.now().strftime('%Y%m%d_%H%M%S') + result_filename = os.path.join(RESULTS_FOLDER, f'axes_map_{current_date}.txt') + lognames = [] + + globbed_files = glob.glob('/tmp/adxl345-*.csv') + if not globbed_files: + print("No CSV files found in the /tmp folder to analyze and find the axes_map!") + sys.exit(1) + + sorted_files = sorted(globbed_files, key=os.path.getmtime, reverse=True) + filename = sorted_files[0] + + # Wait for the file handler to be released by Klipper + while is_file_open(filename): + time.sleep(2) + + # Analyze the CSV to find the axes_map parameter + lognames.append(filename) + results = axesmap_calibration(lognames, accel) + + with open(result_filename, 'w') as f: + f.write(results) + + return # Utility function to get old files based on their modification time @@ -210,20 +243,21 @@ def main(): os.makedirs(folder) if len(sys.argv) < 2: - print("Usage: is_workflow.py [SHAPER|BELTS|VIBRATIONS]") + print("Usage: is_workflow.py [BELTS|SHAPER|VIBRATIONS|AXESMAP]") sys.exit(1) if sys.argv[1].lower() == 'belts': - fig, png_filename = get_belts_graph() + create_belts_graph() elif sys.argv[1].lower() == 'shaper': - fig, png_filename = get_shaper_graph() + create_shaper_graph() elif sys.argv[1].lower() == 'vibrations': - fig, png_filename = get_vibrations_graph(axis_name=sys.argv[2]) + create_vibrations_graph(axis_name=sys.argv[2]) + elif sys.argv[1].lower() == 'axesmap': + find_axesmap(accel=sys.argv[2]) else: - print("Usage: is_workflow.py [SHAPER|BELTS|VIBRATIONS]") + print("Usage: is_workflow.py [BELTS|SHAPER|VIBRATIONS|AXESMAP]") sys.exit(1) - fig.savefig(png_filename) clean_files() print(f"Graphs created. You will find the results in {RESULTS_FOLDER}") diff --git a/K-ShakeTune/shaketune_cmd.cfg b/K-ShakeTune/shaketune_cmd.cfg index bb48844..e4d667c 100644 --- a/K-ShakeTune/shaketune_cmd.cfg +++ b/K-ShakeTune/shaketune_cmd.cfg @@ -2,3 +2,5 @@ command: ~/printer_data/config/K-ShakeTune/scripts/shaketune.sh timeout: 600.0 verbose: True + +[respond] diff --git a/docs/README.md b/docs/README.md index 28e66dc..c3488c7 100644 --- a/docs/README.md +++ b/docs/README.md @@ -4,8 +4,9 @@ ### Detailed documentation -First, check out **[input shaping and tuning generalities](./is_tuning_generalities.md)** to understand how it all works and what to look for when taking these measurements. -Then look at the documentation for each type of graph by clicking on them below to better understand your results and tune your machine! +Before running any tests, you should first run the `AXES_MAP_CALIBRATION` macro to detect the and set Klipper's accelerometer axes_map parameter and validate that your accelerometer is working correctly and properly mounted. Then, check out **[input shaping and tuning generalities](./is_tuning_generalities.md)** to understand how it all works and what to look for when taking these measurements. + +Finally look at the documentation for each type of graph by clicking on them below tu run the tests and better understand your results to tune your machine! | [Belts graph](./macros/belts_tuning.md) | [Axis input shaper graphs](./macros/axis_tuning.md) | [Vibrations graph](./macros/vibrations_tuning.md) | |:----------------:|:------------:|:---------------------:| diff --git a/docs/macros/axis_tuning.md b/docs/macros/axis_tuning.md index 842cd68..b09a14c 100644 --- a/docs/macros/axis_tuning.md +++ b/docs/macros/axis_tuning.md @@ -11,7 +11,6 @@ Then, call the `AXES_SHAPER_CALIBRATION` macro and look for the graphs in the re | parameters | default value | description | |-----------:|---------------|-------------| -|VERBOSE|1|Wether to log things in the console| |FREQ_START|5|Starting excitation frequency| |FREQ_END|133|Maximum excitation frequency| |HZ_PER_SEC|1|Number of Hz per seconds for the test| diff --git a/docs/macros/belts_tuning.md b/docs/macros/belts_tuning.md index 2e60cc2..fc6551a 100644 --- a/docs/macros/belts_tuning.md +++ b/docs/macros/belts_tuning.md @@ -11,7 +11,6 @@ Then, call the `BELTS_SHAPER_CALIBRATION` macro and look for the graphs in the r | parameters | default value | description | |-----------:|---------------|-------------| -|VERBOSE|1|Wether to log things in the console| |FREQ_START|5|Starting excitation frequency| |FREQ_END|133|Maximum excitation frequency| |HZ_PER_SEC|1|Number of Hz per seconds for the test| diff --git a/docs/macros/vibrations_tuning.md b/docs/macros/vibrations_tuning.md index 309ad27..84d1f10 100644 --- a/docs/macros/vibrations_tuning.md +++ b/docs/macros/vibrations_tuning.md @@ -16,7 +16,6 @@ Call the `VIBRATIONS_CALIBRATION` macro with the direction and speed range you w |SIZE|60|size in mm of the area where the movements are done| |DIRECTION|"XY"|direction vector where you want to do the measurements. Can be set to either "XY", "AB", "ABXY", "A", "B", "X", "Y", "Z", "E"| |Z_HEIGHT|20|z height to put the toolhead before starting the movements. Be careful, if your ADXL is under the nozzle, increase it to avoid a crash of the ADXL on the bed of the machine| -|VERBOSE|1|Wether to log the current speed in the console| |ACCEL|3000 (or max printer accel)|accel in mm/s^2 used for all the moves. Try to keep it relatively low to avoid bad oscillations that affect the measurements, but but high enough to reach constant speed for >~70% of the segments| |MIN_SPEED|20|minimum speed of the toolhead in mm/s for the movements| |MAX_SPEED|200|maximum speed of the toolhead in mm/s for the movements| diff --git a/requirements.txt b/requirements.txt index be8c8d0..ce083b9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,4 +8,5 @@ packaging==23.2 Pillow==10.1.0 pyparsing==3.1.1 python-dateutil==2.8.2 +scipy==1.11.4 six==1.16.0