第一节 stm32电机驱动与编码器读取反馈
第二节 stm32电机pid控制
第三节 stm32线速度标定
第四节 stm32添加mpu6050得到angle角度
第五节 实现STM32与ubuntu系统下的ROS串口DMA通信,传输底盘速度等信息
第六节 ROS计算和发布里程计与tf变换
系列教材包含
底盘搭建与stm32代码编写,ros激光雷达建图与导航编写,实现动态避障与导航
底盘包含
两轮差速轮(自制)
四轮全向轮(所属团队大家一起搭建)
底盘不同就是在底盘的运动分解与控制,ros部分里程计计算和本地规划器不同,两轮用的base_local_Planner,四轮用的teb_local_planner,来规划发布速度控制底盘
gjhhust / Repositories · GitHubhttps://github.com/gjhhust?tab=repositories
目录
系列文章目录
前言
一、pid介绍
二、pid简单调整方法
总结
今天来为大家介绍pid控制
相信pid大家不陌生,就算陌生也没关系,从头写一下pid控制,pid就是要明确控制目标(setpoint),控制对象当前量(current_value),以及pid输出
在我刚开始就已知不懂控制三个量的关系,这里避雷一下,就是pid最终计算的量与控制目标不是一个量纲的概念
打个比方,你需要控制电机转速至50cm/s,则setpoint就是50,此时当前量肯定就是编码器测得的速度而输出量是什么?是0-900的一个数字!因为你能改变电机转速,也就是改变current_value的直接手段就是改变占空比,也就是TIM_SetCompare1(TIM1,500);中500的那个值,至于500与速度什么关系我们不需要清除,只要pid知道当前占空比低,也就是转速低,还未达到setpoint,那么pid输出就大,当current_value越接近setpoint,pid输出也就减小,最后基本达到setpoint,输出就基本不变了,也就是你只需要有三个量在,然后调一下pid三个参数,也就是三个参数组成的算法来推这个pid输出量。
先贴出pid算法代码
pid.c
typedef struct
{
float Kp; //比例系数Proportional
float Ki; //积分系数Integral
float Kd; //微分系数Derivative
float Ek; //当前误差
float Ek1; //前一次误差 e(k-1)
float Ek2; //再前一次误差 e(k-2)
float LocSum; //累计积分位置
}PID_LocTypeDef;
/************************************************
函数名称 : PID_Loc
功 能 : PID位置(Location)计算
参 数 : SetValue ------ 设置值(期望值)
ActualValue --- 实际值(反馈值)
PID ----------- PID数据结构
返 回 值 : PIDLoc -------- PID位置
作 者 : strongerHuang
*************************************************/
float PID_Loc(float SetValue, float ActualValue, PID_LocTypeDef *PID)
{
float PIDLoc; //位置
PID->Ek = SetValue - ActualValue;
PID->LocSum += PID->Ek; //累计误差
PIDLoc = PID->Kp * PID->Ek + (PID->Ki * PID->LocSum) + PID->Kd * (PID->Ek1 - PID->Ek);
PID->Ek1 = PID->Ek; return PIDLoc;
}
代码解释
有了pid算法如上,我们只需要定义一个pid的结构体,比如是left_PID;来控制左电机转速
则pid控制流程就是,先硬件初始化好,然后能够得到左电机当前速度赋值给left_speed_now,接着定义PID结构体这里是left_PID
然后调用如下语句即可pid控制,我一般放在一个固定的计时器中断里,比如上一节的TIM6内,5ms测速一次,我可以定义一个计数器flag,进一次中断+1,判断10ms时可以pid控制一次。
//左电机速度由TIM1 CH1pwm控制,目标控制到50cm/s
TIM_SetCompare1(TIM1,PID_Loc(50, left_speed_now, &left_PID));
下载程序完后你会发现电机不动,这是因为你没有给PID三个kp,ki,kd参数,都是0
在keil的debug中,此时将添加到left_PID watch1内,监控发现参数都是0,此时尝试给kp值20,观察电机情况,如果不稳定转动,那么你就减小kp值直到转速稳定,此时再观察测速得到的left_speed_now,大概率会在40cm/s左右或者其它某个值附近波动(这里假设是40cm/s附近),你看反正达不到50cm/s,这就是静态误差,需要增加ki。
与此同时我们要先给left_PID.LocSum赋值大小200(具体怎么给可以专门去学,这里简单就是,你静态误差此时速度差了10cm/s左右,而对应的占空比差了应该就是100左右,也就是你TIM_SetCompare1内给了500测速比如说是40cm/s,对应的占空比600测速是50cm/s,所有此时速度固定差了10cm/s,占空比固定差了100,而这个LocSum则要根据输出量也就是占空比来给,这就是最大静态误差就是200,上面情况是差了100,所以我们的ki给个0.5就差不多,0.5*200 = 100,这是个经验公式,就是大概教会你这几个值的含义)
此时如果静态误差还有,则继续增大ki到基本没有误差,过大会导致转速不稳定,上下浮动大。
以上只是简单的电机pid调控,满足普通需求,适合入门,更深入可以搜索资料。
完成了pid的速度控制,底盘就动起来了。你给一个速度就可以转起来了。