正弦波频率拟合

发布于 2024-08-18 08:08:02 字数 738 浏览 2 评论 0原文

这个问题基于之前的类似问题。

我有以下方程和调整后的(一些随机数据): 0.44*sin(N* 2*PI/30)

我试图使用 FFT 从生成的数据中获取频率。然而,频率最终接近但不等于频率(这使得波比预期的要大一些)

FFT 的最大频率是 7hz,但预期频率是 (30/2PI) 4.77hz。

我已经提供了 FFT 图表和绘制值。

alt text

我使用的代码是:

[sampleFFTValues sFreq] = positiveFFT(sampledata, 1);
sampleFFTValues = abs(sampleFFTValues);
[v sFFTV]= max(sampleFFTValues)

正FFT可以是在这里找到。基本上,它将 FFT 图居中并切断负信号。

我的问题是如何使 FFT 更准确,而不必仅采用最小二乘法来计算频率?

This question is based on a previous similar question.

I have the following equation and an adjusted (some random data): 0.44*sin(N* 2*PI/30)

I am trying to use the FFT to get the frequency from the data generated. However the frequency ends up being close but not equal to the frequency (which makes the wave a bit larger than intended)

The frequencies that are at the maximum for the FFT is 7hz, however the expected frequency is (30/2PI) 4.77hz.

I've included a graph of the FFT and plotted values.

alt text

The code I am using is:

[sampleFFTValues sFreq] = positiveFFT(sampledata, 1);
sampleFFTValues = abs(sampleFFTValues);
[v sFFTV]= max(sampleFFTValues)

Positive FFT can be found here. Basically it centers the FFT graph and cuts off the negative signals.

My question is how can I get the FFT to be more accurate without having to resort to least squares for just the frequency?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

沙沙粒小 2024-08-25 08:08:02

我认为 FFT 不适合(准)周期信号的精细分辨率频率测量 - 见下文。

每个离散 FFT 都在非整数 bin 频率上扩展(即在不完全对应于特定 FFT 的频率步长之一的任何频率上);这些“中间”频率将被涂抹/散布在最近的整数箱周围。该扩展的形状(“扩展函数”)取决于用于 FFT 的窗口函数。这种传播函数(为了简化和概括事物)要么非常窄但非常不规则(非常高的峰值/非常低的谷),要么更宽但不那么不规则。理论上,您可以对正弦波进行非常精细的频率扫描,并为每个波形计算 FFT,然后您可以通过保存所有 FFT 的输出以及导致该输出的频率来“校准”函数的形状和行为,然后通过将待测信号的 FFT 输出与之前保存的结果进行比较,找到“最接近”的结果,从而找到更准确的频率。

付出很多努力。

但如果您只需要测量单个信号的频率,请不要这样做。

相反,尝试测量波长。这可以像测量样本中过零之间的距离一样简单(也许需要多个周期才能获得更高的精度 - 哎呀,如果有那么多周期,请测量 1000 个周期),然后将采样率除以该频率即可得出频率。更简单、更快、更精确。

示例:48000 Hz 采样率、4.77 Hz 信号仅通过使用最粗略的方法测量一个周期的长度即可获得约 0.0005 Hz 的分辨率。 (如果采用 n 个周期,频率分辨率也会乘以 n。)

I don't think FFT is good for a fine-resolution frequency measurement for (quasi)periodic signals - see below.

Every discrete FFT has spreading on non-integer bin frequencies (that is on any frequency which does not exactly correspond to one of the frequency steps of the particular FFT); these "intermediate" frequencies will be smeared/spread out around the nearest integer bin. The shape of this spreading ("spreading function") depends on the windowing function used for the FFT. This spreading function - to simplify and generalize things - is either very narrow but very-very ragged (very high peaks/very low valleys), or wider but less ragged. In theory, you could do a very fine frequency sweep of sine waves and calculate FFT for each of them, and then you could "calibrate" the function's shape and behaviour by saving outputs of all FFTs together with the frequency that resulted in that output, and then by comparing the FFT output of the signal to be measured to the previously saved results and finding the "closest" one find a more exact frequency.

Lots of effort.

But don't do this if you only need to measure frequency of a single signal.

Instead try to measure wavelength. This can be as simple as measuring the distance between zero crosses (perhaps for multiple cycles to get more precision - heck, measure 1000 cycles if you have that many) in samples, and divide the sample rate by that to arrive at the frequency. Much simpler, faster and much more precise.

