How to make an FRF with my accelerometer Data and FFT?

46 views (last 30 days)
Dear, Matlab Users.
I have some inquiries about my accelerometer Data, that was processed by a Dewesoft Software.
So, I am gonna share my code and data, and I would like to know if there any suggestion to this resolution.
Sensitivy: 102 mV/g, or 10.40 mV/m/s^2
%Load data
clear all
load("C:\Users\joant\Desktop\Field_Research\Matlab_Code\data_test.mat")
whos
close all
%Plot the array according to the data
%Data of Channel 1
g1= transpose(Data1_352C33OLD)
t1= transpose(Data1_time_352C33OLD); % time
dt=1/(Sample_rate) % period
L=length(g1)
%Iterate
% Figure of Channel 1
figure(1)
plot(t1,g1,'b.-')
set(gca,'Fontsize',14)
xlabel('time(s)')
ylabel('g')
xlim([min(t1) max(t1)])
%ylim([-6 6])
grid on
% Calculate Fourier transform of force
points=round((t1(L))/dt) %Calculate the points
A_F= g1; % This is the Force for setting in the fft.
freq= (0:1/(dt*points):(1-1/(2*points))/dt)'; %Hz
freq=freq(1:round(points/2+1),:); %Hz
length(freq)
length(fft(A_F))
%In this part I need help
A_fft=fft(g1); %without the conversion by 9.8 m/s^2
abs_A=abs(A_fft)
figure(4)
plot(freq,abs_A(1:length(freq)))
xlim([0 6]) % Because 5 Hz is 300 RPM
%ylim([-400 400])
xlabel('Frequency (Hz)')
ylabel('g')
%According to the practice in the laboratory the result is the following
%image.
This was my process to obtain the FFT, I would like to know if this process is correct?. Because when I plot this data is not the same values in y-axis that I had in the Dewesoft software.
Dewesoft fft(g) (attached) vs matlab fft(g) (attached)
Question #2
According to a Mechanical vibration book, I have the next equation to find the FRF. I applied this but my FRF y axis value is too high so, I don't know If I didn't applied correctly. That information is in my code and I use the following equation.
w= natural frequency = 31.42 rad/s^2.
I assumpted that A/F is g because according to the book, it says the next information: "Because the acceloremeter produces a voltage that is proportional to acceleration, we obtain the accelerance, A/F(w), from the dynamic signal analyzer".
My graph result:
This graph it doesn't have sense, because I need values aroun of 0.15-0.17 in the first vibration mode. So, I would like to know if there any suggestion how to resolve this.
Best Regards,
Jo98.

Accepted Answer

Mathieu NOE
Mathieu NOE on 4 Dec 2023
hello
I got the correct result if I assume that your data is in g and not volts (so your analyser has already used the sensor sensivity when storing the data)
there can be some minor difference in terms of frequency and amplitude as I am not aware of what type of window / nfft is used on your side
load("data_test.mat")
%Plot the array according to the data
%Data of Channel 1
signal = double(Data1_352C33OLD);
time= Data1_time_352C33OLD; % time
[samples,channels] = size(signal);
dt = mean(diff(time));
Fs = 1/dt;
%% decimate (if needed)
% NB : decim = 1 will do nothing (output = input)
decim = 10;
if decim>1
Fs = Fs/decim;
for ck = 1:channels
newsignal(:,ck) = decimate(signal(:,ck),decim);
end
signal = newsignal;
end
samples = length(signal);
time = (0:samples-1)*1/Fs;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% FFT parameters
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
NFFT = 1000; % for maximal resolution take NFFT = signal length (but then no averaging possible)
OVERLAP = 0.75; % overlap will be used only if NFFT is shorter than signal length
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% display 1 : time domain plot
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
figure(1),
plot(time,signal,'b');grid on
title(['Time plot / Fs = ' num2str(Fs) ' Hz ']);
xlabel('Time (s)');ylabel('Amplitude');
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% display 2 : averaged FFT spectrum
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
[freq, spectrum_raw] = myfft_peak(signal,Fs,NFFT,OVERLAP);
figure(2),plot(freq,spectrum_raw,'b');grid on
df = freq(2)-freq(1); % frequency resolution
title(['Averaged FFT Spectrum / Fs = ' num2str(Fs) ' Hz / Delta f = ' num2str(df,3) ' Hz ']);
xlabel('Frequency (Hz)');ylabel('Amplitude');
function [freq_vector,fft_spectrum] = myfft_peak(signal, Fs, nfft, Overlap)
% FFT peak spectrum of signal (example sinus amplitude 1 = 0 dB after fft).
% Linear averaging
% signal - input signal,
% Fs - Sampling frequency (Hz).
% nfft - FFT window size
% Overlap - buffer percentage of overlap % (between 0 and 0.95)
[samples,channels] = size(signal);
% fill signal with zeros if its length is lower than nfft
if samples<nfft
s_tmp = zeros(nfft,channels);
s_tmp((1:samples),:) = signal;
signal = s_tmp;
samples = nfft;
end
% window : hanning
window = hanning(nfft);
window = window(:);
% compute fft with overlap
offset = fix((1-Overlap)*nfft);
spectnum = 1+ fix((samples-nfft)/offset); % Number of windows
% % for info is equivalent to :
% noverlap = Overlap*nfft;
% spectnum = fix((samples-noverlap)/(nfft-noverlap)); % Number of windows
% main loop
fft_spectrum = 0;
for i=1:spectnum
start = (i-1)*offset;
sw = signal((1+start):(start+nfft),:).*(window*ones(1,channels));
fft_spectrum = fft_spectrum + (abs(fft(sw))*4/nfft); % X=fft(x.*hanning(N))*4/N; % hanning only
end
fft_spectrum = fft_spectrum/spectnum; % to do linear averaging scaling
% one sidded fft spectrum % Select first half
if rem(nfft,2) % nfft odd
select = (1:(nfft+1)/2)';
else
select = (1:nfft/2+1)';
end
fft_spectrum = fft_spectrum(select,:);
freq_vector = (select - 1)*Fs/nfft;
end
  10 Comments
