Buck-Boost变换器介绍之峰值电流模式控制Buck
本文主要介绍Buck-Boost的峰值电流模式控制的Buck原理。
仿真文件在开发板的资料中。
峰值电流模式控制
本节主要介绍如何使用STM32G474实现峰值电流模式控制的Buck。
- 电路增益计算
使用DSP控制,我们需要考虑DAC模块、ADC模块和反馈电路的增益。
开发板的电压采用的是差分电路采样的,所以反馈电路的增益计算如下:
MCU的ADC采样电压范围是,12位ADC的输出范围是,所以ADC的增益如下:
假设输出电压为5V,则对应的ADC基准值计算如下:
MCU的DAC电压范围是,12位DAC的输出范围是,所以DAC的增益如下:
Buck 数字控制的K如下:
计算的Python代码如下:
详情
import math
Vout = 5.00
Gpd = 3300/(56000+51)
Gadc = (math.pow(2,12)-1)/(3.3)
Gdac = (3.3)/(math.pow(2,12)-1)
K = 1/(Gpd*Gadc*Gdac)
Vref = Vout*Gpd*Gadc
print("Gpd",Gpd)
print("Gadc",Gadc)
print("Vref",Vref)
print("Gdac",Gdac)
print("K",K)
"""
Gpd 0.05887495316765089
Gadc 1240.909090909091
Vref 365.2923230629249
Gdac 0.0008058608058608059
K 16.985151515151514
"""
- 斜率补偿的计算
斜率补偿的计算过程可以参考《混合式数字与全数字电源控制实战》书本中的计算。计算的公式已经输入到下文的环路设计的Python代码中,运行代码就会计算出斜率补偿所需要的电压值。
II型数字补偿器
II型补偿器有2个极点和1个零点,相位提升可以达到90°,其传递函数如下。
利用双线性变换,将带入上式可得到如下形式的离散传递函数。
由上式的离散传递函数可得II型补偿器(2P2Z)的差分方程公式如下。
其中:n=当前采样, n-1=前一次采样,y[n] =当前补偿器输出(例如:占空比),y[n-1]和 y[n-2]为之前的补偿器输出;x[n] =当前补偿器输入(所需值和参考值之间的误差)、x[n-1]和 x[n-2]为之前的误差值。
其中:
注:极点和零点的单位都是rad/s
使用Python推导A和B系数,代码如下。
详情
# import libraries
import numpy as np
import sympy as sp
# 符号定义
wp0,wp1,wz1,s,z,Ts = sp.symbols('wp0 wp1 wz1 s z Ts')
# 双线性变换
s = (2/Ts)*((1-z**(-1))/(1+z**(-1)))
# 连续系统II型补偿器
H2P2Z = (wp0/s)*((1+s/wz1)/(1+s/wp1))
# sympy.cancel()方法,将表达式化简为标准p/q形式,相对分子和分母幂次展开
H2P2Z_D = sp.cancel(H2P2Z,z)
# sympy.fraction()方法,提取表达式的分子和分母
numerator,denominator = sp.fraction(H2P2Z_D)
# sympy.collect()方法,配合coeff可将特定变量幂次的系数收集起来
Scaled = sp.collect(denominator,z).coeff(z,2)
# 先提取相应变量幂次的系数,接着借助sympy.factor()方法,找到数学表达式因式分解的因子。
B2 = sp.factor(sp.collect(numerator,z).coeff(z,0)/Scaled)
B1 = sp.factor(sp.collect(numerator,z).coeff(z,1)/Scaled)
B0 = sp.factor(sp.collect(numerator,z).coeff(z,2)/Scaled)
A2 = sp.factor(-sp.collect(denominator,z).coeff(z,0)/Scaled)
A1 = sp.factor(-sp.collect(denominator,z).coeff(z,1)/Scaled)
#打印相关系数表达式
print("H2P2Z_D = ",H2P2Z_D)
print("\n")
print("B2 = ",B2)
print("B1 = ",B1)
print("B0 = ",B0)
print("A2 = ",A2)
print("A1 = ",A1)
# 计算实例化系数
wp0_res = 2*np.pi*100
wz1_res = 2*np.pi*100
wp1_res = 2*np.pi*10e3
Ts_res = 1.0/100e3
# 借助sympy.subs()方法,将数学表达式中的变量或表达式的所有实例替换为其他变量或表达式或值。
B2_res = B2.subs([(wp0,wp0_res),(wp1,wp1_res),(wz1,wz1_res),(Ts,Ts_res)])
B1_res = B1.subs([(wp0,wp0_res),(wp1,wp1_res),(wz1,wz1_res),(Ts,Ts_res)])
B0_res = B0.subs([(wp0,wp0_res),(wp1,wp1_res),(wz1,wz1_res),(Ts,Ts_res)])
A2_res = A2.subs([(wp0,wp0_res),(wp1,wp1_res),(wz1,wz1_res),(Ts,Ts_res)])
A1_res = A1.subs([(wp0,wp0_res),(wp1,wp1_res),(wz1,wz1_res),(Ts,Ts_res)])
print("\n")
#round,四舍五入保留几位小数
print("B2 = ",round(B2_res,6))
print("B1 = ",round(B1_res,6))
print("B0 = ",round(B0_res,6))
print("A2 = ",round(A2_res,6))
print("A1 = ",round(A1_res,6))
"""
H2P2Z_D = (2*Ts**2*wp0*wp1*wz1*z + Ts**2*wp0*wp1*wz1 - 2*Ts*wp0*wp1 + z**2*(Ts**2*wp0*wp1*wz1 + 2*Ts*wp0*wp1))/(-2*Ts*wp1*wz1 - 8*wz1*z + 4*wz1 + z**2*(2*Ts*wp1*wz1 + 4*wz1))
B2 = Ts*wp0*wp1*(Ts*wz1 - 2)/(2*wz1*(Ts*wp1 + 2))
B1 = Ts**2*wp0*wp1/(Ts*wp1 + 2)
B0 = Ts*wp0*wp1*(Ts*wz1 + 2)/(2*wz1*(Ts*wp1 + 2))
A2 = (Ts*wp1 - 2)/(Ts*wp1 + 2)
A1 = 4/(Ts*wp1 + 2)
B2 = -0.238306
B1 = 0.001502
B0 = 0.239808
A2 = -0.521886
A1 = 1.521886
"""
环路设计
使用零极点对消方法,可以将II型补偿器的零极点放置于以下位置:
零点或者极点的频率 | 说明 |
---|---|
开关频率(采样频率)【单周期采样】 | |
补偿器的第1个极点,可以调节穿越频率和低频增益 | |
补偿器的第2个极点,对消ESR零点 | |
补偿器的第1个零点 |
计算的Python代码如下:
详情
import os
import math
import numpy as np
import matplotlib.pyplot as plt
import control as ctrl
import scipy
import csv
Vin = 12.0
Vout = 5.00
IoutMax = 4.0
PWM_Clock = 170.0e6*32
PWM_frequency = 200.0e3 # Switching frequency
PhaseMargin = 50.0 # Phase margin
PWM_Period = int(PWM_Clock/PWM_frequency)
R_load = (Vout/IoutMax)
C = 440 * math.pow(10,-6) #uF
R_C = 53*math.pow(10,-3)/2.0 #mR
Ts = 1.0/PWM_frequency
Gpd = 3300/(56000+51)
Gadc = (math.pow(2,12)-1)/(3.3)
#Gpwm = (1)/(PWM_Period)
Gdac = (3.3)/(math.pow(2,12)-1)
K = 1/(Gpd*Gadc*Gdac)
Vref = Vout*Gpd*Gadc
D =Vout/Vin
Tpwm = 1.0/(PWM_frequency)
Kil = 1.0*0.020*10.0
n=1
L=22e-6 #uH
Vcpp = -((0.18-D)*Kil*Tpwm*Vin*n*n)/L
print("Vcpp:",str(Vcpp*1000.0),"mV")
print("Vcpp x2.5:",str(Vcpp*2.5*1000.0),"mV")
def Bode_plt(index,Input_p0,Input_p1,Input_z1):
fp0 = Input_p0 # Pole at the origin
fp1 = Input_p1 # First pole
fz1 = Input_z1 # First zero
# 计算实例化系数
wp0 = 2*math.pi*fp0
wp1 = 2*math.pi*fp1
wz1 = 2*math.pi*fz1
B0 = Ts*wp0*wp1*(Ts*wz1 + 2)/(2*wz1*(Ts*wp1 + 2))
B1 = Ts*Ts*wp0*wp1/(Ts*wp1 + 2)
B2 = Ts*wp0*wp1*(Ts*wz1 - 2)/(2*wz1*(Ts*wp1 + 2))
A1 = 4/(Ts*wp1 + 2)
A2 = (Ts*wp1 - 2)/(Ts*wp1 + 2)
print("/**")
print("fsw:",str(PWM_frequency),"Hz")
print("Period:",str(PWM_Period))
print("Gpd:",str(Gpd))
print("Gadc:",str(Gadc))
print("Gdac:",str(Gdac))
print("fp0:",str(fp0),"Hz")
print("fp1:",str(fp1),"Hz")
print("fz1:",str(fz1),"Hz")
print("*/")
print("#define BUCK_LOOP_REF ("+str(int(Vref))+")")
print("#define BUCK_LOOP_K ("+str(K)+")")
print("#define BUCK_LOOP_B0 ("+str(B0)+")")
print("#define BUCK_LOOP_B1 ("+str(B1)+")")
print("#define BUCK_LOOP_B2 ("+str(B2)+")")
print("#define BUCK_LOOP_B3 ("+str(0.00)+")")
print("#define BUCK_LOOP_A1 ("+str(A1)+")")
print("#define BUCK_LOOP_A2 ("+str(A2)+")")
print("#define BUCK_LOOP_A3 ("+str(0.00)+")")
print("#define BUCK_SLOPE_VPP ("+ str(Vcpp*2.5) +")")
############ discrete z transfer function. ############
z = ctrl.tf('z')
f = np.logspace(2, 5, 401)
w = 2 * np.pi * f
Hpd = ((B2*z**(-2))+(B1*z**(-1)) +B0 )/(-(A2*z**(-2))-(A1*z**(-1))+1)
Hpd.dt = Ts
mag,phase,omega=ctrl.bode_plot(Hpd,w,dB=True,Hz=True,deg=True,plot=True, grid=True, label='Hpd_'+str(index))
if(0):
# 混合式数位与全数位电源控制实战 65 页
# P.65
fc = 1000.0
Iloop_fz1 = 1/(2*math.pi*R_load*C)
#Iloop_fz1 =fc/5
Iloop_fp1 = 1/(2*math.pi*R_C*C)
TempA = (1.23*fc*Kil*(L+0.32*R_load*Ts))
TempB = math.sqrt(1-4*math.pow(fc,2)*math.pow(Ts,2)+16*math.pow(fc,4)*math.pow(Ts,4))
TempC = math.sqrt(1+ (39.48*C*C*fc*fc*L*L*R_load*R_load)/(math.pow(L+0.32*R_load*Ts,2) ))
Iloop_fp0 = (TempA*TempB*TempC)/(2*math.pi*L*R_load)
else:
Iloop_fp0 = 1020
Iloop_fp1 = 13649.65206620029
Iloop_fz1 = 300
Bode_plt(0,Iloop_fp0,Iloop_fp1,Iloop_fz1)
plt.legend(loc ="lower right")
plt.legend()
plt.show()
"""
Vcpp: 129.09090909090912 mV
Vcpp x2.5: 322.7272727272728 mV
/**
fsw: 200000.0 Hz
Period: 27200
Gpd: 0.05887495316765089
Gadc: 1240.909090909091
Gdac: 0.0008058608058608059
fp0: 1020 Hz
fp1: 13649.65206620029 Hz
fz1: 300 Hz
*/
#define BUCK_LOOP_REF (365)
#define BUCK_LOOP_K (16.985151515151514)
#define BUCK_LOOP_B0 (0.6031112504472649)
#define BUCK_LOOP_B1 (0.005657529143117214)
#define BUCK_LOOP_B2 (-0.5974537213041478)
#define BUCK_LOOP_B3 (0.0)
#define BUCK_LOOP_A1 (1.6468926553672316)
#define BUCK_LOOP_A2 (-0.6468926553672315)
#define BUCK_LOOP_A3 (0.0)
#define BUCK_SLOPE_VPP (0.3227272727272728)
"""
使用Python代码计算出的补偿器的A和B系数如下(对应开发板中的环路参数代码):
/**
fsw: 200000.0 Hz
Period: 27200
Gpd: 0.05887495316765089
Gadc: 1240.909090909091
Gdac: 0.0008058608058608059
fp0: 1020 Hz
fp1: 13649.65206620029 Hz
fz1: 300 Hz
*/
#define BUCK_LOOP_REF (365)
#define BUCK_LOOP_K (16.985151515151514)
#define BUCK_LOOP_B0 (0.6031112504472649)
#define BUCK_LOOP_B1 (0.005657529143117214)
#define BUCK_LOOP_B2 (-0.5974537213041478)
#define BUCK_LOOP_B3 (0.0)
#define BUCK_LOOP_A1 (1.6468926553672316)
#define BUCK_LOOP_A2 (-0.6468926553672315)
#define BUCK_LOOP_A3 (0.0)
#define BUCK_SLOPE_VPP (0.3227272727272728)
实际电路环路测量
测试条件 | |
---|---|
输入电压 | 12V |
输出电压 | 5V |
输出负载 | 1.5Ω |
环路分析仪器 | 鼎阳SDS814X HD + SAG1021I |
按键说明 | 单击按键1 开机,单机按键2关机 |
我们可以使用环路分析仪器在R37两端(LoopA和LoopB)注入信号,测量Buck电路的环路。
测量的结果如下:
测量结果 | |
---|---|
穿越频率 | 4.896 kHz |
相位裕量 | 52.01° |
幅值裕量 | 13.26dB |
参考文档
[1] 《混合式数位与全数位电源控制实战》
[2] Buck-boost converter using the STM32F334 Discovery kit
[3] Designing Stable Digital Power Supplies
提示
本人在此发布博文(包括但不限于汉字、拼音、阿拉伯字母 、图片、影像,以及前述之各种任意组合等等)均为随意敲击键盘所出,用于检验本人电脑键盘录入、屏幕显示的机械、光电性能,并不代表本人观点。如需要详查请直接与键盘发明者及生产厂商法人代表联系。