Skip to content

19.3 离散时间补偿器设计

上一节我们像做数学实验一样,把连续时间的模拟补偿器「翻译」成了离散时间的数字代码。我们有了双线性映射,有了 Tustin 变换,甚至还有频率预畸变这种精细的手段来保证精度。

但纸上得来终觉浅。

当你真的把那个 Gcd(z) 塞进 MCU 或者 DSP 里,试图让那个 1MHz 的 Buck 变换器稳稳输出 1.8V 时,你会发现现实世界比 s 平面要粗暴得多。

在这一节,我们不谈新的数学工具,我们把所有的东西——采样延迟、计算延迟、抗混叠滤波器——全部扔进同一个环路里,看看那个你引以为傲的「穿越频率」和「相位裕度」到底还剩多少底气。


19.3.1 环路增益:考虑现实的残酷

在数字控制的电源里,环路增益 Td 的定义必须把所有环节都算进去。别漏了任何一个,它们都会在波特图上找你要账。

一个完整的数字控制环路增益长这样(用频率响应表示):

Td(jω)=H(s)Gvd(s)estd|sjωGcd(z)|zejωTs

(式 19.55)

拆解来看,这里发生了几件事:

  1. H(s)Gvd(s):这是老朋友,功率级的控制到输出传递函数,乘以传感器增益。
  2. estd:这是一个纯延迟环节。注意,环路增益里不包括零阶保持器(ZOH)。ZOH 的建模通常是放在 Gcd 的映射过程中去处理的,或者更准确地说是隐含在离散化过程中。但那个实实在在的时间延迟 td——从 ADC 采样到占空比真正更新到 MOSFET 栅极的时间——必须显式地加在这里。
  3. Gcd(z):这是我们在上一节辛辛苦苦设计出来的离散补偿器。

模拟 vs 数字:迟到的代价

如果把式 19.55 和经典的模拟电压模式环路增益(第 9 章的式 9.4)对比,你会发现数字版有两个显著的不同:

  • 那个讨厌的延迟项 estd
  • 补偿器的离散采样特性Gcd)。

延迟这个东西,在低频时看起来人畜无害,但频率越高,它带来的相位滞后就越致命。我们来算一笔账。

示例:延迟是如何吃掉你的相位裕度的

假设我们还在设计那个同步 Buck 变换器。

  • 开关频率 fs=1 MHzTs=1μs)。
  • 目标穿越频率 fc=100 kHz
  • 模拟补偿器:经典的 PID 结构。
    • 低频零点 fL=8 kHz
    • 高频零点 fz=33 kHz
    • 高频极点 fp1=300 kHz
    • 第二个高频极点 fp2=1 MHz(这个我们在模拟里通常放在补偿器里,但在数字里,这个家伙更适合作为抗混叠滤波器放在 H(s) 里)。
    • 中频增益 Gcm=5.45
  • 稳态点V=Vref=1.8 V,输入 Vg=5 V,所以占空比 D0.36

在纯模拟世界里(td=0),这个设计能给你 52 的相位裕度,非常完美。

但在数字世界里,延迟是不可避免的。我们来看三种情况,把它们的相位损失一笔笔算清:

情况 1:神仙般的性能(最小延迟) 假设你的数字控制器极快,A/D 转换和计算几乎瞬间完成,计算延迟 tctrl0。 此时总延迟仅为调制器延迟:td=DTs=0.36μs。 在穿越频率 fc=100 kHz 处,这个延迟会引入多少相位滞后?

Δϕ=ωctd=2π(100×103)(0.36×106)13

结果:原来的 52 裕度瞬间缩水到 5213=39。还能用,但不舒服了。

情况 2:现实世界的性能(中等延迟) 假设 A/D 和计算花了半个开关周期,tctrl=Ts/2=0.5μs。 总延迟:td=DTs+Ts/2=0.86μs。 计算相位滞后:Δϕ31结果:相位裕度跌到 5231=21。这已经是在边缘试探了,稍微来点参数漂移就可能震荡。

情况 3:糟糕的实现(最大延迟) 假设你的代码写得比较随意,或者 MCU 很慢,计算占满了一个周期,tctrl=Ts=1μs。 总延迟:td=DTs+Ts=1.36μs。 计算相位滞后:Δϕ49结果:相位裕度仅剩 5249=3结论:这已经不是控制了,这是在试图驯服一头野马,而且大概率会被甩下来。

这个例子极其残酷地指出了一个事实:在高频开关电源的数字控制中,环路延迟是核心限制因素。如果你想保持 100kHz 的带宽,你的代码必须跑得非常快。


19.3.2 设计流程:五步走

基于前面的教训,我们需要一套标准化的设计流程,把延迟、抗混叠滤波器和离散化全部统筹起来。这里有一个「五步走」策略,它能保证你从模拟设计平滑过渡到数字实现,并且少踩坑。

步骤 1:定义对象(带上延迟)

首先,我们要写出未补偿的环路增益 Tud(s)。注意,这里必须把你要用的延迟 td 和抗混叠滤波器 H(s) 都算进去。

Tud(s)=H(s)Gvd(s)Gdelay(s)=H(s)Gvd(s)estd

(式 19.58)

这里有个细节:抗混叠滤波器 H(s) 通常是一个低通滤波器。如果你在模拟 PID 设计里有一个高频极点(比如 fp2),把它挪到 H(s) 里作为抗混叠滤波器极点是极其明智的。这样你的数字补偿器 Gc(s) 就可以专注于 PID 的极零点布置,不用管那个高频噪声的脏活了。

步骤 2:模拟先行

别一上来就写差分方程。先在 s 域把模拟补偿器 Gc(s) 设计好。

  • 使用第 9 章讲过的经典设计法(K因子、手工极零点布置等)。
  • 注意:在 Gc(s) 里,不要包含那个高频滚降极点(fp2),因为我们在第一步已经把它移到 H(s) 里了。
  • 调整:考虑到延迟 td 会在 fc 处吃掉相位,你可能需要在模拟设计阶段就预留一些额外的相位裕度,或者调整零点位置来补偿。

步骤 3:离散化映射

拿到 Gc(s) 后,用我们上一节的双线性映射把它变成 Gcd(z)

关键技巧:强烈建议使用带预畸变的双线性映射。 设置预畸变频率 fprewarp 等于你的目标穿越频率 fc

fprewarp=fc

(式 19.59)

这样做能保证在最重要的穿越频率点 fc 处,数字补偿器的增益和相位与模拟设计完美一致。这是最稳妥的打法。

步骤 4:验证闭环

Gcd(z) 代入完整的环路增益公式(式 19.55),画出 Td(jω) 的波特图。

检查清单

  1. 穿越频率 fc 对吗?
  2. 相位裕度(PM)够吗?
  3. 如果不对,是延迟太大了?还是预畸变没用对?

这一步一定要用 MATLAB 或 Python 跑一下,肉眼算 z 域的相位是找死。

步骤 5:代码实现

验证 OK 后,就可以把 Gcd(z) 转换成代码了(下一节 19.4 会详细讲怎么用级联型或者并联型结构来实现它,以及如何处理积分饱和)。


19.3.3 实战演练:重新设计那个 100kHz 环路

光说不练假把式。我们再把刚才那个同步 Buck 变换器的例子完整走一遍。

设计目标

  • 输入 Vg=5 V,输出 Vref=1.8 V
  • L=1μHC=200μFfs=1 MHz
  • 穿越频率 fc=100 kHz,相位裕度 PM=52

已知条件

  • 功率级传递函数参数:Gd0=5fesr=1 MHzf011.3 kHzQ2.3
  • 延迟假设:假设我们用了一款很给力的 DSP,计算延迟极小,td=DTs=0.36μs
  • 抗混叠滤波器:我们在 H(s) 里放入一个 fp2=1 MHz 的低通极点。

第一步:重整 PID 参数

因为延迟 td100 kHz 处引入了 13 的相位滞后,我们不能直接照搬模拟 PID 的参数。 我们需要让 PD 部分提供更大的超前相位。

  • 目标超前相位:原来的需求 + 补偿延迟的损失 52+13=65
  • 根据模拟设计公式(式 9.57),为了得到 65 超前,我们需要调整零极点位置:
    • 新零点 fz=22 kHz(模拟版是 33 kHz,往前挪了一点以增加相位提升)。
    • 新极点 fp1=450 kHz(模拟版是 300 kHz,往后挪一点以拉开跨度)。
  • 低频积分零点 fL=8 kHz 保持不变。

第二步:计算中频增益

为了达到 100 kHz 的穿越频率,我们需要重新计算中频增益 Gcm

Gcm=fzfp1(fcf0)21Vg3.5

(式 19.62)

第三步:映射到 Z 域

现在我们有了新的模拟补偿器 Gc(s)(式 19.61 的参数已更新)。 利用预畸变双线性映射,且 fprewarp=fc=100 kHz,我们得到:

Gcd(z)=31.7593(z0.9493)(z0.8654)(z1)(z+0.1881)

(式 19.63)

你可以看到这个传递函数的系数非常具体,没有任何含糊。这就是我们要写进代码里的那个东西。

第四步:验证

最终结果是这样的:把模拟控制器(无延迟)和数字控制器(包含 td=0.36μs 延迟)的波特图叠在一起看。

你会发现:

  1. 增益曲线:几乎完美重合。这正是带预畸变双线性映射的功劳。
  2. 相位曲线:在 100 kHz 处,虽然有点偏差,但我们成功地把相位裕度拉回了目标值附近。
  3. 结论:通过预先在模拟设计阶段补偿延迟的影响,并在离散化时使用预畸变,我们成功地在数字域复现了模拟域的性能。

19.3.4 代码背后的故事(MATLAB 脚本解析)

最后,我们来拆解一下生成这些波形的 MATLAB 脚本。这不仅仅是画图,这其实是数字控制设计的标准验证流程。

