Fast Fourier Transform component detection issue
1 visualizzazione (ultimi 30 giorni)
Mostra commenti meno recenti
I want to detect the different components in a signal.
Here is an example of a signal:
Fs = 1000; % Sampling frequency
T = 1/Fs; % Sampling period
L = 100; % Length of signal
t = (0:L-1)*T; % Time vector
X = 0;
for i = 50:50:500
X = X + sin(2*pi*i*t);
end
Then when I run the FFT:
Y = fft(X);
P2 = abs(Y/L);
P1 = P2(1:L/2+1);
P1(2:end-1) = 2*P1(2:end-1);
f = Fs*(0:(L/2))/L;
subplot(4,1,2)
plot(f,P1)
title('Single-Sided Amplitude Spectrum of X(t)')
xlabel('f (Hz)')
ylabel('|P1(f)|')
This make sesne becasue my signal includes the summation of sin(2*pi*i*t) where i is frome 50 to 500
However, when I make a new signal from 50 to 600 and run the same FFT code
X = 0;
for i = 50:50:600
X = X + sin(2*pi*i*t);
end
How come I dont get the peaks at 400 and 450 anymore, even though they are still components when I add sin(2*pi*i*t) from 50 to 600?
Additionally, is there a limit to the number of components I can detect from the FFT, if I keep the Length of signal constant?
0 Commenti
Risposta accettata
David Goodmanson
il 25 Mag 2020
Hello awezmm,
This occurs because of a combination of aliasing and the spacing of the chosen frequencies. For sampling frequency Fs, and a time array of spacing 1/Fs, aiasing says
sin(2*pi*f0*t) = sin(2*pi*(f0 +-Fs)*t).
There are a lot of equally spaced frequencies in the sum, but consider just the original frequency 450 and the added frequency 550.
sin(2*pi*550*t) = sin(2*pi*(550-1000)*t) = sin(2*pi*(-450)*t) = -sin(2*pi*450*t)
and if you add this to the original sin(2*pi*450*t) you get zero. Plotting (2*pi*450*t) + sin(2*pi*550*t) in the time domain (with time array spacing 1/Fs) shows this. Similarly, frequency 600 cancels out 400, 650 cancels out 350 etc.
What about f = 500 = Fs/2 ? It's included in the original set of frequencies but doesn't show up in the plot. The argument above will show that it's zero in the time domain. By another way, since time each time in the time array is some integer n times the spacing 1/Fs,
sin(2*pi*f0*t) = sin(2*pi*(Fs/2)*n*(1/Fs)) = sin(pi*n) = 0 for all n
and a plot in the time domain shows the same thing.
All this can be illustrated in the frequency domain as well. The best way to do that is change the frequency span from [0 to Fs] to the equivalent span [-Fs/2 to Fs/2]. As is all too often done, your plot throws away the negative frequencies and takes abs of the positive ones. But the discarded information is quite useful. Since
sin(2*pi*f*t) = ( exp(2*pi*i*f*t) -exp(-2*pi*i*f*t) )/(2*i),
then (ignoring the factor of 2i), the spectrum has a positive amplitude at f and an equal but negative amplitude at -f.
For the sum of the sines at 450 and 550 the spectrum looks like
| |
-------------------------------------------------------
| |
-550 -450 0 450 550
When aliasing is used to take 550 to -450 and -550 to 450, the result is
| |
-------------------------------------------------------
| |
-550 -450 0 450 550
so the amplitudes cancel and you get 0.
If you had used cosine instead of sine, the results would have been completely different. In that case all the amplitudes are positive and the peak at 550 doubles the peak at 450 instead of canceling it. Changing sine to cosine in the code will illustrate this.
Più risposte (0)
Vedere anche
Prodotti
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!