Reputation: 2405
I have a signal with a phase that is around 40 Hz, with small amounts of noise. I am trying to analyze it to find the frequency in 1 second blocks, I am using python to do a simulation of this. I found that the blocked FFT analysis was not accurate, so I looked at specific blocks to see why this was happening and found that at later times, the FFT was not making sense and having a spike around the 40 Hz where it should. I am using Python for this simulation and here is the code:
First create the signal:
# Time
time = 500
# sample spacing
T = 1.0 / 5000.0
sample_freq = 1.0/T
#number of points
N = time / T
x = np.linspace(0.0, N*T, N)
noise = np.random.normal(scale = 0.01, size = len(x))
noisy_freq = 40 + noise
y = 50.0 * np.sin(noisy_freq * 2.0*np.pi*x) + 1.0*np.sin(80.0 * 2.0*np.pi*x)
Then I looked at the FFT for the first second and receive:
and zoomed in to around 40 Hz
Then I looked at the 10th second block:
and zoomed to around 40 Hz:
It is visible the signal is degrading already and this horizontal line is beginning to develop which I'm not sure what is is from.
Then I looked at the 100th second and this is what I found:
and zoomed to around 40 Hz:
and the FFT response is showing barely any certainty of a spike around 40 Hz. I cannot figure out why the signal degrades at later times. I have tried using windowing functions, but this does not help.
Here is the code I use to create the FFT:
sample_freq = 1/T
time_step = 10
step = int(time_step * sample_freq)
x = x[100/T:101/T]
y = y[100/T:101/T]
flat = flat_top_windowing(len(y))
y = y*flat
yf = np.abs(np.fft.fft(y))
x_n = x.size
xf = np.fft.fftfreq(x_n,1/sample_freq)
plt.close()
plt.plot(xf, 2.0/N * yf[0:N/2])
plt.grid()
plt.show()
Upvotes: 2
Views: 314
Reputation: 14577
The problem is with the generated signal:
np.sin(noisy_freq * 2.0*np.pi*x)
As the time advances (values in variable x
), the multiplication noisy_freq*x
means that noisy_freq
variations have an ever increasing impact on the sin
phase. Given increasing phase variations, the actual instantaneous frequency varies that much more (to the extent that it eventually looks like it randomly jumps all over the whole spectrum).
To generate a frequency modulated signal, you should instead integrate the frequency contributions with:
dphi = 2.0*np.pi*noisy_freq[:-1]*T; # per sample frequency contributions
dphi = np.insert(dphi, 0, 0); # set the initial phase to 0
phi = np.cumsum(dphi); # integrate phase
y = 50.0 * np.sin(phi) + 1.0*np.sin(80.0 * 2.0*np.pi*x)
Upvotes: 2