PID算法C18程序的实现
PID 计算资源需求
DS=Pdu(k)+I t/ti(uk)+ D TD/T duk+du(k-1)
puk-i *T/TI*uk+d*(uk-2* uk-1 + uk-2)
三个系统状态是需要的 UK UK-1 UK-2
还有P I D 的参数也是需要的
当然还有个 采样时间 T (似乎也有人 把积分时间 T 和微分时间T 分开了? 我不是很明白不管他)
应为不同的硬件体系 我们需要计算数据的位数 有差异(可能需要int型 去算 也可能用 long ,floAt 等)
应为是C18下的 我先试用INT 去做
#define PID_TYPE int
这样以后换类型也省事
于是我们定义1个结构体
struct pid_unit { PID_TYPE pid_sens[3]; // 用来保存 UK UK-1 UK-2 三个时刻的输出偏差PID_TYPE pid_cpid[3]; // 当然是 P I D 三个参数咯PID_TYPE pid_dpid[3]; // P 部分计算值 I部分计算值 D 部分计算值 这三个值相加就是PID 的输出};初始化PIDvoid pid_init(struct pid_unit *unit, PID_TYPE p, PID_TYPE i, PID_TYPE d) { unit->pid_cpid[0] = p; //PID 比例系数 初始化 没得说 哈unit->pid_cpid[1] = i; unit->pid_cpid[2] = d; unit->pid_dpid[0] = 0;//P i d 个个部分都假定为0 不过实际也是0#24unit->pid_dpid[1] = 0; //unit->pid_dpid[2] = 0; //unit->pid_sens[0] = 0; // 当前差值unit->pid_sens[1] = 0; //unit->pid_sens[2] = 0; //}
接下来 就是计算部分了
第一部分 P部分 计算
unit->pid_dpid[0] = unit->pid_sens[0] * unit->pid_cpid[0]; //就是P*UK
然后是I部分 。。不过大家会发现I还需要前一次的计算结果。。咋办。。
第一次 用的是0。n那么第二次 用的就是现在的咯
所以要保存现在的值 给下一次用
同时保存上一次的值 到上上一次
说的这么拗口,。那是我语文没学好
其实就是保存三个时间状态值
丢弃最老的 保存最新的
unit->pid_sens[1] = unit->pid_sens[0];
unit->pid_sens[0] = input;
unit->pid_dpid[1] = unit->pid_sens[0] * unit->pid_cpid[1] * time;
等我吃个饭再来 有点问题
GOOGLE 源码是:
unit->pid_dpid[1] += unit->pid_sens[0] * unit->pid_cpid[1] * time;
而ΔU=U(k)-U(k-1)=Kp*[e(k)-e(k-1)]+Ki*e(k)+Kd*[e(k)-2*e(k-1)+e(k-2)]
是肯定没问题的。。所以 似乎GOOGLE 上源码不对哦,,大家要注意了
D部分 Kd*[e(k)-2*e(k-1)+e(k-2)
unit->pid_dpid[2] = ((unit->pid_sens[0] - 2*unit->pid_sens[1]+unit->pid_sens[2])/time) *unit->pid_cpid[2];
然后对P I D 求和
unit->pid_dpid[0] + unit->pid_dpid[1] + unit->pid_dpid[2];
故有PID 计算子函数如下
PID_TYPE pid_control(struct pid_unit *unit, PID_TYPE input, PID_TYPE time) { // adjust the FIFO preserving the sensor data unit->pid_sens[1] = unit->pid_sens[0]; unit->pid_sens[0] = input; // calculate each pid variable unit->pid_dpid[0] = unit->pid_sens[0] * unit->pid_cpid[0]; unit->pid_dpid[1] = unit->pid_sens[0] * unit->pid_cpid[1] * time; unit->pid_dpid[2] = (unit->pid_sens[0] - unit->pid_sens[1])/time *unit->pid_cpid[2]; return unit->pid_dpid[0] + unit->pid_dpid[1] + unit->pid_dpid[2]; }
评论