【数字电源/MATLAB+PLECS】如何进行 Buck 数字电源仿真(五)duty 限幅和抗积分饱和怎么处理
篇章内容第 1 篇Buck 电路介绍与项目准备第 2 篇PLECS 搭建开环 Buck 功率级第 3 篇Buck 电感、电容和开关频率初步计算第 4 篇MATLAB/Simulink 搭建离散 PI 控制器第 5 篇占空比限幅与抗积分饱和第 6 篇软启动功能设计第 7 篇保护状态机怎么锁存故障并关断 PWM第 8 篇负载突变测试与波形分析第 9 篇ADC 噪声、采样延迟和 duty 抖动第 10 篇将仿真控制逻辑整理为 C 风格代码第四章已经把离散 PI 电压环跑通了采样 Vout、计算误差、更新积分项、输出 duty再让 Buck 平均功率级响应。但是这个控制器还缺一个很关键的工程边界duty 不能无限大积分项也不能无限累加。在真实数字电源里PWM 占空比一定有上下限。比如驱动器需要留死区、Bootstrap 高边驱动需要刷新时间、硬件也可能规定最大导通比例。软件上如果只把 duty 输出夹住但积分项还在背后继续累加就会出现积分饱和也就是常说的 windup。这篇就专门处理这个问题。配套 GitHub 仓库digital-power-buck-sim-lab本章提供 MATLAB 离散平均模型仿真脚本、Simulink 控制逻辑截图、CSV 原始数据和正文波形图。正文主波形来自 MATLAB R2024b 运行脚本后的导出结果。本章先回答什么问题本文只做一件事在离散 PI 电压环后面加入 duty 上下限并比较“只限幅”和“限幅加抗积分饱和”的差异。本章会讲清楚duty_raw和duty_cmd为什么要分开为什么只加 Saturation 还不够积分项 windup 是怎么在波形里出现的条件积分 anti-windup 的判断逻辑怎么写Vin 恢复后为什么无抗饱和会产生更高过冲调试时应该同时观察Vout、duty_raw、duty_cmd、integrator和saturation flag本章暂时不处理软启动过压、过流、欠压保护保护状态机ADC 噪声和采样延迟C 代码工程化MOSFET Vds、二极管电流和开关损耗这些内容放到后续章节。第五章只把 PI 输出的边界和积分器边界讲清楚。duty_raw 和 duty_cmd 要分开第四章的 PI 输出可以写成e[k] Vref[k] - Vout[k] xI[k] xI[k-1] Ki * Ts * e[k] duty_raw[k] Dff Kp * e[k] xI[k]如果没有限幅duty_raw会直接送给 PWM。加入 duty 限幅后软件里应该分成两个量duty_cmd[k] clamp(duty_raw[k], duty_min, duty_max)其中变量含义duty_rawPI 计算出来的原始占空比指令duty_cmd经过上下限限制后真正送给 PWM 的占空比duty_min最小占空比限制duty_max最大占空比限制这两个量必须同时观测。如果只看duty_cmd你会看到 duty 被卡在上限但看不到 PI 控制器内部其实还在继续把duty_raw往上推。真正容易造成恢复慢和过冲的正是这个内部状态。本章使用的控制结构本章沿用第四章的 Buck 平均功率级思路在控制器后面加入 Saturation 和 anti-windup gate这张图按下面顺序看位置作用error Vref - Vout计算电压误差Kp / Integrator xI生成比例项和积分项raw duty Dff P IPI 原始输出Duty saturation 0.05…0.55把实际输出 duty 限制在 0.05 到 0.55Anti-windup gate判断积分项是否允许继续更新Averaged Buck plantBuck 平均功率级Vin profile 24-20-24输入电压先跌落再恢复用来触发 duty 上限这里要注意一点Saturation 只限制输出给功率级的duty_cmd它不会自动处理积分项。积分项是否继续更新是 anti-windup gate 的职责。本章仿真工况为了让 duty 限幅真正发生本章故意设置一个会触发上限的输入电压跌落项目数值Vin 初值24VVin 跌落3ms 时从 24V 降到 20VVin 恢复6ms 时从 20V 回到 24VVref12V负载2.4Ω约 5AL22uHC100uFfsw / 控制频率200kHzTs5usKp0.05Ki200duty_min0.05duty_max0.55为什么选duty_max 0.5520V 输入时如果仍想维持 12V 输出理想 Buck 至少需要D 12V / 20V 0.6考虑模型里的 0.02Ω 串联压降本章脚本计算出的需求约为required_duty_at_vin_sag ≈ 0.605而本章把 duty 上限设为 0.55。也就是说Vin 跌落期间控制器就算把 duty 打满也暂时无法维持 12V。这个工况的作用是让读者清楚看到输出能力不够时积分项如果继续累加会在输入恢复后反过来制造问题。只加 duty 限幅会发生什么先看整体结果图里有三条曲线曲线含义No duty limit没有限幅的参考情况用来观察 PI 想要的 raw dutyLimit only只把 duty_cmd 限制到 0.55不处理积分项Limit anti-windupduty 限幅同时限制积分项继续向饱和方向累加3ms 时 Vin 从 24V 掉到 20V。由于duty_max 0.55小于维持 12V 所需的约 0.605所以限幅后的两种控制器都会出现 Vout 下跌。这时不要误解 anti-windup 的作用。抗积分饱和不能突破硬件 duty 上限也不能让一个本来供能不够的工况突然恢复到 12V。它真正解决的是另一个问题当输出已经被硬件上限卡住时不要让积分项继续向错误方向累加。6ms 时 Vin 恢复到 24V。此时两种控制器的差异开始变得明显控制方式Vin 恢复后的最高 Vout读法只加 duty 限幅约 14.62V积分项已经积得很高duty 继续顶在上限输出过冲更高限幅 抗积分饱和约 13.13V积分项没有明显 windupVin 恢复后更快退出饱和这组参数的读法是在同样的功率级、同样的 Kp/Ki、同样的 duty 上限下anti-windup 明显减少了由积分项累加带来的额外过冲。windup 在积分项里怎么看只看 Vout 还不够。真正能说明 windup 的是 integrator。下面这张图把积分项和饱和状态单独画出来3ms 到 6ms 是 Vin 跌落区间。此时 duty 已经被卡在上限Vout 仍然低于 12V误差e[k]为正。如果只加 duty 限幅积分项仍然按下面公式继续加xI[k] xI[k-1] Ki * Ts * e[k]因为误差一直为正xI会一路上升。本章仿真中limit only 的积分项峰值约为limit_no_aw_integrator_peak ≈ 0.670而加入 anti-windup 后积分项峰值约为limit_aw_integrator_peak ≈ 0.0176这就是第五章最关键的观察点duty_cmd 看起来都被卡在 0.55但控制器内部状态完全不同。指标只加限幅限幅 抗积分饱和integrator 峰值约 0.670约 0.0176raw duty 峰值约 1.218约 0.614饱和总时长约 5.53ms约 2.94msVin 恢复后退出饱和约 2.58ms约 0.22ms这个表格说明anti-windup 不是让输出在 Vin 跌落时神奇恢复而是让控制器在恢复条件到来时不被历史积分项拖住。raw duty 和 limited duty 的差异再单独看 duty上半图是只加限幅。duty_cmd被卡在 0.55但duty_raw继续上冲最高到了约 1.218。真实 PWM 不可能输出 121.8% duty但 PI 内部已经把这个“想要更大 duty”的状态记住了。下半图是加入 anti-windup。duty_raw仍然会短暂超过 0.55因为误差确实要求控制器增加 duty。但当控制器判断自己已经处在高限幅并且误差还在要求继续增大 duty 时就暂停积分项继续累加。这样duty_raw不会远离 duty 上限。这也是工程代码里要同时保留两个量的原因duty_raw 用来判断控制器内部想输出多少 duty_cmd 用来实际驱动 PWM如果二者差距越来越大基本就说明控制器已经进入限幅区间需要检查 anti-windup、限流、输入电压和功率级能力。条件积分 anti-windup 怎么写本章采用最容易讲清楚、也最容易落地到 MCU 的条件积分方法。先计算当前原始 dutyduty_raw_pre Dff Kp * e[k] xI[k-1]然后判断是否允许积分项继续更新if duty_raw_pre duty_max and e[k] 0: freeze integrator elif duty_raw_pre duty_min and e[k] 0: freeze integrator else: xI[k] xI[k-1] Ki * Ts * e[k]这段逻辑的含义是状态误差方向积分动作duty 已经顶到上限误差还要求继续增大 duty暂停积分duty 已经顶到上限误差开始要求减小 duty允许积分把积分项拉回来duty 已经压到下限误差还要求继续减小 duty暂停积分duty 已经压到下限误差开始要求增大 duty允许积分把积分项拉回来duty 未触及上下限任意误差正常积分它不是“双保险式”重复限幅。Saturation 的职责是限制实际 PWM 输出anti-windup 的职责是限制积分状态继续向饱和方向累加。两个模块处理的是不同对象一个处理输出命令一个处理内部状态。Vin 恢复后为什么差异最大很多人第一次看 anti-windup会把注意力放在 Vin 跌落期间。其实真正应该看的是 Vin 恢复之后。下面把 6ms 附近放大6ms 时 Vin 从 20V 回到 24V。功率级供能能力恢复了但只加限幅的控制器还保留着很高的积分项。结果是Vin 已经恢复Vout 已经开始升高duty 仍然被历史积分项顶在高位输出继续冲高这就是 windup 最典型的后果。加入 anti-windup 后积分项在限幅期间没有明显堆高。Vin 恢复后duty 能更快退出上限输出过冲也明显降低。本章指标里Vin 恢复后的最高输出电压从约 14.62V 降到约 13.13V降低约 1.49V。本章工程边界这一章完成的是控制器边界处理不是完整电源保护。本章能证明检查项本章证据工程判断duty 上限生效duty_cmd 被限制在 0.55PWM 输出边界可控只加限幅会 windupintegrator 峰值约 0.670只限制输出不够抗饱和有效integrator 峰值降到约 0.0176积分状态边界可控Vin 恢复后过冲降低Vout 峰值从约 14.62V 降到约 13.13V恢复过程更可控饱和退出更快约 2.58ms 降到约 0.22ms控制器不再被历史积分项拖住本章不能证明不覆盖内容原因硬件可以直接上电还没有软启动和保护状态机MOSFET 应力安全平均模型不看开关节点和器件应力过流一定安全本章没有限流环和故障关断最终 Kp/Ki 最优本章重点是限幅和 anti-windup 机制这就是分层的意义第五章只把 duty 和积分项的边界补上软启动和保护状态机继续放到后面。本章常见误区1. 加了 Saturation 就等于 anti-windup不等于。Saturation 只限制实际输出的duty_cmd。如果积分项仍然继续累加控制器内部的duty_raw可能已经远远超过上限。等输入恢复或负载变轻时这个历史积分项会让 duty 继续偏高造成额外过冲。2. anti-windup 能让供能不足时也稳定 12V不能。如果Vin * duty_max本身不足以支撑输出电压anti-windup 也不能突破物理上限。它能做的是在限幅期间保护积分状态让工况恢复后控制器更快回到正常区域。3. 只看 Vout 就能判断 anti-windup 是否正确不够。至少要同时看Voutduty_rawduty_cmdintegratorsaturation flag尤其是duty_raw - duty_cmd的差值。如果这个差值持续变大就要怀疑积分项正在 windup。4. duty_max 可以随便设不能。真实项目里的 duty 上限来自硬件和安全边界包括死区、驱动能力、Bootstrap 刷新、最大导通时间、电感电流、输入电压范围和保护策略。本章使用duty_max 0.55是为了形成清晰的限幅工况真实项目需要按硬件约束重新计算。本篇总结第五章把第四章的离散 PI 电压环补上了两个关键边界duty 输出边界积分状态边界本章最重要的工程结论是duty 限幅只管实际 PWM 输出anti-windup 才管积分项是否继续向饱和方向累加。本章仿真结果表明只加 duty 限幅时integrator峰值约 0.670raw duty峰值约 1.218加入 anti-windup 后integrator峰值约 0.0176raw duty峰值约 0.614Vin 恢复后的 Vout 过冲从约 14.62V 降到约 13.13VVin 恢复后退出饱和的时间从约 2.58ms 降到约 0.22ms下一篇继续处理另一个上硬件前必须补上的模块软启动。软启动解决的是“参考值不能从 0 瞬间跳到 12V”的问题它和本章的 anti-windup 一样都是让控制器从仿真闭环走向工程可用的必要步骤。本章配套文件仓库入口https://github.com/Old-Ding/digital-power-buck-sim-lab类型文件作用教程文章blog/05-duty-limit-anti-windup.md本章正文复现说明docs/05-duty-limit-anti-windup-reproduce.md运行步骤和结果说明MATLAB 主仿真脚本scripts/export_matlab_duty_limit_anti_windup_waveforms.m运行离散平均模型并导出正文波形Simulink 逻辑截图脚本scripts/export_simulink_duty_limit_anti_windup_snapshot.m生成控制逻辑模型和截图Simulink 逻辑模型models/simulink/buck_duty_limit_anti_windup_logic.slx展示 duty 限幅和 anti-windup 的结构关系Simulink 逻辑截图assets/screenshots/05-simulink-duty-limit-anti-windup-logic.png本章控制结构图原始数据waveforms/05-matlab-duty-limit-anti-windup-trace.csv三种控制方式的完整时序数据指标汇总waveforms/05-matlab-duty-limit-anti-windup-summary.csv本章表格中的关键指标正文波形waveforms/05-matlab-*.png本章使用的 MATLAB 主波形运行方式matlab-batchrun(scripts/export_simulink_duty_limit_anti_windup_snapshot.m); exitmatlab-batchrun(scripts/export_matlab_duty_limit_anti_windup_waveforms.m); exit如果 MATLAB 没有加入系统 PATH可以把matlab替换成你本机 MATLAB 的完整路径。技术交流如果你在复现模型、运行脚本或判断 anti-windup 波形时遇到问题可以加入技术交流群交流。本仓库中的模型、脚本、数据和图表可以直接使用交流群主要用于复现答疑和后续技术交流。渠道信息QQ 群嵌入式交流群1056095456加群链接https://qm.qq.com/q/rygrSD2Ddu微信交流微信入口会不定期更新可在 QQ 群内获取提问时建议附上 Simulink 逻辑截图、summary CSV、Vout/duty_raw/duty_cmd/integrator 波形和你自己的判断过程。这样更容易定位问题也更容易形成有效交流。