Fast Fourier Transform component detection issue

조회 수: 2(최근 30일)
awezmm 2020년 5월 23일
댓글: awezmm 2020년 5월 25일
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);
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;
title('Single-Sided Amplitude Spectrum of X(t)')
xlabel('f (Hz)')
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);
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?

채택된 답변

David Goodmanson
David Goodmanson 2020년 5월 25일
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.
  댓글 수: 1
awezmm 2020년 5월 25일
This is a very well explained answer. Thank you very much!

댓글을 달려면 로그인하십시오.

추가 답변(0개)

Community Treasure Hunt

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

Start Hunting!

Translated by