一般经验

前馈帮助PI输出更快达到稳定。前馈值若使用滤波,滤波越狠,前馈越滞后,非但不能帮助PI更快稳定,还可能会带来副作用。通常前馈还需要乘以一定系数(0.8~0.9)。

双环PI的控制器通常电流环不容易出现问题,如果出现等幅震荡,通常是电压环有问题。

空载或者启动阶段电流太小,双向Buck/Boost的输入输出侧如果有很大的电容或者电池,两侧会互充,电感电流时正时负。为了避免这个情况,可以关闭拓扑的副管,走体二极管续流,从而变成异步的Buck/Boost。

闭环带宽越大,0dB的范围越大,理论跟踪效果也就越好。但是带宽太大,低频段的开环增益往往被抬升太高,系统容易不稳定。

直觉上通常系统是非奇异而连续变化的,即并联一个很大的电阻,和未并联,差别不会太大。debug时变化点往往出现在比例上变化大的地方,如空载满载等。

满载时设计留足余量的控制器在空载不一定能用。带载时一般比空载时稳定一些。

(半桥)LLC死区太小,MOS管电容下降无法到0v,也就无法实现ZVS。LLC死区太大,MOS管体二极管导通后又关闭,然后MOS管电容与谐振腔的电感电容一起振荡,导致桥臂中点电压浮动。

如何实现恒流恒压:双环竞争,输出电流环和输出电压环。如何实现功率限制:根据最大功率计算输出电流环参考电流即可。如何模拟PV源:动态调整最大功率,在最大功率点左右按比例线性衰减功率(电流环参考电流)即可。

双环竞争算法参考:

  1. 基于半桥谐振变换器的控制策略研究 - 道客巴巴 (doc88.com) P61。
  2. [开关电源 软件算法]电压电流双环竞争-CSDN博客

为什么双环PI

为什么设计成双环PI?为什么、以及何时会出现近等幅震荡?

graph LR
in((Vref)) --> 电压PI
--> 电流PI
--> add1(("+"))
--> L["1/Ls"]
-- "iL(s)" --> C["1/Cs"]
--> out(("vo"))

vo((vo)) -.-> 电压PI
iL((iL)) -.-> 电流PI
前馈((前馈)) -.-> add1

以上图空载时Buck控制框图为例(后续省略前馈)。通常电流环带宽远大于电压环带宽,因此电流PI连同其控制对象 (1/Ls) 一起形成闭环时,传递函数可以看成1。此时直接就化简掉了一个环路,变成下面这个样子:

graph LR
in((Vref)) --> 电压PI
-- "iL(s)" --> C["1/Cs"]
--> out(("vo"))
vo(("vo")) -.-> 电压PI

由此发现,设计成双环PI后,每个环的控制对象都是一阶的,因此控制效果比直接控制二阶的系统要简单,并且参数设计也容易。不过这个条件并非一定要满足的。

为什么震荡

忽略内环,电压PI控制器的传递函数为:$K_p(1+\frac{K_i}{s})$,整个电压环的开环传函为:

$$
K_p \frac{1}{Cs} + K_pK_i \frac{1}{Cs^2}
= K_p(\frac{s+K_i}{Cs^2})
$$

闭环特征方程为:

$$
Cs^2 + K_ps+K_p K_i = 0
\newline
\Rightarrow
s= \frac{-K_p \pm \sqrt{K_p^2 - 4K_pK_iC}}{2C}
$$
从特征根上看,如果$K_p^2 - 4K_pK_iC < 0$,根就一定具有虚部,从而发生震荡。特征根的虚部是振荡频率,因此震荡频率为:
$$
\omega_d = \left | \frac{\sqrt{K_p^2 - 4K_pK_iC}}{2C} \right | \space \space rad/s
$$
如果$K_p$越小、$C$越大,这个极点就越接近虚轴,震荡存在的时间就越长。以$C=2000\mu F$,$K_i=0.01$为例,其调节时间越达到1.56s,在100ms内观察几乎是等幅震荡了。注:这个系统与一般二阶系统不同,因而调节时间不能用一般的形态进行计算,可以通过仿真观察。

如果电流环带宽不远大于电压环带宽?

系统不一定不稳定。只是条件越不满足,电压环Bode图变形越严重。外环控制的对象不再那么简单,只是对分析来说变得复杂。先说结论:如果电流环带宽不远大于电压环带宽,电流环无法忽略,会使得系统震荡的极点的位置会发生偏移(朝着s右半平面),更加容易发生震荡、不稳定的情况。