Example: 48000 Hz sample rate, 4.77 Hz signal results in ~0.0005 Hz resolution just by measuring the length of one cycle with the crudest approach. (If you take n cycles, the frequency resolution multiplies by n as well.)

許願樹丅啲祈禱 2024-08-25 08:08:02

正如其他人所提到的,您误解了信号的频率。让我举个例子来澄清一些事情:

Fs = 200;                        %# sampling rate
t = 0:1/Fs:1-1/Fs;               %# time vector of 1 second 
f = 6;                           %# frequency of signal
x = 0.44*sin(2*pi*f*t);          %# sine wave

N = length(x);                   %# length of signal
nfft = N;                        %# n-point DFT, by default nfft=length(x)
                                 %# (Note: it is faster if nfft is a power of 2)
X = abs(fft(x,nfft)).^2 / nfft;  %# square of the magnitude of FFT

cutOff = ceil((nfft+1)/2);       %# nyquist frequency
X = X(1:cutOff);                 %# FFT is symmetric, take first half
X(2:end -1) = 2 * X(2:end -1);   %# compensate for the energy of the other half
fr = (0:cutOff-1)*Fs/nfft;       %# frequency vector

subplot(211), plot(t, x)
title('Signal (Time Domain)')
xlabel('Time (sec)'), ylabel('Amplitude')

subplot(212), stem(fr, X)
title('Power Spectrum (Frequency Domain)')
xlabel('Frequency (Hz)'), ylabel('Power')

time_Frequency_domain

现在您可以看到 FFT 中的峰值对应于原始值6Hz 处信号的频率

[v idx] = max(X);
fr(idx)
ans = 
      6

我们甚至可以检查 Parseval 定理是否成立:

( sum(x.^2) - sum(X) )/nfft < 1e-6

选项 2

或者,我们可以使用信号处理工具箱函数:

%# estimate the power spectral density (PSD) using the periodogram
h = spectrum.periodogram;
hopts = psdopts(h);
set(hopts, 'Fs',Fs, 'NFFT',nfft, 'SpectrumType','onesided')

hpsd = psd(h, x, hopts);
figure, plot(hpsd)

Pxx = hpsd.Data;
fr = hpsd.Frequencies;
[v idx]= max(Pxx)
fr(idx)

avgpower(hpsd)

periodogram

请注意,该函数使用对数刻度: plot(fr ,10*log10(Pxx)) 而不是 plot(fr,Pxx)

As mentioned by others, you are misinterpreting the frequency of the signal. Let me give an example to clear a few things:

Fs = 200;                        %# sampling rate
t = 0:1/Fs:1-1/Fs;               %# time vector of 1 second 
f = 6;                           %# frequency of signal
x = 0.44*sin(2*pi*f*t);          %# sine wave

N = length(x);                   %# length of signal
nfft = N;                        %# n-point DFT, by default nfft=length(x)
                                 %# (Note: it is faster if nfft is a power of 2)
X = abs(fft(x,nfft)).^2 / nfft;  %# square of the magnitude of FFT

cutOff = ceil((nfft+1)/2);       %# nyquist frequency
X = X(1:cutOff);                 %# FFT is symmetric, take first half
X(2:end -1) = 2 * X(2:end -1);   %# compensate for the energy of the other half
fr = (0:cutOff-1)*Fs/nfft;       %# frequency vector

subplot(211), plot(t, x)
title('Signal (Time Domain)')
xlabel('Time (sec)'), ylabel('Amplitude')

subplot(212), stem(fr, X)
title('Power Spectrum (Frequency Domain)')
xlabel('Frequency (Hz)'), ylabel('Power')

time_frequency_domain

Now you can see that the peak in the FFT corresponds to the original frequency of the signal at 6Hz

[v idx] = max(X);
fr(idx)
ans = 
      6

We can even check that Parseval's theorem holds:

( sum(x.^2) - sum(X) )/nfft < 1e-6

Option 2

Alternatively, we can use the signal processing toolbox functions:

%# estimate the power spectral density (PSD) using the periodogram
h = spectrum.periodogram;
hopts = psdopts(h);
set(hopts, 'Fs',Fs, 'NFFT',nfft, 'SpectrumType','onesided')

