@@ -52,7 +52,7 @@ gcode:
|
|||||||
ACCELEROMETER_MEASURE CHIP={accel_chip} NAME=axemap
|
ACCELEROMETER_MEASURE CHIP={accel_chip} NAME=axemap
|
||||||
|
|
||||||
RESPOND MSG="Analysis of the movements..."
|
RESPOND MSG="Analysis of the movements..."
|
||||||
RUN_SHELL_COMMAND CMD=shaketune PARAMS="AXESMAP {accel}"
|
RUN_SHELL_COMMAND CMD=shaketune PARAMS="--type axesmap --accel {accel} --chip_name {accel_chip}"
|
||||||
|
|
||||||
# Restore the previous acceleration values
|
# Restore the previous acceleration values
|
||||||
SET_VELOCITY_LIMIT ACCEL={old_accel} ACCEL_TO_DECEL={old_accel_to_decel} SQUARE_CORNER_VELOCITY={old_sqv}
|
SET_VELOCITY_LIMIT ACCEL={old_accel} ACCEL_TO_DECEL={old_accel_to_decel} SQUARE_CORNER_VELOCITY={old_sqv}
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ gcode:
|
|||||||
{% set max_freq = params.FREQ_END|default(133.3)|float %}
|
{% set max_freq = params.FREQ_END|default(133.3)|float %}
|
||||||
{% set hz_per_sec = params.HZ_PER_SEC|default(1)|float %}
|
{% set hz_per_sec = params.HZ_PER_SEC|default(1)|float %}
|
||||||
{% set axis = params.AXIS|default("all")|string|lower %}
|
{% set axis = params.AXIS|default("all")|string|lower %}
|
||||||
|
{% set keep_results = params.KEEP_N_RESULTS|default(3)|int %}
|
||||||
|
{% set keep_csv = params.KEEP_CSV|default(True) %}
|
||||||
|
|
||||||
{% set X, Y = False, False %}
|
{% set X, Y = False, False %}
|
||||||
|
|
||||||
@@ -29,7 +31,7 @@ gcode:
|
|||||||
|
|
||||||
RESPOND MSG="X axis frequency profile generation..."
|
RESPOND MSG="X axis frequency profile generation..."
|
||||||
RESPOND MSG="This may take some time (1-3min)"
|
RESPOND MSG="This may take some time (1-3min)"
|
||||||
RUN_SHELL_COMMAND CMD=shaketune PARAMS=SHAPER
|
RUN_SHELL_COMMAND CMD=shaketune PARAMS="--type shaper {% if keep_csv %}--keep_csv{% endif %}"
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if Y %}
|
{% if Y %}
|
||||||
@@ -38,5 +40,8 @@ gcode:
|
|||||||
|
|
||||||
RESPOND MSG="Y axis frequency profile generation..."
|
RESPOND MSG="Y axis frequency profile generation..."
|
||||||
RESPOND MSG="This may take some time (1-3min)"
|
RESPOND MSG="This may take some time (1-3min)"
|
||||||
RUN_SHELL_COMMAND CMD=shaketune PARAMS=SHAPER
|
RUN_SHELL_COMMAND CMD=shaketune PARAMS="--type shaper {% if keep_csv %}--keep_csv{% endif %}"
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
M400
|
||||||
|
RUN_SHELL_COMMAND CMD=shaketune PARAMS="--type clean --keep_results {keep_results}"
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ gcode:
|
|||||||
{% set min_freq = params.FREQ_START|default(5)|float %}
|
{% set min_freq = params.FREQ_START|default(5)|float %}
|
||||||
{% set max_freq = params.FREQ_END|default(133.33)|float %}
|
{% set max_freq = params.FREQ_END|default(133.33)|float %}
|
||||||
{% set hz_per_sec = params.HZ_PER_SEC|default(1)|float %}
|
{% set hz_per_sec = params.HZ_PER_SEC|default(1)|float %}
|
||||||
|
{% set keep_results = params.KEEP_N_RESULTS|default(3)|int %}
|
||||||
|
{% set keep_csv = params.KEEP_CSV|default(True) %}
|
||||||
|
|
||||||
TEST_RESONANCES AXIS=1,1 OUTPUT=raw_data NAME=b FREQ_START={min_freq} FREQ_END={max_freq} HZ_PER_SEC={hz_per_sec}
|
TEST_RESONANCES AXIS=1,1 OUTPUT=raw_data NAME=b FREQ_START={min_freq} FREQ_END={max_freq} HZ_PER_SEC={hz_per_sec}
|
||||||
M400
|
M400
|
||||||
@@ -18,4 +20,6 @@ gcode:
|
|||||||
|
|
||||||
RESPOND MSG="Belts comparative frequency profile generation..."
|
RESPOND MSG="Belts comparative frequency profile generation..."
|
||||||
RESPOND MSG="This may take some time (3-5min)"
|
RESPOND MSG="This may take some time (3-5min)"
|
||||||
RUN_SHELL_COMMAND CMD=shaketune PARAMS=BELTS
|
RUN_SHELL_COMMAND CMD=shaketune PARAMS="--type belts {% if keep_csv %}--keep_csv{% endif %}"
|
||||||
|
M400
|
||||||
|
RUN_SHELL_COMMAND CMD=shaketune PARAMS="--type clean --keep_results {keep_results}"
|
||||||
|
|||||||
@@ -16,6 +16,9 @@ gcode:
|
|||||||
{% set accel = params.ACCEL|default(3000)|int %} # accel value used to move on the pattern
|
{% set accel = params.ACCEL|default(3000)|int %} # accel value used to move on the pattern
|
||||||
{% set accel_chip = params.ACCEL_CHIP|default("adxl345") %} # ADXL chip name in the config
|
{% set accel_chip = params.ACCEL_CHIP|default("adxl345") %} # ADXL chip name in the config
|
||||||
|
|
||||||
|
{% set keep_results = params.KEEP_N_RESULTS|default(3)|int %}
|
||||||
|
{% set keep_csv = params.KEEP_CSV|default(True) %}
|
||||||
|
|
||||||
{% set mid_x = printer.toolhead.axis_maximum.x|float / 2 %}
|
{% set mid_x = printer.toolhead.axis_maximum.x|float / 2 %}
|
||||||
{% set mid_y = printer.toolhead.axis_maximum.y|float / 2 %}
|
{% set mid_y = printer.toolhead.axis_maximum.y|float / 2 %}
|
||||||
{% set nb_samples = ((max_speed - min_speed) / speed_increment + 1) | int %}
|
{% set nb_samples = ((max_speed - min_speed) / speed_increment + 1) | int %}
|
||||||
@@ -153,7 +156,9 @@ gcode:
|
|||||||
|
|
||||||
RESPOND MSG="Machine and motors vibration graph generation..."
|
RESPOND MSG="Machine and motors vibration graph generation..."
|
||||||
RESPOND MSG="This may take some time (3-5min)"
|
RESPOND MSG="This may take some time (3-5min)"
|
||||||
RUN_SHELL_COMMAND CMD=shaketune PARAMS="VIBRATIONS {direction} {accel}"
|
RUN_SHELL_COMMAND CMD=shaketune PARAMS="--type vibrations --axis_name {direction} --accel {accel} --chip_name {accel_chip} {% if keep_csv %}--keep_csv{% endif %}"
|
||||||
|
M400
|
||||||
|
RUN_SHELL_COMMAND CMD=shaketune PARAMS="--type clean --keep_results {keep_results}"
|
||||||
|
|
||||||
# Restore the previous acceleration values
|
# Restore the previous acceleration values
|
||||||
SET_VELOCITY_LIMIT ACCEL={old_accel} ACCEL_TO_DECEL={old_accel_to_decel} SQUARE_CORNER_VELOCITY={old_sqv}
|
SET_VELOCITY_LIMIT ACCEL={old_accel} ACCEL_TO_DECEL={old_accel_to_decel} SQUARE_CORNER_VELOCITY={old_sqv}
|
||||||
|
|||||||
@@ -5,14 +5,11 @@
|
|||||||
############################################
|
############################################
|
||||||
# Written by Frix_x#0161 #
|
# Written by Frix_x#0161 #
|
||||||
|
|
||||||
# Usage:
|
# This script is designed to be used with gcode_shell_commands directly from Klipper
|
||||||
# This script was designed to be used with gcode_shell_commands directly from Klipper
|
# Use the provided Shake&Tune macros instead!
|
||||||
# Parameters availables:
|
|
||||||
# BELTS - To generate belts diagrams after calling the Klipper TEST_RESONANCES AXIS=1,(-)1 OUTPUT=raw_data
|
|
||||||
# SHAPER - To generate input shaper diagrams after calling the Klipper TEST_RESONANCES AXIS=X/Y OUTPUT=raw_data
|
|
||||||
# VIBRATIONS - To generate vibration diagram after calling the custom (Frix_x#0161) VIBRATIONS_CALIBRATION macro
|
|
||||||
|
|
||||||
|
|
||||||
|
import optparse
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
import glob
|
import glob
|
||||||
@@ -24,7 +21,6 @@ from datetime import datetime
|
|||||||
#################################################################################################################
|
#################################################################################################################
|
||||||
RESULTS_FOLDER = os.path.expanduser('~/printer_data/config/K-ShakeTune_results')
|
RESULTS_FOLDER = os.path.expanduser('~/printer_data/config/K-ShakeTune_results')
|
||||||
KLIPPER_FOLDER = os.path.expanduser('~/klipper')
|
KLIPPER_FOLDER = os.path.expanduser('~/klipper')
|
||||||
STORE_RESULTS = 3
|
|
||||||
#################################################################################################################
|
#################################################################################################################
|
||||||
|
|
||||||
from graph_belts import belts_calibration
|
from graph_belts import belts_calibration
|
||||||
@@ -51,7 +47,7 @@ def is_file_open(filepath):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def create_belts_graph():
|
def create_belts_graph(keep_csv):
|
||||||
current_date = datetime.now().strftime('%Y%m%d_%H%M%S')
|
current_date = datetime.now().strftime('%Y%m%d_%H%M%S')
|
||||||
lognames = []
|
lognames = []
|
||||||
|
|
||||||
@@ -86,12 +82,18 @@ def create_belts_graph():
|
|||||||
# Generate the belts graph and its name
|
# Generate the belts graph and its name
|
||||||
fig = belts_calibration(lognames, KLIPPER_FOLDER)
|
fig = belts_calibration(lognames, KLIPPER_FOLDER)
|
||||||
png_filename = os.path.join(RESULTS_FOLDER, RESULTS_SUBFOLDERS[0], f'belts_{current_date}.png')
|
png_filename = os.path.join(RESULTS_FOLDER, RESULTS_SUBFOLDERS[0], f'belts_{current_date}.png')
|
||||||
|
fig.savefig(png_filename, dpi=150)
|
||||||
|
|
||||||
|
# Remove the CSV files if the user don't want to keep them
|
||||||
|
if not keep_csv:
|
||||||
|
for csv in lognames:
|
||||||
|
if os.path.exists(csv):
|
||||||
|
os.remove(csv)
|
||||||
|
|
||||||
fig.savefig(png_filename)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
def create_shaper_graph():
|
def create_shaper_graph(keep_csv):
|
||||||
current_date = datetime.now().strftime('%Y%m%d_%H%M%S')
|
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
|
# Get all the files and sort them based on last modified time to select the most recent one
|
||||||
@@ -120,16 +122,21 @@ def create_shaper_graph():
|
|||||||
# Generate the shaper graph and its name
|
# Generate the shaper graph and its name
|
||||||
fig = shaper_calibration([new_file], KLIPPER_FOLDER)
|
fig = shaper_calibration([new_file], KLIPPER_FOLDER)
|
||||||
png_filename = os.path.join(RESULTS_FOLDER, RESULTS_SUBFOLDERS[1], f'resonances_{current_date}_{axis}.png')
|
png_filename = os.path.join(RESULTS_FOLDER, RESULTS_SUBFOLDERS[1], f'resonances_{current_date}_{axis}.png')
|
||||||
|
fig.savefig(png_filename, dpi=150)
|
||||||
|
|
||||||
fig.savefig(png_filename)
|
# Remove the CSV file if the user don't want to keep it
|
||||||
return
|
if not keep_csv:
|
||||||
|
if os.path.exists(new_file):
|
||||||
|
os.remove(new_file)
|
||||||
|
|
||||||
|
return axis
|
||||||
|
|
||||||
|
|
||||||
def create_vibrations_graph(axis_name, accel):
|
def create_vibrations_graph(axis_name, accel, chip_name, keep_csv):
|
||||||
current_date = datetime.now().strftime('%Y%m%d_%H%M%S')
|
current_date = datetime.now().strftime('%Y%m%d_%H%M%S')
|
||||||
lognames = []
|
lognames = []
|
||||||
|
|
||||||
globbed_files = glob.glob('/tmp/adxl345-*.csv')
|
globbed_files = glob.glob(f'/tmp/{chip_name}-*.csv')
|
||||||
if not globbed_files:
|
if not globbed_files:
|
||||||
print("No CSV files found in the /tmp folder to create the vibration graphs!")
|
print("No CSV files found in the /tmp folder to create the vibration graphs!")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
@@ -143,7 +150,7 @@ def create_vibrations_graph(axis_name, accel):
|
|||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
|
|
||||||
# Cleanup of the filename and moving it in the result folder
|
# Cleanup of the filename and moving it in the result folder
|
||||||
cleanfilename = os.path.basename(filename).replace('adxl345', f'vibr_{current_date}')
|
cleanfilename = os.path.basename(filename).replace(chip_name, f'vibr_{current_date}')
|
||||||
new_file = os.path.join(RESULTS_FOLDER, RESULTS_SUBFOLDERS[2], cleanfilename)
|
new_file = os.path.join(RESULTS_FOLDER, RESULTS_SUBFOLDERS[2], cleanfilename)
|
||||||
shutil.move(filename, new_file)
|
shutil.move(filename, new_file)
|
||||||
|
|
||||||
@@ -157,23 +164,28 @@ def create_vibrations_graph(axis_name, accel):
|
|||||||
# Generate the vibration graph and its name
|
# Generate the vibration graph and its name
|
||||||
fig = vibrations_calibration(lognames, KLIPPER_FOLDER, axis_name, accel)
|
fig = vibrations_calibration(lognames, KLIPPER_FOLDER, axis_name, accel)
|
||||||
png_filename = os.path.join(RESULTS_FOLDER, RESULTS_SUBFOLDERS[2], f'vibrations_{current_date}_{axis_name}.png')
|
png_filename = os.path.join(RESULTS_FOLDER, RESULTS_SUBFOLDERS[2], f'vibrations_{current_date}_{axis_name}.png')
|
||||||
|
fig.savefig(png_filename, dpi=150)
|
||||||
|
|
||||||
# Archive all the csv files in a tarball and remove them to clean up the results folder
|
# Archive all the csv files in a tarball in case the user want to keep them
|
||||||
with tarfile.open(os.path.join(RESULTS_FOLDER, RESULTS_SUBFOLDERS[2], f'vibrations_{current_date}_{axis_name}.tar.gz'), 'w:gz') as tar:
|
if keep_csv:
|
||||||
for csv_file in glob.glob(os.path.join(RESULTS_FOLDER, RESULTS_SUBFOLDERS[2], f'vibr_{current_date}*.csv')):
|
with tarfile.open(os.path.join(RESULTS_FOLDER, RESULTS_SUBFOLDERS[2], f'vibrations_{current_date}_{axis_name}.tar.gz'), 'w:gz') as tar:
|
||||||
tar.add(csv_file, recursive=False)
|
for csv_file in lognames:
|
||||||
|
tar.add(csv_file, recursive=False)
|
||||||
|
|
||||||
|
# Remove the remaining CSV files not needed anymore (tarball is safe if it was created)
|
||||||
|
for csv_file in lognames:
|
||||||
|
if os.path.exists(csv_file):
|
||||||
os.remove(csv_file)
|
os.remove(csv_file)
|
||||||
|
|
||||||
fig.savefig(png_filename)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
def find_axesmap(accel):
|
def find_axesmap(accel, chip_name):
|
||||||
current_date = datetime.now().strftime('%Y%m%d_%H%M%S')
|
current_date = datetime.now().strftime('%Y%m%d_%H%M%S')
|
||||||
result_filename = os.path.join(RESULTS_FOLDER, f'axes_map_{current_date}.txt')
|
result_filename = os.path.join(RESULTS_FOLDER, f'axes_map_{current_date}.txt')
|
||||||
lognames = []
|
lognames = []
|
||||||
|
|
||||||
globbed_files = glob.glob('/tmp/adxl345-*.csv')
|
globbed_files = glob.glob(f'/tmp/{chip_name}-*.csv')
|
||||||
if not globbed_files:
|
if not globbed_files:
|
||||||
print("No CSV files found in the /tmp folder to analyze and find the axes_map!")
|
print("No CSV files found in the /tmp folder to analyze and find the axes_map!")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
@@ -201,10 +213,10 @@ def get_old_files(folder, extension, limit):
|
|||||||
files.sort(key=lambda x: os.path.getmtime(x), reverse=True)
|
files.sort(key=lambda x: os.path.getmtime(x), reverse=True)
|
||||||
return files[limit:]
|
return files[limit:]
|
||||||
|
|
||||||
def clean_files():
|
def clean_files(keep_results):
|
||||||
# Define limits based on STORE_RESULTS
|
# Define limits based on STORE_RESULTS
|
||||||
keep1 = STORE_RESULTS + 1
|
keep1 = keep_results + 1
|
||||||
keep2 = 2 * STORE_RESULTS + 1
|
keep2 = 2 * keep_results + 1
|
||||||
|
|
||||||
# Find old files in each directory
|
# Find old files in each directory
|
||||||
old_belts_files = get_old_files(os.path.join(RESULTS_FOLDER, RESULTS_SUBFOLDERS[0]), '.png', keep1)
|
old_belts_files = get_old_files(os.path.join(RESULTS_FOLDER, RESULTS_SUBFOLDERS[0]), '.png', keep1)
|
||||||
@@ -236,31 +248,51 @@ def clean_files():
|
|||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
# Check if results folders are there or create them
|
# Parse command-line arguments
|
||||||
|
usage = "%prog [options] <logs>"
|
||||||
|
opts = optparse.OptionParser(usage)
|
||||||
|
opts.add_option("-t", "--type", type="string", dest="type",
|
||||||
|
default=None, help="type of output graph to produce")
|
||||||
|
opts.add_option("--accel", type="int", default=None, dest="accel_used",
|
||||||
|
help="acceleration used during the vibration macro or axesmap macro")
|
||||||
|
opts.add_option("--axis_name", type="string", default=None, dest="axis_name",
|
||||||
|
help="axis tested during the vibration macro")
|
||||||
|
opts.add_option("--chip_name", type="string", default="adxl345", dest="chip_name",
|
||||||
|
help="accelerometer chip name in klipper used during the vibration macro or the axesmap macro")
|
||||||
|
opts.add_option("-n", "--keep_results", type="int", default=3, dest="keep_results",
|
||||||
|
help="number of results to keep in the result folder after each run of the script")
|
||||||
|
opts.add_option("-c", "--keep_csv", action="store_true", default=False, dest="keep_csv",
|
||||||
|
help="weither or not to keep the CSV files alongside the PNG graphs image results")
|
||||||
|
options, args = opts.parse_args()
|
||||||
|
|
||||||
|
if options.type is None:
|
||||||
|
opts.error("You must specify the type of output graph you want to produce (option -t)")
|
||||||
|
elif options.type.lower() is None or options.type.lower() not in ['belts', 'shaper', 'vibrations', 'axesmap', 'clean']:
|
||||||
|
opts.error("Type of output graph need to be in the list of 'belts', 'shaper', 'vibrations', 'axesmap' or 'clean'")
|
||||||
|
else:
|
||||||
|
graph_mode = options.type
|
||||||
|
|
||||||
|
# Check if results folders are there or create them before doing anything else
|
||||||
for result_subfolder in RESULTS_SUBFOLDERS:
|
for result_subfolder in RESULTS_SUBFOLDERS:
|
||||||
folder = os.path.join(RESULTS_FOLDER, result_subfolder)
|
folder = os.path.join(RESULTS_FOLDER, result_subfolder)
|
||||||
if not os.path.exists(folder):
|
if not os.path.exists(folder):
|
||||||
os.makedirs(folder)
|
os.makedirs(folder)
|
||||||
|
|
||||||
if len(sys.argv) < 2:
|
if graph_mode.lower() == 'belts':
|
||||||
print("Usage: is_workflow.py [BELTS|SHAPER|VIBRATIONS|AXESMAP]")
|
create_belts_graph(keep_csv=options.keep_csv)
|
||||||
sys.exit(1)
|
print(f"Belt graph created. You will find the results in {RESULTS_FOLDER}/{RESULTS_SUBFOLDERS[0]}")
|
||||||
|
elif graph_mode.lower() == 'shaper':
|
||||||
if sys.argv[1].lower() == 'belts':
|
axis = create_shaper_graph(keep_csv=options.keep_csv)
|
||||||
create_belts_graph()
|
print(f"{axis} input shaper graph created. You will find the results in {RESULTS_FOLDER}/{RESULTS_SUBFOLDERS[1]}")
|
||||||
elif sys.argv[1].lower() == 'shaper':
|
elif graph_mode.lower() == 'vibrations':
|
||||||
create_shaper_graph()
|
create_vibrations_graph(axis_name=options.axis_name, accel=options.accel_used, chip_name=options.chip_name, keep_csv=options.keep_csv)
|
||||||
elif sys.argv[1].lower() == 'vibrations':
|
print(f"{options.axis_name} vibration graph created. You will find the results in {RESULTS_FOLDER}/{RESULTS_SUBFOLDERS[2]}")
|
||||||
create_vibrations_graph(axis_name=sys.argv[2], accel=sys.argv[3])
|
elif graph_mode.lower() == 'axesmap':
|
||||||
elif sys.argv[1].lower() == 'axesmap':
|
print(f"WARNING: AXES_MAP_CALIBRATION is currently very experimental and may produce incorrect results... Please validate the output!")
|
||||||
find_axesmap(accel=sys.argv[2])
|
find_axesmap(accel=options.accel_used, chip_name=options.chip_name)
|
||||||
else:
|
elif graph_mode.lower() == 'clean':
|
||||||
print("Usage: is_workflow.py [BELTS|SHAPER|VIBRATIONS|AXESMAP]")
|
print(f"Cleaning output folder to keep only the last {options.keep_results} results...")
|
||||||
sys.exit(1)
|
clean_files(keep_results=options.keep_results)
|
||||||
|
|
||||||
|
|
||||||
clean_files()
|
|
||||||
print(f"Graphs created. You will find the results in {RESULTS_FOLDER}")
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|||||||
13
README.md
13
README.md
@@ -21,19 +21,15 @@ Check out the **[detailed documentation of the Shake&Tune module here](./docs/RE
|
|||||||
|
|
||||||
Follow these steps to install the Shake&Tune module in your printer:
|
Follow these steps to install the Shake&Tune module in your printer:
|
||||||
1. Be sure to have a working accelerometer on your machine. You can follow the official [Measuring Resonances Klipper documentation](https://www.klipper3d.org/Measuring_Resonances.html) to configure one. Validate with an `ACCELEROMETER_QUERY` command that everything works correctly.
|
1. Be sure to have a working accelerometer on your machine. You can follow the official [Measuring Resonances Klipper documentation](https://www.klipper3d.org/Measuring_Resonances.html) to configure one. Validate with an `ACCELEROMETER_QUERY` command that everything works correctly.
|
||||||
1. Install the system libraries that are needed to run the custom Python scripts:
|
1. Install the Shake&Tune package by running over SSH on your printer:
|
||||||
```bash
|
|
||||||
sudo apt update && sudo apt install python3-venv libopenblas-dev libatlas-base-dev -y
|
|
||||||
```
|
|
||||||
1. Then, you can install the Shake&Tune package by running over SSH on your printer:
|
|
||||||
```bash
|
```bash
|
||||||
wget -O - https://raw.githubusercontent.com/Frix-x/klippain-shaketune/main/install.sh | bash
|
wget -O - https://raw.githubusercontent.com/Frix-x/klippain-shaketune/main/install.sh | bash
|
||||||
```
|
```
|
||||||
1. Finally, append the following to your `printer.cfg` file and restart Klipper (if prefered, you can include only the needed macros: using `*.cfg` is a convenient way to include them all at once):
|
1. Then, append the following to your `printer.cfg` file and restart Klipper (if prefered, you can include only the needed macros: using `*.cfg` is a convenient way to include them all at once):
|
||||||
```
|
```
|
||||||
[include K-ShakeTune/*.cfg]
|
[include K-ShakeTune/*.cfg]
|
||||||
```
|
```
|
||||||
1. Optionally, if you want to get automatic updates, add the following to your `moonraker.cfg` file:
|
1. Finally, if you want to get automatic updates, add the following to your `moonraker.cfg` file:
|
||||||
```
|
```
|
||||||
[update_manager Klippain-ShakeTune]
|
[update_manager Klippain-ShakeTune]
|
||||||
type: git_repo
|
type: git_repo
|
||||||
@@ -45,9 +41,6 @@ Follow these steps to install the Shake&Tune module in your printer:
|
|||||||
install_script: install.sh
|
install_script: install.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
> **Note**:
|
|
||||||
>
|
|
||||||
> If already using my old IS workflow scripts, please remove everything before installing this new module. This include the macros, the Python scripts, the `plot_graph.sh` and the `[gcode_shell_command plot_graph]` section that are not needed anymore.
|
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ Then, call the `AXES_SHAPER_CALIBRATION` macro and look for the graphs in the re
|
|||||||
|FREQ_END|133|Maximum excitation frequency|
|
|FREQ_END|133|Maximum excitation frequency|
|
||||||
|HZ_PER_SEC|1|Number of Hz per seconds for the test|
|
|HZ_PER_SEC|1|Number of Hz per seconds for the test|
|
||||||
|AXIS|"all"|Axis you want to test in the list of "all", "X" or "Y"|
|
|AXIS|"all"|Axis you want to test in the list of "all", "X" or "Y"|
|
||||||
|
|KEEP_N_RESULTS|3|Total number of results to keep in the result folder after running the test. The older results are automatically cleaned up|
|
||||||
|
|KEEP_CSV|True|Weither or not to keep the CSV data file alonside the PNG graphs|
|
||||||
|
|
||||||
|
|
||||||
## Graphs description
|
## Graphs description
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ Then, call the `BELTS_SHAPER_CALIBRATION` macro and look for the graphs in the r
|
|||||||
|FREQ_START|5|Starting excitation frequency|
|
|FREQ_START|5|Starting excitation frequency|
|
||||||
|FREQ_END|133|Maximum excitation frequency|
|
|FREQ_END|133|Maximum excitation frequency|
|
||||||
|HZ_PER_SEC|1|Number of Hz per seconds for the test|
|
|HZ_PER_SEC|1|Number of Hz per seconds for the test|
|
||||||
|
|KEEP_N_RESULTS|3|Total number of results to keep in the result folder after running the test. The older results are automatically cleaned up|
|
||||||
|
|KEEP_CSV|True|Weither or not to keep the CSV data files alonside the PNG graphs|
|
||||||
|
|
||||||
|
|
||||||
## Graphs description
|
## Graphs description
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ Call the `VIBRATIONS_CALIBRATION` macro with the direction and speed range you w
|
|||||||
|SPEED_INCREMENT|2|speed increments of the toolhead in mm/s between every movements|
|
|SPEED_INCREMENT|2|speed increments of the toolhead in mm/s between every movements|
|
||||||
|TRAVEL_SPEED|200|speed in mm/s used for all the travels moves|
|
|TRAVEL_SPEED|200|speed in mm/s used for all the travels moves|
|
||||||
|ACCEL_CHIP|"adxl345"|accelerometer chip name in the config|
|
|ACCEL_CHIP|"adxl345"|accelerometer chip name in the config|
|
||||||
|
|KEEP_N_RESULTS|3|Total number of results to keep in the result folder after running the test. The older results are automatically cleaned up|
|
||||||
|
|KEEP_CSV|True|Weither or not to keep the CSV data files alonside the PNG graphs (archived in a tarball)|
|
||||||
|
|
||||||
|
|
||||||
## Graphs description
|
## Graphs description
|
||||||
|
|||||||
26
install.sh
26
install.sh
@@ -27,6 +27,32 @@ function preflight_checks {
|
|||||||
echo "[ERROR] Klipper service not found, please install Klipper first!"
|
echo "[ERROR] Klipper service not found, please install Klipper first!"
|
||||||
exit -1
|
exit -1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
install_package_requirements
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to check if a package is installed
|
||||||
|
function is_package_installed {
|
||||||
|
dpkg -s "$1" &> /dev/null
|
||||||
|
return $?
|
||||||
|
}
|
||||||
|
|
||||||
|
function install_package_requirements {
|
||||||
|
packages=("python3-venv" "libopenblas-dev" "libatlas-base-dev")
|
||||||
|
packages_to_install=""
|
||||||
|
|
||||||
|
for package in "${packages[@]}"; do
|
||||||
|
if is_package_installed "$package"; then
|
||||||
|
echo "$package is already installed"
|
||||||
|
else
|
||||||
|
packages_to_install="$packages_to_install $package"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ -n "$packages_to_install" ]; then
|
||||||
|
echo "Installing missing packages: $packages_to_install"
|
||||||
|
sudo apt update && sudo apt install -y $packages_to_install
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function check_download {
|
function check_download {
|
||||||
|
|||||||
Reference in New Issue
Block a user