UliEngineering を使って Python でコンデンサ充電の単純ダイオードモデルとショックレーモデルを比較する

UliEngineering Python ライブラリを使うと、コンデンサ充電における単純な固定電圧降下ダイオードモデルとショックレーダイオードモデルを簡単に比較できます。

この例では、単純モデルは 10mA の基準電流でショックレーモデルと一致させています。上側のサブプロットは充電中のコンデンサ電圧の絶対値を示し、下側のサブプロットは ショックレー - 単純 の差を示しています。

compare_diode_models_for_capacitor_charging.py
from UliEngineering.Electronics.Capacitors import capacitor_resistor_charge_time
from UliEngineering.Electronics.Diode import *
import matplotlib.pyplot as plt
import numpy as np

plt.style.use('ggplot')

SOURCE_VOLTAGE = 5.0
CAPACITANCE = 100e-6
RESISTANCE = 470.0
REFERENCE_CURRENT = 10e-3


def build_models(simple_drop, ideality_factor):
  saturation_current = shockley_diode_saturation_current(
    simple_drop,
    REFERENCE_CURRENT,
    ideality_factor=ideality_factor,
  )
  return (
    SimpleDiodeModel(simple_drop),
    ShockleyDiodeModel(saturation_current, ideality_factor=ideality_factor),
  )


def charge_curves(simple_model, shockley_model):
  max_voltage = (SOURCE_VOLTAGE - simple_model.minimum_series_voltage()) * 0.999
  voltage_grid = np.linspace(0.0, max_voltage, 1200)

  simple_times = capacitor_resistor_charge_time(
    CAPACITANCE,
    RESISTANCE,
    SOURCE_VOLTAGE,
    voltage_grid,
    initial_voltage=0.0,
    diode_model=simple_model,
  )
  shockley_times = capacitor_resistor_charge_time(
    CAPACITANCE,
    RESISTANCE,
    SOURCE_VOLTAGE,
    voltage_grid,
    initial_voltage=0.0,
    diode_model=shockley_model,
  )

  common_time = np.linspace(0.0, max(simple_times[-1], shockley_times[-1]), 1200)
  simple_voltage = np.interp(common_time, simple_times, voltage_grid)
  shockley_voltage = np.interp(common_time, shockley_times, voltage_grid)
  return common_time, simple_voltage, shockley_voltage


def render_plot(title, simple_model, shockley_model, outfile):
  time_axis, simple_voltage, shockley_voltage = charge_curves(simple_model, shockley_model)
  difference = shockley_voltage - simple_voltage

  fig, axes = plt.subplots(2, 1, figsize=(7, 6), sharex=True)
  axes[0].plot(time_axis * 1000.0, simple_voltage, label='Simple diode model', linewidth=2)
  axes[0].plot(time_axis * 1000.0, shockley_voltage, label='Shockley diode model', linewidth=2)
  axes[0].set_ylabel('Capacitor voltage (V)')
  axes[0].set_title(title)
  axes[0].legend(loc='lower right')
  axes[0].grid(True, which='both', linestyle='--', linewidth=0.5)

  axes[1].plot(time_axis * 1000.0, difference, linewidth=2)
  axes[1].axhline(0.0, color='black', linewidth=1, alpha=0.5)
  axes[1].set_xlabel('Time (ms)')
  axes[1].set_ylabel('Voltage delta (V)')
  axes[1].grid(True, which='both', linestyle='--', linewidth=0.5)

  fig.tight_layout()
  fig.savefig(outfile)
  plt.close(fig)


render_plot(
  'Capacitor charge curve: Schottky diode approximation',
  *build_models(0.3, 1.05),
  'capacitor_charge_schottky_simple_vs_shockley.svg',
)

render_plot(
  'Capacitor charge curve: Silicon diode approximation',
  *build_models(0.7, 1.9),
  'capacitor_charge_silicon_simple_vs_shockley.svg',
)

ショットキーダイオードの比較

capacitor charge schottky simple vs shockley.svg

シリコンダイオードの比較

capacitor charge silicon simple vs shockley.svg

なぜショックレーモデルはこんなに違うのか?

重要なポイントは、この 2 つのダイオードモデルが異なる物理的な問いに答えているということです。

単純ダイオードモデルは、例えばシリコンダイオードで 0.7V のような固定の順方向降下を仮定します。つまり RC 回路は常に概ね次のような電圧を見ます:

$$ V_R = V_{source} - V_C - V_D $$

ここで V_D は一定です。言い換えれば、ダイオードは常に一定の電圧オフセットとして扱われます。

ショックレーモデルはダイオードの降下を一定に保ちません。その代わり、順方向電圧は電流に応じて概ね次のように変化します:

$$ I = I_S \left(e^{\frac{V_D}{nV_T}} - 1\right) $$

したがって、充電電流が変化するとダイオード電圧も変化します。

この例では、両モデルは 10mA という 1 つの動作点でのみ一致させています。つまり、その電流の近くでのみ最もよく一致します。充電のごく初期では電流がその基準値に近いため、両方の曲線はほぼ重なって始まります。

その後、コンデンサが充電されて電流が低下します。ここでモデルが分かれます:

  • 単純モデルでは、ダイオードは依然として同じ固定電圧を降下します。
  • ショックレーモデルでは、電流が低下すると順方向電圧も低下します。
  • ショックレーダイオードは源電圧を「使い切る」量が少なくなるため、抵抗-コンデンサ経路に残る電圧が多くなります。
  • その結果コンデンサがより速く充電され、ショックレーの曲線が単純モデルの曲線の上に移動します。

このため、差は充電プロセスの中盤で最も顕著になります。単純モデルは電流の変化に反応できませんが、ショックレーモデルはまさにそれを行います。

なぜ差にピークが現れるのか?

ピークが生じる理由は 2 つあります: 1 つは物理的な理由、もう 1 つは数値的な理由です。

1. 物理的な理由

t = 0 では、電流が一致点に近いため両モデルは近い値を取ります。電流が 10mA を下回ると、ショックレーの順方向電圧は固定降下の近似を下回るため、ショックレーのコンデンサ電圧がどんどん先行します。

これにより、差は初期に増大します。

2. プロット・シミュレーション上の理由

コードは、ショックレー解の無制限な漸近的終点まで 2 つのモデルを比較しません。その代わり、次の値までの電圧グリッドのみを構築します:

max_voltage_snippet.py
max_voltage = (SOURCE_VOLTAGE - simple_model.minimum_series_voltage()) * 0.999

つまり、両方の曲線は単純モデルの最終電圧の約 99.9% に達するまでしか比較されません。

次に、np.interp() を使って両方の電圧トレースを共通の時間軸に再サンプリングします。ショックレーモデルがその比較上限電圧に達すると、補間されたトレースはプロットの終端で平坦になりますが、単純モデルはまだ追いつこうとしています。

つまり:

  • 初期では、両モデルが同じ初期電圧から始まるため差は小さい。
  • 中盤では、順方向降下が電流とともに減少するためショックレーモデルが先行する。
  • 終盤では、ショックレーのトレースはすでに選択した比較上限に達しているため、単純モデルが徐々に追いつく。
  • その結果、プロットされた差は再び縮小し、最終的にゼロに戻ります。

したがって、このピークはダイオード方程式の「謎の特徴」ではありません。電流に依存するダイオードの振る舞いと、この特定のプロットが固定電圧範囲でのみ両モデルを比較しているという事実の組み合わせから生じています。


同じカテゴリの類似記事をチェック: エレクトロニクス Python