« 高周波・RFニュース 2024年7月30日 Gartner/QorvoのEVのバッテリマネジメントシステム(BMS)解説、Qualcommのスマートグラスインタビュー、6GとISAC解説、Tachyon NetworksとPerasoの60GHz FWA、電気設計のためのAIツール、Wi-Fi 7とプライベート5Gは共存するか?など | トップページ | 高周波・RFニュース 2024年7月31日 Qorvo、Skyworksの決算発表、QualcommがSnapdragon 4s Gen 2を発表、u-bloxの測位ソリューションがNVIDIAに採用、MarvellがStructera CXLを発表、IEEE IMS2024の論文集が公開、TDKのAI新会社 »

2024年7月30日 (火)

Pythonの高周波ライブラリscikit-rfを使ってマイクロ波LCフィルタ合成をする(3) プロトタイプLPFから BPF(バンドパスフィルタ)を設計・合成してチェビシェフとバタワースを比べる。

以前にLPF(ローパスフィルタ)の設計をやってみた。

Pythonの高周波ライブラリscikit-rfを使ってマイクロ波LCフィルタ合成をする(1)プロトタイプLPF(チェビシェフ、バタワース)の素子の値を計算する関数をMatthai, Young & JonesのMicrowave Filters, Impedance-matching networks, and coupling structureを基に作る。 

 Pythonの高周波ライブラリscikit-rfを使ってマイクロ波LCフィルタ合成をする(2) Circuit機能を使ってL,CをつなげていってLPF(ローパスフィルタ)を合成してSパラメータを得る。チェビシェフとバタワースを比較したり素子の繋がりを図示したり。

今回はBPF(バンドパスフィルタ)。LPFからシャントCをLC並列に、シリーズLをLC直列に変換することでバンドパスフィルタが作れる。

どういう変換をするかはこれらを参照:

Microwave Filters, Impedance-Matching Networks, and Coupling Structures

Microwave Filters for Communication Systems: Fundamentals, Design, and Applications

LPFと違うのは帯域幅も指定する必要があること。LCの値を計算する関数は以下の通り。


def LC_BPF(n, f0, df, z0 = 50.0, first_element = "series", type = "Chebyshev", ripple = 0.1):
    """
    信号源、負荷の特性インピーダンスZo、中心周波数f0, 帯域幅dfのBPFのL,C素子の値をndarrayで返す関数
    n : フィルタの次数(チェビシェフの場合、偶数だと負荷のインピーダンスが50Ωになりません)
    f0 : 中心周波数[GHz]
    df : 帯域幅[GHz]
    z0 : 信号源の特性インピーダンス
    first_element : 最初にシリーズのLCが来る場合"series", 最初にシャントのLCが来る場合"shunt"
    type : チェビシェフの場合"Chebyshev", バタワースの場合 "Butterworth"
    ripple : チェビシェフの場合のリップルの大きさをdBで表したもの
    """
    gk = prototype_LPF(n, type, ripple)

    LC_elements = np.zeros((n + 2, 2))
    LC_elements[0, 0] = z0
    LC_elements[n + 1, 0] = gk[n+1] * z0
    d = df/f0
    w0 = 2 * np.pi * f0 * 1.0E9
    if first_element == "series":
        for k in range(1, n + 1):
            if k % 2 != 0:
                LC_elements[k,0] = gk[k] * z0 / (d * w0)
                LC_elements[k,1] = d / (z0 * w0 * gk[k])
            else:
                LC_elements[k,0] = d * z0/ (w0 * gk[k])
                LC_elements[k,1] = gk[k] / (z0 * w0 * d)
    elif first_element == "shunt":
        for k in range(1, n + 1):
            if k % 2 != 0:
                LC_elements[k,0] = d * z0/ (w0 * gk[k])
                LC_elements[k,1] = gk[k] / (z0 * w0 * d)
            else:
                LC_elements[k,0] = gk[k] * z0 / (d * w0)
                LC_elements[k,1] = d / (z0 * w0 * gk[k])
    return LC_elements

これを使って3次のチェビシェフフィルタを計算すると

