如何使用 UliEngineering 在 Python 中比较电容充电的简单二极管模型与 Shockley 二极管模型

你可以使用 UliEngineering Python 库轻松比较电容充电的简单恒压降二极管模型与 Shockley 二极管模型。

在这个示例中,简单模型在参考电流 10mA 处与 Shockley 模型进行匹配。上方的子图显示充电过程中的电容绝对电压,下方的子图显示两者之差 Shockley - 简单模型

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

为什么 Shockley 模型差异如此明显?

关键在于这两种二极管模型回答的是不同的物理问题。

简单二极管模型假设正向压降固定不变,例如硅二极管的 0.7V。这意味着 RC 网络两端的电压始终约为:

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

其中 V_D 为常数。换句话说,二极管被当作一个始终导通的固定电压偏移量来处理。

Shockley 模型并不保持二极管压降恒定。正向电压与电流的关系近似为:

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

因此当充电电流变化时,二极管电压也会随之变化。

在这个示例中,两个模型仅在一个工作点匹配:10mA。这意味着它们只在该电流附近最为吻合。在充电开始时,电流接近该参考值,因此两条曲线几乎重合。

之后,电容开始充电,电流逐渐下降。此时两个模型开始分离:

这就是差异在充电过程中段最为明显的原因。简单模型无法响应电流的变化,而 Shockley 模型恰恰做到了这一点。

为什么差值会出现峰值?

峰值出现有两个原因:一个是物理原因,一个是数值原因。

1. 物理原因

t = 0 时,两个模型很接近,因为电流接近匹配点。当电流降至 10mA 以下时,Shockley 正向电压低于恒压降近似值,因此 Shockley 电容电压越来越超前。

这使得差值在初始阶段逐渐增大。

2. 绘图/仿真原因

代码并没有将两个模型一直比较到 Shockley 解的无约束渐近终点。相反,它只构建了一个电压网格,上限为:

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

因此两条曲线只比较到它们达到简单模型最终电压的大约 99.9% 处。

然后,两条电压轨迹都使用 np.interp() 重采样到共同的时间轴上。一旦 Shockley 模型达到该上限比较电压,其插值轨迹在图表末尾变得平坦,而简单模型仍在追赶。

这意味着:

因此,峰值并不是二极管方程的"神秘特性"。它来自于与电流相关的二极管行为,以及该特定图表仅在固定电压范围内比较两个模型这一事实的结合。


Check out similar posts by category: Electronics, Python