PID公式:
Kp:比例
Ki:积分
Kd:微分
举栗:水缸深1m,已经有0.2m,需要加满
比例控制:
经过比例控制,最后会水位卡在0.8m,称为暂态误差或稳态误差
积分控制:
在比例控制下添加积分控制,消除稳态误差。(不严谨的解释积分——堆积一起,这里表示累加)
微分控制:
当快加满控制倒水量,防止超过容量1m。
理解刹车:提前刹车减速,防止过线
实际微分项绝对值为负数
//首先定义PID结构体用于存放一个PID的数据
typedef struct
{
float kp,ki,kd;//三个系数
float error,lastError;//误差、上次误差
float integral,maxIntegral;//积分、积分限幅
float output,maxOutput;//输出、输出限幅
}PID;
//用于初始化pid参数的函数
void PID_Init(PID *pid,float p,float i,float d,float maxI,float maxOut)
{
pid->kp = p;
pid->ki = i;
pid->kd = d;
pid->maxIntegral = maxI;
pid->maxOutput = maxOut;
}
//进行一次pid计算
//参数为(pid结构体,目标值,反馈值),计算结果放在pid结构体的output成员中
void PID_Calc(PID *pid,float reference,float feedback)
{
//更新数据
pid->lastError = pid->error;//将上一次error存起来
pid->error = reference-feedback;//计算新error
//微分
float dout = pid->kd * (pid->error - pid->lastError);
//比例
float pout = pid->kp * pid->error;
//积分
pid->integral += pid->ki * pid->error; //进行累加
//积分限幅
if(pid->integral > pid->maxIntegral) //是否大于最大输入值
{
pid->integral = pid->maxIntegral;
}
else if(pid->integral < -pid->maxIntegral)
{
pid->integral = -pid->maxIntegral;
}
//计算输出
pid->output = pout+dout + pid->integral;
//输出限幅
if(pid->output > pid->maxOutput)
{
pid->output = pid->maxOutput;
}
else if(pid->output < -pid->maxOutput)
{
pid->output = -pid->maxOutput;
}
}
PID mypid;//创建一个PID结构体变量
int main()
{
PID_Init(&mypid,10,1,5,800,1000);//初始化PID参数
while(1)
{
float feedbackValue=...;//这里获取到被控对象的反馈值
float targetValue=...;//这里获取到目标值
PID_Calc(&mypid,targetValue,feedbackValue);//进行PID计算,结果在output成员变量中设定执行器输出大小(mypid.output);
delay(10);
}
}
(不严谨的理解微分——越分越细)
不严谨的PID:P现在;I过去;D未来