开环控制没问题,闭环一加PID舵机就抖。采样周期设的1ms,PID参数用MATLAB整定过,定点位宽16位。怀疑是编码器读数跨时钟域没处理好,但不确定。该怎么系统排查?
2026年FPGA大赛经验:省赛用安路EG4做「多路舵机+编码器闭环控制」,PID一上就抖,是采样周期、定点位宽还是时钟域的问题?
5 个回答

先别急着怀疑定点位宽,16位在舵机这种应用里其实够用,真正容易翻车的是编码器和PID不在同一个时间基准上。你可以按这个顺序排:第一步,确认编码器读数是先同步到控制时钟域再进PID的,安路的板子上如果编码器走的是异步输入,直接拿来算差分就是随机跳变,PID对速度项特别敏感,一抖就是它。第二步,把PID输出先限幅、积分单独做抗饱和,定点乘法要留意中间结果位宽,16位输入乘16位系数会到32位,如果你截断回16位时舍位方向不对,低速段会来回震荡。第三步,拿ILA或者安路自己的在线逻辑分析抓编码器原始计数、同步后计数、PID输出这三路,看抖动周期是不是跟采样周期或编码器边沿对齐,对齐了基本就能定位。
给你一个常见小例子:有人开环好好的,闭环一上舵机嗡嗡响,最后发现是编码器四倍频在1ms里只走了两三个计数,速度环算出来的值分辨率太粗,PID一直在两个数之间跳。这种情况要么拉长采样周期,要么把速度环改成位置环加低通。风险在于,如果你一上来就调PID参数去压抖动,很可能把真实问题掩盖成参数问题,省赛现场再改就来不及了。建议先做个最小闭环:固定占空比让舵机转,只跑编码器读数和显示,确认读数平滑再上PID。你那块EG4的编码器接口是走普通IO还是专用计数资源,这个条件不同排查路径会差挺多。

这个问题表面是PID抖,根子上是你在用软件思维做一个硬件实时系统,排查顺序其实就是把「谁的时间基准不干净」一层层剥开。
开环没问题说明执行链路和舵机驱动是好的,闭环一加就抖,说明反馈量或者反馈的时机出了问题。编码器是异步信号,它的边沿和你的控制时钟没有任何关系,如果不做两级同步再计数,计数器可能在同一个时钟沿采到亚稳态,读数偶尔跳一个大数,PID的微分项直接把它放大成抖动。所以第一件事是确认编码器信号有没有同步到控制时钟域,这个不确认,后面调什么都是盲调。
确认完之后看采样周期。1ms对舵机够用,但要看你编码器一圈多少线、减速比多少。如果1ms里只走几个计数,速度值本身量化噪声就很大,PID再准也是在噪声上做运算。常见做法是速度环采样周期适当放长,或者对速度做滑动平均,位置环可以保持快一点。
再往下才是定点位宽和溢出。16位本身不丢人,问题在于中间运算。位置误差乘Kp、速度乘Kd,两个16位一乘就是32位,如果你在中间某一步截回16位,低位信息丢了,积分项又在慢慢累积,就会出现低频摆动。这时候要看积分有没有单独限幅,输出有没有饱和处理,饱和时积分是不是还在涨。
排查路径我建议固定成:先看波形,ILA同时抓编码器原始、同步后计数、PID输出和PWM占空比,找抖动周期和谁对齐;再单环测试,先只跑位置环P,再加I,最后加D,每加一项看波形变化;最后才回去调参数。省赛时间紧,很多人一抖就回去改Kp,结果把时钟域问题调成了参数问题。
如果非要取舍,前期花半天把同步和采样周期理清楚,比后面两天调参数划算得多。你现在的编码器是增量式还是绝对式,接口那边有没有已经做过滤波,这个决定了同步电路要不要额外加消抖。

