受動素子を用いた様々なフィルタの周波数応答

# はじめに
受動電気部品であるRLC素子を用いてフィルタ回路を作成するとき、パラメータを変えることで最も信号を伝えやすい周波数帯が変化する。このように、信号の周波数に対して通りにくさを与えたものをフィルタ装置という。具体的には、低周波数のみの信号を通し、高周波数の信号を遮断するローパスフィルタ、高周波数のみの信号を通し、低周波数の信号を遮断するハイパスフィルタが有名どころである。ところで、この二つのフィルタを連結接続すれば、目的の周波数帯付近の信号を通すフィルタを作ることができる。これをバンドフィルタと呼ぶ。今回は、フィルタ回路の伝達関数から周波数伝達関数をプログラムにより計算してボード線図を作成することで、それらフィルタの原理を理解することを目的とする。具体的には、RとL素子のみを用いてローパス、ハイパスフィルタを作成し、それを合成させることで、以下のボード線図のような応答を示す、バンドパスフィルタを構築する。

![バンドフィルタゲイン.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1686019/68f10608-3f86-4f9e-bd36-a25f84edd85c.png)


# ローパスフィルタ
$R,L$素子を用いた、以下のようなローパスフィルタを考える。リアクトルは高周波成分を遮断することから、以下の回路でローパスフィルタの機能を果たすことができるということが感覚的に理解できる。

ローパスフィルタの伝達関数は以下の通りである。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1686019/3e2f93c6-eeee-45bf-80cc-88ca461656dd.png)

```math
G_{low}(s)=\frac{v_{out}}{v_{in}}=\frac{R}{R+sL}
```
ここで、$v_in=A \sin \omega t$の入力を与えたもの定常出力、つまり周波数応答を見たいので周波数伝達関数からボード線図を作成する。

したがって、以下の記事を参考に、下記のプログラムを作成した。
## ゲイン
```python RL_low.py
import numpy as np
import matplotlib.pyplot as plt
import japanize_matplotlib
omega = np.arange(0.0, 100.0, 0.001)
s=1j*omega
L=100*10**-3
R=0.1

#伝達関数G（s）→G(jω)
G=R/(R+s*L)
#ゲインの定義
g=20*np.log10(abs(G))
#横軸対数表示
plt.gca().set_xscale('log')
plt.plot(omega, g, 'b-')
plt.title('ボード線図（ゲイン）')
plt.xlabel('ω[rad/s]')
plt.ylabel('ゲイン[dB]')
plt.savefig("ローパスフィルタゲイン.png")
plt.show()
```

このプログラムを実行すると以下のようなグラフが出力される。


![ローパスフィルタゲイン.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1686019/56223da7-59bb-471f-9352-88e478369c92.png)


このように、入力信号の周波数が低いほどゲインは0[dB]と大きくなる。

一方で、位相のボード線図は以下のプログラムにより描写することができる。
## 位相角
```python RL_low_theta.py
import numpy as np
import matplotlib.pyplot as plt
import japanize_matplotlib
omega = np.arange(0.0, 100.0, 0.001)

s=1j*omega

L=100*10**-3
R=0.1

#伝達関数G（s）→G(jω)
G=R/(R+s*L)
# #ゲインの定義
# g=20*np.log10(abs(G))
# #横軸対数表示
# plt.gca().set_xscale('log')
# plt.plot(omega, g, 'b-')
# plt.title('ボード線図（ゲイン）')
# plt.xlabel('ω[rad/s]')
# plt.ylabel('ゲイン[dB]')

# plt.savefig("ローパスフィルタゲイン.png")

# plt.show()

#位相角の定義

#複素数の偏角（弧度法）を度数法に直す

theta = np.degrees(np.angle(G))

#横軸対数表示
plt.gca().set_xscale('log')
plt.plot(omega, theta, 'b-')
plt.title('ボード線図（位相角）')
plt.xlabel('ω[rad/s]')
plt.ylabel('位相[度]')
plt.savefig("ローパスフィルタ位相.png")
plt.show()
```
これを実行すると以下のようなグラフが出力される。

![ローパスフィルタ位相.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1686019/b9f989e1-2755-449c-8934-fbeb8aa08285.png)

これは、直流のような低周波数帯では位相はあまりずれず、周波数を上げていくほどずれていくことを示唆している。


