- int cal_pid(int target, int feedbck)
- {
- static int last_err;
- int err, err_sum;
-
- err = target - feedback;
-
- err_sum += err;
-
- out = kp * err + ki * err_sum + kd * (err - last_err);
-
- last_err = err;
-
- return out;
- }
积分饱和就是,积分项数值一直朝一个方向累加(一直减小或一直增大)。导致积分项的值非常大或非常小。下次改变目标值后,由于积分项绝对值太大,导致控制器调整输出的速度变慢。所以要增加一些代码逻辑来抗积分饱和。
这里根据百度出来的结果,简单举几种方法:
误差大于或小于某个值,关闭积分器;
在基础代码片段更改如下语句即可:
- if(err > 10)
- {
- err_sum += err;
- }
将基础代码段中的err_sum限制在一定的取值范围内。
- err_sum += err;
- if(err_sum > 8000)
- {
- err_sum = 8000; // 该值可根据应用场景灵活变动
- }
- else if(err_sum <-8000)
- {
- err_sum = -8000;
- }
当pid计算得到的值大于系统输出值时,就将积分项减去多余的值。
- out = kp * err + ki * err_sum + kd * (err - last_err); //这里假设out是直接输出到定时器的值
- if(out > MAX_DUTY) // MAX_DUTY是定时器PWM的最大输出值,初始化是就能确定了
- {
- int extra = out - MAX_DUTY;
- if(err > 0)
- {
- err_sum -= extra;
- }
- else
- {
- err_sum += extra;
- }
-
- out = kp * err + ki * err_sum + kd * (err - last_err);
- }
增量PID用的比较少,虽然对积分饱和有改善,但会引入其它问题。
暂时不深究这个方案。
PID参数整定绝对是PID最核心的内容了。笔者用的最多的就是试凑法,其它方法笔者也不懂。
下图是当年刚接触PID时记录的一些参数整定口诀。感谢当年一起参加电赛的小伙伴整理的资料。
