PID的是典型的误差反馈控制系统,是古典控制理论中最为常见的一种控制方法,而且至今仍被广泛使用,对于电机的闭环控制,我使用增量式PID进行控制,设定的采集以及计算时间为100ms,电机的输出PWM范围为0-10000,方向使用电平单独控制,在这个控制过程中仅仅使用了PI两项,并没有使用D项,PI控制电机的效果比较理想。
(二)程序编写 (1)h文件//普通速度环 基本速度控制
//简易增量式PID
typedef struct
{
int16 exval;
int16 nowval;
float kp;
float ki;
float kd;
int16 nowError;
float increase;
int16 lastError;
int16 beforError;
int16 out;
float maxout;
float minout;
}SpeedPIDTypedef;
extern SpeedPIDTypedef SpeedPIDLeft,SpeedPIDRight;
void pid_param_init(void);
int16 SimpleIncremental_PID(SpeedPIDTypedef *pid,int16 _exval,int16 _nowval);
(2)C文件
void pid_param_init(void)
{
SpeedPIDLeft.maxout = 10000;
SpeedPIDLeft.minout = -10000;
SpeedPIDLeft.kp = 0.0f;
SpeedPIDLeft.ki = 0.0f;
SpeedPIDRight.maxout = 10000;
SpeedPIDRight.minout = -10000;
SpeedPIDRight.kp = 0.0f;
SpeedPIDRight.ki = 0.0f;
}
SpeedPIDTypedef SpeedPIDLeft,SpeedPIDRight;
int16 SimpleIncremental_PID(SpeedPIDTypedef *pid,int16 _exval,int16 _nowval)
{
//运算
pid->exval = _exval;
pid->nowval = _nowval;
//当前误差
pid->nowError = pid->exval - pid->nowval;
//增量
pid->increase =
pid->kp * (float)(pid->nowError - pid->lastError) +
pid->ki * (float)pid->nowError +
pid->kd * (float)(pid->nowError - 2 * pid->lastError + pid->beforError);
//更新误差
pid->lastError = pid->nowError;
pid->beforError = pid->lastError;
pid->out += (int16)pid->increase;
//限制幅度
pid->out = range_protect(pid->out,(int32)pid->minout,(int32)pid->maxout);
//输出
return pid->out;
}
(3)100ms定时器中断
void Speed_Control(void)
{
Read_Encoder();
pwm_r = SimpleIncremental_PID(&SpeedPIDRight,speed_r,encoder1_val);
pwm_l = SimpleIncremental_PID(&SpeedPIDLeft,speed_l,encoder0_val);
SpeedSet(pwm_l,pwm_r);
}
(三)参数调整
调试时首先将各项数值置零,对于增量型PI控制器可以先从I项开始调整,先给I项一个较小的数值,然后逐渐增大,直到开始轻微震荡,然后把数值调整到震荡数值的2/3即可,然后需要调整P项,也是跟I项调整方式差不多,主要是利用I项快速跟随误差,利用P项抑制超调。
放一张调试图:



