1. 程式人生 > >FFT-Matlab初步實現

FFT-Matlab初步實現

 

/****************************************************/

/****************************************************/

/****************************************************/

下面是具體說明

1、FFT:頻譜關於中間位置對稱,只需要觀察  0:1:N/2(這N/2+1個點)(時域採集N個點,頻域只需要觀察N/2+1個點)

2、MATLAB中FFT的頻譜,應該看幅值

3、X軸頻率點的設定:取樣頻率為Fs,頻譜圖顯示的最高頻率為Fs/2(取樣定理)

  :X軸頻率點:(0:1:N/2)*Fs/N

4、複數幅值修正

 5、

/****************************************************/

/****************************************************/

/****************************************************/

栗子及實踐部分

一、訊號

1

2

3

4

5

6

7

8

9

10

11

12

%% FFT

clear;clc;close all

Fs=1000;    % 採集頻率

T=1/Fs;     % 採集時間間隔

N=2000;     % 採集訊號的長度--取樣點數

f1=33;      % 第一個餘弦訊號的頻率

f2=200;     % 第二個餘弦訊號的頻率

t=(0:1:N-1)*T;  % 定義整個採集時間點

t=t';           % 轉置成列向量

y=1.2+2.7*cos(2*pi*f1*t+pi/4)+5*cos(2*pi*f2*t+pi/6);  % 時域訊號

二、繪製時域訊號

1

2

3

4

5

6

%% 繪製時域訊號

figure

plot(t,y)

xlabel('時間')

ylabel('訊號值')

title('時域訊號')

  

三、FFT變換、並繪製-幅值、實部、虛部

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

%% fft變換

Y=fft(y);    % Y為fft變換的結果,為複數向量

A=abs(Y);    % 複數的幅值(模)

RE=real(Y);  % 複數的實部

IM=imag(Y);  % 複數的虛部

%% 繪製fft變換結果(幅值,實部,虛部)

figure

subplot(3,1,1)

plot(0:1:N-1,A)

xlabel('序號 0 ~ N-1')

ylabel('幅值')

grid on

%% 頻域只讀取0:1:N/2

subplot(3,1,2)

plot(0:1:N-1,RE)

xlabel('序號 0 ~ N-1')

ylabel('實部')

grid on

subplot(3,1,3)

plot(0:1:N-1,IM)

xlabel('序號 0 ~ N-1')

ylabel('虛部')

grid on

  

可以看出頻域中的點關於(N/2)對稱,所以只需要觀察(0:1:N/2)

四、更改相位

幅值不受影響,但實部或虛部的值,會出現0的情況==>看MATLAB中FFT的頻譜,應該看幅值

 繪製半譜圖(幅值的)後--我們發現-幅值-相位-頻率---均和時域對應不上。

==>進行幅值-修正

五、進行幅值-修正--並繪製圖形

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

%% fft變換

Y=fft(y);          % Y為fft變換結果,複數向量

Y=Y(1:N/2+1);      % 只看變換結果的一半即可

A=abs(Y);          % 複數的幅值(模)

f=(0:1:N/2)*Fs/N;  % 生成頻率範圍

f=f';              % 轉置成列向量

%% 幅值修正

A_adj=zeros(N/2+1,1);

A_adj(1)=A(1)/N;        % 頻率為0的位置

A_adj(end)=A(end)/N;    % 頻率為Fs/2的位置

A_adj(2:end-1)=2*A(2:end-1)/N;

%% 繪製頻率幅值圖

figure

subplot(2,1,1)

plot(f,A_adj)

xlabel('頻率 (Hz)')

ylabel('幅值 (修正後)')

title('FFT變換幅值圖')

grid on

%% 繪製頻譜相點陣圖

subplot(2,1,2)

phase_angle=angle(Y);   % angle函式的返回結果為弧度

phase_angle=rad2deg(phase_angle);

plot(f,phase_angle)

xlabel('頻率 (Hz)')

ylabel('相位角 (degree)')

title('FFT變換相點陣圖')

grid on

放大後可以看到,此時,幅值-頻率都和時域一致

此時FFT的相點陣圖是雜亂無章的--不用擔心,沒有頻率處的相位是無意義的--我們只需要放大看各個(實際存在的)頻率點的相位即可

可以看到--f1=33Hz處為45度,即pi/4--是正確的

六、實際操作:請分析一個未知的採集訊號 (example.mat),並確定該採集訊號的頻率成分。其中, 訊號的採集頻率 Fs = 2500 Hz

程式碼

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

clear;clc;close all

load('example')

Fs=2500;      % 採集頻率

T=1/Fs;       % 採集時間間隔

N=length(y);  % 採集訊號的長度

t=(0:1:N-1)*T;   % 定義整個採集時間點

t=t';            % 轉置成列向量

% 繪製時域訊號

figure

plot(t,y)

xlabel('時間')

ylabel('訊號值')

title('時域訊號')

% fft變換

Y=fft(y);          % Y為fft變換結果,複數向量

Y=Y(1:N/2+1);      % 只看變換結果的一半即可

A=abs(Y);          % 複數的幅值(模)

f=(0:1:N/2)*Fs/N;  % 生成頻率範圍

f=f';              % 轉置成列向量

% 幅值修正

A_adj=zeros(N/2+1,1);

A_adj(1)=A(1)/N;       % 頻率為0的位置

A_adj(end)=A(end)/N;   % 頻率為Fs/2的位置

A_adj(2:end-1)=2*A(2:end-1)/N;

% 繪製頻率幅值圖

figure

subplot(2,1,1)

plot(f,A_adj)

xlabel('頻率 (Hz)')

ylabel('幅值 (修正後)')

title('FFT變換幅值圖')

grid on

% 繪製頻譜相點陣圖

subplot(2,1,2)

phase_angle=angle(Y);    % angle函式的返回結果為弧度

phase_angle=rad2deg(phase_angle);

plot(f,phase_angle)

xlabel('頻率 (Hz)')

ylabel('相位角 (degree)')

title('FFT變換相點陣圖')

grid on