Fast Fourier Transform component detection issue
1 vue (au cours des 30 derniers jours)
Afficher commentaires plus anciens
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
![](https://www.mathworks.com/matlabcentral/answers/uploaded_files/298668/image.png)
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)|')
![](https://www.mathworks.com/matlabcentral/answers/uploaded_files/298673/image.png)
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
![](https://www.mathworks.com/matlabcentral/answers/uploaded_files/298678/image.png)
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 commentaires
Réponse acceptée
David Goodmanson
le 25 Mai 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.
Plus de réponses (0)
Voir également
Catégories
En savoir plus sur Get Started with Signal Processing Toolbox dans Help Center et File Exchange
Produits
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!