前言:在此篇中我们会介绍PID算法具体在C语言代码中是什么表现,与串级PID的作用与运用。
一、PID代码
先回顾以下PID数学公式
//首先定义PID结构体用于存放一个PID的数据
typedef struct
{
uint16_t kp,ki,kd;//三个系数
uint16_t error,lastError;//误差、上次误差
uint16_t integral,maxIntegral;//积分、积分限幅
uint16_t output,maxOutput;//输出、输出限幅
}PID;
//用于初始化pid参数的函数
void PID_Init(PID *pid,uint16_t p,uint16_t i,uint16_t d,uint16_t maxI,uint16_t maxOut)
{
pid->kp=p;//调参只要改动这三个值就行p,i,d
pid->ki=i;
pid->kd=d;
pid->maxIntegral=maxI;
pid->maxOutput=maxOut;
}
//进行一次pid计算
//参数为(pid结构体,目标值,反馈值),计算结果放在pid结构体的output成员中
void PID_Calc(PID *pid,uint16_t reference,uint16_t feedback)
{
//更新数据
pid->lastError=pid->error;//将旧error存起来
pid->error=reference-feedback;//计算新error
//计算微分
uint16_t dout=(pid->error-pid->lastError)*pid->kd;//误差的差值乘以Kd
//计算比例
uint16_t pout=pid->error*pid->kp;//误差乘以Kp
//计算积分
pid->integral+=pid->error*pid->ki;//误差的累加乘以Ki
//积分限幅
if(pid->integral > pid->maxIntegral) pid->integral=pid->maxIntegral;//积分过大则限幅赋值为max
else if(pid->integral < -pid->maxIntegral) pid->integral=-pid->maxIntegral;//积分过小则赋值为min
//计算输出
pid->output=pout+dout+pid->integral;//输出值为P+I+D
//输出限幅
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)//进入循环运行
{
uint16_t feedbackValue=...;//这里获取到被控对象的反馈值
uint16_t targetValue=...;//这里获取到目标值
PID_Calc(&mypid,targetValue,feedbackValue);//进行PID计算,结果在output成员变量中
设定执行器输出大小(mypid.output);
delay(10);//等待一定时间再开始下一次循环
}
}
代码参考自skythinker616大佬