-
-
Save kmobs/3a09cc28ec79e62f28d8db2179be7909 to your computer and use it in GitHub Desktop.
## Prerequisite | |
I recommend running Dmitry’s latest resonance testing branch and using the pulses method outlined below: | |
https://github.com/Klipper3d/klipper/issues/4560 | |
https://github.com/dmbutyugin/klipper/tree/resonance-test-methods | |
Once you have your graph generated, you can pull the raw CSV values into your favorite graphing software. We will use the half power method to calculate the damping ratio. | |
Find your highest resonant frequency and divide the amplitude at this point 1.41 (or the square root of 2). Note the frequency of the intersects at this amplitude. | |
The two formulas that we will use are Q=f0/(f2-f1) where f0 is your highest resonant frequency, f2 is your higher frequency at the half power intersect, and f1 is the lower. | |
The second formula is Q=1/(2*damping ratio) | |
From this you can solve for your damping ratio. | |
Damping ratio = (f2-f1)/(2f0) | |
You can then test your value. To do this, you need to make a small (hacky) change to input_shaper.py if you want to iterate them both at the same time. In input_shaper.py in the extras folder of your klipper directory, change the line damping_ratio_x, damping_ratio_y) on line 135 to damping_ratio_x, damping_ratio_x) | |
You’ll need to completely restart your klipper instance with systemctl restart klipper via ssh. Or just restart your pi completely. Do not just restart via the UI of fluidd/mainsail | |
You can then use the resonance test STL and iterate your damping value with the tuning tower command. (TUNING_TOWER COMMAND=SET_INPUT_SHAPER PARAMETER=DAMPING_RATIO_X START=<some value> Factor= <some value>. I personally iterated from 0 to .11ish with a factor of .002. | |
You can then inspect the output and where you think it looks best. Your calculated value should get you in just about the right space if your IS graphs are clean. |
You could use docker for running the Rscript above:
docker run -ti -v "$PWD":/home/docker -w /home/docker -u root r-base /bin/sh
Run it like this within the container:
Rscript yourscript.R
Be sure to alter the path to your resonances csv and your script.
I have revised versions of the scripts that are a lot easier to use.
For the X axis:
resonances <- read.csv(dir('/tmp/', full.names=T, pattern="^resonances_x"))
peak_power<-max(resonances$psd_xyz)
peak_freq<-resonances$freq[resonances$psd_xyz==peak_power]
half_power<-peak_power/sqrt(2)
# install.packages("rootSolve")
library(rootSolve)
roots<-uniroot.all(approxfun(resonances$freq,resonances$psd_xyz-half_power),c(1,135))
plot(resonances$freq,resonances$psd_xyz,
type = "l",
main = "Frequency Response and Damping Ratio",
xlab = "Frequency [Hz]",
ylab = "Power")
abline(h=half_power,v=roots)
points(peak_freq,peak_power)
Damping_Ratio=(roots[2]-roots[1])/(2*peak_freq)
Damping_Ratio
for the Y axis:
resonances <- read.csv(dir('/tmp/', full.names=T, pattern="^resonances_y"))
peak_power<-max(resonances$psd_xyz)
peak_freq<-resonances$freq[resonances$psd_xyz==peak_power]
half_power<-peak_power/sqrt(2)
# install.packages("rootSolve")
library(rootSolve)
roots<-uniroot.all(approxfun(resonances$freq,resonances$psd_xyz-half_power),c(1,135))
plot(resonances$freq,resonances$psd_xyz,
type = "l",
main = "Frequency Response and Damping Ratio",
xlab = "Frequency [Hz]",
ylab = "Power")
abline(h=half_power,v=roots)
points(peak_freq,peak_power)
Damping_Ratio=(roots[2]-roots[1])/(2*peak_freq)
Damping_Ratio
Por que no los dos? You can run this to get both X and Y damping ratios if you've generated both CSVs:
resonances_X <- read.csv(dir('/tmp/', full.names=T, pattern="^resonances_x"))
resonances_Y <- read.csv(dir('/tmp/', full.names=T, pattern="^resonances_y"))
peak_power_X<-max(resonances_X$psd_xyz)
peak_power_Y<-max(resonances_Y$psd_xyz)
peak_freq_X<-resonances_X$freq[resonances_X$psd_xyz==peak_power_X]
peak_freq_Y<-resonances_Y$freq[resonances_Y$psd_xyz==peak_power_Y]
half_power_X<-peak_power_X/sqrt(2)
half_power_Y<-peak_power_Y/sqrt(2)
install.packages("rootSolve")
library(rootSolve)
roots_X<-uniroot.all(approxfun(resonances_X$freq,resonances_X$psd_xyz-half_power_X),c(1,135))
roots_Y<-uniroot.all(approxfun(resonances_Y$freq,resonances_Y$psd_xyz-half_power_Y),c(1,135))
Damping_Ratio_X=(roots_X[2]-roots_X[1])/(2*peak_freq_X)
Damping_Ratio_Y=(roots_Y[2]-roots_Y[1])/(2*peak_freq_Y)
Damping_Ratio_X
Damping_Ratio_Y
@churls5495 I didn't know how to do that in R. It was just easier for me to do two different files. But thanks for that extra revision!
Check out this repo which automates the above - https://github.com/lhndo/ResHelper
Little question. Does it matter in what order you do the calibration? For example, I first do SHAPER_CALIBRATE and then calculate the dampening freq. Is this the correct order? Does order even matter?
@celtare21 you must execute the test_resonances
command so that it can output the CSV required to compute the damping ratio. shaper_calibrate
will not do this.
I put together a Python script to calculate the damping ratio, might be a bit more convenient to run:
# Script reads input shaper csv file and computes damping ratio as (f2 - f1) / (2 * f0) where f0 is the peak psd_xyz amplitude frequency and f1 and f2 are the frequencies at which the amplitude is 1/sqrt(2) of the peak amplitude.
# CSV columns:
# freq, psd_x, psd_y, psd_z, psd_xyz
import sys
import numpy as np
import pandas as pd
import scipy.interpolate as interpolate
# Read input file
if len(sys.argv) < 2:
print("Usage: %s <input file>" % sys.argv[0])
sys.exit(1)
input_file = sys.argv[1]
df = pd.read_csv(input_file, sep=',', header=0, names=['freq', 'psd_x', 'psd_y', 'psd_z', 'psd_xyz'])
peak_amplitude = df['psd_xyz'].max()
peak_freq = df['freq'][df['psd_xyz'].idxmax()]
f_ampl = peak_amplitude / np.sqrt(2)
# Interpolate psd_xyz to find frequency at which psd_xyz is 1/sqrt(2) of peak amplitude on both sides of peak frequency
f1 = interpolate.interp1d(df['psd_xyz'][df['freq'] < peak_freq], df['freq'][df['freq'] < peak_freq])(f_ampl)
f2 = interpolate.interp1d(df['psd_xyz'][df['freq'] > peak_freq], df['freq'][df['freq'] > peak_freq])(f_ampl)
# Compute damping ratio
damping_ratio = (f2 - f1) / (2 * peak_freq)
print("Peak frequency: %f" % peak_freq)
print("Damping ratio: %f" % damping_ratio)
Just takes the csv file as an argument
The graph and csv produced by klipper is the PSD of the vibration, which corresponds to power or amplitude squared. The half power method is done by looking for width at half-maximum of the power graph, which corresponds to 1/sqrt(2) of the amplitude graph.
I would expect the correct damping ratio to be measured from 1/2 of the PSD instead of 1/sqrt(2). Were the measurements accurate using 1/sqrt(2)?
NASA published a way to get better estimate from the same graph. See equation 83.
It is noted in the document that the f_hi-f_low/2*f_peak method accurate if zeta < 0.05. See equation 67.
https://ntrs.nasa.gov/api/citations/20170005173/downloads/20170005173.pdf
On the photos its not clear that the print got better after changing the damping ratio. Is it really worth the fuss?
I wrote an R script to recreate the plot above and calculate the Damping Ratio given the resonances_*.csv file: