正弦波周波数フィッティング
-
22-09-2019 - |
質問
この質問は、 以前の同様の質問。
次の方程式と調整された(ランダムなデータ)があります。0.44*sin(N*2*PI/30)
FFTを使用して、生成されたデータから周波数を取得しようとしています。ただし、周波数は最終的には周波数に近くなりますが、等しくはありません (これにより、波が意図したものより少し大きくなります)。
FFT の最大周波数は 7hz ですが、予想される周波数は (30/2PI) 4.77hz です。
FFT のグラフとプロットされた値が含まれています。
私が使用しているコードは次のとおりです。
[sampleFFTValues sFreq] = positiveFFT(sampledata, 1);
sampleFFTValues = abs(sampleFFTValues);
[v sFFTV]= max(sampleFFTValues)
正の FFT は次のように実行できます。 ここで見つかりました. 。基本的に、FFT グラフを中央に配置し、負の信号を遮断します。
私の質問は、周波数のみの最小二乗法に頼らずに、FFT をより正確にする方法を教えてください。
解決
私はFFTが(準)周期信号のための細かい分解能の周波数測定に適していないと思います - 。下記を参照してください。
すべての離散FFTは(正確に特定のFFTの周波数ステップの1つに対応しない任意の周波数である)非整数ビン周波数に広がっています。これらの「中間」周波数は、最も近い整数ビンを中心に広がっ/不鮮明されます。この拡散(「拡散関数」)の形状は、FFTのために使用される窓関数に依存します。物事を単純化し、一般化する - - この拡散関数は、いずれかの非常に狭いですが、非常に、非常に(非常に高いピーク/非常に低い谷)不揃い、またはより広い未満不揃い。理論的には、あなたはそれらのそれぞれの正弦波と計算FFTの非常に細かい周波数掃引を行うことができ、その後、あなたは、その出力が生じた周波数と一緒にすべてのFFTの出力を保存することにより、「キャリブレーション」機能の形状と行動できましたそしてその後、以前に保存した結果を被測定信号のFFT出力を比較し、「最も近い」を見つけることによって、一つは、より正確な周波数を見つける。
努力の多くます。
しかし、あなたは、単一の信号の周波数を測定する必要がある場合はこれをしない。
の代わりに波長を測定してみてください。試料中、及び周波数に到達することにより、サンプルレートを分割する - これは(ヘック、あなたはその多くを持っている場合、1000サイクルを測定おそらく複数サイクルのより高い精度を得るために)ゼロ交差の間の距離を測定するような単純なようであることができます。はるかに簡単、迅速かつはるかに正確ます。
例:48000 Hzのサンプリングレート、単に最も生々しいアプローチとの 1 のサイクルの長さを測定することによって〜0.0005 Hzの分解能で4.77 Hzの信号をもたらします。 (あなたが取る場合は、のことでN の周期、周波数分解能乗算 N の同様。)
他のヒント
、あなたは信号の周波数を誤って解釈しています。私はいくつかのことをクリアする例を挙げてみましょう。
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')
これは6Hzの
での信号の元の周波数にFFTの対応におけるピークことがわかります[v idx] = max(X);
fr(idx)
ans =
6
私たちも、パーセバルの定理には、保持していることを確認することができます
( 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)
この関数は、対数スケールを使用することを
注:代わりplot(fr,10*log10(Pxx))
plot(fr,Pxx)
Nは、秒単位の時間であると仮定すると、あなたの周波数は1 / 30Hzの(y=A * sin( 2* PI * f * t)
)です。
周波数分解能=サンプルレート/ FFTポイント
サンプルレートは、ナイキスト判断基準によって決定され、サンプルレート(サンプル/秒)は、例えば、分析されるべき少なくとも2倍の最大周波数である必要があります24kHzのまで分析するための48kHzの。 (「実生活」のデータについては、それのバッファのビットを持っていることは良い)。
だから、あなたはあなたのFFTのサイズを大きくする必要があるかもしれません。
あなたが探しているのは周波数推定方法であり、たくさんあります。FFT は、いくつかの推定方法の 1 つのコンポーネントです。例のように、ピーク振幅ビンを使用するだけでは、最悪の分解能が得られます (ただし、他の正確に周期的な正弦波に対しては最大のノイズ耐性が得られます)。ノイズが低い状況では、補間することができます。対数振幅の放物線補間は一般的な推定器の 1 つですが、FFT 結果の同期補間は長方形ウィンドウの場合により適している可能性があります。ゼロパディングとより長い FFT の実行は、基本的に補間と同等です。
ゼロノイズでの正確な正弦波の場合は、FFT を忘れて、3 つの未知数で方程式を解くだけです。これには、3 つまたは 4 つの非エイリアス サンプル ポイントが含まれる可能性があります。これを行うためのアルゴリズムが必要です。 ここ そして ここ.
他にもいくつかの周波数推定方法を私の記事にリストしています。 DSP ウェブページ.
あなたが関数から生成されている場合は、サンプルでの作業に対して、あなたは多くのポイントを生成することができ、周波数ビンは、高精度のために非常に小さいので、BIG FFTを実行します。しかし、それは基本的な問題を解決することはありません。
まず、あなたの質問に修正:(30 / 2PI)は、周波数ではありません。あなたの信号の周波数は、あなたが使用しているものは何でもサンプリングレート1/30 *です。 第二に、あなたはれるsampleDataベクトルの長さだったものを私に言うことができますか? FFTは、値のベクトルを返すとき、i番目の値のf_iに対応するI / NをN =は、ベクトルの長さであるとI \ [0、N-1]で あなたは正確に私はいくつかの整数を1/30に等しくなるように、I / Nを求めています。それを作るしようとしない場合、私は、すなわち、Nはの今、の?、30の倍数に使用したベクトルの長さだった30の倍数でなければなりません*言い換えれば、Nは30に等しくなければならない、とそれは問題を解決する必要があります。
窓関数を試してみてください!