# ハイパスフィルタ
一方で、ハイパスフィルタは、回路の素子を反転（RをLに、LをRに）すればいいので、以下のような回路図になる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1686019/8db42bfd-8b58-4dbf-ac76-91c0b385606c.png)

```math
G_{high}(s)=\frac{v_{out}}{v_{in}}=\frac{sL}{R+sL}
```
これをプログラムに反映させると以下のようになる。
## ゲイン
```python RL_high.py
import numpy as np
import matplotlib.pyplot as plt
import japanize_matplotlib
omega = np.arange(0.0, 100.0, 0.001)


s=1j*omega

L=100*10**-3
R=0.1

#伝達関数G（s）→G(jω)
G=s*L/(R+s*L)
#ゲインの定義
g=20*np.log10(abs(G))
#横軸対数表示
plt.gca().set_xscale('log')
plt.plot(omega, g, 'b-')
plt.title('ボード線図（ゲイン）')
plt.xlabel('ω[rad/s]')
plt.ylabel('ゲイン[dB]')

plt.savefig("ハイパスフィルタゲイン.png")

plt.show()
```
このプログラムにより、以下のようなグラフが得られる。

![ハイパスフィルタゲイン.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1686019/4ac8a8b2-7fd9-497c-ba78-35e1a2f8cdc9.png)

周波数が上がるほど、伝達効率が良くなる。


一方で、位相のボード線図は以下のプログラムにより描写することができる。
## 位相角
``` python RL_high_theta.py
import numpy as np
import matplotlib.pyplot as plt
import japanize_matplotlib
omega = np.arange(0.0, 100.0, 0.001)

s=1j*omega

L=100*10**-3
R=0.1

#伝達関数G（s）→G(jω)
G=s*L/(R+s*L)
# #ゲインの定義
# g=20*np.log10(abs(G))
# #横軸対数表示
# plt.gca().set_xscale('log')
# plt.plot(omega, g, 'b-')
# plt.title('ボード線図（ゲイン）')
# plt.xlabel('ω[rad/s]')
# plt.ylabel('ゲイン[dB]')

# plt.savefig("ハイパスフィルタゲイン.png")

# plt.show()

#位相角の定義

#複素数の偏角（弧度法）を度数法に直す

theta = np.degrees(np.angle(G))

#横軸対数表示
plt.gca().set_xscale('log')
plt.plot(omega, theta, 'b-')
plt.title('ボード線図（位相角）')
plt.xlabel('ω[rad/s]')
plt.ylabel('位相[度]')
plt.savefig("ハイパスフィルタ位相.png")
plt.show()
```

![ハイパスフィルタ位相.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1686019/08d7f73d-fbf2-43ec-92c5-20005b30850c.png)


# バンドパスフィルタ
最後に、ローパスフィルタとハイパスフィルタを連結したバンドパスフィルタについて述べる。
以下のような回路構成を考える。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1686019/31fa2dd0-947b-46ce-b6f1-a8aaea1cbcb5.png)

この、フィルタ回路の伝達関数は少し複雑だが、以下のように表すことができる。

ただし、導出には並列回路の合成抵抗や分流の式を利用した。

```math
G_{band}(s)=\frac{v_{out}}{v_{in}}=\frac{sL_2}{sL_1+(\frac{R_1(R_2+sL_2)}{R_1+(R_2+sL_2)})}\times \frac{R_1}{(R_2+sL_2)+R_1}
```

これをプログラムに反映させると以下のようになる。

## ゲイン

``` python RL_band.py
import numpy as np
import matplotlib.pyplot as plt
import japanize_matplotlib
omega = np.arange(0.0, 100.0, 0.001)

s=1j*omega

L1=100*10**-3
L2=200*10**-3

R1=0.1
R2=0.2

#伝達関数G（s）→G(jω)
G=s*L2/(s*L1+R1*(R2+s*L2)/(R1+(R2+s*L2)))*R1/((R2+s*L2)+R1)
#ゲインの定義
g=20*np.log10(abs(G))
#横軸対数表示
plt.gca().set_xscale('log')
plt.plot(omega, g, 'b-')
plt.title('ボード線図（ゲイン）')
plt.xlabel('ω[rad/s]')
plt.ylabel('ゲイン[dB]')
plt.savefig("バンドパスフィルタゲイン.png")
plt.show()
``` 
これを実行すると以下のようなグラフが出力される。

