FFT của Python sóng vuông

Phần đầu tiên của mã tạo ra 30 chu kỳ của sóng vuông trong một thời gian tăng/giảm nhất định [tính theo% của chu kỳ]. Sau đó, FFT của sóng vuông được tính. Biểu đồ đầu tiên hiển thị một chu kỳ của sóng vuông và biểu đồ thứ hai hiển thị FFT của sóng vuông. Tôi đã sử dụng một tiện ích để có thể nhanh chóng vẽ đồ thị và xem ảnh hưởng của thời gian tăng/giảm đối với phổ tần số của sóng vuông

Trọng tâm. Tìm hiểu cách vẽ biểu đồ FFT của sóng hình sin và sóng cosine bằng Python. Hiểu FFTshift. Vẽ phổ một mặt, hai mặt và chuẩn hóa bằng FFT

Giới thiệu

Nhiều văn bản có sẵn để giải thích những điều cơ bản của Biến đổi Fourier rời rạc và cách triển khai rất hiệu quả của nó – Biến đổi Fourier nhanh [FFT]. Thông thường, chúng ta phải đối mặt với nhu cầu tạo ra các tín hiệu chuẩn, đơn giản [sin, cosin, xung Gaussian, sóng vuông, xung chữ nhật cô lập, phân rã hàm mũ, tín hiệu chirp] cho mục đích mô phỏng. Tôi dự định trình bày [trong một loạt bài viết] cách tạo ra các tín hiệu cơ bản này bằng Python và cách biểu diễn chúng trong miền tần số bằng FFT. Nếu bạn thiên về lập trình Matlab, hãy truy cập tại đây

Bài viết này là một phần của cuốn sách Digital Modulations using Python, ISBN. 978-1712321638 có sẵn ở định dạng sách điện tử [PDF] và Bìa mềm [bản cứng]

Sóng hình sin

Để tạo sóng hình sin, bước đầu tiên là cố định tần số f của sóng hình sin. Ví dụ, chúng ta muốn tạo ra một

sóng hình sin có biên độ cực tiểu và cực đại lần lượt là -1V và +1V. Với tần số của sóng hình sin, bước tiếp theo là xác định tốc độ lấy mẫu.

Đối với các tín hiệu băng cơ sở, quá trình lấy mẫu diễn ra đơn giản. Theo định lý lấy mẫu Nyquist Shannon, để tái tạo trung thực tín hiệu liên tục trong miền rời rạc, người ta phải lấy mẫu tín hiệu ở tốc độ

cao hơn ít nhất hai lần tần số tối đa
contained in the signal [actually, it is twice the one-sided bandwidth occupied by a real signal. For a baseband signal bandwidth [
đến ] và tần số tối đa trong một băng tần nhất định là tương đương nhau].

Để triển khai Python, chúng ta hãy viết một hàm để tạo tín hiệu hình sin bằng thư viện Numpy của Python. Numpy là một thư viện cơ bản cho các tính toán khoa học trong Python. Để sử dụng gói numpy, nó cần được nhập. Ở đây, chúng tôi đang nhập gói numpy và đổi tên nó thành bí danh ngắn hơn np

import numpy as np

Tiếp theo, chúng tôi xác định hàm tạo tín hiệu sóng hình sin với các tham số cần thiết

def sine_wave[f,overSampRate,phase,nCyl]:
	"""
	Generate sine wave signal with the following parameters
	Parameters:
		f : frequency of sine wave in Hertz
		overSampRate : oversampling rate [integer]
		phase : desired phase shift in radians
		nCyl : number of cycles of sine wave to generate
	Returns:
		[t,g] : time base [t] and the signal g[t] as tuple
	Example:
		f=10; overSampRate=30;
		phase = 1/3*np.pi;nCyl = 5;
		[t,g] = sine_wave[f,overSampRate,phase,nCyl]
	"""
	fs = overSampRate*f # sampling frequency
	t = np.arange[0,nCyl*1/f-1/fs,1/fs] # time base
	g = np.sin[2*np.pi*f*t+phase] # replace with cos if a cosine wave is desired
	return [t,g] # return time base and signal g[t] as tuple

Chúng tôi lưu ý rằng sóng hình sin được xác định bên trong một tệp có tên signalgen. py. Chúng tôi sẽ thêm nhiều chức năng tương tự như vậy trong cùng một tệp. Mục đích là để giữ tất cả các chức năng tạo tín hiệu liên quan, trong một tệp duy nhất. Cách tiếp cận này có thể được mở rộng sang lập trình hướng đối tượng. Bây giờ chúng ta đã xác định hàm sóng hình sin trong signalgen. py, tất cả những gì chúng ta cần làm là gọi nó với các tham số cần thiết và vẽ kết quả đầu ra

"""
Simulate a sinusoidal signal with given sampling rate
"""
import numpy as np
import matplotlib.pyplot as plt # library for plotting
from signalgen import sine_wave # import the function

