3. 峰值电流模式控制Buck变换器
任务定义
本案例实现峰值电流模式控制的Buck变换器仿真模型,重点解决占空比大于50%时产生的次谐波振荡问题。通过加入固定斜率斜坡补偿,验证系统在宽占空比范围内的稳定性,并考察负载阶跃与输入电压阶跃下的动态响应速度。仿真基于Python编写,使用scipy.integrate求解状态方程,不依赖专用电路仿真器,便于观察控制环路内部信号。
控制原理与参数设计
峰值电流模式控制包含两个环路:内环为电流环,当电感电流达到参考值i_ref时关断开关管;外环为电压环,通过PI控制器调节i_ref以稳定输出电压。电流环的采样保持特性导致其离散传递函数存在右半平面零点,当占空比D>0.5时该零点位于单位圆外,产生次谐波振荡。加入斜坡补偿后,等效于在电流比较器输入端叠加斜率m_c的斜坡信号,当m_c ≥ (m_2 - m_1)/2时系统无条件稳定,其中m_1为电感电流上升斜率,m_2为下降斜率。
本案例选择m_c = 0.75 × m_2,该值满足稳定性条件且不过度牺牲电流环带宽。Buck变换器参数:输入电压V_in = 24V,输出电压V_out = 12V(稳态D=0.5),电感L = 100μH,电容C = 470μF,负载电阻R = 2.4Ω(输出功率60W),开关频率f_sw = 100kHz。电压环PI参数:K_p = 0.5,K_i = 2000,通过MATLAB Sisotool或手动整定获得约5kHz的穿越频率与60°相位裕度。
仿真模型实现
采用状态空间平均与开关周期级混合仿真:每个开关周期内,根据当前占空比决定开关状态,使用scipy.integrate.odeint在子区间内精确求解电感电流与电容电压。电流比较器在每个开关周期开始时采样电感电流,当电流达到i_ref - m_c × t时关断开关管(t为周期内时间),由此确定实际占空比。电压环PI控制器以输出电压误差为输入,在每个开关周期更新i_ref。仿真总时长5ms(500个开关周期),足以观察瞬态过程。
import numpy as np
from scipy.integrate import odeint
import matplotlib.pyplot as plt
# 电路参数
V_in = 24.0 # 输入电压(V)
V_ref = 12.0 # 参考电压(V)
L = 100e-6 # 电感(H)
C = 470e-6 # 电容(F)
R = 2.4 # 负载电阻(Ω)
f_sw = 100e3 # 开关频率(Hz)
T_sw = 1.0 / f_sw # 开关周期(s)
# 控制参数
K_p = 0.5 # PI比例系数
K_i = 2000.0 # PI积分系数
m_c_ratio = 0.75 # 斜坡补偿系数(相对于m2)
# 仿真参数
t_total = 5e-3 # 总仿真时间
n_cycles = int(t_total * f_sw)
t_span = np.linspace(0, T_sw, 50) # 每个开关周期内50个子步
# 状态变量: [iL, vC, i_ref, integrator]
state = np.array([0.0, 0.0, 1.0, 0.0])
iL_log = np.zeros(n_cycles * 50)
vC_log = np.zeros(n_cycles * 50)
t_log = np.zeros(n_cycles * 50)
duty_log = np.zeros(n_cycles)
def buck_deriv(x, t, sw_state):
"""Buck变换器状态方程"""
iL, vC = x
if sw_state == 1: # 开关管导通
diL_dt = (V_in - vC) / L
else: # 开关管关断
diL_dt = -vC / L
dvC_dt = (iL - vC / R) / C
return [diL_dt, dvC_dt]
def simulate_cycle(state, duty, t_start):
"""仿真单个开关周期,返回周期末状态"""
iL, vC, i_ref, integrator = state
# 导通阶段
t_on = duty * T_sw
if t_on > 0:
t_seg = np.linspace(0, t_on, 25)
sol = odeint(buck_deriv, [iL, vC], t_seg, args=(1,))
iL, vC = sol[-1]
# 关断阶段
t_off = T_sw - t_on
if t_off > 0:
t_seg = np.linspace(0, t_off, 25)
sol = odeint(buck_deriv, [iL, vC], t_seg, args=(0,))
iL, vC = sol[-1]
return np.array([iL, vC, i_ref, integrator])
# 主仿真循环
for k in range(n_cycles):
iL, vC, i_ref, integrator = state
# 电压环PI更新参考电流
error = V_ref - vC
integrator += error * T_sw
i_ref = K_p * error + K_i * integrator
i_ref = max(0.1, min(20.0, i_ref)) # 限幅
# 电流环确定占空比(含斜坡补偿)
m1 = (V_in - vC) / L # 电流上升斜率
m2 = vC / L # 电流下降斜率
m_c = m_c_ratio * m2 # 补偿斜坡
# 求解 iL + (m1+mc)*t = i_ref + mc*t => t = (i_ref - iL)/m1
if i_ref > iL:
t_on = (i_ref - iL) / m1
else:
t_on = 0
duty = min(1.0, max(0.0, t_on / T_sw))
# 更新状态
state = simulate_cycle(state, duty, k * T_sw)
state[2] = i_ref
state[3] = integrator
# 记录数据
idx_start = k * 50
t_local = np.linspace(k*T_sw, (k+1)*T_sw, 50)
# 近似记录(实际应分段记录,此处简化)
iL_log[idx_start:idx_start+50] = state[0]
vC_log[idx_start:idx_start+50] = state[1]
t_log[idx_start:idx_start+50] = t_local
duty_log[k] = duty
# 绘制结果
fig, (ax1, ax2, ax3) = plt.subplots(3, 1, figsize=(10, 8), sharex=True)
ax1.plot(t_log*1e3, vC_log, 'b-', linewidth=0.8)
ax1.set_ylabel('输出电压 (V)')
ax1.axhline(V_ref, color='r', linestyle='--', label='参考电压')
ax1.legend()
ax1.grid(True)
ax2.plot(t_log*1e3, iL_log, 'g-', linewidth=0.8)
ax2.set_ylabel('电感电流 (A)')
ax2.grid(True)
ax3.plot(np.arange(n_cycles)*T_sw*1e3, duty_log, 'm-', linewidth=0.8)
ax3.set_ylabel('占空比')
ax3.set_xlabel('时间 (ms)')
ax3.grid(True)
plt.tight_layout()
plt.savefig('peak_current_mode_buck.png', dpi=150)
plt.show()
验证方法与判定标准
运行上述代码后,通过以下三个维度验证系统性能:
- 稳定性验证:观察稳态时电感电流波形。若电流纹波在每个开关周期内形状一致、无交替大小波,且占空比恒定,则无次谐波振荡。重点检查占空比接近0.7(通过将V_ref改为16.8V)时是否仍稳定。
- 负载阶跃响应:在仿真至2ms时将负载电阻从2.4Ω突变为1.2Ω(输出功率加倍),观察输出电压跌落幅度与恢复时间。判定标准:电压跌落小于200mV,恢复时间小于0.5ms,且无振荡。
- 输入电压阶跃响应:在仿真至3ms时将V_in从24V突变为30V,观察占空比自动调整过程。判定标准:输出电压过冲小于100mV,调节时间小于0.3ms。
预期输出:稳态时输出电压为12V±50mV,电感电流纹波约1.2A(峰峰值),占空比稳定在0.5。加入斜坡补偿后,即使占空比达到0.7也不会出现次谐波振荡。上述波形图将保存为peak_current_mode_buck.png,可通过观察图形直接判断是否满足判定标准。
运行方式与依赖
需要安装Python 3.8+、numpy、scipy、matplotlib。将代码保存为peak_current_mode_buck.py,在终端执行python peak_current_mode_buck.py即可运行。仿真耗时约10秒(取决于CPU性能),完成后当前目录生成peak_current_mode_buck.png波形图。若需测试负载阶跃,可在主循环中if k == 200: R = 1.2;若需测试输入电压阶跃,可在if k == 300: V_in = 30.0处修改参数后重新运行。