RLCバンドパスフィルタのシミュレーション

Python
Sponsored

概要

この記事では、直列RLCバンドパスフィルタを例に、アナログフィルタ回路のシミュレーションを行う方法について解説する。

今回はPython言語を用いて、350Hz付近の周波数を持つ波形を選択的に通過させるフィルタに対し、350Hz、10,000Hz、50Hzの波を入力した際の出力を描画することを目標にする。

この記事を読むことで、コイルやコンデンサを含み、全体の挙動が微分方程式で表されるような電子回路について、LTSpiceのようなシミュレーションを1から実装して動作を検証できるようになる

直列RLCバンドパスフィルタ

回路図

本記事では、コイル・コンデンサ・抵抗を直列に接続した直列RLCバンドパスフィルタを取り扱う。

この回路により、 \(V_{in}\) として入力した電圧のうち、特定の周波数帯域の成分のみを \(V_{out}\) として取り出すことができる。

パラメータ

今回は、コイルのインダクタンス \(L\) 、コンデンサのキャパシタンス \(C\) 、抵抗値 \(R\) を以下のように設定した。

  • \(L=1\mathrm{mH}\)
  • \(C=200\mathrm{\mu F}\)
  • \(R=10\mathrm{\Omega}\)

フィルタの性質

直列RLCバンドパスフィルタの中心周波数 \(f_0\) 、低周波側カットオフ周波数 \(f_{CL}\) 、高周波側カットオフ周波数 \(f_{CH}\) は以下の式で求められる。

  • 中心周波数: \(f_0=\frac{1}{2\pi\sqrt{LC}}\)
  • 低周波側カットオフ周波数: \(f_{CL}=\frac{1}{2\pi RC}\)
  • 高周波側カットオフ周波数: \(f_{CH}=\frac{R}{2\pi L}\)

なお、カットオフ周波数は \(3\mathrm{dB}\) の減衰が得られる周波数として定義される。

前節で設定したパラメータから計算すると

  • \(f_0=\frac{1}{2\pi\sqrt{10^{-3}\cdot 2\cdot10^{-4}}}\simeq 356\mathrm{Hz}\)
  • \(f_{CL}=\frac{1}{2\pi\cdot 10\cdot 2\cdot 10^{-4}}\simeq 80\mathrm{Hz}\)
  • \(f_{CH}=\frac{10}{2\pi\cdot 10^{-3}}\simeq 1592\mathrm{Hz}\)

となり、 \(V_{in}\) として入力した周波数ごとの、\(V_{out}\) で得られるゲインの変化を図示すると以下のようになる。

微分方程式からシミュレーションを行う

直列RLCバンドパスフィルタの微分方程式

回路図より、電圧について以下の関係式が成り立つ。

$$V_{in}=V_L+V_C+V_R$$

右辺の電圧を、回路を流れる電流 \(i\) を用いてそれぞれ表現すると

$$V_{in}=L\frac{di}{dt}+\frac{1}{C}\int i dt+Ri$$

という微分方程式が得られる。

微分方程式の離散化

ここで、 \(I_c=\int i dt\) とおき、微分方程式を離散化すると

$$V_{in}(t)=L\frac{\Delta i(t)}{\Delta t}+\frac{1}{C}I_c(t)+Ri(t)$$

となる。ここで、離散化に基づく以下の関係式

$$i(t)=i(t-1)+\frac{\Delta i(t)}{\Delta t}\Delta t\tag{1}$$

$$I_c(t)=I_c(t-1)+i(t)\Delta t=I_c(t-1)+\left\{i(t-1)+\frac{\Delta i(t)}{\Delta t}\Delta t\right\}\Delta t\tag{2}$$

を適用し、 \(\frac{\Delta i(t)}{\Delta t}\) について解くと