先别把锅甩给16位定点位宽,舵机闭环抖到这个程度,位宽一般不是主因。你可以按这个顺序过一遍。第一步,编码器输入是不是两级触发器同步过再进计数器。异步边沿直接喂给同步逻辑,计数器偶尔跳一个大数,PID的D项会立刻把它放大成抖动,开环看不出来正是因为开环不用反馈。第二步,速度环的采样周期是否和位置环一样是1ms。舵机一圈线数乘减速比再除以1ms,如果算下来每个周期只走两三个计数,速度值本身就是量化噪声,MATLAB整定出来的参数再漂亮也是在噪声上做运算,这时候要么把速度环放慢,要么对速度做滑动平均。第三步才是定点溢出和积分饱和,16位输入乘16位系数中间结果是32位,你截回16位时如果直接丢低位,低速段会来回震,同时积分项要单独限幅。排查工具上,用安路自己的在线逻辑分析抓三条线:编码器原始计数、同步后计数、PID输出。看抖动周期跟谁对齐,跟采样周期对齐就是量化或积分问题,跟编码器边沿对齐基本就是跨时钟域。另外提醒一句,省赛评审看的是系统稳定性,别为了追响应速度把参数压到临界点,留点余量比跑分好看更划算。你板子上编码器是单端还是差分输入,接的是普通IO还是带时钟能力的管脚?

先说结论:按你描述的现象,最值得先怀疑的不是16位位宽,而是反馈量的时间基准干不干净。舵机这类执行机构本身带宽就不高,16位定点在位置环里通常够用,真正让闭环抖起来的是编码器读数里混进了跨时钟域的随机跳变,PID的微分项又恰好是个高通放大器,一跳就被放大成抖动。
所以我建议你沿一条主线走:先把反馈路径的时序正确性钉死,再谈参数和位宽。
第一步,确认编码器信号进FPGA后有没有做两级同步再进计数器。编码器输出和你的控制时钟没有任何相位关系,如果直接拿异步边沿去驱动同步计数器,偶尔的亚稳态会让计数值瞬间跳一个大数。开环时你不看反馈,所以感觉不到;闭环一上,这个跳变立刻通过D项变成舵机抖动。做法是先把A/B相各自打两拍同步到控制时钟域,再做四倍频和计数,或者直接用厂商IP里的正交解码模块,确认它的输入同步级别。
第二步,看速度环采样周期和量化噪声的匹配。1ms对位置环合适,但速度环要看你一圈线数乘减速比再除以1ms。如果算下来每周期只走两三个计数,速度本身就是量化噪声,MATLAB整定的参数再漂亮也是在噪声上做运算。这时要么把速度环放慢,要么对速度做滑动平均或低通,位置环保持快一点。
第三步才是定点溢出和积分饱和。16位输入乘16位系数中间结果是32位,截回16位时舍位方向不对,低速段会来回震;积分项要单独限幅,别只限总输出。
排查工具上,用安路自带的在线逻辑分析抓三路:编码器原始计数、同步后计数、PID输出。看抖动周期是不是和采样周期或编码器边沿对齐,对齐了基本就能定位。你现在的编码器是几线、减速比多少,方便的话说一下,能帮你算算速度环该放多快。

先把你这个现象拆开看:开环不抖、闭环才抖,说明执行链路和舵机本身没大毛病,问题几乎一定出在反馈量进PID的那条路径上。所以排查主线我建议就一条:先证明反馈是干净的,再谈参数和位宽。别反过来,先调参数会让你在噪声上反复横跳,越调越乱。
第一层,编码器信号到底有没有同步到你的控制时钟域。舵机控制时钟和编码器输出是两套时间基准,编码器边沿和你1ms采样点没有任何相位关系。如果A/B相直接进计数器,偶尔采到亚稳态,计数值会瞬间跳一个大数。开环时你不读反馈,自然感觉不到;闭环一上,这个跳变被PID的微分项放大,舵机就嗡。做法是A/B各自打两拍同步,再做正交解码和四倍频计数,或者直接调厂商IP里带输入同步的解码模块。这一步没确认,后面全是盲调。
第二层,就算同步做好了,还要看1ms里编码器走了几个计数。一圈线数乘四倍频再除减速比,如果1ms只走两三个数,速度值本身就是量化噪声,MATLAB整定出来的参数再漂亮也是拿噪声当输入。这时候要么速度环放慢,要么对速度做滑动平均,位置环可以保持快一点。
第三层才是你怀疑的定点位宽。16位在舵机这种带宽不高的应用里通常够用,真正容易翻车的是中间结果截断和积分饱和。16位乘16位会到32位,你截回16位时舍位方向不对,低速段会来回震;积分项要单独限幅,不然一积累就顶死。
排查工具上,用安路自带的在线逻辑分析抓三路:编码器原始计数、同步后计数、PID输出。看抖动周期是不是和采样周期或编码器边沿对齐,对齐了基本就定位了。你板子上编码器是走普通IO还是差分/专用输入,这个先确认下?
发表回答
登录后可在本页底部提交回答