如何使用 UliEngineering 在 Python 中比较电容充电的简单二极管模型与 Shockley 二极管模型
你可以使用 UliEngineering Python 库轻松比较电容充电的简单恒压降二极管模型与 Shockley 二极管模型。
在这个示例中,简单模型在参考电流 10mA 处与 Shockley 模型进行匹配。上方的子图显示充电过程中的电容绝对电压,下方的子图显示两者之差 Shockley - 简单模型。
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',
)肖特基二极管比较
硅二极管比较
为什么 Shockley 模型差异如此明显?
关键在于这两种二极管模型回答的是不同的物理问题。
简单二极管模型假设正向压降固定不变,例如硅二极管的 0.7V。这意味着 RC 网络两端的电压始终约为:
其中 V_D 为常数。换句话说,二极管被当作一个始终导通的固定电压偏移量来处理。
Shockley 模型并不保持二极管压降恒定。正向电压与电流的关系近似为:
$$ I = I_S \left(e^{\frac{V_D}{nV_T}} - 1\right) $$因此当充电电流变化时,二极管电压也会随之变化。
在这个示例中,两个模型仅在一个工作点匹配:10mA。这意味着它们只在该电流附近最为吻合。在充电开始时,电流接近该参考值,因此两条曲线几乎重合。
之后,电容开始充电,电流逐渐下降。此时两个模型开始分离:
- 在简单模型中,二极管仍然保持相同的固定压降。
- 在 Shockley 模型中,较低的电流产生较低的正向电压。
- 由于 Shockley 二极管现在"消耗"的源电压更少,电阻-电容支路上剩余的电压更多。
- 这使得电容充电更快,因此 Shockley 曲线会上升到简单模型曲线之上。
这就是差异在充电过程中段最为明显的原因。简单模型无法响应电流的变化,而 Shockley 模型恰恰做到了这一点。
为什么差值会出现峰值?
峰值出现有两个原因:一个是物理原因,一个是数值原因。
1. 物理原因
在 t = 0 时,两个模型很接近,因为电流接近匹配点。当电流降至 10mA 以下时,Shockley 正向电压低于恒压降近似值,因此 Shockley 电容电压越来越超前。
这使得差值在初始阶段逐渐增大。
2. 绘图/仿真原因
代码并没有将两个模型一直比较到 Shockley 解的无约束渐近终点。相反,它只构建了一个电压网格,上限为:
max_voltage = (SOURCE_VOLTAGE - simple_model.minimum_series_voltage()) * 0.999因此两条曲线只比较到它们达到简单模型最终电压的大约 99.9% 处。
然后,两条电压轨迹都使用 np.interp() 重采样到共同的时间轴上。一旦 Shockley 模型达到该上限比较电压,其插值轨迹在图表末尾变得平坦,而简单模型仍在追赶。
这意味着:
- 在初期,差值很小,因为两个模型从相同的初始电压开始。
- 在中段,Shockley 模型超前,因为其正向压降随电流减小。
- 在接近末尾时,Shockley 轨迹已达到所选的比较上限,因此简单模型逐渐追赶上来。
- 结果,绘制的差值再次缩小,最终趋向于零。
因此,峰值并不是二极管方程的"神秘特性"。它来自于与电流相关的二极管行为,以及该特定图表仅在固定电压范围内比较两个模型这一事实的结合。