14 Commits

Author SHA1 Message Date
af9fee36ed Update README.md
Some checks failed
Smoke Tests / Klippy Tests (DangerKlippers/danger-klipper) (push) Has been cancelled
Smoke Tests / Klippy Tests (klipper3d/klipper) (push) Has been cancelled
Smoke Tests / lint (push) Has been cancelled
2024-08-01 16:52:24 +03:00
6b2cedfa28 Обновить README.md
Some checks are pending
Smoke Tests / Klippy Tests (DangerKlippers/danger-klipper) (push) Waiting to run
Smoke Tests / Klippy Tests (klipper3d/klipper) (push) Waiting to run
Smoke Tests / lint (push) Waiting to run
2024-08-01 01:04:04 +03:00
04ff95921e Обновить install.sh
Some checks are pending
Smoke Tests / Klippy Tests (DangerKlippers/danger-klipper) (push) Waiting to run
Smoke Tests / Klippy Tests (klipper3d/klipper) (push) Waiting to run
Smoke Tests / lint (push) Waiting to run
2024-08-01 00:58:47 +03:00
871dd72a88 Обновить moonraker.conf
Some checks are pending
Smoke Tests / Klippy Tests (DangerKlippers/danger-klipper) (push) Waiting to run
Smoke Tests / Klippy Tests (klipper3d/klipper) (push) Waiting to run
Smoke Tests / lint (push) Waiting to run
2024-08-01 00:34:32 +03:00
Félix Boisselier
66f5e32e4c typo in doc 2024-07-01 12:42:59 +02:00
Félix Boisselier
c12653e1f7 Merge pull request #138 from Frix-x/develop
v4.1.0
2024-06-30 22:41:30 +02:00
Félix Boisselier
8cf81bcb44 better sync of the peaks pair for close frequencies 2024-06-30 22:41:06 +02:00
Félix Boisselier
92a651b6a6 switched to pearson coefficient for belts similarity 2024-06-30 22:27:46 +02:00
Félix Boisselier
6712506862 fixed potential out of bounds error in belt graphs 2024-06-30 20:30:05 +02:00
Félix Boisselier
6e49c2c607 inverted belts colors to revert the behavior as pre-v4 2024-06-30 11:14:14 +02:00
Félix Boisselier
4a99e95882 Merge pull request #136 from Frix-x/develop
v4.0.2
2024-06-27 22:33:20 +02:00
Félix Boisselier
f5a74c29e1 fixed pyproject.toml project name 2024-06-27 22:25:04 +02:00
Aaron Haun
f87713eacd feat: automated testing GitHub action (#134) 2024-06-27 18:35:07 +02:00
Félix Boisselier
f045b8a49e fixed a mistake about some code that shouldn't be here... 2024-06-27 18:31:41 +02:00
11 changed files with 165 additions and 69 deletions

69
.github/workflows/test.yml vendored Normal file
View File

@@ -0,0 +1,69 @@
name: Smoke Tests
on:
workflow_dispatch:
push:
jobs:
klippy_testing:
name: Klippy Tests
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
klipper_repo:
- klipper3d/klipper
- DangerKlippers/danger-klipper
steps:
- name: Checkout shaketune
uses: actions/checkout@v4
with:
path: shaketune
- name: Checkout Klipper
uses: actions/checkout@v4
with:
path: klipper
repository: ${{ matrix.klipper_repo }}
ref: master
- name: Install build dependencies
run: |
sudo apt-get update
sudo apt-get install -y build-essential
- name: Build klipper dict
run: |
pushd klipper
cp ../shaketune/ci/smoke-test/klipper-smoketest.kconfig .config
make olddefconfig
make out/compile_time_request.o
popd
- name: Setup klippy env
run: |
python3 -m venv --prompt klippy klippy-env
./klippy-env/bin/python -m pip install -r klipper/scripts/klippy-requirements.txt
./klippy-env/bin/python -m pip install -r shaketune/requirements.txt
- name: Install shaketune
run: |
ln -s $PWD/shaketune/shaketune $PWD/klipper/klippy/extras/shaketune
- name: Klipper import test
run: |
./klippy-env/bin/python klipper/klippy/klippy.py --import-test
- name: Klipper integrated test
run: |
pushd klipper
mkdir ../dicts
cp ../klipper/out/klipper.dict ../dicts/linux_basic.dict
../klippy-env/bin/python scripts/test_klippy.py -d ../dicts ../shaketune/ci/smoke-test/klippy-tests/simple.test
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
cache: 'pip'
- name: install ruff
run: |
pip install ruff
- name: run ruff tests
run: |
ruff check

View File

@@ -13,7 +13,7 @@ Follow these steps to install Shake&Tune on your printer:
1. Be sure to have a working accelerometer on your machine and a `[resonance_tester]` section defined. You can follow the official [Measuring Resonances Klipper documentation](https://www.klipper3d.org/Measuring_Resonances.html) to configure it. 1. Be sure to have a working accelerometer on your machine and a `[resonance_tester]` section defined. You can follow the official [Measuring Resonances Klipper documentation](https://www.klipper3d.org/Measuring_Resonances.html) to configure it.
1. Install Shake&Tune by running over SSH on your printer: 1. Install Shake&Tune 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://cloud.reijii.org/gitea/reijii/klippain-shaketune-telegramm/raw/branch/main/install.sh | bash
``` ```
1. Then, append the following to your `printer.cfg` file and restart Klipper: 1. Then, append the following to your `printer.cfg` file and restart Klipper:
``` ```

View File

@@ -0,0 +1,34 @@
CONFIG_LOW_LEVEL_OPTIONS=y
# CONFIG_MACH_AVR is not set
# CONFIG_MACH_ATSAM is not set
# CONFIG_MACH_ATSAMD is not set
# CONFIG_MACH_LPC176X is not set
# CONFIG_MACH_STM32 is not set
# CONFIG_MACH_HC32F460 is not set
# CONFIG_MACH_RP2040 is not set
# CONFIG_MACH_PRU is not set
# CONFIG_MACH_AR100 is not set
CONFIG_MACH_LINUX=y
# CONFIG_MACH_SIMU is not set
CONFIG_BOARD_DIRECTORY="linux"
CONFIG_CLOCK_FREQ=50000000
CONFIG_LINUX_SELECT=y
CONFIG_USB_VENDOR_ID=0x1d50
CONFIG_USB_DEVICE_ID=0x614e
CONFIG_USB_SERIAL_NUMBER="12345"
CONFIG_WANT_GPIO_BITBANGING=y
CONFIG_WANT_DISPLAYS=y
CONFIG_WANT_SENSORS=y
CONFIG_WANT_LIS2DW=y
CONFIG_WANT_LDC1612=y
CONFIG_WANT_SOFTWARE_I2C=y
CONFIG_WANT_SOFTWARE_SPI=y
CONFIG_NEED_SENSOR_BULK=y
CONFIG_CANBUS_FREQUENCY=1000000
CONFIG_INITIAL_PINS=""
CONFIG_HAVE_GPIO=y
CONFIG_HAVE_GPIO_ADC=y
CONFIG_HAVE_GPIO_SPI=y
CONFIG_HAVE_GPIO_I2C=y
CONFIG_HAVE_GPIO_HARD_PWM=y
CONFIG_INLINE_STEPPER_HACK=y

View File

@@ -0,0 +1,9 @@
[mcu]
serial: /tmp/klipper_host_mcu
[printer]
kinematics: none
max_velocity: 300
max_accel: 300
[shaketune]

View File

@@ -0,0 +1,4 @@
DICTIONARY linux_basic.dict
CONFIG simple.cfg
G4 P1000

View File

@@ -39,9 +39,9 @@ Aside from the actual belt tension, the resonant frequency/amplitude of the curv
The Cross-Belts plot is an innovative cool way to compare the frequency profiles of the belts at every frequency point. In this plot, each point marks the amplitude response of each belt at different frequencies, connected point by point to trace the frequency spectrum. Ideally, these points should align on the diagonal center line, indicating that both belts have matching energy response values at each frequency. The Cross-Belts plot is an innovative cool way to compare the frequency profiles of the belts at every frequency point. In this plot, each point marks the amplitude response of each belt at different frequencies, connected point by point to trace the frequency spectrum. Ideally, these points should align on the diagonal center line, indicating that both belts have matching energy response values at each frequency.
The good zone, wider at the bottom (low-amplitude regions where the deviation doesn't matter much) and narrower at the top right (high-energy region where the main peaks lie), represents acceptable deviations. So **you want all points to be close to the ideal center line and as many as possible within the green zone**, as this means that the bands are well tuned and behave similarly. The good zone, wider at the bottom (low-amplitude regions where the deviation doesn't matter much) and narrower at the top right (high-energy region where the main peaks lie), represents acceptable deviations. So **you want all points to be close to the ideal center line and as many as possible within the green zone**, as this means that the belts are well tuned and behave similarly.
Paired peaks of exactly the same frequency will be on the same point (labeled α1/α2, β1/β2, ...) and the distance from the center line will show the difference in energy. For paired peaks that also have a frequency delta between them, they are displayed as two points (labeled α1 and α2, ...) and the additional distance between them along the plotted line represents their frequency delta. Paired peaks at the same frequency will be on the same point (labeled α1/α2, β1/β2, ...) and the distance from the center line will show the difference in energy. For paired peaks that also have a frequency delta between them, they are displayed as two points (labeled α1 and α2, ...) and the additional distance between them along the plotted line represents their frequency delta.
### Estimated similarity and mechanical issues indicator ### Estimated similarity and mechanical issues indicator

View File

@@ -64,7 +64,7 @@ function check_download {
if [ ! -d "${K_SHAKETUNE_PATH}" ]; then if [ ! -d "${K_SHAKETUNE_PATH}" ]; then
echo "[DOWNLOAD] Downloading Klippain Shake&Tune module repository..." echo "[DOWNLOAD] Downloading Klippain Shake&Tune module repository..."
if git -C $shaketunedirname clone https://github.com/Frix-x/klippain-shaketune.git $shaketunebasename; then if git -C $shaketunedirname clone https://cloud.reijii.org/gitea/reijii/klippain-shaketune-telegramm.git $shaketunebasename; then
chmod +x ${K_SHAKETUNE_PATH}/install.sh chmod +x ${K_SHAKETUNE_PATH}/install.sh
printf "[DOWNLOAD] Download complete!\n\n" printf "[DOWNLOAD] Download complete!\n\n"
else else

View File

@@ -1,8 +1,7 @@
## Klippain Shake&Tune automatic update management ## Klippain Shake&Tune automatic update management
[update_manager Klippain-ShakeTune] [update_manager Klippain-ShakeTune]
type: git_repo type: git_repo
origin: https://github.com/Frix-x/klippain-shaketune.git origin: https://cloud.reijii.org/gitea/reijii/klippain-shaketune-telegramm.git
path: ~/klippain_shaketune path: ~/klippain_shaketune
virtualenv: ~/klippy-env virtualenv: ~/klippy-env
requirements: requirements.txt requirements: requirements.txt

View File

@@ -1,5 +1,5 @@
[project] [project]
name = "Shake&Tune" name = "shake_n_tune"
description = "Klipper streamlined input shaper workflow and calibration tools" description = "Klipper streamlined input shaper workflow and calibration tools"
readme = "README.md" readme = "README.md"
requires-python = ">= 3.9" requires-python = ">= 3.9"

View File

@@ -19,6 +19,7 @@ import matplotlib.font_manager
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
import matplotlib.ticker import matplotlib.ticker
import numpy as np import numpy as np
from scipy.stats import pearsonr
matplotlib.use('Agg') matplotlib.use('Agg')
@@ -210,8 +211,8 @@ def plot_compare_frequency(
ax: plt.Axes, signal1: SignalData, signal2: SignalData, signal1_belt: str, signal2_belt: str, max_freq: float ax: plt.Axes, signal1: SignalData, signal2: SignalData, signal1_belt: str, signal2_belt: str, max_freq: float
) -> None: ) -> None:
# Plot the two belts PSD signals # Plot the two belts PSD signals
ax.plot(signal1.freqs, signal1.psd, label='Belt ' + signal1_belt, color=KLIPPAIN_COLORS['purple']) ax.plot(signal1.freqs, signal1.psd, label='Belt ' + signal1_belt, color=KLIPPAIN_COLORS['orange'])
ax.plot(signal2.freqs, signal2.psd, label='Belt ' + signal2_belt, color=KLIPPAIN_COLORS['orange']) ax.plot(signal2.freqs, signal2.psd, label='Belt ' + signal2_belt, color=KLIPPAIN_COLORS['purple'])
psd_highest_max = max(signal1.psd.max(), signal2.psd.max()) psd_highest_max = max(signal1.psd.max(), signal2.psd.max())
@@ -343,14 +344,12 @@ def plot_versus_belts(
common_freqs: np.ndarray, common_freqs: np.ndarray,
signal1: SignalData, signal1: SignalData,
signal2: SignalData, signal2: SignalData,
interp_psd1: np.ndarray,
interp_psd2: np.ndarray,
signal1_belt: str, signal1_belt: str,
signal2_belt: str, signal2_belt: str,
) -> None: ) -> None:
ax.set_title('Cross-belts comparison plot', fontsize=14, color=KLIPPAIN_COLORS['dark_orange'], weight='bold') ax.set_title('Cross-belts comparison plot', fontsize=14, color=KLIPPAIN_COLORS['dark_orange'], weight='bold')
max_psd = max(np.max(interp_psd1), np.max(interp_psd2)) max_psd = max(np.max(signal1.psd), np.max(signal2.psd))
ideal_line = np.linspace(0, max_psd * 1.1, 500) ideal_line = np.linspace(0, max_psd * 1.1, 500)
green_boundary = ideal_line + (0.35 * max_psd * np.exp(-ideal_line / (0.6 * max_psd))) green_boundary = ideal_line + (0.35 * max_psd * np.exp(-ideal_line / (0.6 * max_psd)))
ax.fill_betweenx(ideal_line, ideal_line, green_boundary, color='green', alpha=0.15) ax.fill_betweenx(ideal_line, ideal_line, green_boundary, color='green', alpha=0.15)
@@ -364,8 +363,8 @@ def plot_versus_belts(
linewidth=2, linewidth=2,
) )
ax.plot(interp_psd1, interp_psd2, color='dimgrey', marker='o', markersize=1.5) ax.plot(signal1.psd, signal2.psd, color='dimgrey', marker='o', markersize=1.5)
ax.fill_betweenx(interp_psd2, interp_psd1, color=KLIPPAIN_COLORS['red_pink'], alpha=0.1) ax.fill_betweenx(signal2.psd, signal1.psd, color=KLIPPAIN_COLORS['red_pink'], alpha=0.1)
paired_peak_count = 0 paired_peak_count = 0
unpaired_peak_count = 0 unpaired_peak_count = 0
@@ -374,31 +373,27 @@ def plot_versus_belts(
label = ALPHABET[paired_peak_count] label = ALPHABET[paired_peak_count]
freq1 = signal1.freqs[peak1[0]] freq1 = signal1.freqs[peak1[0]]
freq2 = signal2.freqs[peak2[0]] freq2 = signal2.freqs[peak2[0]]
nearest_idx1 = np.argmin(np.abs(common_freqs - freq1))
nearest_idx2 = np.argmin(np.abs(common_freqs - freq2))
if nearest_idx1 == nearest_idx2: if abs(freq1 - freq2) < 1:
psd1_peak_value = interp_psd1[nearest_idx1] ax.plot(signal1.psd[peak1[0]], signal2.psd[peak2[0]], marker='o', color='black', markersize=7)
psd2_peak_value = interp_psd2[nearest_idx1]
ax.plot(psd1_peak_value, psd2_peak_value, marker='o', color='black', markersize=7)
ax.annotate( ax.annotate(
f'{label}1/{label}2', f'{label}1/{label}2',
(psd1_peak_value, psd2_peak_value), (signal1.psd[peak1[0]], signal2.psd[peak2[0]]),
textcoords='offset points', textcoords='offset points',
xytext=(-7, 7), xytext=(-7, 7),
fontsize=13, fontsize=13,
color='black', color='black',
) )
else: else:
psd1_peak_value = interp_psd1[nearest_idx1] ax.plot(
psd1_on_peak = interp_psd1[nearest_idx2] signal1.psd[peak2[0]], signal2.psd[peak2[0]], marker='o', color=KLIPPAIN_COLORS['orange'], markersize=7
psd2_peak_value = interp_psd2[nearest_idx2] )
psd2_on_peak = interp_psd2[nearest_idx1] ax.plot(
ax.plot(psd1_on_peak, psd2_peak_value, marker='o', color=KLIPPAIN_COLORS['orange'], markersize=7) signal1.psd[peak1[0]], signal2.psd[peak1[0]], marker='o', color=KLIPPAIN_COLORS['purple'], markersize=7
ax.plot(psd1_peak_value, psd2_on_peak, marker='o', color=KLIPPAIN_COLORS['purple'], markersize=7) )
ax.annotate( ax.annotate(
f'{label}1', f'{label}1',
(psd1_peak_value, psd2_on_peak), (signal1.psd[peak1[0]], signal2.psd[peak1[0]]),
textcoords='offset points', textcoords='offset points',
xytext=(0, 7), xytext=(0, 7),
fontsize=13, fontsize=13,
@@ -406,7 +401,7 @@ def plot_versus_belts(
) )
ax.annotate( ax.annotate(
f'{label}2', f'{label}2',
(psd1_on_peak, psd2_peak_value), (signal1.psd[peak2[0]], signal2.psd[peak2[0]]),
textcoords='offset points', textcoords='offset points',
xytext=(0, 7), xytext=(0, 7),
fontsize=13, fontsize=13,
@@ -415,16 +410,12 @@ def plot_versus_belts(
paired_peak_count += 1 paired_peak_count += 1
for _, peak_index in enumerate(signal1.unpaired_peaks): for _, peak_index in enumerate(signal1.unpaired_peaks):
freq1 = signal1.freqs[peak_index] ax.plot(
freq2 = signal2.freqs[peak_index] signal1.psd[peak_index], signal2.psd[peak_index], marker='o', color=KLIPPAIN_COLORS['purple'], markersize=7
nearest_idx1 = np.argmin(np.abs(common_freqs - freq1)) )
nearest_idx2 = np.argmin(np.abs(common_freqs - freq2))
psd1_peak_value = interp_psd1[nearest_idx1]
psd2_peak_value = interp_psd2[nearest_idx1]
ax.plot(psd1_peak_value, psd2_peak_value, marker='o', color=KLIPPAIN_COLORS['purple'], markersize=7)
ax.annotate( ax.annotate(
str(unpaired_peak_count + 1), str(unpaired_peak_count + 1),
(psd1_peak_value, psd2_peak_value), (signal1.psd[peak_index], signal2.psd[peak_index]),
textcoords='offset points', textcoords='offset points',
fontsize=13, fontsize=13,
weight='bold', weight='bold',
@@ -434,16 +425,12 @@ def plot_versus_belts(
unpaired_peak_count += 1 unpaired_peak_count += 1
for _, peak_index in enumerate(signal2.unpaired_peaks): for _, peak_index in enumerate(signal2.unpaired_peaks):
freq1 = signal1.freqs[peak_index] ax.plot(
freq2 = signal2.freqs[peak_index] signal1.psd[peak_index], signal2.psd[peak_index], marker='o', color=KLIPPAIN_COLORS['orange'], markersize=7
nearest_idx1 = np.argmin(np.abs(common_freqs - freq1)) )
nearest_idx2 = np.argmin(np.abs(common_freqs - freq2))
psd1_peak_value = interp_psd1[nearest_idx1]
psd2_peak_value = interp_psd2[nearest_idx1]
ax.plot(psd1_peak_value, psd2_peak_value, marker='o', color=KLIPPAIN_COLORS['orange'], markersize=7)
ax.annotate( ax.annotate(
str(unpaired_peak_count + 1), str(unpaired_peak_count + 1),
(psd1_peak_value, psd2_peak_value), (signal1.psd[peak_index], signal2.psd[peak_index]),
textcoords='offset points', textcoords='offset points',
fontsize=13, fontsize=13,
weight='bold', weight='bold',
@@ -476,16 +463,21 @@ def plot_versus_belts(
# Original Klipper function to get the PSD data of a raw accelerometer signal # Original Klipper function to get the PSD data of a raw accelerometer signal
def compute_signal_data(data: np.ndarray, max_freq: float) -> SignalData: def compute_signal_data(data: np.ndarray, common_freqs: np.ndarray, max_freq: float) -> SignalData:
helper = shaper_calibrate.ShaperCalibrate(printer=None) helper = shaper_calibrate.ShaperCalibrate(printer=None)
calibration_data = helper.process_accelerometer_data(data) calibration_data = helper.process_accelerometer_data(data)
freqs = calibration_data.freq_bins[calibration_data.freq_bins <= max_freq] freqs = calibration_data.freq_bins[calibration_data.freq_bins <= max_freq]
psd = calibration_data.get_psd('all')[calibration_data.freq_bins <= max_freq] psd = calibration_data.get_psd('all')[calibration_data.freq_bins <= max_freq]
_, peaks, _ = detect_peaks(psd, freqs, PEAKS_DETECTION_THRESHOLD * psd.max()) # Re-interpolate the PSD signal to a common frequency range to be able to plot them one against the other
interp_psd = np.interp(common_freqs, freqs, psd)
return SignalData(freqs=freqs, psd=psd, peaks=peaks) _, peaks, _ = detect_peaks(
interp_psd, common_freqs, PEAKS_DETECTION_THRESHOLD * interp_psd.max(), window_size=20, vicinity=15
)
return SignalData(freqs=common_freqs, psd=interp_psd, peaks=peaks)
###################################################################### ######################################################################
@@ -517,8 +509,9 @@ def belts_calibration(
signal2_belt += belt_info.get(signal2_belt, '') signal2_belt += belt_info.get(signal2_belt, '')
# Compute calibration data for the two datasets with automatic peaks detection # Compute calibration data for the two datasets with automatic peaks detection
signal1 = compute_signal_data(datas[0], max_freq) common_freqs = np.linspace(0, max_freq, 500)
signal2 = compute_signal_data(datas[1], max_freq) signal1 = compute_signal_data(datas[0], common_freqs, max_freq)
signal2 = compute_signal_data(datas[1], common_freqs, max_freq)
del datas del datas
# Pair the peaks across the two datasets # Pair the peaks across the two datasets
@@ -526,18 +519,13 @@ def belts_calibration(
signal1 = signal1._replace(paired_peaks=pairing_result.paired_peaks, unpaired_peaks=pairing_result.unpaired_peaks1) signal1 = signal1._replace(paired_peaks=pairing_result.paired_peaks, unpaired_peaks=pairing_result.unpaired_peaks1)
signal2 = signal2._replace(paired_peaks=pairing_result.paired_peaks, unpaired_peaks=pairing_result.unpaired_peaks2) signal2 = signal2._replace(paired_peaks=pairing_result.paired_peaks, unpaired_peaks=pairing_result.unpaired_peaks2)
# Re-interpolate the PSD signals to a common frequency range to be able to plot them one against the other point by point # R² proved to be pretty instable to compute the similarity between the two belts
common_freqs = np.linspace(0, max_freq, 500) # So now, we use the Pearson correlation coefficient to compute the similarity
interp_psd1 = np.interp(common_freqs, signal1.freqs, signal1.psd) correlation, _ = pearsonr(signal1.psd, signal2.psd)
interp_psd2 = np.interp(common_freqs, signal2.freqs, signal2.psd) similarity_factor = correlation * 100
similarity_factor = np.clip(similarity_factor, 0, 100)
# Calculating R^2 to y=x line to compute the similarity between the two belts
ss_res = np.sum((interp_psd2 - interp_psd1) ** 2)
ss_tot = np.sum((interp_psd2 - np.mean(interp_psd2)) ** 2)
similarity_factor = (1 - (ss_res / ss_tot)) * 100
ConsoleOutput.print(f'Belts estimated similarity: {similarity_factor:.1f}%') ConsoleOutput.print(f'Belts estimated similarity: {similarity_factor:.1f}%')
# mhi = compute_mhi(similarity_factor, num_peaks, num_unpaired_peaks)
mhi = compute_mhi(similarity_factor, signal1, signal2) mhi = compute_mhi(similarity_factor, signal1, signal2)
ConsoleOutput.print(f'[experimental] Mechanical health: {mhi}') ConsoleOutput.print(f'[experimental] Mechanical health: {mhi}')
@@ -582,11 +570,11 @@ def belts_calibration(
# Add the accel_per_hz value to the title # Add the accel_per_hz value to the title
title_line5 = f'| Accel per Hz used: {accel_per_hz} mm/s²/Hz' title_line5 = f'| Accel per Hz used: {accel_per_hz} mm/s²/Hz'
fig.text(0.55, 0.915, title_line5, ha='left', va='top', fontsize=14, color=KLIPPAIN_COLORS['dark_purple']) fig.text(0.551, 0.915, title_line5, ha='left', va='top', fontsize=10, color=KLIPPAIN_COLORS['dark_purple'])
# Plot the graphs # Plot the graphs
plot_compare_frequency(ax1, signal1, signal2, signal1_belt, signal2_belt, max_freq) plot_compare_frequency(ax1, signal1, signal2, signal1_belt, signal2_belt, max_freq)
plot_versus_belts(ax3, common_freqs, signal1, signal2, interp_psd1, interp_psd2, signal1_belt, signal2_belt) plot_versus_belts(ax3, common_freqs, signal1, signal2, signal1_belt, signal2_belt)
# Adding a small Klippain logo to the top left corner of the figure # Adding a small Klippain logo to the top left corner of the figure
ax_logo = fig.add_axes([0.001, 0.894, 0.105, 0.105], anchor='NW') ax_logo = fig.add_axes([0.001, 0.894, 0.105, 0.105], anchor='NW')

View File

@@ -34,13 +34,6 @@ IN_DANGER = False
class ShakeTune: class ShakeTune:
def __init__(self, config) -> None: def __init__(self, config) -> None:
try:
from extras.danger_options import get_danger_options
IN_DANGER = True # check if Shake&Tune is running in DangerKlipper
except ImportError:
continue
self._pconfig = config self._pconfig = config
self._printer = config.get_printer() self._printer = config.get_printer()
gcode = self._printer.lookup_object('gcode') gcode = self._printer.lookup_object('gcode')