サイトマップ

回路の素101 002 アンプ:ボルテージフォロア 交流結合型

回路の素101 002 アンプ:ボルテージフォロア 交流結合型

オペアンプを使用して、入力信号の交流成分のみ出力する
入力インピーダンスが非常に高いため、出力インピーダンスが高い信号を受信することができる
また出力インピーダンスも低くすることができる

回路図作成

以下の3条件の回路を作成する

これらの回路でシミュレーションを実施する

応答性確認

各シミュレーションを tranモード に変更し、正弦波に対する応答性を確認する

import matplotlib.pyplot as plt
import numpy as np

from PyLTSpice import SimCommander

fnames = [
    'PrimaryCircuit1-002_1',
    'PrimaryCircuit1-002_2',
    'PrimaryCircuit1-002_3',
]

fname_tmp = '_tran'
for fname in fnames:
    LTC = SimCommander(fname + '.asc')

    line_no = LTC._get_line_starting_with('.ac')  # ac記述を探す
    sim_cmd = LTC.netlist[line_no]
    LTC.netlist[line_no] = sim_cmd.replace('.ac', ';ac')  # コメントにする
    line_no = LTC._get_line_starting_with(';tran')  # tran記述を探す
    sim_cmd = LTC.netlist[line_no]
    LTC.netlist[line_no] = sim_cmd.replace(';tran', '.tran')  # 有効化する
    print(LTC.netlist[line_no], end='')  # 確認
    
    # 編集したnetlistの情報でバッチ処理を実行する
    run_net_file = fname + fname_tmp + '.net'
    LTC.run(run_filename=run_net_file)
    LTC.wait_completion()
.tran 0 5m 0 0.1u
.tran 0 5m 0 0.1u
.tran 0 5m 0 0.1u
from PyLTSpice import RawRead

fig = plt.figure(figsize=(6, 3))
ax1 = fig.add_subplot(1, 1, 1)

for i, fname in enumerate(fnames):
    name_ = 'circuit%d' % (i + 1)
    #rawファイルよりプロットに必要な情報を取得する
    run_raw_file = fname + fname_tmp + '.raw'
    LTR = RawRead(run_raw_file)
    x     = LTR.get_trace('time')
    tmp1  = LTR.get_trace('V(vout)')
    ax1.plot(x.get_time_axis(0) * 1000, tmp1.get_wave(0), label=name_)

tmp1  = LTR.get_trace('V(vin)')
ax1.plot(x.get_time_axis(0) * 1000, tmp1.get_wave(0), label='Vin')

ax1.legend(); ax1.grid()
ax1.set_xlabel('[ms]'); ax1.set_ylabel('V$_{out}$[V]')

fig.tight_layout()

回路1,3は直流成分が除去され、入力の0.5Vオフセットが除去されている
回路2だとバイアスに2.5Vが追加できている

周波数特性の確認

シミュレーションを acモード で実行し、正弦波に対する応答性を確認する
今回の回路図の場合、デフォルトの設定で実施すればよい

from PyLTSpice import SimCommander

fnames = [
    'PrimaryCircuit1-002_1',
    'PrimaryCircuit1-002_2',
    'PrimaryCircuit1-002_3',
]

fname_tmp = '_ac'
for fname in fnames:
    LTC = SimCommander(fname + '.asc')

    line_no = LTC._get_line_starting_with('.ac')
    print(LTC.netlist[line_no], end='')  # 確認
    
    # 編集したnetlistの情報でバッチ処理を実行する
    run_net_file = fname + fname_tmp + '.net'
    LTC.run(run_filename=run_net_file)
    LTC.wait_completion()
.ac oct 40 1 10Meg
.ac oct 40 1 10Meg
.ac oct 40 1 10Meg
from PyLTSpice import RawRead

fig = plt.figure(figsize=(6, 4))
ax1 = fig.add_subplot(2, 1, 1)
ax2 = fig.add_subplot(2, 1, 2, sharex=ax1)

for i, fname in enumerate(fnames):
    name_ = 'circuit%d' % (i + 1)
    #rawファイルよりプロットに必要な情報を取得する
    run_raw_file = fname + fname_tmp + '.raw'
    LTR = RawRead(run_raw_file)
    freq  = np.abs(LTR.get_trace('frequency').get_wave(0))
    Vout  = LTR.get_trace("V(vout)").get_wave(0)
    ax1.plot(freq, 20*np.log10(np.abs(Vout)),    label=name_)
    ax2.plot(freq, np.angle(Vout) / np.pi * 180, label=name_)

ax1.legend(fontsize=9); ax1.grid()
ax1.set_xlabel("[Hz]"); ax1.set_ylabel("Gain[dB]")
ax1.set_xscale('log')
ax1.set_ylim(-5, 2)

