FFT a lot of detail around a certain frequency

I have an arbitrary signal, and I need to know the frequency spectrum of the signal that I receive when performing an FFT. The problem is that I need a lot of resolution just around this particular frequency. The problem is that if I increase the width of the window or if I increase the sampling rate, it will be too slow and I get a lot of detail all over the world. I want only a lot of detail at one point and minimal detail all over the world.

I tried to use the Goertzel filter only in the area that I needed, and then FFT everywhere, but it didn’t cause me anymore, which I believe was expected.

Any ideas? My only idea at the moment is to sweep domestic production around the value that I want.

Thank.

+4
source share
1 answer

Increasing the sampling rate will not give you a higher spectral resolution; it will give you higher frequency information that you are not interested in. The only way to increase the spectral resolution is to increase the window length. There is a way to increase the length of your window artificially by zero filling, but this only gives you a “fake resolution”, it just gives a smooth curve between normal points. Thus, the only way is to measure the data over a longer period, there is no free lunch.

. , ( , ), ( - , ). , , FFT . , . f_demod x.

, , , , , .

  • , , 2 , .

  • exp(2*pi*i*f_demod*t). FFT , . , , f_demod.

. :

from __future__ import division
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.mlab import psd
from scipy.signal import decimate

f_line = 123.456
f_demod = 122

f_sample = 1000
t_total = 100
t_win = 10
ratio = 10

t = np.arange(0, t_total, 1 / f_sample) 
x = np.sin(2*np.pi*f_line * t) + np.random.randn(len(t)) # sine plus white noise
lo = 2**.5 * np.exp(-2j*np.pi*f_demod * t) # local oscillator
y = decimate(x * lo, ratio) # demodulate and decimate to 100 Hz
z = decimate(y, ratio) # decimate further to 10 Hz

nfft = int(round(f_sample * t_win))
X, fx = psd(x, NFFT = nfft, noverlap = nfft/2, Fs = f_sample)

nfft = int(round(f_sample * t_win / ratio))
Y, fy = psd(y, NFFT = nfft, noverlap = nfft/2, Fs = f_sample / ratio)

nfft = int(round(f_sample * t_win / ratio**2))
Z, fz = psd(z, NFFT = nfft, noverlap = nfft/2, Fs = f_sample / ratio**2)

plt.semilogy(fx, X, fy + f_demod, Y, fz + f_demod, Z)
plt.xlabel('Frequency (Hz)')
plt.ylabel('PSD (V^2/Hz)')
plt.legend(('Full bandwidth FFT', '100 Hz FFT', '10 Hz FFT'))
plt.show()

:

enter image description here

, , . , , , , decimate, , , 10. , , .. 1000 , 3 10 .

+6

Source: https://habr.com/ru/post/1530790/


All Articles