我们队今年电赛选了电源类题目,用紫光同创的板子做数字电源闭环,仿真里PID调得好好的,一上板输出电压就周期性振荡,示波器看PWM占空比在抖。队友说是ADC采样时刻和PWM载波不同步导致的,也有人说是PID参数离散化没做对。有没有做过数字电源的学长说说,FPGA做电源类赛题到底该怎么对齐采样和载波,避免这种上电就振的问题?
2026年电赛备赛,队伍用国产紫光同创FPGA做电源类赛题,为什么PID环路一上电就振荡,是采样时钟和PWM载波没对齐吗?
4 个回答

先别急着怀疑参数,上电就振荡这个现象,八成是采样和载波没对齐。FPGA里PWM一般是靠计数器跟比较值比大小生成的,ADC触发如果随便用个分频或者跟PWM计数器没关系,那每个周期采到的就是波形上随机的一点,等效于引入一个随占空比变化的延迟,PID看到的是抖动的反馈量,自然越调越振。
排查顺序建议这样:先把PID整个旁路,输出固定占空比,用示波器看输出电压稳不稳,稳了说明功率级和驱动没问题;然后手动让ADC在PWM计数器到零或者到峰值时触发,采一个固定直流输入,看采样值稳不稳;最后再闭环,PID输出先限幅。
对齐做法通常是让PWM计数器到周期中点或零点时产生一个触发脉冲,送给ADC的启动脚,或者用同一时钟域下的状态机控制采样时刻。你们用的紫光同创具体型号和ADC是片内还是外挂的?这个会影响触发路径怎么接。

数字电源闭环里,采样时刻和PWM载波的关系,本质上决定了你这个控制环路到底有没有一个稳定的延迟模型。很多人仿真能过,是因为仿真里默认采样瞬间拿到的是当前时刻的真实值,而实际FPGA里ADC转换要时间,触发到数据回来可能差好几个时钟,再送进PID算完更新比较值,又隔了一段。这几段延迟加起来如果正好落在环路带宽对应的相位裕度上,就会振。
先说对齐这件事。常见的做法是让PWM用一个向上或上下计数的计数器,周期值决定开关频率。上下计数时,计数器到零和到峰值各有一个自然的事件点,通常选在峰值或者谷值触发ADC,这样采样点落在电感电流纹波的中点,避开开关瞬间的尖峰噪声。触发信号从PWM模块引出来,直接连到ADC的启动端,保证两者同源同拍。如果ADC是外挂的SPI接口,那触发后还要等转换完成的中断或标志,这段时间是固定延迟,只要固定,PID里可以当成已知的滞后,问题不大;怕的是它随温度或配置变化。
再说离散化。你在MATLAB或者Python里调的PID,如果是连续的Kp、Ki、Kd,上板前要转成差分方程。位置式还是增量式,积分项有没有做抗饱和,微分项有没有加低通,这些都会影响上电瞬间的表现。特别是上电时输出从零开始,积分项会快速累积,如果限幅没做,占空比一下就冲到极限,然后反馈过冲,再往回拉,就形成低频振荡。这个振荡频率通常比开关频率低很多,示波器上看是包络在动。
还有一个容易被忽略的点是量化误差。ADC位数、PID系数的定点位宽、占空比比较值的分辨率,三者叠加起来,当误差小到一定程度时PID输出会在几个LSB之间跳,这叫极限环。它不一定表现为大振荡,但会让人误以为环路不稳。解决方法是给积分项设一个死区,或者提高占空比分辨率。
排查的时候我建议按这个顺序:第一步,开环固定占空比,确认功率级本身不振荡;第二步,只跑ADC采样,把采样值通过DAC或者串口打出来,看对齐前后波形差别;第三步,闭环但把Ki设为零,只留比例,看能不能稳;第四步逐步加积分。每一步都只用示波器看一个量,别同时改几个地方。
学习路径上,如果你们队里没人做过数字电源,建议先拿一块现成的MCU或者DSP跑一遍经典的平均电流模式控制,把采样、计算、更新这条时序链路摸清楚,再搬到FPGA上。FPGA的优势是并行和确定性延迟,但前提是你真的把每个时钟周期数清楚了。你们现在ADC是片内还是外挂,采样率大概多少?这个决定了触发方案能选多细。

补一个容易被忽略的风险:就算采样和载波对齐了,如果ADC的转换时间和你的PID计算时间加起来超过了半个开关周期,那这个环路在物理上就没法用当前开关频率稳定工作。这时候要么降开关频率,要么换更快的ADC,要么把PID计算流水线化,让它在下一个周期才更新占空比,接受一拍延迟。
举个常见的坑:有人把ADC触发设在计数器过零,但PID算完更新比较值是在计数器已经走过一段之后,结果这个周期用的还是上一周期的结果,等效延迟一个周期。如果开关频率是100kHz,一个周期10微秒,这个延迟在相位上就不少了。验证方法很简单,在PID输出更新那一刻翻转一个IO,和PWM波形一起看,量一下从采样触发到占空比真正变化的时钟数,心里就有数了。
替代做法也有:如果实在对不齐,可以先用固定采样率、跟PWM异步的方式跑,但把PID带宽压得很低,让环路对面那个抖动不敏感。这属于治标,比赛现场应急可以,长期还是建议做成同步。你们板子上ADC和PWM是不是同一个时钟源?这个先确认一下。

先别急着给PID换参数,上电就振这件事,我建议你按「一个周期里到底发生了什么」这条线走一遍,比零散地怀疑采样或离散化更快定位。
数字电源的闭环,本质是每个开关周期采样一次、算一次、更新一次。只要这三件事在时间上错位,PID看到的就不是当前周期的真实状态,而是一个带延迟、带抖动的旧值。仿真里默认采样是理想的、计算是零耗时的,所以你调出来的参数在上板后自然不成立。
具体到紫光同创这类FPGA方案,最常见的错位是这样产生的:PWM靠一个计数器跟比较值比大小生成,ADC触发如果来自一个独立分频,或者来自软件里随手写的延时,那每个周期采样点相对载波的位置就是飘的。哪怕只飘几十纳秒,落在电感电流纹波的斜坡上,反馈量就会随占空比变化而抖动,PID把它当成真实误差去纠,结果越纠越振。
所以第一步不是调参,是让采样点固定下来。做法是让ADC触发信号从PWM计数器派生:上下计数时取峰值或谷值,单向计数时取周期回卷那一刻,触发脉冲直接送给ADC启动端,保证同源同拍。这一步做完,用示波器同时看PWM和一路翻转IO,确认采样确实落在你想要的相位上。
第二步才是离散化的一致性。你仿真里用的PID如果是连续域传函,直接拿系数往FPGA里塞,那积分项和微分项的等效周期跟你实际调用周期对不上,相位裕度会悄悄跑掉。正确做法是把PID按实际采样周期T做离散化,并且保证这个T跟PWM周期严格一致,不能一个用计数器周期、一个用固定分频。
第三步,量化误差累积。定点实现里积分器位宽不够,或者系数截断太狠,小信号下会一直往一个方向漂,表现出来也像低频振荡。这个用仿真对比定点与浮点结果就能看出来,别等到上板才发现。
排查顺序我建议:先开环固定占空比,看功率级本身稳不稳;再固定采样点开环看反馈量稳不稳;最后闭环,PID输出先限幅。三步都过,振荡基本就没了。你们ADC是片内的还是外挂SPI的?这决定了触发到数据回来这段延迟要不要单独补偿。
发表回答
登录后可在本页底部提交回答