f = 10 #frequency = 10 Hz
overSampRate = 30 #oversammpling rate
fs = f*overSampRate #sampling frequency
phase = 1/3*np.pi #phase shift in radians
nCyl = 5 # desired number of cycles of the sine wave

[t,x] = sine_wave[f,overSampRate,phase,nCyl] #function call

plt.plot[t,x] # plot using pyplot library from matplotlib package
plt.title['Sine wave f='+str[f]+' Hz'] # plot title
plt.xlabel['Time [s]'] # x-axis label
plt.ylabel['Amplitude'] # y-axis label
plt.show[] # display the figure

Python là ngôn ngữ phần mềm dựa trên trình thông dịch xử lý mọi thứ ở dạng kỹ thuật số. Để có được sóng hình sin mượt mà, tốc độ lấy mẫu phải cao hơn nhiều so với tốc độ lấy mẫu tối thiểu được yêu cầu theo quy định, tức là ít nhất gấp đôi tần số

– theo định lý Nyquist-Shannon. Do đó, chúng ta cần lấy mẫu tín hiệu đầu vào ở tốc độ cao hơn đáng kể so với tiêu chí Nyquist quy định. Tỷ lệ lấy mẫu quá mức cao hơn cần nhiều bộ nhớ hơn để lưu trữ tín hiệu. Nên giữ hệ số lấy mẫu quá mức ở một giá trị chấp nhận được.

Hệ số lấy mẫu quá mức

được chọn trong hàm trước đó. Đây là để vẽ một sóng hình sin liên tục mượt mà. Do đó, tốc độ lấy mẫu trở thành
. Nếu muốn có sự dịch pha cho sóng hình sin, hãy chỉ định nó.

Hình 1. Một sóng hình sin tần số 10Hz với 5 chu kỳ và độ lệch pha 1/3π radian

Các đại diện khác nhau của FFT

Vì FFT chỉ là phép tính số của

DFT điểm, nên có nhiều cách để vẽ kết quả. FFT, được triển khai trong Scipy. gói fftpack, là một thuật toán được xuất bản năm 1965 bởi J. W. Cooley và
J. W. Tuckey để tính toán hiệu quả DFT.

Các hàm SciPy triển khai FFT và IFFT có thể được gọi như sau

from scipy.fftpack import fft, ifft
X = fft[x,N] #compute X[k]
x = ifft[X,N] #compute x[n]

1. Vẽ các giá trị thô của DFT

Trục x chạy từ đến

– đại diện cho giá trị mẫu. Do các giá trị DFT phức tạp nên độ lớn của DFT
được vẽ trên trục y. Từ biểu đồ này, chúng tôi không thể xác định tần số của hình sin được tạo ra.

import numpy as np
import matplotlib.pyplot as plt
from scipy.fftpack import fft

NFFT=1024 #NFFT-point DFT      
X=fft[x,NFFT] #compute DFT using FFT    

fig1, ax = plt.subplots[nrows=1, ncols=1] #create figure handle
nVals = np.arange[start = 0,stop = NFFT] # raw index for FFT plot
ax.plot[nVals,np.abs[X]]      
ax.set_title['Double Sided FFT - without FFTShift']
ax.set_xlabel['Sample points [N-point DFT]']        
ax.set_ylabel['DFT Values']
fig1.show[]

Hình 2. FFT hai mặt – không có FFTShift

2. Âm mưu FFT – vẽ các giá trị thô theo trục tần số chuẩn hóa

Trong phiên bản tiếp theo của biểu đồ, trục tần số [trục x] được chuẩn hóa thành đơn vị. Chỉ cần chia chỉ mục mẫu trên trục x cho chiều dài của FFT. Điều này chuẩn hóa trục x theo tốc độ lấy mẫu . Tuy nhiên, chúng ta không thể tìm ra tần số của hình sin từ biểu đồ.

import numpy as np
import matplotlib.pyplot as plt
from scipy.fftpack import fft

NFFT=1024 #NFFT-point DFT  
X=fft[x,NFFT] #compute DFT using FFT     

fig2, ax = plt.subplots[nrows=1, ncols=1] #create figure handle
   
nVals=np.arange[start = 0,stop = NFFT]/NFFT #Normalized DFT Sample points         
ax.plot[nVals,np.abs[X]]     
ax.set_title['Double Sided FFT - without FFTShift']        
ax.set_xlabel['Normalized Frequency']
ax.set_ylabel['DFT Values']
fig2.show[]

Hình 3. FFT hai mặt với trục x được chuẩn hóa [0 đến 1]

3. Biểu đồ FFT – vẽ các giá trị thô theo tần số chuẩn hóa [tần số dương và âm]

Như các bạn đã biết, trong miền tần số, các giá trị chiếm cả trục tần số dương và âm. Để vẽ các giá trị DFT trên một trục tần số có cả giá trị dương và âm, giá trị DFT tại chỉ số mẫu phải được căn giữa ở giữa mảng. Điều này được thực hiện bằng cách sử dụng chức năng FFTshift trong Scipy Python. Trục x chạy từ

