True Amplitude of the FFT of accelerometer data?
16 views (last 30 days)
Show older comments
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.
0 Comments
Answers (1)
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
Fsd = 200; % Desired Sampling Frequency
[a_y, time] = resample(a_y0, time0, Fsd); % Use ‘resample’ To Produce Regularly-Sampled Vectors
T = mean(diff(time))
Fs = 1/T
% 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"])
.
2 Comments
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);
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"])
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
.
See Also
Categories
Find more on Spectral Measurements in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!