hpsd = psd(h, x, hopts);
figure, plot(hpsd)

Pxx = hpsd.Data;
fr = hpsd.Frequencies;
[v idx]= max(Pxx)
fr(idx)

avgpower(hpsd)

periodogram

Note that this function uses a logarithmic scale: plot(fr,10*log10(Pxx)) instead of plot(fr,Pxx)

诠释孤独 2024-08-25 08:08:02

假设 N 是以秒为单位的时间,则频率为 1/30Hz (y=A * sin( 2* PI * f * t))

频率分辨率 = 采样率 / FFT 点数

采样率由下式确定根据奈奎斯特标准,采样率(样本/秒)必须至少是要分析的最大频率的两倍,例如 48kHz 用于分析高达 24kHz 的频率。 (对于“现实生活”数据,最好有一点缓冲区)。

因此,您可能需要增加 FFT 的大小。

Assuming N is time in seconds, your frequency is 1/30Hz (y=A * sin( 2* PI * f * t))

Frequency Resolution = Sample Rate / FFT Points

The sample rate is determined by the nyquist criterium, the sample rate (samples/second) must be at least two times the maximum frequency to be analyzed, e.g. 48kHz for analysing up to 24kHz. (For "real life" data, it's good to have a bit of a buffer).

So, you might need to increase the size of your FFT.

眼波传意 2024-08-25 08:08:02

您正在寻找的是一种频率估计方法,并且有很多方法。 FFT 是多种估计方法的组成部分。仅使用峰值幅度箱(如您的示例中所示)会给您带来最差的分辨率(但对任何其他完全周期性的正弦曲线具有最大的抗噪能力)。在低噪声情况下,您可以进行插值。对数幅度的抛物线插值是一种常见的估计器,但 FFT 结果的同步插值对于矩形窗口可能更好。补零并进行更长的 FFT 基本上相当于插值。

对于零噪声中的精确正弦曲线,忘记 FFT,只需求解 3 个未知数的方程,这可能涉及少至 3 或 4 个非混叠样本点,执行此操作的算法 此处在这里

我在 DSP 网页 上列出了一些其他频率估计方法。

What you are looking for is a frequency estimation method, and there are many. An FFT is one component of several estimation methods. Just using the peak magnitude bin, as in your example, gives you the worst resolution (but the greatest noise immunity to any other exactly periodic sinusoids). In low noise situations, you can interpolate. Parabolic interpolation of the log magnitude is one common estimator, but Sync interpolation of the FFT results may be better for a rectangular window. Zero-padding and doing a longer FFT is basically equivalent to interpolation.

For an exact sinusoid in zero noise, forget the FFT, and just solve the equation in 3 unknowns, which may involve as little as 3 or 4 non-aliased sample points, algorithms for doing this here and here.

I list a few other frequency estimation methods on my DSP web page.

晒暮凉 2024-08-25 08:08:02

如果您从函数生成,而不是使用样本,则可以生成很多点并运行大 fft,因此频率仓非常小,可以实现高精度。但这并不能解决根本问题。

If you are generating from a function, versus working with samples, you can generate a LOT of points and run a BIG fft so the frequency bins are very small for high precision. But it won't solve the basic problem.

轮廓§ 2024-08-25 08:08:02

首先,更正您的问题:(30/2PI)不是频率。信号的频率是 1/30 * 无论您使用什么采样率。
其次,你能告诉我样本数据向量的长度是多少吗?当 FFT 返回值向量时,第 i 个值将对应于 f_i = i/N,其中 N 是向量长度,i \in [0,N-1]
对于某个整数 i,您希望 i/N 恰好等于 1/30。换句话说,N 应该等于 30*i,即 N 应该是 30 的倍数。 现在,您使用的向量的长度是 30 的倍数吗? 如果不是,请尝试制作它,并且那应该可以解决问题。

First, a correction to your question: (30/2PI) is not the frequency. The frequency of your signal is 1/30 * whatever sampling rate you have used.
Second, can you tell me what was the length of sampledata vector? When FFT returns a vector of values, the ith value will correspond to f_i = i/N where N is length of vector and i \in [0,N-1]
You want i/N to exactly equal 1/30 for some integer i. In other words, N should equal 30*i, i.e., N should be a multiple of 30. Now, was the length of vector you used, a multiple of 30? If not try making it, and that should solve the problem.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文