1、位置型PID的简单实现
/*定义结构体*/
typedef struct
{
float setpoint; //设定值
float Kp; //比例系数
float Kd; //积分系数
float Ki; //微分系数
float integral;//积分值
float lasterror; //前一拍偏差
float result; //输出值
}PID;
下面实现PID控制器:
void PIDRegulation(PID *vPID, float processValue)//输出PID变量地址和当前采样值
{
float thisError;
thisError=vPID->setpoint-processValue;//当前误差等于设定值减去当前值
vPID->integral+=thisError;//误差积分,把所有误差累加起来
vPID->result=vPID->Kp*thisError + vPID->Ki*vPID->integral + vPID->Kd*(thisError-vPID->lasterror);
vPID->lasterror=thisError;
}
以上没有考虑任何干扰条件,仅仅只是对数学公式的计算机语言化。
2、增量型PID的简单实现
上面的位置型是最基本的PID公式,什么是增量型呢。比如前一篇讲到的温度控制。现在温度是30度,目标是50度,那么我们这一次给它加温10度,让它变化到40度。那么下一次要加多少度呢?(假设为N度),这个N度就是我们说地 增量,增量的公式实际是 U(k)-U(k-1),就是位置型结果的两次相减。
/*定义结构体*/
typedef struct
{
float setpoint; //设定值
float Kp; //比例系数
float Kd; //积分系数
float Ki; //微分系数
float lasterror; //前一拍偏差
float preerror; //前两拍偏差
float result; //输出值
}PID;//比上面少了个积分值,因为相减掉了
void PIDRegulation(PID *vPID, float processValue)
{
float thisError;
float increment;
float pError,dError,iError;
thisError=vPID->setpoint-processValue; //当前误差等于设定值减去当前值
//计算公式中除系数外的三个 乘数
pError=thisError-vPID->lasterror;//两次偏差差值err(k)-err(k-1)
iError=thisError;
dError=thisError-2*(vPID->lasterror)+vPID->preerror;
increment=vPID->Kp*pError+vPID->Ki*iError+vPID->Kd*dError; //增量计算
vPID->preerror=vPID->lasterror; //存放偏差用于下次运算
vPID->lasterror=thisError;
vPID->result+=increment;//结果当然是上次结果 加上本次增量
}
位置型PID特点:
位置型PID控制的输出与整个过去的状态有关,用到了偏差的累加值,容易产生累积偏差。
位置型PID适用于执行机构不带积分部件的对象。
位置型的输出直接对应对象的输出,对系统的影响比较大。
增量型PID控制器的基本特点:
增量型PID算法不需要做累加,控制量增量的确定仅与最近几次偏差值有关,计算偏差的影响较小。
增量型PID算法得出的是控制量的增量,对系统的影响相对较小。
采用增量型PID算法易于实现手动到自动的无扰动切换。
参考:https://www.cnblogs.com/foxclever/p/8902029.html
PID的算法很简单,难点是确认三个系数。
下面这里提到了N种方法,反正我还没看懂。
参考:https://www.cnblogs.com/steed/p/7808303.html