MATLAB: Noise in FFT of acceleration after windowing

accelerationffthanningMATLABnoisewindowing

clearvars
clc
acc = importdata('acc.mat');
time = importdata('time.mat');
signal = acc; % input the time domain data to variable "signal"
L = length(signal); % length of signal
L2 = L/2 + 1; % define half the signal length for post-fft
L2 = fix(L2); % fix to integer value
frequency = linspace(0,L2,L2); % create frequency array
frequency = frequency';
step = time(2,1) - time(1,1); % find initial step
frequency = frequency / (step*L); % normalise frequency to measured frequencies
signal2 = hann(L).*signal; % apply hanning window
nsamples = L-1; % number of fft samples
% prepare the fft
rawFFT = fft(signal2); % raw fft calculation
phases = unwrap(angle(rawFFT)); % unwrap phases
amplitudes2 = 2*abs(rawFFT)/nsamples; % amplitudes of harmonics
% set the continuous component first
amplitudes2(1) = amplitudes2(1)/2; % halve dc component because single-sided fft
amplitudes1 = amplitudes2(1:L2); % take one side of fft
% take first 1000 points (only interested up to ~20kHz)
amplitudes = amplitudes1(1:1000);
freq = frequency(1:1000);
I am calculating the vibration spectra from acceleration-time results, the result has much noise. I have moved the significant time domain peak to the centre of the time domain and used a hanning window to help, but it is still noisy.
windowing_hannL_1cyc_central_symmetric.png fft_hanningL_1cyc_central.png
Any help appreciated, time and acceleration data attached.

Best Answer

Your signal has broad-band noise, so no frequency-selective filter (of which windows are a subset as you are using them) will elimiinate it. You may be able to eliminate most of the noise using wavelets. The best you can likely do otherwise is to use a Savitsky-Golay filter (the sgolayfilt function).
This is how I implemented it:
D1 = load('acc.mat');
T = load(' time.mat');
acc = D1.acc;
time = T.time;
L = numel(time);
Ts = mean(diff(time));
Fs = 1/Ts;
Fn = Fs/2;
FTacc = fft(acc)/L;
Fv = linspace(0, 1, fix(L/2) + 1)*Fn;
Iv = 1:numel(Fv);
figure
plot(Fv, abs(FTacc(Iv))*2)
grid
xlim([0, 1E+5])
xlabel('Frequency')
ylabel('Amplitude')
title('Fourier Transform')
sgf = sgolayfilt(acc, 3, fix(L/750));
figure
plot(time, acc)
hold on
plot(time, sgf)
hold off
grid
xlim([0.022 0.027]) % ‘Zoom’ To See Detail
xlabel('Time')
ylabel('Amplitude')
legend('Original Signal', 'Savitzky-Golay Filtered Signal', 'Location','NE')
Experiment with the third argument to sgolayfilt (framelength’) to get the result you want.