第五节 直流电机PID控制程序
对于PID调节,大家都可能知道他的口诀:
参数整定找最佳,从小到大顺序查
先是比例后积分,最后再把微分加
曲线振荡很频繁,比例度盘要放大
曲线漂浮绕大湾,比例度盘往小扳
曲线偏离回复慢,积分时间往下降
曲线波动周期长,积分时间再加长
曲线振荡频率快,先把微分降下来
动差大来波动慢,微分时间应加长
理想曲线两个波,前高后低4比1
一看二调多分析,调节质量不会低
现在我们将这个口诀应用到程序,先定义PID数据的结构体:
/*********************************************************************************
定义一个PID结构体
*********************************************************************************/
typedef struct __PID_ {
int SetPoint; // 给定值
// int nextPoint; // 上次的
int Kp; // 比例常数 Proportional Const
int Ki; // 积分常数 Integral Const
int Kd; // 微分常数 Derivative Const
int LastError; // Error[-1]
int PrevError; // Error[-2]
int SumError; // Sums of Errors
int LastOut; // 上次的输出量
int MaxOut;
int MinOut;
} PID;
PID控制的实现程序:
/*********************************************************************************
函数名:PID_Aaccount
函数功能:进行PID增量式结算
输入参数:*PP--指向需要结算的PID ,NextPoint当前的反馈值
输出参数:PID结算后的给定值
*********************************************************************************/
int PID_Account( PID *pp, int NextPoint )
{
int Error;
int Add_out=0;
Error = pp->SetPoint - NextPoint; // 偏差
// Add_out = (pp->Kp*(pp->LastError - pp->PrevError)
// + pp->Ki*Error
// + pp->Kd*(Error-2*pp->LastError+pp->PrevError))/1000;
Add_out = (pp->Kp*(Error - pp->LastError)
+ pp->Ki*Error
+ pp->Kd*(Error-2*pp->LastError+pp->PrevError))/1000;
pp->PrevError = pp->LastError; //存储上次偏差
pp->LastError = Error; //存储本次偏差
pp->LastOut = pp->LastOut + Add_out; //存储本次输出
if (pp->LastOut > pp->MaxOut){
pp->LastOut = pp->MaxOut;
} else if (pp->LastOut < pp->MinOut) {
pp->LastOut = pp->MinOut;
}
return (pp->LastOut);
}
/*********************************************************************************
函数名:PID_Addaccount
函数功能:进行PID置位式结算
输入参数:*PP--指向需要结算的PID ,NextPoint当前的反馈值
输出参数:PID结果
*********************************************************************************/
int PID_AddAccount( PID *pp, int NextPoint )
{
int dError,Error;
Error = pp->SetPoint - NextPoint; // 偏差
pp->SumError += Error; // 积分
dError = pp->LastError - pp->PrevError; // 当前微分
pp->PrevError = pp->LastError; //存储上次偏差
pp->LastError = Error; //存储本次偏差
return (pp->Kp * Error/1000 // 比例项
+ pp->Ki * pp->SumError/1000 // 积分项
+ pp->Kd * dError/1000 // 微分项
);
}
/*********************************************************************************
函数名:PIDInit
函数功能:PID数据初始化
输入参数:*pp需要初始化的PID
输出参数:
*********************************************************************************/
void PIDInit (PID *pp)
{
pp->SetPoint = 0; // 给定值
pp->Kp= 0; // 比例常数 Proportional Const
pp->Ki= 0; // 积分常数 Integral Const
pp->Kd= 0; // 微分常数 Derivative Const
pp->LastError= 0; // Error[-1]
pp->PrevError= 0; // Error[-2]
pp->SumError= 0; // Sums of Errors
pp->LastOut= 0; // 上次的输出量
pp->MaxOut = 0;
pp->MinOut = 0;
}
这是PID控制直流电机的核心算法。这个算法让我屡试不爽,在校期间历经2次省赛、1次国赛,毕业后在实际项目中使用一次,效果绝佳。亲,好好研究下,让你的电机控制更精准更完美。