True Amplitude of the FFT of accelerometer data?

16 views (last 30 days)
Hi There,
I am developing a dynamic mass balancing machine with BNO055's Accelerometer with Arduino UNO to measure vibration of the shaft rotating on bearings, the shaft is driven by stepper motor with belt drive (1:1 Ratio) I have gathered some acceleration data from the sensor and tried performing FFT on the data , but I can't seem to find it meaningfull as the x-axis of the fft spectrum shows some different values than expected. I have attached both the raw data ( Timestamps,X,Y,Z ) and the matlab code. Can anyone help with some guidance on the topic !
Specs:
RPM = 375
Data Sampling Frquency = 200 Hz
PS: As the motor is attached to the frame there are vibration noise to it (also a problem , i think....). Suggestions are welcome.

Answers (1)

Star Strider
Star Strider on 2 Apr 2025
You apparently want your ‘time’ vector to be in milliseconds, however you do not convert it to milliseconds.
This approach converts it to miilliseconds, then uses resample to produce a regularly-sampled vectors, and proceeds from there. I added a table of the most prominent peaks and their frequencies.
Try this —
% filename = 'Unbalanced W(24.4) rpm(375) radi(72.2) Sf(200).xlsx';
filename = 'Unbalanced W(2... Sf(200).xlsx';
rawdata = readmatrix(filename);
time0= rawdata(:,1);
time0 = time0 * 1E-3;
a_y0 = rawdata(:,3);
Tsd = std(diff(time0)) % The Data Are Not Regularly Sampled Or This Would Be Close To Zero
Tsd = 7.2011e-04
Fsd = 200; % Desired Sampling Frequency
[a_y, time] = resample(a_y0, time0, Fsd); % Use ‘resample’ To Produce Regularly-Sampled Vectors
T = mean(diff(time))
T = 0.0050
Fs = 1/T
Fs = 200
% Fs =200; % Sampling frequency
% T = 1/Fs; % Sampling period
L = length(time); % Length of signal
figure(1)
plot(time,a_y)
Y = fft(a_y-mean(a_y)); % Subtract ‘mean’ To Eliminate D-C Offset
figure(2); % I Am Not Certain What You Want The Frequency Vector To Be Here
plot(Fs/L*(0:L-1),abs(Y),"LineWidth",1);
title("Complex Magnitude of fft Spectrum");
xlabel("f (Hz)");
ylabel("|fft(X)|");
figure(3);
plot(Fs/L*(-L/2:L/2-1),abs(fftshift(Y)),"LineWidth",1)
title("fft Spectrum in the Positive and Negative Frequencies");
xlabel("f (Hz)");
ylabel("|fft(X)|");
figure(4)
P2 = abs(Y/L);
P1 = P2(1:L/2+1);
P1(2:end-1) = 2*P1(2:end-1);
f = Fs/L*(0:(L/2));
plot(f,P1,"LineWidth",1)
title("Single-Sided Amplitude Spectrum of a_y")
xlabel("f (Hz)")
ylabel("|P1(f)|")
[pks,locs] = findpeaks(P1, MinPeakProminence = 0.5);
Peaks_Freqs = table(f(locs).', pks, VariableNames=["Frequency (Hz)","Magnitude"])
Peaks_Freqs = 3x2 table
Frequency (Hz) Magnitude ______________ _________ 20.174 0.64945 47.696 0.82568 52.13 0.67519
.
  2 Comments
Vatsal
Vatsal on 2 Apr 2025
Really Appreciate your answer to the problem.
Just a thing:
What is the unit of the magnitude in last fft spectrum , can i somehow relate to it's time domain signal to know the exact acceleration in (m/s²) peak at that particular time point.
Again Thank You!
Star Strider
Star Strider on 2 Apr 2025
Edited: Star Strider on 3 Apr 2025
My pleasure!
The magnitude uints are the same as the original amplitude units. Your code does not square them or square the original signal, so they are not the ‘power’ version of it.
The usual approach is to multiply the magnitudes by 2 in the single-sided Fourier transform, to account for the two-sided fft splitting the original signal energy between the two halves of the spectrum. Multiplying the single-sided magnitudes by 2 partially corrects for this, and gives a more appropriate estimate. Your original code dis not do this multiplication, so I did not add it.
I definitely suggest multiplying the original amplitudes by 2, so here that would be ‘P1’.
EDIT — (3 Apr 2025 at 20:20)
My analysis of your data would be —
filename = 'Unbalanced W(2... Sf(200).xlsx';
rawdata = readmatrix(filename);
time0= rawdata(:,1);
time0 = time0 * 1E-3;
a_y0 = rawdata(:,3);
Tsd = 7.2011e-04
Tsd = 7.2011e-04
Fsd = 200; % Desired Sampling Frequency
[a_y, time] = resample(a_y0, time0, Fsd); % Use ‘resample’ To Produce Regularly-Sampled Vectors
[FTs1,Fv] = FFT1(a_y,time);
[pks,locs] = findpeaks(abs(FTs1)*2, MinPeakProminence = 0.5);
Peaks_Freqs = table(Fv(locs), pks, VariableNames=["Frequency (Hz)","Magnitude"])
Peaks_Freqs = 3x2 table
Frequency (Hz) Magnitude ______________ _________ 20.19 1.1237 47.705 1.1651 52.124 1.0153
figure
plot(Fv, abs(FTs1)*2)
grid
title("Single-Sided Amplitude Spectrum of a_y")
xlabel("f (Hz)")
ylabel("|P1(f)|")
function [FTs1,Fv] = FFT1(s,t)
% One-Sided Numerical Fourier Transform
% Arguments:
% s: Signal Vector Or Matrix
% t: Associated Time Vector
t = t(:);
L = numel(t);
if size(s,2) == L
s = s.';
end
Fs = 1/mean(diff(t));
Fn = Fs/2;
NFFT = 2^nextpow2(L);
FTs = fft((s - mean(s)) .* hann(L).*ones(1,size(s,2)), NFFT)/sum(hann(L));
Fv = Fs*(0:(NFFT/2))/NFFT;
% Fv = linspace(0, 1, NFFT/2+1)*Fn;
Iv = 1:numel(Fv);
Fv = Fv(:);
FTs1 = FTs(Iv,:);
end
.

Sign in to comment.

Products


Release

R2024b

Community Treasure Hunt

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

Start Hunting!