FFT plot accuracy & Scaling

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

%if true
Y = fft(data/L);
Try above

Also reduce Fs

%f true
Fs = 5000/1570
Yeah I pretty much get the exact same graph
Same as you wanted as in first graph or second ?
Not much changed sorry it still looks like the second graph.
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
dpb
dpb on 8 Dec 2020
Edited: dpb on 8 Dec 2020
" 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.
Yeah thats what I was thinking as well, in terms of accuracy its pretty much there anyways. Thank you all for the help!
VBBV
VBBV on 9 Dec 2020
Edited: VBBV on 9 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

Sign in to comment.

Answers (0)

Tags

Asked:

on 8 Dec 2020

Edited:

on 9 Dec 2020

Community Treasure Hunt

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

Start Hunting!