深入淺出通信原理Python代碼版
深入淺出通信原理是陳愛軍的心血之作,於通信人家園連載,此處僅作python代碼筆記訓練所用
陳老師的連載從多項式乘法講起,一步一步引出卷積、傅立葉級數展開、旋轉向量、三維頻譜、IQ調制、數字調制等一系列通信原理知識
連載1:從多項式乘法說起
import sympy
x = sympy.Symbol('x')
sympy.expand((x+1)*(x*x+2*x+5))
這種計算方法總結起來就是:
反褶:一般多項式都是按x的降冪排列,這里將其中一個多項式的各項按x的升冪排列。
平移:將按x的升冪排列的多項式每次向右平移一個項。
相乘:垂直對齊的項分別相乘。
求和:相乘的各結果相加。反褶、平移、相乘、求和-這就是通信原理中最常用的一個概念“卷積”的計算過程。
連載2:卷積的表達式
將多項式轉換成矩陣形式
連載3: Python計算卷積
import numpy as np
np.convolve([1,1],[1,2,5]) #上例,result:[1, 3, 7, 5]
# 楊輝三角,輸入行數,輸出對應行的值
def pascal_triangle(n):
if n == 0:
return 1
elif n == 1:
return [1,1]
else:
return np.convolve([1,1],pascal_triangle(n-1))
# test code
for i in range(0,7):
print(pascal_triangle(i))
# 楊輝三角,迭代器形式
def triangles():
nlist=[1]
while True:
yield nlist
nlist.append(0)
nlist = [nlist[i] + nlist[i-1] for i in range(len(nlist))]
# test code
tr = triangles()
for i in range(0,7):
print(next(tr))
連載4:將信號表示成多項式的形式
連載5:歐拉公式證明
import sympy
x = sympy.Symbol('x')
sympy.series(sympy.exp(sympy.I*x), x, 0, 10) #series perform Taylor expansion
sympy.expand(series(sin(x), x, 0, 10))
sympy.expand(series(cos(x), x, 0, 10))
利用泰勒展開,從輸出結果易看出歐拉公式成立
理解復數
引自[連載23,利用歐拉公式理解復數)
連載6:利用卷積計算兩個信號的乘積
若兩個信號均表示成多項式形式,則可通過卷積計算信號相乘結果。
連載7: 信號進行傅里葉級數展開
周期T的函數f(t)展開成傅里葉級數(直流分量、余弦分量,正選分量多項式之和):
展開成復指數信號之和:
Ref: 書寫多行大括號
ck是復傅里葉系數
以角頻率w為橫軸,傅里葉系數ck為縱軸,畫出頻譜圖
# Further improvement:https://blog.csdn.net/u012915522/article/details/91506120
import matplotlib.pyplot as plt
plt.subplot(3,1,1)
plt.stem([0,1,2,3],[6,5,1,0],use_line_collection=True)
plt.yticks([0,1,5,6])
# plt.axis('off')
plt.xticks([0,1,2,3],('0','w','2w','3w'))
plt.subplot(3,1,2)
plt.stem([0,1,2,3],[2,3,0,0],use_line_collection=True)
plt.xticks([0,1,2,3],('0','w','2w','3w'))
plt.yticks([0,1,2,3])
plt.subplot(3,1,3)
plt.stem([0,1,2,3],[12,28,17,3],use_line_collection=True)
plt.xticks([0,1,2,3],('0',r'$\omega$w','2w','3w'))
plt.yticks([3,17,12,28])
# plt.axis('off')
plt.tight_layout()
plt.show()
連載8:時域信號相乘相當於頻域卷積
由連載6顯然如此
時域 | FFT | 頻域 |
---|---|---|
f(t) | \(f(t)=\sum_{n=-\infty}^{+\infty}f[n]^{jkw_0t}\) | f[n] |
g(t) | $$g(t)=\sum_{n=-\infty}^{+\infty}g[n]^{jkw_0t}$$ | g[n] |
y(t)=f(t)g(t) | \(y(t)=\sum_{n=-\infty}^{+\infty}y[n]^{jkw_0t}\) | y[n]=f[n]*g[n] |
連載9:用余弦信號合成方波信號
plt.suptitle('逐步合成方波', fontproperties='stsong')
plt.subplot(3,1,1)
x = np.arange(0,20,0.1)
y1 = 0.5+0.637*np.cos(x)
plt.plot(x,y1)
plt.title(r'$y_1(x)=0.5+0.637*cos(x)$',fontsize=10)
plt.subplot(3,1,2)
y2 = 0.5+0.637*np.cos(x)-0.212*np.cos(3*x)
plt.plot(x,y2)
plt.title(r'$y_2(x)=0.5+0.637*cos(x)-0.212cos(3x)$',fontsize=10)
plt.subplot(3,1,3)
y3 = 0.5+0.637*np.cos(x)-0.212*np.cos(3*x)+0.127*np.cos(5*x)
plt.plot(x,y3)
plt.title(r'$y_3(x)=0.5+0.637*cos(x))-0.212cos(3x)+0.127cos(5x)$',fontsize=10)
plt.tight_layout()
plt.show()
連載12:正弦信號及余弦信號頻譜圖
繪制正弦及余弦信號的頻譜圖
# sin(w0t) & cos(w0t) spectrum
fig = plt.figure('Sine & Cosine Wave', (10,8))
ax = axisartist.Subplot(fig, 2,2,1)
# plt.subplot(4,1,1)
fig.add_axes(ax)
# ax.axis[:].set_visible(False) # 隱藏默認坐標軸
# ax.axis["x"] = ax.new_floating_axis(0, 0)
# ax.axis["y"] = ax.new_floating_axis(1, 0)# 新建坐標軸X-Y
# ax.axis["x"].set_axis_direction('top')
# ax.axis["y"].set_axis_direction('left')# 設置刻度標識方向
# ax.axis["x"].set_axisline_style("->", size = 20.0)
ax.axis["bottom"].set_axisline_style("-|>", size = 1.5)
ax.axis["left"].set_axisline_style("->", size = 1.5)
ax.axis["top"].set_visible(False)
ax.axis["right"].set_visible(False)
# ax.axis["y"].set_axisline_style("->", size = 20.0)#加上坐標軸箭頭
ax.stem([-1,1],[0.5,0.5],use_line_collection=True)
ax.set_title('y = cos($\omega_0t$),$c_{-1}=1/2,c_1=1/2$',fontsize = 15, pad = 20)
ax.set_xticks([-1,0,1])
ax.set_xticklabels([r'$-\omega$','0',r'$\omega$'])
ax.set_xlabel('Angular frequency')
ax.set_yticks([0.5])
ax.set_ylabel('magnitude')
ax2 = axisartist.Subplot(fig, 2,2,3)
fig.add_axes(ax2)
ax2.axis["left"].set_axisline_style("->", size = 1.5)
ax2.axis["top"].set_visible(False)
ax2.axis["right"].set_visible(False)
ax2.stem([-1,1],[0,0],use_line_collection=True)
ax2.set_xticks([-1,0,1])
ax2.set_xticklabels([r'$-\omega$','0',r'$\omega$'])
ax2.set_xlabel('Angular frequency')
ax2.set_yticks([0])
ax2.set_ylabel('phase')
fig.subplots_adjust(hspace=10)
ax3 = axisartist.Subplot(fig, 2,2,2)
fig.add_axes(ax3)
ax3.axis["left"].set_axisline_style("->", size = 1.5)
ax3.axis["top"].set_visible(False)
ax3.axis["right"].set_visible(False)
ax3.stem([-1,1],[0.5,0.5],use_line_collection=True)
ax3.set_title('y = sin($\omega_0t$),$ c_{-1}=j/2,c_1=-j/2 $,fontsize = 15, pad = 20)
ax3.set_xticks([-1,0,1])
ax3.set_xticklabels([r'$-\omega$','0',r'$\omega$'])
ax3.set_xlabel('Angular frequency')
ax3.set_yticks([0.5])
ax3.set_ylabel('magnitude')
ax4 = axisartist.Subplot(fig, 2,2,4)
fig.add_axes(ax4)
ax4.axis["left"].set_axisline_style("->", size = 1.5)
ax4.axis["top"].set_visible(False)
ax4.axis["right"].set_visible(False)
ax4.stem([-1,1],[1.5708,-1.5708],use_line_collection=True)
ax4.set_xticks([-1,0,1])
ax4.set_xticklabels([r'$-\omega$','0',r'$\omega$'])
ax4.set_xlabel('Angular frequency')
ax4.set_yticks([np.pi/2,0,-np.pi/2])
ax4.set_yticklabels([r'$\pi/2$','0',r'$-\pi/$'])
ax4.set_ylabel('phase')
plt.tight_layout()
plt.show()
由該圖可看出,實信號的頻譜是共軛對稱的,及\(c_k&c_{-k}\)是互為共軛:模相等,相位相反。
而且出現負頻率
余正弦信號的三維頻譜圖
這個太難,以我的淺薄知識,用Python繪制不出來,故從陳老師處直接盜圖,但是可以從正弦信號三維頻譜看出即使復傅里葉系數是虛數,其原始信號仍有可能是實數
通過復傅立葉級數展開將實信號分解為了一系列的旋轉向量之和(由此引出了復數,使得實信號的表達式中出現了復數),但由於逆時針和順時針旋轉的向量成對出現,而且成對出現的旋轉向量的初始相位關於實軸對稱,旋轉的角速度相同,旋轉方向相反,所以這些旋轉向量合成的結果最終還是一個實信號(只在實軸上有分量,虛軸上的分量相互抵消掉了)。
李薩育圖形
使用互相成諧波頻率關系的兩個信號分別作為X和Y偏轉信號送入示波器時,這兩個信號分別在X軸、Y軸方向同時作用於電子束而描繪出穩定的圖形,這些穩定的圖形就叫“李薩育圖形”
Lissajous curve, 用來展示兩個相互垂直的簡諧振動的合成。
公式:
def lissajous(q,fignum):
theta = np.arange(0, 2*np.pi, 0.01)
x = np.cos(theta)
y = np.sin(q*theta)
plt.subplot(1,fignum,q)
plt.axis('off')
plt.plot(x,y)
return
plt.figure(figsize=(10,2))
fignum=5
for i in range(fignum):
lissajous(i+1,fignum)
實信號和復信號的波形對比
直接采用陳老師的三維頻譜圖:
在下面兩張圖中:x軸(實軸)、y軸(虛軸)所在的平面是復平面,t軸(時間軸)垂直於復平面。
上圖為實信號f(t)=cos(2πt)的波形圖。
下圖為復信號f(t)=cos(2πt)+jsin(2πt)的波形圖。
對比這兩張圖,很容易得出:實信號在復平面上投影時只有實軸方向有分量,而復信號在復平面上投影時實軸和虛軸方向都有分量。
最后說一句,由於博客部分圖片顯示不出,特貼上個人備份GitHub地址