01-基本原理
其实pid就是一个反馈的过程,所以如果当前值大于目标值,就应该设置小一点,如果小于,就该设置的大一点。
所以目前设置的测速的增加方向,与设置pwm为正值的方向一致。则误差值应该为目标值减去当前值,这样才能达到反馈的目的。
02-代码编撰
0-pwm速度设置
/**
* @brief 电机输出控制
* @param motor_pwm: 占空比 0-7200
* @retval None
*/
void Set_Pwm(int motor_pwm)
{
if(motor_pwm>0)
{
BIN1=1;
BIN2=0; //前进
}
else if(motor_pwm<0)
{
BIN1=0;
BIN2=1; //后退
}
else //停止
{
BIN1=0;
BIN2=0;
}
PWMB=myabs(motor_pwm);//pwm绝对值
TIM_SetCompare4(TIM1, PWMB);
}
1-定义pid参数结构体
typedef struct
{
float target_val; //目标值
float Error; /*第 k 次偏差 */
float LastError; /* Error[-1],第 k-1 次偏差 */
float PrevError; /* Error[-2],第 k-2 次偏差 */
float Kp,Ki,Kd; //比例、积分、微分系数
float integral; //积分值
float output_val; //输出值
}PID;
2-pid初始化
/**
* @brief PID参数初始化
* @note 无
* @retval 无
*/
void PID_param_init()
{
PosionPID.target_val=3600;
PosionPID.output_val=0.0;
PosionPID.Error=0.0;
PosionPID.LastError=0.0;
PosionPID.integral=0.0;
PosionPID.Kp = 10;
PosionPID.Ki = 0.5;
PosionPID.Kd = 0.8;
}
3-位置式pid控制器
/**
* @brief 位置PID算法实现
* @param actual_val:实际测量值
* @note 无
* @retval 通过PID计算后的输出
*/
float PosionPID_realize(PID *pid, float actual_val)
{
/*计算目标值与实际值的误差*/
pid->Error = pid->target_val - actual_val;
/*积分项*/
pid->integral += pid->Error;
/*PID算法实现*/
pid->output_val = pid->Kp * pid->Error +
pid->Ki * pid->integral +
pid->Kd *(pid->Error -pid->LastError);
/*误差传递*/
pid-> LastError = pid->Error;
/*返回当前实际值*/
return pid->output_val;
}
4-增量式pid控制器
/**
* @brief 速度PID算法实现
* @param actual_val:实际值
* @note 无
* @retval 通过PID计算后的输出
*/
float addPID_realize(PID *pid, float actual_val)
{
/*计算目标值与实际值的误差*/
pid->Error = pid->target_val - actual_val;
/*PID算法实现,照搬公式*/
pid->output_val += pid->Kp * (pid->Error - pid-> LastError) +
pid->Ki * pid->Error +
pid->Kd *(pid->Error -2*pid->LastError+pid->PrevError);
/*误差传递*/
pid-> PrevError = pid->LastError;
pid-> LastError = pid->Error;
/*返回当前实际值*/
return pid->output_val;
}
03调试
1-测试极性
观察在pwm为正时,编码器是否为正
此时极性为反,修改一下setpwm的方向就行
2-测试pwm极性
发现当pwm值为0-10时转动极快,到了980-999时几近不转,此时应该修正,修改一下映射关系,将1000映射为0。
3-发现问题
1-正转的时候能够稳定的运行,反转的时候就会走一下卡顿一下(头痛)
最后发现,正转,反转时候需要的pwm占空比不同。正转时占空比越大跑的越快,反转时占空比越大跑的越慢。
2-能稳定在速度为0,但是可以很轻易的摆动。(正拧有一定力气,反拧没有力气)
发现原因,根据上文的关系,正转反转不是需要相反的占空比嘛。但是在一个为90,一个为10的情况下(即相互相反),一个可以转,一个不能转
最终的问题:接线接错了……
如果各位遇见这样的问题的话,记得一定要先排查接线是否有误,别像我似的排查一下午弄出来这么些鬼东西。
4-上位机调试
现在问题已经基本全部解决,能够较为稳定的运行在目标速度,可以进行上位机调参进行优化了。
我认为其实位置式中仅p值,调节的时候就代表一直在加速,只不过误差大的时候加速快,误差小的时候加速慢,直到达到一个值,使pwm值与误差正好对应,此时会形成静差(应该是这样的)。所以调节p值达到的目的应该是能够稳定在一个位置并发生小幅度震荡。之后调节的i值反而是影响响应速度与减少震荡的关键。
之后用vofa上位机捏一个差不多的曲线就行。
调试经验:暂无,以后补充。
04-疑问解释
(纯瞎掰,不用在意)
1-位置式pid
如果调节速度环,那么,只调节p值的话,
①原有速度3m/s,误差7m/s,pwm值占空比为50,此时通过pid控制器将占空比设置为70
②速度升高为6m/s,误差4m/s,pwm值占空比经过pid控制器设置为40,占空比减小了,速度进而下降了
这应该不是所谓稳态误差一类吧(我理解的稳态误差是由于阻力导致的,而不是程序问题导致的)
所以这是为什么?
个人理解:
我认为其实位置式中仅p值,调节的时候就代表一直在加速,只不过误差大的时候加速快,误差小的时候加速慢,直到达到一个值,使pwm值与误差正好对应,此时会形成静差(应该是这样的)。所以调节p值达到的目的应该是能够稳定在一个位置并发生小幅度震荡。之后调节的i值反而是影响响应速度与减少震荡的关键。
2-增量式pid
完全不理解