STM32F4平台CMSIS库PID控制器Q15定点数参数归一化疑问
嘿,我来帮你理清这个定点数PID的疑惑!咱们一步步拆解核心问题,帮你搞清楚缩放逻辑和小误差下的输出问题。
1. 先澄清Q格式的误区
你提到的「Q15定点数」其实范围是**-1 ≤ x < 1**(1位符号位+15位小数,本质是把数值乘以215用整数表示),但你的Kp=2.7056已经远超Q15的最大值,所以你实际用的是**Q13格式**(相当于把数值乘以213,范围大概是-4到4),这个选择没问题,但核心原则是:所有参与PID计算的变量(误差e(n)、输出y(n)、Kp/Ki/Kd)必须统一使用同一Q格式,否则运算逻辑会完全混乱。
2. CMSIS arm_pid_q15()的运算逻辑
这个函数是专门为定点数优化设计的,输入、输出、参数都是同一种Q格式的整数,函数内部已经处理了定点数的乘法溢出和缩放逻辑,完全不需要你手动除以缩放因子!但要注意两个关键:
- 你传入的Kp/Ki/Kd必须是转换后的Q格式整数(比如你计算的22164和696,对应Q13格式)
- 输入的误差e(n)也必须先转换成同一Q格式:比如实际误差是2(物理量),转换为Q13就是
2 * 2^13 = 16384,绝对不能直接用实际值2代入 - 输出的y(n)同样是Q13格式的整数,你需要把它除以2^13才能得到对应的实际物理量输出
3. 解决小误差下输出为0的问题
你之前的计算错误在于没有把实际误差转换成Q格式:你直接用了实际误差e(n)=2当成Q13的整数代入,导致计算结果偏小到转换后为0。正确的计算应该是:
假设实际误差e(n)=2,转换为Q13是16384;初始状态e(n-1)=0,y(n-1)=0
y(n) = 0 + (22164+696)16384 - 221640 = 22860*16384 = 374538240
这个结果是Q13格式的整数,转换为实际值是374538240 / 8192 = 45720(当然这个值偏大,因为还有个关键问题没处理)
另外一个容易忽略的点:你的Ki参数可能没做离散化处理!如果Ki=0.085是连续系统里的积分增益,放到离散PID中必须先乘以采样周期Ts。比如你的采样周期是10ms,离散后的Ki就是0.085*0.01=0.00085,再转Q13就是0.00085*8192≈7,这样小误差下的输出就不会轻易被截断为0了。
4. 优化建议
- 先确定PID的采样周期Ts,把连续域的Ki转换为离散域的Ki值,再进行Q格式转换
- 如果Kp大于1,建议调整Q格式或做参数归一化:比如把所有参数和输入输出都除以4,让Kp变成0.6764,这样就能用Q15格式(精度更高),之后输出再乘以4还原
- 对于小误差的精度问题,可以考虑用Q31格式(STM32F4支持32位运算),更多的小数位能减少截断误差,避免小误差下输出为0的情况
总结一下:CMSIS的PID函数不需要手动除以缩放因子,但必须保证所有变量(参数、输入、输出)统一Q格式,同时别忘了连续域到离散域的参数转换,选对Q格式才能兼顾范围和精度。
内容的提问来源于stack exchange,提问作者Francesco

