一、概述
1.1 P I D含义解释
P:Prorosal(比例)力和error比例关系 P越大越灵敏
Kp静态误差系数
D:Derivative(微分) Kd-->抖动现象
Update——Angle
void update_angle(motor_angle* _angle,uint16_t angle_fb)
{
_angle->encoder = angle_fb;
if(_angle->encoder_is_init)
{
if(_angle->encoder - _angle->last_encoder > 4096)
_angle->round_cnt --;
else if(angle->encoder - _angle->last_encoder < - 4096)
_angle->round_cnt ++;
}
else
{
_angle->encoder_offset = _angle->encoder;
_angle->encoder_is_init = 1;
}
_angle->angle_offset = _angle->encoder_offset /8192.0f * 360.0f;
_angle->last_encoder = _angle->encoder;
_angle->total_encoder = _angle->round_cnt * 8192 + _angle->encoder - _angle->encoder_offset;
_angle->angle = _angle->total_encoder/8192.0f * 360.f;
}
I:Integral(积分)对误差进行累积-->稳态误差
三个参数都不能太大,否则过冲
适用于二阶以内信息系统
1.2控制系统概述
反馈是在输出后的与期望比较,前馈是对干扰进行检测或是预判得到的
传感器是测量作用,用于测量实际输出与期望输出之间的差值,并反馈给输入,然后做出调节
这里和运放的负反馈机制一样
参数详解
误差
控制器输出
执行器输出
实际输出
1.3连续离散信号
离散系统通常加保持器所以横线
1.4P I D公式理解
无人机事例
只有P的话 P增大到100 上升到99m就悬停了 所以我们引用I 来累积误差
I
D
如果没有D,升降不平稳,防止超调
D图示
1.4.1概念补充
1.4.1.1 积分限幅
情境引入
工人按住无人机,I会累积很多,一旦松开,起飞的时候飞的就很高
设置上限卡住
1.4.1.2积分分离
1.4.1.3微分先行
二、调参
P I D 整定(一般PI就行,系统振荡明显在加上Kd)
Kp 尽量调的接近目标值
Ki 从小到大给,越大消除误差啊效果好一点
Kd 让振荡效果减弱,但是不能太大,要不然相应很慢
三、应用
RM M3508速度单环
代码讲解
RM电机M3508速度单环
chassis_motor_pid[i].SpeedPID.target = 500;
chassis_motor_pid[i].SpeedPID.current = motor_chassis[i].speed_rpm;
pid_calc(&chassis_motor_pid[i].SpeedPID);
/*位置pid算法*/
void pid_calc(_pid* pid)
{
pid->e = pid->target - pid->current; //计算error
pid->p_out = (int32_t)(pid->Kp * pid->e); //计算p_out
pid->i_out += (int32_t)(pid->Ki * pid->e); //计算i_out
//积分限幅
limit(&(pid->i_out),pid->IntegralLimit);
/* //积分分离 可以不要 只要限幅和上面的i_out
if (fabs(pid->e) < I_Band)
{
pid->i_out += (int32_t)(pid->Ki * pid->e);
}
else
{
pid->i_out = 0;
} */
pid->d_out = (int32_t )(pid->Kd * (pid->e - pid->last_e)); //计算d_out
pid->total_out = pid->p_out + pid->i_out + pid->d_out;
//pid输出限幅
limit(&(pid->total_out),pid->MaxOutput);
pid->last_e = pid->e;
}
RM6020速度、角度双环(电机只能执行速度,量纲转化)
外环totalout 就是内环的target
以下是伪代码,内外环均需要做pid
update_angle(&manipulator_motor_pid[i].angle,motor_manipulator[i].angle);
manipulator_motor_pid[i].AnglePID.current = manipulator_motor_pid[i].angle.angle;
pid_calc(&manipulator_motor_pid[i].AnglePID);
manipulator_motor_pid[i].SpeedPID.target = manipulator_motor_pid[i].AnglePID.total_out;
manipulator_motor_pid[i].SpeedPID.current = manipulator_motor_pid[i].speed_rpm;
pid_calc(&manipulator_motor_pid[i].SpeedPID);
/*位置pid算法*/
void pid_calc(_pid* pid)
{
pid->e = pid->target - pid->current; //计算error
pid->p_out = (int32_t)(pid->Kp * pid->e); //计算p_out
pid->i_out += (int32_t)(pid->Ki * pid->e); //计算i_out
//积分限幅
limit(&(pid->i_out),pid->IntegralLimit);
/* //积分分离 可以不要 只要限幅和上面的i_out
if (fabs(pid->e) < I_Band)
{
pid->i_out += (int32_t)(pid->Ki * pid->e);
}
else
{
pid->i_out = 0;
} */
pid->d_out = (int32_t )(pid->Kd * (pid->e - pid->last_e)); //计算d_out
pid->total_out = pid->p_out + pid->i_out + pid->d_out;
//pid输出限幅
limit(&(pid->total_out),pid->MaxOutput);
pid->last_e = pid->e;
}