![バンドフィルタゲイン.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1686019/68f10608-3f86-4f9e-bd36-a25f84edd85c.png)

このグラフから、中央帯付近の周波数信号は簡単に通過できるが、それ以外の場合だと極端に難しくなることが分かる。

ちなみに、RLフィルタにおいて$\omega L=R$前後の$\omega$で挙動が大きく変化する。
なので、$\omega=\frac{R}{L}$と示せる。したがって、


```math
\frac{R_L}{L_L}<\omega <\frac{R_H}{L_H}
```
というような、コイルと抵抗のパラメータを決定した場合、上記の角周波数の範囲の信号を通しやすく(0dB付近)それ以外の信号を遮断するようなフィルタを作成することができる。

### 中央帯が広い場合のプログラム

そこで、角周波数の中央帯の範囲が広い場合のプログラムを作成した。
``` python RL_band_wide.py
import numpy as np
import matplotlib.pyplot as plt
import japanize_matplotlib
omega = np.arange(0.0, 1000.0, 0.001)

s=1j*omega

L1=10*10**-3
L2=1000*10**-3

R1=0.1
R2=0.1

#伝達関数G（s）→G(jω)
G=s*L2/(s*L1+R1*(R2+s*L2)/(R1+(R2+s*L2)))*R1/((R2+s*L2)+R1)
#ゲインの定義
g=20*np.log10(abs(G))
#横軸対数表示
plt.gca().set_xscale('log')
plt.plot(omega, g, 'b-')
plt.title('ボード線図（ゲイン）')
plt.xlabel('ω[rad/s]')
plt.ylabel('ゲイン[dB]')
plt.savefig("バンドフィルタゲイン_広い中央帯.png")
plt.show()
```
このプログラムを実行すると以下のようになる。

![バンドフィルタゲイン_広い中央帯.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1686019/d5ed8d7e-8931-44ee-9866-44e46dff59bc.png)
このように、
```math
\frac{R_L}{L_L}<\omega <\frac{R_H}{L_H}
```

の中央帯の信号のみを通しやすいフィルタを作成することができる。


## 位相角
``` python RL_band_theta.py
import numpy as np
import matplotlib.pyplot as plt
import japanize_matplotlib
omega = np.arange(0.0, 100.0, 0.001)

s=1j*omega

L1=100*10**-3
L2=200*10**-3

R1=0.1
R2=0.2

#伝達関数G（s）→G(jω)
G=s*L2/(s*L1+R1*(R2+s*L2)/(R1+(R2+s*L2)))*R1/((R2+s*L2)+R1)
# #ゲインの定義
# g=20*np.log10(abs(G))
# #横軸対数表示
# plt.gca().set_xscale('log')
# plt.plot(omega, g, 'b-')
# plt.title('ボード線図（ゲイン）')
# plt.xlabel('ω[rad/s]')
# plt.ylabel('ゲイン[dB]')
# plt.savefig("バンドパスフィルタゲイン.png")
# plt.show()

#位相角の定義

#複素数の偏角（弧度法）を度数法に直す

theta = np.degrees(np.angle(G))

#横軸対数表示
plt.gca().set_xscale('log')
plt.plot(omega, theta, 'b-')
plt.title('ボード線図（位相角）')
plt.xlabel('ω[rad/s]')
plt.ylabel('位相[度]')
plt.savefig("バンドフィルタ位相.png")
plt.show()
```
一方で、位相の場合はハイパス、ローパスフィルタよりも変化の範囲が大きくなる。

![バンドフィルタ位相.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1686019/961d119a-9834-40c6-9d69-0ae39eb2685e.png)


# まとめ

今回は、ローパス、ハイパス、バンドパスフィルタの3タイプについて周波数応答をボード線図を用いることで調査した。結果、名前のとおり、ローパスフィルタは直流成分のような比較的周波数が低い信号帯を選択的に通過させた。一方で、ハイパスフィルタは真逆で、直流成分のような比較的周波数が低い信号を遮断した。
そこで、2つのフィルタを連結させたバンドパスフィルタでは着目したい周波数付近の信号だけ選択的に通過させることができた。このことは、RLC回路の共振にも通ずるところがあるように思える。

# 参考文献

https://www.aps-web.jp/academy/ec/541/

https://detail-infomation.com/band-pass-filter/

https://analogista.jp/bandpass/