How to obtain correct frequency and amplitude via FFT
124 views (last 30 days)
Show older comments
Hi
I have tried to test a Fast Fourier Transform using a simple example signal. The signal has a length of 2 seconds, a frequency of f = 2 and an amplitude of a = 3. However, when I apply the FFT and determine the maxima via the command findpeaks, I get f = 1.8311 and a = 2.5763. This means that the results differ quite a lot from my input.
I have already looked around here in the forum, but so far I have not been able to find a real solution to my problem. I hope that someone here has an idea what I am doing wrong.
I'd appricate the help! Thanks
clear all; close all; clc;
% create sinusoidal signal
f_sign = 2 ; % signal frequency
a_sign = 3 ; % signal amplitude
t_sign = 2 ; % length of signal [s]
dt_sign = 0.0001 ; % sample rate [s]
nt_sign = t_sign/dt_sign ; % discrete number of datapoints
t = 0:dt_sign:t_sign ; % Time vector
y = a_sign*sin(2*pi*f_sign*t) ; % create signal
% Fourier transformation
y_fft = y - mean(y);
nfft = 2^nextpow2(nt_sign);
FFT = fft(y_fft,nfft)/nt_sign;
FFT = 2*abs(FFT(1:nfft/2+1));
fs=1/dt_sign;
f = fs/2*linspace(0,1,nfft/2+1);
% find maximum amplitude and frequency
[pks,locs] = findpeaks(FFT,f);
[pks_max,idx_pks_max] = max(pks);
locs_max = locs(idx_pks_max);
% results
f_fft = locs_max
a_fft = pks_max
6 Comments
Star Strider
on 17 Jan 2023
The multiplication-by-2 is important, and is in the documentation. The reason is that the signal energy is divided (in the two-sided fft) between the ‘positive’ and ‘negative’ frequencies. The multiplication-by-2 (in either the one-sided to two-sided fft corrects) for this, giving an appropriate amplitude.
Paul
on 17 Jan 2023
Edited: Paul
on 18 Jan 2023
I thought I was clear that my comment was only relevant to the FFT(1) and FFT(N/2+1), which are the elements of FFT that correspond to f(1) and f(end). So, I'm only talking about those two elements.
Suppose we have "sine wave" at zero frequency with amplitude = 3. For simplicity, I'll assume N = 8.
N = 8;
n = (0:(N-1));
x = 3*cos(0*n)
X = fft(x)/N
As we can see, the first point in X is 3, which is the amplitude of the input. So why multiply X(1) by 2?
Now, let the frequency be pi, i.e., the Nyquist frequency
x = 3*cos(pi*n)
X = fft(x)/N
The element X(N/2+1) that corresponds to the Nyquist frequency is 3, which is the amplitude of the input. Why multiply
X(N/2+1) by 2?
Keep in mind that if N is odd, no element of X corresponds to the Nyquist frequency. But we still have the same issue with X(1) regardless.
P1 = P2(1:L/2+1);
P1(2:end-1) = 2*P1(2:end-1);
i.e., the first element of P1 is not multiplied by 2, and neither is the last element for L even.
Accepted Answer
Star Strider
on 10 Jan 2023
Increase the frequency resolution (I doubled it here, although you can increase it further) with
nfft = 2^nextpow2(nt_sign)*2
and the results significantly improve.
With that:
f_fft = 1.9836
a_fft = 3.0070
and you can likely get improved accuracy with finer ffrequency resolution.
% clear all; close all; clc;
% create sinusoidal signal
f_sign = 2 ; % signal frequency
a_sign = 3 ; % signal amplitude
t_sign = 2 ; % length of signal [s]
dt_sign = 0.0001 ; % sample rate [s]
nt_sign = t_sign/dt_sign ; % discrete number of datapoints
t = 0:dt_sign:t_sign ; % Time vector
y = a_sign*sin(2*pi*f_sign*t) ; % create signal
% Fourier transformation
y_fft = y - mean(y);
nfft = 2^nextpow2(nt_sign)*2
FFT = fft(y_fft,nfft)/nt_sign;
FFT = 2*abs(FFT(1:nfft/2+1));
fs=1/dt_sign;
f = fs/2*linspace(0,1,nfft/2+1);
% find maximum amplitude and frequency
[pks,locs] = findpeaks(FFT,f);
[pks_max,idx_pks_max] = max(pks);
locs_max = locs(idx_pks_max);
% results
f_fft = locs_max
a_fft = pks_max
.
2 Comments
More Answers (0)
See Also
Categories
Find more on Fourier Analysis and Filtering 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!