matlab
 1 % Synchronous Buck converter parameters
 2 Vg = 5;  Vref = 1.8; D = Vref/Vg; % Input and reference voltages, duty cycle
 3 L = 1e-6;  RL = 30e-3;           % Inductance and series resistance
 4 C = 200e-6; Resr = 0.8e-3;       % Capacitance and capacitor ESR
 5 fo = 1/(2*pi*sqrt(L*C));         % Pole frequency
 6 R = 1000;                        % Load resistance
 7 fs = 1e6; Ts = 1/fs;             % Switching frequency and period
 8 
 9 s = tf('s'); z = tf('z',Ts);     % Define s and z

前 9 行是纯粹的背景设置。定义了 L、C、Resr 这些物理参数,以及最重要的 sz 两个算子。注意 tf('z', Ts) 这一步,它帮我们处理了采样时间的关联。

matlab
11 % Open-loop control to output transfer function
12 Gvd = Vg*(Resr+1/s/C)/(Resr + 1/s/C + s*L + RL); 
13 fp2 = 1e6; H = 1/(1 + s/2/pi/fp2);      % Sensor transfer function
14 Tu = H * Gvd;                            % Uncompensated loop gain, no delay

12-14 行:构建功率级模型。 这里 H(s) 直接把那个 1 MHz 的极点加进去了,这就是我们的抗混叠滤波器。

matlab
16 % Analog PID compensator
17 fc = 100e3;                         % Cross-over frequency
18 fL = 8e3; fz = 33e3; fp1 = 300e3;   % Corner frequencies (Original Analog Values)
19 Gcm = sqrt(fz/fp1)*(fc/fo)^2/Vg;    % Mid-frequency gain
20 % Analog compensator transfer function
21 Gc = Gcm*(1 + 2*pi*fL/s)*(1 + s/2/pi/fz)/(1+s/2/pi/fp1); 
22 T = Gc*Tu;                           % Loop gain with analog compensator

16-22 行:这是作为参照组的模拟补偿器设计。注意这里的参数(fz = 33e3 等)是原始模拟值,还没考虑延迟补偿。

matlab
24 % Uncompensated loop gain, including delay
25 td = D*Ts;                    % Delay in the digital control loop
26 Tu.IODelay = td;              % Delay
27 Tud = c2d(Tu,Ts,'impulse');   % Mapping of Tu with delay

24-27 行这是数字设计的关键转折点。

  • 我们计算了延迟 td
  • 我们把这个延迟作为属性 IODelay 赋给了 Tu。在 MATLAB 里,这是处理纯延迟最干净的方法。
  • c2d(..., 'impulse'):这一步把带延迟的连续模型 Tu(s) 离散化成了 Tud(z)
matlab
28 % Analog PID compensator redesigned for digital implementation
29 fL = 8e3; fz = 22e3; fp1 = 450e3;    % Corner frequencies (New values!)
30 Gcm = sqrt(fz/fp1)*(fc/fo)^2/Vg;     % Mid-frequency gain
31 Gca = Gcm*(1 + 2*pi*fL/s)*(1 + s/2*pi*fz)/(1+s/2*pi/fp1);
32 % Digital compensator transfer function
33 Gcd = c2d(Gca, Ts, 'prewarp', 2*pi*fc);
34 Td = Tud*Gcd;                         % Loop gain with digital compensator

28-34 行这是数字补偿器的生成过程。

  • 注意看第 29 行:fzfp1 的值变了!这正是我们为了补偿 13 相位滞后而做的重新设计。
  • 第 33 行:c2d(..., 'prewarp', ...)。预畸变频率设为了 2πfc。这行代码直接把设计好的模拟补偿器变成了我们需要的 Gcd(z)
matlab
36 % Compare magnitude and phase responses of T and Td
37 options = bodeoptions; options.Grid = 'on'; 
38 options.FreqUnits = 'Hz';  options.XLim = [100, 500e3]; 
39 bode(T, 'k', options); hold on; 
40 bode(Td, 'b', options);

剩下的就是画图比对了。

这个脚本不仅仅是一个绘图工具,它是一个完整的数字控制环路验证模板。下次你设计任何数字电源,把这个脚本里的 L、C、fs 换掉,调整一下 fz/fp1,你就能得到属于你的波特图。

💡 为什么「五步走」非要先做模拟再做离散:很多新手一上来就想直接在 z 域里布置零极点,结果通常是一团乱麻——因为 z 平面的极零点和我们脑子里那套「频率/相位」直觉是错位的(z=1 是直流,z=1 是奈奎斯特,单位圆才稳定)。先在 s 域把熟悉的 PID 调好,再靠预畸变「翻译」过去,本质上是借模拟域这套成型的工程直觉当脚手架,离散化只负责忠实搬运。这就是为什么工业界几乎没人直接在 z 域从头画补偿器。

还记得上一节末尾那个「一键操作」的承诺吗?这个脚本兑现了那个承诺。


参考说明:参考自 geqianQWQ 同学阅读《Fundamentals of Power Electronics》的笔记,仅作理解线索;本文为结合自己理解重新整理的学习笔记,不涉及对原书的复制或翻译。

面向嵌入式学习者的硬件学习笔记