FFT實用解析

2021-08-13 22:07:34 字數 4433 閱讀 4746

fft是離散傅利葉變換的快速演算法,可以將乙個訊號變換

到頻域。有些訊號在時域上是很難看出什麼特徵的,但是如

果變換到頻域之後,就很容易看出特徵了。這就是很多訊號

分析採用fft變換的原因。另外,fft可以將乙個訊號的頻譜

提取出來,這在頻譜分析方面也是經常用的。

雖然很多人都知道fft是什麼,可以用來做什麼,怎麼去

做,但是卻不知道fft之後的結果是什意思、如何決定要使用

多少點來做fft。

現在圈圈就根據實際經驗來說說fft結果的具體物理意義。

乙個模擬訊號,經過adc取樣之後,就變成了數碼訊號。取樣

定理告訴我們,取樣頻率要大於訊號頻率的兩倍,這些我就

不在此羅嗦了。

取樣得到的數碼訊號,就可以做fft變換了。n個取樣點,

經過fft之後,就可以得到n個點的fft結果。為了方便進行fft

運算,通常n取2的整數次方。

假設取樣頻率為fs,訊號頻率f,取樣點數為n。那麼fft

之後結果就是乙個為n點的複數。每乙個點就對應著乙個頻率

點。這個點的模值,就是該頻率值下的幅度特性。具體跟原始

訊號的幅度有什麼關係呢?假設原始訊號的峰值為a,那麼fft

的結果的每個點(除了第乙個點直流分量之外)的模值就是a

的n/2倍。而第乙個點就是直流分量,它的模值就是直流分量

的n倍。而每個點的相位呢,就是在該頻率下的訊號的相位。

第乙個點表示直流分量(即0hz),而最後乙個點n的再下乙個

點(實際上這個點是不存在的,這裡是假設的第n+1個點,也

可以看做是將第乙個點分做兩半分,另一半移到最後)則表示

取樣頻率fs,這中間被n-1個點平均分成n等份,每個點的頻率

依次增加。例如某點n所表示的頻率為:fn=(n-1)*fs/n。

由上面的公式可以看出,fn所能分辨到頻率為為fs/n,如果

取樣頻率fs為1024hz,取樣點數為1024點,則可以分辨到1hz。

1024hz的取樣率取樣1024點,剛好是1秒,也就是說,取樣1秒

時間的訊號並做fft,則結果可以分析到1hz,如果取樣2秒時

間的訊號並做fft,則結果可以分析到0.5hz。如果要提高頻率

分辨力,則必須增加取樣點數,也即取樣時間。頻率解析度和

取樣時間是倒數關係。

假設fft之後某點n用複數a+bi表示,那麼這個複數的模就是

an=根號a*a+b*b,相位就是pn=atan2(b,a)。根據以上的結果,

就可以計算出n點(n≠1,且n<=n/2)對應的訊號的表示式為:

an/(n/2)*cos(2*pi*fn*t+pn),即2*an/n*cos(2*pi*fn*t+pn)。

對於n=1點的訊號,是直流分量,幅度即為a1/n。

由於fft結果的對稱性,通常我們只使用前半部分的結果,

即小於取樣頻率一半的結果。

好了,說了半天,看著公式也暈,下面圈圈以乙個實際的

訊號來做說明。

假設我們有乙個訊號,它含有2v的直流分量,頻率為50hz、

相位為-30度、幅度為3v的交流訊號,以及乙個頻率為75hz、

相位為90度、幅度為1.5v的交流訊號。用數學表示式就是如下:

s=2+3*cos(2*pi*50*t-pi*30/180)+1.5*cos(2*pi*75*t+pi*90/180)

式中cos引數為弧度,所以-30度和90度要分別換算成弧度。
我們以256hz的取樣率對這個訊號進行取樣,總共取樣256點。

按照我們上面的分析,fn=(n-1)*fs/n,我們可以知道,每兩個

點之間的間距就是1hz,第n個點的頻率就是n-1。我們的訊號

有3個頻率:0hz、50hz、75hz,應該分別在第1個點、第51個點、

第76個點上出現峰值,其它各點應該接近0。

我們可以看出,在第1點、第51點、和第76點附近有

比較大的值。我們分別將這三個點附近的資料拿上來細看:

1點: 512+0i

2點: -2.6195e-14 - 1.4162e-13i

3點: -2.8586e-14 - 1.1898e-13i

50點:-6.2076e-13 - 2.1713e-12i

51點:332.55 - 192i

52點:-1.6707e-12 - 1.5241e-12i

75點:-2.2199e-13 -1.0076e-12i

76點:3.4315e-12 + 192i

77點:-3.0263e-14 +7.5609e-13i

