この記事では、Matplotlibで、伝達関数をグラフ化する方法を紹介しています。
Pythonで書くと、ほんとシンプルなコードでわかりやすいですね。
以前は、グラフ表示にExcelを使っていました。関数が複雑になりすぎて、「この関数、何してるんだっけ?」って内容を思い出すのに苦労しました。
今は、Excel → Python へ完全移行しました。
題材の伝達関数は、USB信号で使われている「CTLE」です。
なじみがないと思いますが、CTLEは、電子回路ででてくる用語。信号波形をキレイに補正するための技術(イコライザー)の名称です。
CTLE : Continuous Time Linear Equalizer(連続時間線形イコライザ)
Matplotlibで伝達関数のコードを書く上で、CTLEの知識は、特に不要です。題材として使っているだけです。
では、説明していきます。
もくじ
題材に使う伝達関数:USB3.2 CTLEの概要
USB3.2 CTLEの概要
CTLE(Continuous-Time Linear Equalizer)は、高速通信システムにおいて信号波形の歪みを補正するリニアイコライザです。
伝送路による損失を相殺し、データ転送の品質を向上させる役割を果たします。USB3.2などの通信規格で使われている技術です。
CTLEの伝達関数の式
以下が、USB3.2 Gen1 CTLEの伝達関数H(s)です。
CTLEの伝達関数の特徴を、ざっくり言うと、以下のとおり。
CTLE 伝達関数の特徴
- 複素数 s の関数。(時間 t の関数ではなく)
- 分母・・・2個の極(sの2次関数)を持つ。 分子・・・1個の零(sの1次関数)を持つ。
「伝達関数」そのものについて知りたい方は、教科書を読んでみてください。
ではこれから、上記の伝達関数を、Pythonのコードに落とし込んで、matplotlibでグラフ化していきます。
Matplotlibで描いた伝達関数のグラフ(完成形)
下図が、CTLE伝達関数の周波数特性グラフです。
(伝送レートが 5Gbpsの「USB3.2 Gen1 5Gbps Long Channel CTLE」の周波数特性)
ヨコ軸が周波数[Hz]で、タテ軸がゲイン[dB]です。
入力信号の周波数によって、出力信号がどう変わるか? を表したが、周波数特性のグラフです。略して、「f特」(読み:えふとく)とも言います。
上記のCTLEのグラフを見ると、以下の特徴が読み取れます。
CTLE:周波数特性の特徴
- 伝送レート2.5GHz(5Gbps)付近の周波数成分を、3dB増幅するフィルタ特性がある。
- 低域の周波数成分を、3.5dB減衰するフィルタ特性がある。
伝達関数をグラフ化する準備
動作環境
以下、わたしのPython環境です。
- Windows10 (64bit)
- Python 3.10.9
必要なライブラリ
必要なライブラリは、以下の3つです。
- numpy
- math
- matplotlib
インストールがまだの場合、ターミナルを開いて、以下のようにpipコマンドを実行すればインストールできます。
pip install numpy
pip install math
pip install matplotlib
再びターミナルで、
conda list
と入力すると、パッケージ一覧が表示されます。↓↓ 以下が表示されていればOKです。
numpy
math
matplotlib
Pythonのサンプルコード
bode関数を使う書き方とかありますが、伝達関数H(s)の式を、defで関数を作りました。
[USB3r2_Gen1_5Gbps_LongChannel_CTLE.py]
import numpy
import math
from matplotlib import pyplot as plt
def H1 (s):
Adc = 0.667 # DC gain
wz = 2 * math.pi * (650*10**6) # Zero frequency
wp1 = 2 * math.pi * (1.95*10**9) # First pole frequency
wp2 = 2 * math.pi * (5*10**9) # Second pole frequency
h = ((Adc*wp1*wp2)/wz*(s+wz))/((s+wp1)*(s+wp2))
return h
freq = numpy.logspace(7, 11) # 周波数の範囲 10**7 to 10**11
gain_s = list(map(H1, 1j*2*math.pi*freq)) # y軸のデータをリスト化
gain_abs = numpy.abs(gain_s) # 絶対値へ変換
gain_dB = 20*numpy.log10(gain_abs) # dBへ変換
fig, ax = plt.subplots(figsize=(6,5)) # グラフ1個の場合
plt.title('USB3.2 Gen1 5Gbps Long Channel CTLE') # タイトル
plt.xlabel('frequency [Hz]') # x軸のラベル
plt.ylabel('Magnitude [dB]') # y軸のラベル
plt.plot(freq, gain_dB)
plt.xscale('log') # x軸 対数, y軸 リニア
plt.grid(which="both", ls=':')
# Y軸の目盛りを設定
pos = [-25, -20, -15, -10, -5, 0, 5]
ticks = ['-25', '-20', '-15', '-10', '-5', '0', '5']
ax.set_yticks(pos)
ax.set_yticklabels(ticks)
plt.show()
サンプルコードの解説
- 5行目:CTLEの伝達関数の定義。Pythonでの関数名は、H1(s) としました。
- 6行目:Adc の値は、0.667 固定値で定義。
- 13行目:X軸のデータは、周波数10MHz~100GHzまでをLogで定義。
- 15行目:Y軸のデータは、関数H1(s)の s を j2πf へ置き換えて、map関数で生成。
- 30行目:Y軸の目盛りを設定。デフォルトでplotすると、目盛りの間隔が自動調整されて見づらいので、目盛りの位置とその目盛りの文字列を設定しています。
参考文献
Universal Serial Bus 3.2 Specification >>USB-IF公式サイト
まとめ
この記事では、matplotlib(Python)で、USB CTLE(イコライザ)の伝達関数をグラフ化する方法を紹介しました。
Excelで関数を組んでグラフ化する方法もありますが、書き方が複雑になるので、Pythonで書く方がシンプルでわかりやすいです。
以上、参考になれば幸いです。