仿真试试:

此时不能忽略内环,容易得知此系统存在2个零点(由I导致)和4个极点(由I和控制对象共同导致)。我们将内环也考虑在内,通过matlab仿真:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
% syms s C R Kp Ki Kpi Kii L;
syms s;
Kp = 1.18421; Ki = 10000; % 电压环
Kpi = 0.5; Kii = 6000; % 电流环
C = 2000e-6; L = 150e-6;

%% 考虑内环
Gi = Kpi*(1 + Kii/s) * (1 / (L*s)); % 电流环与控制对象
[n, d] = numden(Gi);
Go = tf(sym2poly(n), sym2poly(d));
Gc = feedback(Go, 1);
B = bandwidth(Gc);
disp("电流环带宽: " + B + "rad/s");

Gv = Kp*(1 + Ki/s) * (Gi/(1+Gi)) * (1/(C*s));

[n, d] = numden(Gv);
Go = tf(sym2poly(n), sym2poly(d));
Gc = feedback(Go, 1);
B = bandwidth(Gc);
disp("考虑内环 电压环带宽: " + B + "rad/s");

figure(1);
subplot(1, 3, 1); step(Gc);
subplot(1, 3, 2); pzmap(Gc);
subplot(1, 3, 3); bode(Gc);

%% 忽略内环
Gv = Kp*(1 + Ki/s) * (1/(C*s)); % 电压环与控制对象

[n, d] = numden(Gv);
Go = tf(sym2poly(n), sym2poly(d));
Gc = feedback(Go, 1);
B = bandwidth(Gc);
disp("忽略内环 电压环带宽: " + B + "rad/s");

figure(2);
subplot(1, 3, 1); step(Gc);
subplot(1, 3, 2); pzmap(Gc);
subplot(1, 3, 3); bode(Gc);

disp("忽略内环 震荡频率: " + imag(sqrt(Kp^2 - 4*Kp*Ki*C)/2/C) + "rad/s")
1
2
3
4
5
输出:
电流环带宽: 7611.2137rad/s
考虑内环 电压环带宽: 4712.4597rad/s
忽略内环 电压环带宽: 3818.8512rad/s
忽略内环 震荡频率: 2415.2439rad/s

执行以上代码时还会生成阶跃响应、零极点、bode图,此处不展示。

不忽略内环,此时经过精挑细选得到的电压环$K_p$参数使得系统调节时间达到9190s,频率约为0.5Hz,而忽略内环时,震荡频率为2415rad/s,相差很大。不忽略内环,若电压环$K_p$取略大,系统迅速发散;取略小,系统几秒内迅速稳定。也就是,$K_p$取大时,这两个参数使得一对极点从左到右跨越了虚轴。而忽略内环时,电压环$K_p$取值很难导致系统发散。

忽略内环时,调节时间只与$K_p$有关。不忽略内环时,调节时间与其他参数相关,使得系统震荡的极点的位置发生偏移(朝着s右半平面),从而更加容易不稳定。

实践:直觉上通常系统是非奇异而连续变化的。在上面的忽略电流环的研究中,发现有一对极点可能会很接近虚轴,因此如果电流环不可忽略,即电压环带宽越来越接近电流环带宽,那么这一对极点就越来越可能突破虚轴到右半平面去,从而造成系统发散。但是在这个过渡过程中,系统是由震荡收敛到震荡发散的,或者表现为等幅震荡。

扩展1:

在控制工程中,几乎所有的控制系统都是高阶系统,分析高阶系统的基本思路是将其简化为一、二阶系统。
工程上常采用闭环主导极点的概念对高阶系统进行近似分析,得到动态性能指标的估算公式。
对于不能简化为低阶系统的高阶系统,可采用数值计算的方法进行仿真,得出系统的瞬态性能指标。
来源:高阶系统分析 (xjtu.edu.cn)

扩展2:

在设计外环的时候,内环的闭环传函应该和外环实际被控对象合并在一起整体作为外环控制的被控对象。

实际中,内环控制的闭环传函最理想最简化的形式应该是一个一阶惯性环节,而外环对应的实际被控对象模型最简单的情况一般也是一个一阶惯性环节。

所以对于外环设计而言,其控制对象至少是一个二阶系统,那么其第二个极点后,幅频特性曲线的斜率变为-40dB/dec,相位滞后会趋向-180°.