đến
trong đó các điểm cuối là 'tần suất gấp' được chuẩn hóa đối với tốc độ lấy mẫu .

import numpy as np
import matplotlib.pyplot as plt
from scipy.fftpack import fft,fftshift

NFFT=1024 #NFFT-point DFT      
X=fftshift[fft[x,NFFT]] #compute DFT using FFT  

fig3, ax = plt.subplots[nrows=1, ncols=1] #create figure handle
    
fVals=np.arange[start = -NFFT/2,stop = NFFT/2]/NFFT #DFT Sample points        
ax.plot[fVals,np.abs[X]]
ax.set_title['Double Sided FFT - with FFTShift']
ax.set_xlabel['Normalized Frequency']
ax.set_ylabel['DFT Values'];
ax.autoscale[enable=True, axis='x', tight=True]
ax.set_xticks[np.arange[-0.5, 0.5+0.1,0.1]]
fig.show[]

hinh 4. FFT hai mặt với trục x được chuẩn hóa [-0. 5 đến 0. 5]

4. Đồ thị FFT – Tần số tuyệt đối trên trục x so với. độ lớn trên trục y

Ở đây, trục tần số chuẩn hóa chỉ được nhân với tốc độ lấy mẫu. Từ biểu đồ bên dưới, chúng ta có thể xác định rằng giá trị tuyệt đối của FFT đạt cực đại tại

. Do đó, tần số của hình sin được tạo ra là
. Các thùy bên nhỏ bên cạnh các giá trị cực đại tại và là do rò rỉ quang phổ.

import numpy as np
import matplotlib.pyplot as plt
from scipy.fftpack import fft,fftshift

NFFT=1024     
X=fftshift[fft[x,NFFT]]

fig4, ax = plt.subplots[nrows=1, ncols=1] #create figure handle

fVals=np.arange[start = -NFFT/2,stop = NFFT/2]*fs/NFFT
ax.plot[fVals,np.abs[X],'b']
ax.set_title['Double Sided FFT - with FFTShift']
ax.set_xlabel['Frequency [Hz]']         
ax.set_ylabel['|DFT Values|']
ax.set_xlim[-50,50]
ax.set_xticks[np.arange[-50, 50+10,10]]
fig4.show[]

Hình 5. FFT hai mặt – Tần số tuyệt đối trên trục x so với. độ lớn trên trục y

5. Phổ công suất – Tần số tuyệt đối trên trục x so với. nguồn trên trục y

Sau đây là đại diện quan trọng nhất của FFT. Nó vẽ đồ thị công suất của từng thành phần tần số trên trục y và tần số trên trục x. Công suất có thể được vẽ theo tỷ lệ tuyến tính hoặc theo tỷ lệ log. Công suất của từng thành phần tần số được tính như

Ở đâu

là biểu diễn miền tần số của tín hiệu
. Trong Python, sức mạnh phải được tính toán với các thuật ngữ chia tỷ lệ phù hợp.

Hình 6. Mật độ phổ công suất sử dụng FFT

Vẽ biểu đồ PSD với trục y trên thang log, tạo ra loại biểu đồ PSD gặp nhiều nhất trong xử lý tín hiệu

FFT của sóng vuông là gì?

Trong miền tần số, mức trung bình tổng thể của tín hiệu là nội dung của nó ở DC hoặc 0Hz -- vì vậy đó là lý do tại sao có cực đại ở 0Hz. FFT của sóng vuông có tâm là 0V có năng lượng ở mọi sóng hài lẻ, bắt đầu từ 1 .

Làm cách nào để vẽ phổ FFT trong Python?

Đặt kích thước hình và điều chỉnh phần đệm giữa và xung quanh các ô con
Khởi tạo 2 biến N và m để tính nu
Tạo tín hiệu [sóng hình sin] bằng cách sử dụng numpy. .
Trả về tần số mẫu Biến đổi Fourier rời rạc
Vẽ các điểm dữ liệu biến đổi tần số và phạm vi

Làm cách nào để triển khai FFT trong Python?

VÍ DỤ. Sử dụng hàm fft và ifft từ scipy để tính phổ biên độ FFT và FFT nghịch đảo để thu được tín hiệu gốc. Vẽ cả hai kết quả. .
DFT đã triển khai. ~120 mili giây
FFT đã triển khai. ~16 mili giây
FFT gọn gàng. ~40 µs
scipy FFT. ~12 µs

Đầu ra của FFT trong Python là gì?

Ghi chú. Bên cạnh đó, bạn có thể nhận thấy rằng fft[] trả về tần số tối đa chỉ hơn 20 nghìn Hertz, chính xác là 22050Hz . Giá trị này chính xác bằng một nửa tốc độ lấy mẫu của chúng tôi và được gọi là tần số Nyquist.

Chủ Đề