LC_BPF(3, 1, 0.1*1, ripple=0.5)
array([[5.00000000e+01, 0.00000000e+00],
[1.27032014e-07, 1.99400884e-13],
[7.25621158e-10, 3.49084307e-11],
[1.27032014e-07, 1.99400884e-13],
[5.00000000e+01, 0.00000000e+00]])
のように計算できる。
でscikit-rfのCircuit機能を使って合成する関数はこちら。

def BPF_synthesis(n, f0, df, fstart, fstop, points, z0=50.0, first_element="series", type = "Chebyshev", ripple = 0.1):
    """
    BPFを合成し、scikit-rfのCircuitとして返す関数
    n : フィルタの次数(チェビシェフの場合、偶数だと負荷のインピーダンスが50Ωになりません)
    f0 : 中心周波数[GHz]
    df : 帯域幅[GHz]
    fstart : 開始周波数[GHz]
    fstop : 終了周波数[GHz]
    points : 周波数点数
    z0 : 信号源の特性インピーダンス
    first_element : 最初にシリーズのLが来る場合"series", 最初にシャントのCが来る場合"shunt"
    type : チェビシェフの場合"Chebyshev", バタワースの場合 "Butterworth"
    ripple : チェビシェフの場合のリップルの大きさをdBで表したもの
    """
    freq = rf.Frequency(start=fstart, stop=fstop, unit='GHz', npoints=points)
    LC_elements = LC_BPF(n, f0, df, z0, first_element, type, ripple)
    tl_media = rf.DefinedGammaZ0(freq, z0=LC_elements[0, 0], gamma=1j*freq.w/rf.c)
    gnd = rf.Circuit.Ground(freq, name='gnd')
    port1 = rf.Circuit.Port(freq, name='port1', z0=z0)
    port2 = rf.Circuit.Port(freq, name='port2', z0=LC_elements[-1, 0])

    if first_element == "series":
        Ls = [0]
        Cs = [0]
        Lp = [0]
        Cp = [0]
        countL = 1
        countC = 1
        for k in range(1, n + 1):
            if k % 2 != 0:
                Ls.append(tl_media.inductor(LC_elements[k,0], name = f"Ls{countL}"))
                Cs.append(tl_media.capacitor(LC_elements[k,1], name = f"Cs{countL}"))
                countL +=1
            else:
                Lp.append(tl_media.inductor(LC_elements[k,0], name = f"Lp{countC}"))
                Cp.append(tl_media.capacitor(LC_elements[k,1], name = f"Cp{countC}"))
                countC += 1
        cnx = [[(port1, 0), (Ls[1],  0)]]
        if n % 2 != 0:
            for k in range(1, n//2 + 1):
                cnx.append([(Ls[k], 1), (Cs[k], 0)])
                cnx.append([(Cs[k], 1), (Lp[k], 0), (Cp[k], 0),  (Ls[k+1], 0)])
            cnx.append([(Ls[n//2 + 1], 1),(Cs[n//2 + 1], 0)])
            cnx.append([(Cs[n//2 + 1], 1), (port2, 0)])
        else:
            for k in range(1, n//2):
                cnx.append([(Ls[k], 1), (Cs[k], 0)])
                cnx.append([(Cs[k], 1), (Lp[k], 0), (Cp[k], 0),  (Ls[k+1], 0)])
            cnx.append([(Ls[n//2], 1), (Cs[n//2], 0)])
            cnx.append([ (Cs[n//2], 1), (Lp[n//2], 0), (Cp[n//2], 0), (port2, 0)])
        gnd_cnx = [(gnd, 0)]
        for k in range(1, n//2 + 1):
            gnd_cnx.append((Lp[k], 1))
            gnd_cnx.append((Cp[k], 1))
        cnx.append(gnd_cnx)
    elif first_element == "shunt":
        Ls = [0]
        Cs = [0]
        Lp = [0]
        Cp = [0]
        countL = 1
        countC = 1
        for k in range(1, n + 1):
            if k % 2 != 0:
                Lp.append(tl_media.inductor(LC_elements[k,0], name = f"Lp{countC}"))
                Cp.append(tl_media.capacitor(LC_elements[k,1], name = f"Cp{countC}"))
                countC += 1
            else:
                Ls.append(tl_media.inductor(LC_elements[k,0], name = f"Ls{countL}"))
                Cs.append(tl_media.capacitor(LC_elements[k,1], name = f"Cs{countL}"))
                countL +=1
        cnx = [[(port1, 0), (Lp[1],  0), (Cp[1], 0), (Ls[1], 0)]]
        gnd_cnx = [(gnd, 0)]
        if n % 2 != 0:
            for k in range(1, n//2):
                cnx.append([(Ls[k], 1), (Cs[k], 0)])
                cnx.append([(Cs[k], 1), (Lp[k+1], 0), (Cp[k+1], 0), (Ls[k+1], 0)])
            cnx.append([(Ls[n//2], 1),(Cs[n//2],0)])    
            cnx.append([(Cs[n//2], 1), (Lp[n//2 + 1], 0), (Cp[n//2 + 1], 0), (port2, 0)])
            for k in range(1, n//2 + 2):
                gnd_cnx.append((Lp[k], 1))
                gnd_cnx.append((Cp[k], 1))
        else:
            for k in range(1, n//2):
                cnx.append([(Ls[k], 1), (Cs[k], 0)])
                cnx.append([(Cs[k], 1), (Lp[k+1], 0), (Cp[k+1], 0),  (Ls[k+1], 0)])
            cnx.append([(Ls[n//2], 1), (Cs[n//2], 0)])
            cnx.append([(Cs[n//2], 1), (port2, 0)])
            for k in range(1, n//2 + 1):
                gnd_cnx.append((Lp[k], 1))
                gnd_cnx.append((Cp[k], 1))
        cnx.append(gnd_cnx)

    return rf.Circuit(cnx)

ではフィルタを合成してみよう。5次のバタワースとチェビシェフの比較をしてみる。

bpf_butterworth =BPF_synthesis(5, 1, 0.1*1,  0.5, 2, 1000,type="Butterworth")
bpf_butterworth.name = "5th order Butterworth"
bpf_chebyshev =BPF_synthesis(5, 1, 0.1*1,  0.5, 2, 1000, ripple=0.5)
bpf_chebyshev.name = "5th order Chebyshev"
fig = plt.figure(figsize=(10,7))
bpf_butterworth.network.plot_s_db(m=1, n=0)
bpf_butterworth.network.plot_s_db(m=0, n=0)
bpf_chebyshev.network.plot_s_db(m=1, n=0)
bpf_chebyshev.network.plot_s_db(m=0, n=0)
plt.ylim(-80, 5)
plt.ylabel("S parameter[dB]")

Bpfsynth01

チェビシェフのほうが急峻だがリップルが入っているのが見える。素子のつながりは

bpf_chebyshev.plot_graph(network_labels=True, edge_labels=True, port_labels=True)
でわかる。とても見にくいが…

Bpfsynth02

« 高周波・RFニュース 2024年7月30日 Gartner/QorvoのEVのバッテリマネジメントシステム(BMS)解説、Qualcommのスマートグラスインタビュー、6GとISAC解説、Tachyon NetworksとPerasoの60GHz FWA、電気設計のためのAIツール、Wi-Fi 7とプライベート5Gは共存するか?など | トップページ | 高周波・RFニュース 2024年7月31日 Qorvo、Skyworksの決算発表、QualcommがSnapdragon 4s Gen 2を発表、u-bloxの測位ソリューションがNVIDIAに採用、MarvellがStructera CXLを発表、IEEE IMS2024の論文集が公開、TDKのAI新会社 »

パソコン・インターネット」カテゴリの記事

学問・資格」カテゴリの記事

日記・コラム・つぶやき」カテゴリの記事

コメント

コメントを書く

(ウェブ上には掲載しません)

« 高周波・RFニュース 2024年7月30日 Gartner/QorvoのEVのバッテリマネジメントシステム(BMS)解説、Qualcommのスマートグラスインタビュー、6GとISAC解説、Tachyon NetworksとPerasoの60GHz FWA、電気設計のためのAIツール、Wi-Fi 7とプライベート5Gは共存するか?など | トップページ | 高周波・RFニュース 2024年7月31日 Qorvo、Skyworksの決算発表、QualcommがSnapdragon 4s Gen 2を発表、u-bloxの測位ソリューションがNVIDIAに採用、MarvellがStructera CXLを発表、IEEE IMS2024の論文集が公開、TDKのAI新会社 »

最近の記事

2025年2月
            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  

最近のコメント

無料ブログはココログ
フォト