oybozkurt
oybozkurt on 19 Nov 2024
Thank you for your quick reply. For example, the acceleration and force values obtained as a result of a hit with a hammer are available in the excel file. Can you check this sample data?
Mathieu NOE
Mathieu NOE on 20 Nov 2024
hello
so I adapted my code for your experimental data - so there is only one hit in your record, I wish you could redo the test with multiple hits in the same record (make 5/6 hits with approx 5 seconds interval).
the benefit of making multiple hits is to reduce the noise effects and average your response curve.
nevertheless , this is the result obtained so far with your single hit record :
hope it helps !
Results
Mode Frequency Damping
____ _________ _________
1 66.147 0.0081933
2 307.36 0.031123
Code :
%% Modal Analysis ( hammer test ) - FRF computation
%% load data
filename = "Acceleration-Force.xlsx";
headerlines = 10;
% force data
data = readmatrix(filename,"Sheet","Force","NumHeaderLines",headerlines,"ExpectedNumVariables",2);
timef = data(:,1);
force_signal = data(:,2);
force_unit = 'N';
% accel data
data = readmatrix(filename,"Sheet","Acceleration","NumHeaderLines",headerlines,"ExpectedNumVariables",2);
timea = data(:,1);
accel_signal = data(:,2);
accel_unit = 'g';
if sum(abs(timef - timea))>eps
error('Time vectors don''t match - double check your data')
else
time = timef;
clear timef timea
end
dt = mean(diff(time));
Fs = 1/dt;
samples = numel(force_signal);
channels = size(accel_signal,2);
%% FFT processing parameters
nfft = 1024*4;
% let's trigger the data (using "zero crossing" on the force signal)
% this is basically the same way a FFT/network analyser operates
pre_trig_duration = 10e-3; % (seconds) - add some time to shift the pulse signal to the right
force_signal_level = 1;
[Zx] = find_zc(time,force_signal,force_signal_level);
Zx = Zx - pre_trig_duration;
%recommended max nfft
if numel(Zx)>1
recommended_max_nfft = floor(min(Fs*diff(Zx)));
else
recommended_max_nfft = numel(time);
end
%% check valid segments (duration in samples must be above nfft
% pulses durations in samples :
pd = [Fs*diff(Zx); samples-Fs*Zx(end)];% add the last pulse duration :
data_valid = find(pd>=nfft);
figure(2),
subplot(2,1,1),plot(time,force_signal)
title('force signal');
xlabel('Time (s)');
ylabel(force_unit);
% warning message
if nfft>recommended_max_nfft
text(max(time)*0.1,max(force_signal)*0.9,['Selected nfft = ' num2str(nfft) ' is above recommended max value : ' num2str(recommended_max_nfft)]);
end
subplot(2,1,2),plot(time,accel_signal)
title('accel signal');
xlabel('Time (s)');
ylabel(accel_unit);
%% FFT processing
% windowing
windowx = ones(nfft,1); % no window on force signal (or use boxcar)
windowy = ones(nfft,1); % no window on response sensor signal (or use a exp window as suggested below if the signal decay rate is too slow).
% windowy = exp(-3*(0:nfft-1)/nfft)'; % 0.1 exp window on response sensor signal
% initialisation
Pxx = zeros(nfft,1);
Pxy = zeros(nfft,channels);
Pyy = zeros(nfft,channels);
% check if data_valid is not empty (can happen if you choose nfft grossly
% oversized)
if isempty(data_valid)
error('No data or nfft too large - check data & nfft settings');
else % we have data and nfft is correctly defined
for ck = 1:numel(data_valid)
% do it only for valid segments
k = data_valid(ck);
% select time data
ind_start = find(time>=Zx(k),1,'first');
% check valid segments (duration in samples must be above nfft
ind = (ind_start :ind_start + nfft -1);
time_measure = time(ind);
time_measure = time_measure - time_measure(1);
force_signal_measure = force_signal(ind);
accel_signal_measure = accel_signal(ind);
% FFT processing
x = force_signal_measure;
y = accel_signal_measure;
xw = windowx.*x;
yw = (windowy*ones(1,channels)).*y;
Xx = fft(xw,nfft);
Yy = fft(yw,nfft,1);
Xx2 = abs(Xx).^2;
Xy2 = Yy.*(conj(Xx)*ones(1,channels));
Yy2 = abs(Yy).^2;
Pxx = Pxx + Xx2;
Pxy = Pxy + Xy2;
Pyy = Pyy + Yy2;
end
% Select first half
if ~any(any(imag([x y])~=0)) % if x and y are not complex
if rem(nfft,2) % nfft odd
select = [1:(nfft+1)/2];
else
select = [1:nfft/2+1]; % include DC AND Nyquist
end
Pxx = Pxx(select);
Pxy = Pxy(select,:);
Pyy = Pyy(select,:);
else
select = 1:nfft;
end
% set up output parameters
Txy = Pxy ./ (Pxx*ones(1,channels)); % transfer function estimate
Cxy = (abs(Pxy).^2)./((Pxx*ones(1,channels)).*Pyy); % coherence function estimate
f = (select - 1)'*Fs/nfft;
end
%% plot model vs identified FRF
flow = 10;
fhigh = Fs/2.56;
figure(4)
subplot(3,1,1),loglog(f,abs(Txy),'r');
title(['FRF estimation based on valid data chuncks # : ' num2str(data_valid')])
xlim([flow fhigh]);
ylabel(['Magnitude (' accel_unit ' / ' force_unit ')']);
subplot(3,1,2),semilogx(f,180/pi*(angle(Txy)),'r');
xlim([flow fhigh]);
ylabel('Phase (°)');
subplot(3,1,3),semilogx(f,Cxy,'r');
xlim([flow fhigh]);
xlabel('Frequency (Hz)');
ylabel('Coh');
ylim([0 1.1]);
%% natural frequencies & damping ratioes
N = 2 ; % number of (dominant) modes to identify
% only use valide data (coherence above 0.9)
ind = Cxy>0.9;
FR = [20 400];
[fn,dr] = modalfit(Txy(ind),f(ind),Fs,N,'FitMethod','lsrf','FreqRange',FR);
T = table((1:N)',fn,dr,'VariableNames',{'Mode','Frequency','Damping'})
T = 2x3 table
Mode Frequency Damping ____ _________ _________ 1 66.147 0.0081933 2 307.36 0.031123
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [Zx] = find_zc(x,y,threshold)
% find time values of positive slope zero (or "threshold" value ) y
% crossing points
% put data in rows
x = x(:);
y = y(:);
% positive slope "zero" crossing detection, using linear interpolation
y = y - threshold;
zci = @(data) find(diff(sign(data))>0); %define function: returns indices of +ZCs
ix=zci(y); %find indices of + zero crossings of x
ZeroX = @(x0,y0,x1,y1) x0 - (y0.*(x0 - x1))./(y0 - y1); % Interpolated x value for Zero-Crossing
Zx = ZeroX(x(ix),y(ix),x(ix+1),y(ix+1));
end

Sign in to comment.

More Answers (2)

oybozkurt
oybozkurt on 5 Jan 2025
Hello Mathieu,
I have been busy trying your programme for a long time, it is very good but I need your help with a few things. Firstly, in some cases it takes points very close to each other as 1st and 2nd mode. Secondly, is there a document you can recommend to understand the technical content of your programme?
  7 Comments
Mathieu NOE
Mathieu NOE on 13 Jan 2025
oh yes indeed - I didn't see the excel file was different with more sheets :)
so I changed the code the load the correct sheets and also to display the magnitude plot now in dB as in signalexpress , I also did some changes for figure 3 display
the commented lines are the previous code version (y log scale) - the new code is magnitude converted in dB ref to the declared units.
then I opted for new modalfit parameters :
N = 1 ; % number of (dominant) modes to identify
FR = [5 300]; %
I see the same values of the dominant mode as in signalexpress (fn = 30 Hz, T = -34 dB ref 1 g/N)
T = 1×4 table
Mode Frequency Damping Gain (dB)
____ _________ _______ _________
1 30.028 0.12593 -33.616
Code updated in attachment

Sign in to comment.


oybozkurt
oybozkurt on 13 Jan 2025
Hello Mathieu,
First of all, thank you for your efforts. How accurately does the modalfit command work? When the graphs for ‘FitMethod’,‘lsrf’ and ‘FitMethod’,‘pp’ are carefully examined, the natural frequencies do not exactly coincide with the peaks, and there are significant differences between damping evaluated using ‘lsrf’ and ‘pp’ for the data I attached. Again, is the damping calculated by the method in the picture I attached or by another method.
  14 Comments
Jo98
Jo98 on 22 Mar 2025
Hello,
I understand it thanks for your help, I was trying to create a code on matlab for creating an SLD from the FRF signal.
As always thanks for your help.
Best Regards.

Sign in to comment.

Tags

Products


Release

R2021a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!