这样一个对象,如果使用PI控制器,要保证足够的稳定裕度并达到回答开头所述的期望控制效果,显然你的环路带宽不可能超过被控对象的第二个极点。

所以,这就限制了外环的带宽。

现在就剩下一个问题,被控对象第二个极点是内环闭环传函的极点还是外环对应的实际被控对象的极点。

①如果第二个极点是内环的极点,那么很明显你就可以知道了,外环的带宽为啥不会明显超过内环带宽。
②如果第二个极点是外环对应的实际被控对象的极点,那么外环带宽实际上有可能超过内环带宽,而系统仍然稳定运行。

工程实际中,通常往往是第一种情况,所以我们会看到,一般外环带宽会比内环带宽低。而为了简化分析方便处理,又会将内环与外环解耦,使得外环带宽往往设置到低于内环带宽的1/10.

作者:张先生
链接:https://www.zhihu.com/question/398204421/answer/3240171225
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

等幅震荡

在现实世界调Buck电路参数时候,发现有些参数(电压环$K_p$比$K_i$小很多时)在开启前馈时会使得输出出现较大幅值的等幅震荡,并且频率为电压环的带宽;当给前馈乘以0.85系数后,这个震荡会衰减;如果不要前馈,震荡就完全消失了。这个现象非常神奇。个人猜测,原因主要有几个:

  1. 震荡收敛但速度慢,观察起来就像是等幅震荡?
  2. 模型参数动态变化?
  3. 干扰信号混入?
  4. 离散化?

通过前面仿真,发现简单的二阶S域模型仿真无法仿真出在1附近等幅震荡的阶跃响应,要么震荡收敛但速度慢(对参数要求很高,几乎不可能),要么迅速发散。当闭环系统特征根出现虚部,就有谐振峰。通过后文知道,电压环带宽与震荡频率在一定条件下是相近的,因此,电压环截止频率附近存在谐振峰,可以将特定频率的干扰信号放大。

震荡频率 = 电压环带宽?

如何证明,电压环$K_p$比$K_i$小很多时,电压环带宽(截止频率)是震荡频率?

已知系统特征根的虚部是振荡频率,如果忽略到只剩下电压环,那么也就是有一对极点的虚部绝对值等于电压环的截止频率。电压环的截止频率为:
$$
K_p(1+K_i/s)\frac{1}{Cs}=0dB=1
\newline
\Rightarrow
s=
\begin{cases}
\frac{2K_i}{\sqrt{(K_p + 4CK_i)/K_p} - 1}
\newline
-\frac{2K_i}{\sqrt{(K_p + 4CK_i)/K_p} + 1}
\end{cases}
$$
当$K_p \ll 4K_iC$时,有:
$$
\begin{cases}
\omega_g = \frac{2K_i}{\sqrt{(K_p + 4CK_i)/K_p} - 1}
\approx \frac{\sqrt{K_pK_i}}{C}
\newline
\omega_d = \frac{\sqrt{K_p^2 - 4K_pK_iC}}{2C}
\approx \frac{\sqrt{K_pK_i}}{C}
\end{cases}
$$
因此,系统的震荡频率在一定的情况内确实非常接近电压环的截止频率。

何时换参

graph LR
in((Vref)) --> 电压环
-- "Iref" --> 电流环
-- "Duty/Gain/..." --> M([调制])
--> 控制对象

如果PI输出已经趋向于0,那么积分器输出也应该是0附近,此时可以直接换参数,并清空积分器。这种情况常见于电压环在空载时的输出。但是对于电流环,其输出的值通常应该是较为连续并且非趋向于0的(如占空比、增益等),如果这个值发生跳变,例如清空了积分器,那么电流环输出会瞬间趋向于0,输出侧的大电容可能就会反向给输入侧充电(双向拓扑),然后导致输入侧电压被拉高,产生尖峰。以双向Boost为例,$V_o=\frac{1}{1-D}V_{in}$,当$D \to 0$,输入就直接等于输出了。若是双向Buck,$V_o=D\cdot V_{in}$,当$D\to 0$,输入可能会被拉高,相当于反向升压了。

所以,如果PI输出非0,并且靠积分器积累到了较大的值,此时换参数不可清空积分器。通过前馈可以减小PI的输出,一定程度上能缓解换参数带来的不良影响。

如果控制误差较大,并且换参数后$K_p$的值变化也大的情况下换参数,输出值跳变可能很大,对系统可能造成不良影响,可以考虑提前计算出换参跳变值,然后加到积分器中

