FFT plot accuracy & Scaling
Show older comments
Currently struggling on knowing whether my fft plot is entirely accurate. Trying to also achieve the correct scaling as well. I have looked at a lot of posts regarding this but still not achieving the same sort of scale. I am trying to achieve this:

But I am getting this:

Fs = 5000/157
data = x
L = length(data)
Y = fft(data)/L
f = Fs/2*linspace(0,1,L/2+1);
plot(f,2*abs(Y(1:L/2+1)))
xlim([0.08 0.78])
set(gca, 'YScale', 'log')
title('Duffing')
xlabel('f (Hz)')
ylabel('Amplitude')
Any help would be much appreciated
9 Comments
VBBV
on 8 Dec 2020
%if true
Y = fft(data/L);
Try above
VBBV
on 8 Dec 2020
Also reduce Fs
%f true Fs = 5000/1570
Bledar Ferati
on 8 Dec 2020
VBBV
on 8 Dec 2020
Same as you wanted as in first graph or second ?
Bledar Ferati
on 8 Dec 2020
Mathieu NOE
on 8 Dec 2020
hi
FYI, this is my fft / averaging / scaling function - please use it as you like :
function [freq_vector,fft_spectrum] = myfft_peak(signal, Fs, nfft, Overlap)
%FFT peak spectrum of signal (example sinus amplitude 1 = 0 dB after fft).
% signal - input signal,
% Fs - Sampling frequency (Hz).
% nfft - FFT window size
% Overlap - buffer overlap % (between 0 and 0.95)
samples = length(signal);
% fill signal with zeros if its length is lower than nfft
if samples<nfft
s_tmp = zeros(nfft,1);
s_tmp((1:samples)) = signal;
signal = s_tmp;
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;
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
" it still looks like the second graph."
Where you divide by L is immaterial so that is/was a do-nothing operation.
The change of Fs = 5000/1570 for Fs = 5000/157 will have changed Fmax by factor/divisor of 10 which seems misguided since your peak frequencies seem to match well.
Your magnitude seems to match pretty well, too; that the fine structure isn't the same is undoubtedly owing to difference in the time series data from which you started vis a vis the reference figure.
Dunno there's much anybody here can tell you without a lot more background information.
Bledar Ferati
on 8 Dec 2020
%true
L = max(data)
f = (Fs/2)*linspace(0,1,L)
plot(f(1:L:end), 2*abs(Y(1:L:end)))
Use max value of data instead of length
Answers (0)
Categories
Find more on Multirate Signal Processing 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!