很明顯,1點、51點、76點的值都比較大,它附近的點值
都很小,可以認為是0,即在那些頻率點上的訊號幅度為0。

接著,我們來計算各點的幅度值。分別計算這三個點的模值,

結果如下:

1點: 512

51點:384

76點:192

按照公式,可以計算出直流分量為:512/n=512/256=2;

50hz訊號的幅度為:384/(n/2)=384/(256/2)=3;75hz訊號的

幅度為192/(n/2)=192/(256/2)=1.5。可見,從頻譜分析出來

的幅度是正確的。

然後再來計算相位資訊。直流訊號沒有相位可言,不用管

它。先計算50hz訊號的相位,atan2(-192, 332.55)=-0.5236,

結果是弧度,換算為角度就是180*(-0.5236)/pi=-30.0001。再

計算75hz訊號的相位,atan2(192, 3.4315e-12)=1.5708弧度,

換算成角度就是180*1.5708/pi=90.0002。可見,相位也是對的。

根據fft結果以及上面的分析計算,我們就可以寫出訊號的表達

式了,它就是我們開始提供的訊號。

總結:假設取樣頻率為fs,取樣點數為n,做fft之後,某

一點n(n從1開始)表示的頻率為:fn=(n-1)*fs/n;該點的模值

除以n/2就是對應該頻率下的訊號的幅度(對於直流訊號是除以

n);該點的相位即是對應該頻率下的訊號的相位。相位的計算

可用函式atan2(b,a)計算。atan2(b,a)是求座標為(a,b)點的角

度值,範圍從-pi到pi。要精確到xhz,則需要取樣長度為1/x秒

的訊號,並做fft。要提高頻率解析度,就需要增加取樣點數,

這在一些實際的應用中是不現實的,需要在較短的時間內完成

分析。解決這個問題的方法有頻率細分法,比較簡單的方法是

取樣比較短時間的訊號,然後在後面補充一定數量的0,使其長度

達到需要的點數,再做fft,這在一定程度上能夠提高頻率分辨力。

具體的頻率細分法可參考相關文獻。

[附錄:本測試資料使用的matlab程式]

close all; %先關閉所有

adc=2; %直流分量幅度

a1=3; %頻率f1訊號的幅度

a2=1.5; %頻率f2訊號的幅度

f1=50; %訊號1頻率(hz)

f2=75; %訊號2頻率(hz)

fs=256; %取樣頻率(hz)

p1=-30; %訊號1相位(度)

p2=90; %訊號相位(度)

n=256; %取樣點數

t=[0:1/fs:n/fs]; %取樣時刻

%訊號

s=adc+a1*cos(2*pi*f1*t+pi*p1/180)+a2*cos(2*pi*f2*t+pi*p2/180);

%顯示原始訊號

plot(s);

title(『原始訊號』);

figure;

y = fft(s,n); %做fft變換

ayy = (abs(y)); %取模

plot(ayy(1:n)); %顯示原始的fft模值結果

title(『fft 模值』);

figure;

ayy=ayy/(n/2); %換算成實際的幅度

ayy(1)=ayy(1)/2;

f=([1:n]-1)*fs/n; %換算成實際的頻率值

plot(f(1:n/2),ayy(1:n/2)); %顯示換算後的fft模值結果

title(『幅度-頻率曲線圖』);

figure;

pyy=[1:n/2];

for i=」1:n/2」

pyy(i)=phase(y(i)); %計算相位

pyy(i)=pyy(i)*180/pi; %換算為角度

end;

plot(f(1:n/2),pyy(1:n/2)); %顯示相位圖

title(『相位-頻率曲線圖』);

看完這個你就明白諧波分析了

**:

php sql 語法解析函式,非常實用

if function exists parse sql if sql 跳過以 或者 開頭的單行注釋 if preg match line 跳過以 包裹起來的單行注釋 if preg match line 多行注釋開始 if substr line,0,2 多行注釋結束 if substr line...

Linux實用指令之echo解析

例項 1.輸出字串 www.smallk.cn 2.n 引數的用法 3.e 引數的用法 linux 的原版解釋 man echo 名字 echo 顯示一行文字 語法 echo 短引數 字串 echo 長引數 描述 標準輸出乙個字串。引數 n 不輸出尾隨換行符 e 啟用反斜槓作為轉義符 e 停用反斜槓...

FFT和Matlab中操作FFT

fft 離散傅氏變換的快速演算法 fft fast fourier transformation 是離散傅氏變換 dft 的快速演算法。即快速傅氏變換。輸入n 1個數,輸出n 1個數 意義不同 輸入是時域,輸出為頻域 輸出是 每個取樣點對應的振幅或者能量值 輸出值的第乙個對應直流分量的振幅,第二個值...