ax2.legend(fontsize=9); ax2.grid()
ax2.set_xlabel("[Hz]"); ax2.set_ylabel("Phase[deg]")
ax2.set_xscale('log')

fig.tight_layout()

高域の特性は、オペアンプの仕様で決まっている
低域は、各回路のハイパスフィルタのカットオフ周波数で決まる

  • 回路1:単純なCR回路
    • カットオフ周波数は、 f_c = \frac{1}{2 \pi C_1 R_1} -> 16Hz
  • 回路2:バイアス電圧付与
    • カットオフ周波数は、 f_c = \frac{1}{2 \pi C_1 R} :  R = \frac{R_1 R_2}{R_1 + R_2}  -> 32Hz
  • 回路3:ブートストラップ
    • カットオフ周波数は、 f_c = \frac{1}{2 \pi C_1 (R_1 + R_2)} -> 14.5Hz

ちなみに、ブートストラップの入力インピーダンスは下記になる
 \frac{1}{2 \pi f C_1} + R_1 + R_2 + 2 \pi f C_2 R_1 R_2

おまけ : ネットリストの u について

PyLTspiceでネットリストを作成すると、  \mu が文字化けしてしまう

!more PrimaryCircuit1-002_1_tran.net
* c:\Users\XXXX\PrimaryCircuit1-002_1.asc
V2 +Vcc 0 5
RLoad Vout 0 10k
V1 Vin 0 SINE(0.5 1 1k) AC 1 0
V3 -Vcc 0 -5
C1 N001 Vin 0.1�  # ここが文字化けしている
R1 N001 0 100k
XU1 N001 Vout +Vcc -Vcc Vout AD820
.tran 0 5m 0 0.1u
;ac oct 40 1 10Meg
.lib ADI1.lib
.backanno
.end

ただし、パラメータを変更する際は u で記載したので問題ない

以下に、今回の回路1で入力のコンデンサを変えた際のカットオフ周波数の変化をシミュレートした例を紹介する

from PyLTSpice import SimCommander

infos_ = [
    ['C1 0.05u', 'C1 N001 Vin 0.05u\n'],
    ['C1 0.1u',  'C1 N001 Vin 0.1u\n'],
    ['C1 0.2u',  'C1 N001 Vin 0.2u\n'],
]

LTC = SimCommander('PrimaryCircuit1-002_1.asc')
fname = 'PrimaryCircuit1-002_1_C1'

line_no = LTC.get_component_info('C1')['line']  # この関数で、該当の行番号を取得できる  
for i, [name_, info_] in enumerate(infos_):
    # netlistの中身を編集する
    LTC.netlist[line_no] = info_
    print(LTC.get_component_info('C1'))  # 確認
    
    # 編集したnetlistの情報でバッチ処理を実行する
    run_net_file = "{}_{}.net".format(fname, i)
    LTC.run(run_filename=run_net_file)
    LTC.wait_completion()
{'designator': 'C1', 'nodes': ' N001 Vin', 'model': None, 'value': '0.05u', 'line': 5}
{'designator': 'C1', 'nodes': ' N001 Vin', 'model': None, 'value': '0.1u', 'line': 5}
{'designator': 'C1', 'nodes': ' N001 Vin', 'model': None, 'value': '0.2u', 'line': 5}
from PyLTSpice import RawRead

fig = plt.figure(figsize=(6, 4))
ax1 = fig.add_subplot(2, 1, 1)
ax2 = fig.add_subplot(2, 1, 2, sharex=ax1)

for i, [name_, info_] in enumerate(infos_):
    #rawファイルよりプロットに必要な情報を取得する
    run_raw_file = "{}_{}.raw".format(fname, i)
    LTR = RawRead(run_raw_file)
    freq  = np.abs(LTR.get_trace('frequency').get_wave(0))
    Vout  = LTR.get_trace("V(vout)").get_wave(0)
    ax1.plot(freq, 20*np.log10(np.abs(Vout)),    label=name_)
    ax2.plot(freq, np.angle(Vout) / np.pi * 180, label=name_)

ax1.legend(fontsize=9); ax1.grid()
ax1.set_xlabel("[Hz]"); ax1.set_ylabel("Gain[dB]")
ax1.set_xscale('log')
ax1.set_ylim(-5, 2)

ax2.legend(fontsize=9); ax2.grid()
ax2.set_xlabel("[Hz]"); ax2.set_ylabel("Phase[deg]")
ax2.set_xscale('log')

fig.tight_layout()

正常にシミュレーションが実施でき、コンデンサを大きくすると、カットオフ周波数が下がっていくことが分かる

参考文献

この記事は以下の書籍を参考にしましたが、
私の拙い知識で書いておりますので、誤り等ありましたらご指摘ください