$$V_{in}(t)=L\frac{\Delta i(t)}{\Delta t}+\frac{1}{C}\left[I_c(t-1)+\left\{i(t-1)+\frac{\Delta i(t)}{\Delta t}\Delta t\right\}\Delta t\right]+R\left\{i(t-1)+\frac{\Delta i(t)}{\Delta t}\Delta t\right\}$$

$$\left\{L+\frac{(\Delta t)^2}{C}+R\Delta t\right\}\frac{\Delta i(t)}{\Delta t}=V_{in}(t)-\frac{I_c(t-1)+i(t-1)\Delta t}{C}-Ri(t-1)$$

$$\frac{\Delta i(t)}{\Delta t}=\frac{V_{in}(t)-\frac{I_c(t-1)+i(t-1)\Delta t}{C}-Ri(t-1)}{L+\frac{(\Delta t)^2}{C}+R\Delta t}\tag{3}$$

となる。

シミュレーションの流れ

前節で微分方程式を \(\frac{\Delta i(t)}{\Delta t}\) について解いたのは、 \(I_c(t)\) や \(i(t)\) に比べ、 \(\frac{\Delta i(t)}{\Delta t}\) の \(V_{in}(t)\) に対する反応が最も速いためである

具体的には、例えば \(V_{in}\) が変化したからといってコンデンサに蓄えられている電荷( \(I_c\) )が急激に変化することは考えにくい。

そして、そもそも \(I_c(t)\) や \(i(t)\) は式 \((1), (2)\) を通して \(\frac{\Delta i(t)}{\Delta t}\) によってその変化量が制御されている。

したがって、フィルタ回路のシミュレーションは以下の手順で実施する。

  1. \(I_c(t-1), i(t-1)\) を用い、式 \((3)\) にしたがって、回路の微分方程式をみたす \(\frac{\Delta i(t)}{\Delta t}\) の値をもとめる。
  2. \(i(t)=i(t-1)+\frac{\Delta i(t)}{\Delta t}\Delta t\) により \(i\) を更新する。
  3. \(I_c(t)=I_c(t-1)+i(t)\Delta t\) により \(I_c\) を更新する。

なお、フィルタ回路の出力端子と抵抗は並列関係にあるので、出力電圧は

$$V_out(t)=V_R(t)=Ri(t)$$

として求めることができる。

Pythonによる実装

シミュレーションでは、サンプリングレートを10,000Hz(10,000フレームで1秒)とし、200フレーム分の電圧波形を直列RLCバンドパスフィルタに入力した。

import numpy as np
from matplotlib import pyplot as plt

def simulate(v, sample=10000, R=10, L=10**-3, C=2*10**-4):
    step = len(v)
    dt = 1 / sample
    save = np.zeros(step)
    i = 0
    Ic = 0
    for t in range(step):
        didt = (v[t] - R*i - (Ic+i*dt)/C) / (L + dt*dt/C + R*dt)
        i += didt * dt
        Ic += i * dt
        save[t] = R*i
    return save

step = 200

v350 = simulate(np.array([np.sin(t*2*np.pi*0.035) for t in range(step)])) # 350Hz
v10000 = simulate(np.array([np.sin(t*2*np.pi*1) for t in range(step)])) # 10000Hz
v50 = simulate(np.array([np.sin(t*2*np.pi*0.005) for t in range(step)])) # 50Hz

plt.plot(v350, label="350Hz")
plt.plot(v10000, label="10,000Hz")
plt.plot(v50, label="50Hz")
plt.legend()
plt.xlabel("time (sec)")
plt.ylabel("Vout")
plt.xticks([50*i for i in range(5)], [50*i/10000 for i in range(5)])
plt.tight_layout()
plt.savefig("Vout.png")

入力したのは振幅が1で周波数がそれぞれ350Hz, 10,000Hz, 50Hzのsin波であり、それぞれに対する出力を描画した。

その結果、中心周波数に近い350Hzの波はほとんどロスなく伝達されたのに対し、カットオフ周波数から遠く離れた10,000Hzの波は大きく減衰した。

Comments