$$
\sum = \sum + \space err[n-1](k_p - k_p’)
$$

下面是Matlab写的一个双向Boost控制换参的仿真:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
clear boostPlant;
clear iLoopCtrl;
clear vLoopCtrl;
clc;

vParam = [8, 2; 0.01, 4]; % 这里有两组电压环参数 一行一组
iLParam = [0.01, 300];

global vLoopPIInt iLLoopPIInt fs Ts;
vLoopPIInt = 0;
iLLoopPIInt = 0;
fs = 80e3;
Ts = 1/fs;

t = 0:Ts:0.5;
len = length(t);
x = 1 + sin(2*pi*1000*t);
x = 1;
iLLoopPIOut = zeros(len, 1);
plantVOut = zeros(len, 1);
plantVin = zeros(len, 1);
plantILOut = zeros(len, 1);


vLoopPIOut = zeros(len, 1);
useParamRec = zeros(len, 1);

vRef = 100;
usedVLoopParam = 1;

swFlag = 0;

for i = 2:len
useParamRec(i) = usedVLoopParam;
vErr = vRef - plantVOut(i-1);
vLoopPIOut(i) = vLoopCtrl(vErr, vParam(usedVLoopParam, :));

iErr = vLoopPIOut(i) - plantILOut(i-1);
iLLoopPIOut(i) = iLoopCtrl(iErr, iLParam);

% if t(i) > 0.25 % directly change duty
% iLLoopPIOut(i) = 0.1;
% end

[plantVOut(i), plantVin(i), plantILOut(i)] = boostPlant(iLLoopPIOut(i));

% if (abs(vErr) < 2)
% vLoopPIInt;
% end
if (abs(vErr) < 1 && swFlag == 0) % 误差小于一定值 换电压环参数
usedVLoopParam = 2;
gap = 0;
% gap = vErr*(vParam(1, 1) - vParam2(1, 1));
vLoopPIInt = vLoopPIInt + gap;
% iLLoopPIInt = 0;
swFlag = 1;
end
end

figure(1);
hold on;
plot(t, plantVOut);
plot(t, plantVin);
plot(t, plantILOut);
plot(t, vLoopPIOut);
plot(t, iLLoopPIOut*100);
plot(t, useParamRec*100);
legend(["VOut", "Vin", "IL", "vLoopPIOut", "iLLoopPIOut", "useParamRec"]);

function out = vLoopCtrl(err, params)
global vLoopPIInt Ts;
satuRange = [-60, 60];
kp = params(1);
ki = params(2);
vLoopPIInt = vLoopPIInt + ki * err * Ts;
vLoopPIInt = satu(vLoopPIInt, satuRange);
out = satu(kp*err + vLoopPIInt, satuRange);
end

function out = iLoopCtrl(err, params)
global Ts iLLoopPIInt;
if isempty(iLLoopPIInt)
iLLoopPIInt = 0;
end
kp = params(1);
ki = params(2);
iLLoopPIInt = iLLoopPIInt + ki * Ts * err;
iLLoopPIInt = satu(iLLoopPIInt, [0.01, 0.85]);
out = satu(kp*err + iLLoopPIInt, [0.01, 0.85]);
end

function [vout, vin, iLout] = boostPlant(Duty)
global Ts;
vs = 50;
L = 15e-6;
C = 100e-6;
Cin = 50e-6;
R = 7500;
rin = 1;
persistent iL vo vcin;
if isempty(iL)
iL = 0;
vo = 0;
vcin = 0;
end
iL = iL + 1/L * (vcin - (1-Duty) * vo) * Ts;
vo = vo + 1/C * ((1-Duty)*iL - vo/R) * Ts;
vcin = vcin + 1/Cin * ((vs - vcin)/rin - iL) * Ts;
vcin = satu(vcin, [-vs*2, vs*2]);
iL = satu(iL, [-120, 120]);
vo = satu(vo, [-400, 400]);
vout = vo;
iLout = iL;
vin = vcin;
end

function y = satu(x, range)
if x > range(2)
y = range(2);
elseif x < range(1)
y = range(1);
else
y = x;
end
end

动态带宽PI控制

一套PI参数无法适用于所有情况,可以调整PI带宽,让系统暂时工作在极端情况下,达到一定情况时,再动态修改PI参数,确保大部分工作时间系统都稳定。

待完善。