前言
本人在大学期间参加了许多的比赛,参加过智能汽车竞赛、全国电赛、蓝桥杯等A类赛事,每一次备赛都是在不断地学习,在2023年参加的广东省工科赛,以省一的成绩圆满结束大学的最后一次竞赛。分享一些在备赛中遇到的问题以及方案,希望给到他人一些帮助,欢迎各位指出错误和相互交流。
一 赛题分析及方案
1 赛题要求
任务由抽签确定,其说明如下: 任务码设置为“1”、“2”两个数字的组合,共四位,表明料仓号及配送至的收 货区号。第一位表示要运送的第一个物料的料仓号码,第二位表示第一个物料运 送的收货区号码,第三位表示要运送的第二个物料的料仓号码,第四位表示第二 个物料运送的收货区号码。如“2112”,该数字组合表明了机器人需要运输的第一 个物料的是 2 号料仓的物料,运送至 1 号收货区;机器人需要运输的第二个物料 是 1 号料仓的物料,运送至 2 号收货区;机器人通过读取场地上放置的二维码获 取配送任务。
2 方案及器件选择
根据赛题的要求,简单概括就是说有两个收货区,小车对两个货物分别配送到收货区,两个货物分别配送到哪个地点以及哪个货物先配送等信息从二维码中获取。配送完毕后回到出发点,小车运行中需要有避障、语音播报相应内容等功能。
分析完赛题后,对小车器件进行选择
器件 | 型号 |
1 轮子 | 麦克纳姆轮 |
2 主控 | STM32F407 |
3 电机 | 带码盘直流减速电机 |
4 电池 | 2s航模锂电池 |
5 电机驱动 | DRV8701双电机驱动 |
6 二维码模块 | GM65 |
7 舵机 | 180°舵机 |
8 测距模块 | VL53-400S激光测距 |
9 避障模块 | 激光漫反射模块 |
10 语音模块 | SYN-6288语音模块 |
11 陀螺仪 | 维特HWT101陀螺仪 |
12 电源模块 | LM2596S稳压模块 |
1轮子采用麦克纳姆轮可以让小车在运行中全向移动;2主控的话还是采用STM32,性能强,资源丰富,使用库函数开发,网上资料也丰富,非常适合小白;5电机驱动之前参加智能车竞赛后就一直在逐飞买这一款使用,相比其他的电机驱动来说,有点小贵,不过很好用,看个人习惯吧;6二维码扫描模块用来扫二维码的,在比赛现场看到有些队伍使用openmv或者k210来扫码,不过感觉效果都不好,都会收到光线的影响,用扫码模块就很好的解决这一问题,而且是扫码距离远、速度快,最主要的是还不贵哈哈哈;8测距模块安装在小车的车头还有小车的左侧,用来定位到达不同的区域;9避障模块使用的是激光漫反射模块,使用起来很方便,读电平就可以了,比赛现场有其他队伍用普通的红外传感器,容易受光线影响;11陀螺仪使用这个款高精度陀螺仪,不受磁场干扰,不漂移,就是贵。烧录器这里推荐一下正点原子的无线烧录器,不用在调车的时候拔来拔去,在使用的时候也遇到了个奇怪的问题,一上语音模块后,烧录器的发送器和接收器就得离的很近才能感应到。
二 控制思路及控制程序
1 控制思路
第一步:按下启动按钮,通过控制舵机打开两个仓门,并控制语音模块发出相应的语音提示。待储物仓装入物料后关闭仓门,机器人自动检查是否关上仓门,若未关上则继续识别,若关上仓门即可开始配送。
第二步:进行配送,利用激光测距模块与陀螺仪进行姿态调整和路径规划,机器人在行进的同时利用红外漫反射进行障碍物的识别,当障碍物进入避障区域时,机器人停下进行左右移动避开障碍物,避障完成后,根据避障时的移动方向再次用激光测距模块与陀螺仪进行姿态调整和路径规划。
第三步:当机器人移动到扫码区时扫描模块识别二维码获取任务。机器人根据任务进行转弯,按激光测距模块设定好的路径自主避障到达对应的收货区。
第四步:小车到达第一个收货区后根据任务码获取的任务发出对应的语音提示,并打开相应的仓门。等待货物取出后关闭仓门。
第五步:待仓门关闭后,按激光测距模块设定好的路径自主避障到达下一个收货区,根据任务码获取的任务发出对应的语音提示,并打开相应的仓门。等待货物取出后关闭仓门。
第六步:配送机器人按激光测距模块与陀螺仪进行姿态调整和路径规划,自主避障原路返回指定出发区。
2 部分控制程序(完整代码在下方)
1 电机控制
四个电机的控制就是使能引脚的高低电平控制电机正反转,控制脉冲引脚通过单片机给脉冲调速。
void MotorCtr(int M1,int M2,int M3,int M4)
{
if(M1==0&&M2==0&&M3==0&&M4==0)
{
TIM_SetCompare1(TIM8,0); TIM_SetCompare2(TIM8,0); TIM_SetCompare3(TIM8,0); TIM_SetCompare4(TIM8,0);
}
if(M1>0)
{
TIM_SetCompare1(TIM8,M1);
GPIO_ResetBits(GPIOG,GPIO_Pin_2);
}
else
{
TIM_SetCompare1(TIM8,0-M1);
GPIO_SetBits(GPIOG,GPIO_Pin_2);
}
if(M2>0)
{
TIM_SetCompare4(TIM8,M2);
GPIO_SetBits(GPIOG,GPIO_Pin_5);
}
else
{
TIM_SetCompare4(TIM8,0-M2);
GPIO_ResetBits(GPIOG,GPIO_Pin_5);
}
if(M3>0)
{
TIM_SetCompare2(TIM8,M3);
GPIO_ResetBits(GPIOG,GPIO_Pin_3);
}
else
{
TIM_SetCompare2(TIM8,0-M3);
GPIO_SetBits(GPIOG,GPIO_Pin_3);
}
if(M4>0)
{
TIM_SetCompare3(TIM8,M4);
GPIO_SetBits(GPIOG,GPIO_Pin_4);
}
else
{
TIM_SetCompare3(TIM8,0-M4);
GPIO_ResetBits(GPIOG,GPIO_Pin_4);
}
}
2 PID算法控制算法
为了小车能够更好地走直线,采用了HW101陀螺仪模块和编码器进行角度环加速度环串级PID运算。小车的每一段路径加到电机上面的PWM值使用的是PID算法,通过激光测距模块获取的距离进行位置环PID运算,再通过HW101陀螺仪模块获取角度进行角度环PID运算,然后将两者PID运算的结果作为速度环的输入进行PID运算,每100ms对车身进行一次矫正。当到达期望值则表示这段路径行驶完成,PID算法运用相比于直接给定PWM值的优势是,前段路程速度较稳定,当越靠近期望值后,速度则会减慢,而直接给定PWM值的话小车运行过程中姿态不稳。
//位置式pid
void wei_pid(pid_param_t *pid,float target,float actul)
{
pid->error=target-actul;
if(-10<pid->error&&pid->error<10) //积分分离
{
pid->integrator+=pid->error;
}else
{
pid->integrator=0;
}
pid->integrator=limit(pid->integrator,250); //积分限幅
pid->out_p=pid->kp*pid->error;
pid->out_d=pid->kd*(pid->last_error-pid->error);
pid->out_i=pid->ki*pid->integrator;
pid->out=pid->out_d+pid->out_i+pid->out_p;
pid->last_error=pid->error;
}
//增量式pid
void zhen_pid(pid_param_t *pid,float target,float actul)
{
pid->error=target-actul;
pid->out_p=pid->kp*(pid->error-pid->last_error);
pid->out_i=pid->ki*pid->error;
pid->out_d=pid->kd*(pid->error-2*pid->last_error+pid->last_last_error);
pid->out+=pid->out_d+pid->out_i+pid->out_p;
pid->last_last_error=pid->last_error;
pid->last_error=pid->error;
}
3 激光测距模块
激光测距也是使用维特科技的产品,使用串口直接接收,一个放在车头的用来检测小车与二维码挡板、收货地两个挡板距离定位和回到出发点前后距离检测定位,左边安装的一个激光测距模块仅仅用来小车回到出发点时对旁边挡板距离测量,用来定位小车左右距离。这一款陀螺仪检测距离可以达到四米,适用本次比赛。
/**********************************************测距模块***********************************************/
uint16_t jiguang_distance;//0-65535
uint16_t jiguang_distance0;
uint16_t jiguang_distance1;
uint16_t jiguang_distance2;
uint16_t jiguang_distance3;
uint16_t jilv_target=200;
void distance()
{
if (U5_GetRxFlag() == 1)
{
jiguang_distance0=(int)(U5_RxPacket[8]-48);
jiguang_distance1=(int)(U5_RxPacket[9]-48);
jiguang_distance2=(int)(U5_RxPacket[10]-48);
jiguang_distance3=(int)(U5_RxPacket[11]-48);
if((jiguang_distance0>57)|(jiguang_distance0==0))
{
jiguang_distance0=0;
}
if((jiguang_distance1>57)|(jiguang_distance1==0))
{
jiguang_distance1=0;
}
if((jiguang_distance2>57)|(jiguang_distance2==0))
{
jiguang_distance2=0;
}
jiguang_distance=jiguang_distance0*1000+jiguang_distance1*100+jiguang_distance2*10+jiguang_distance3;
OLED_ShowNum(1, 1,jiguang_distance, 6);
}
}
4 HWT101陀螺仪
陀螺仪用来矫正车轮悬空导致小车偏移,还用来控制小车转向程度,使用这一款陀螺仪的优点是可以用串口直接接收数据,根据说明去对数据处理就可以得到角度值,还有就是数据不漂移、不受磁场干扰,精度高,适用于多种比赛,不用再去做滤波处理,小白容易上手。
/*************************HWT101陀螺仪***********************************/
uint8_t TH_H;
uint8_t TL_H;
float HWT_DAT;
float HWT_Z = 0.00f;//角度
char HWT_falg=0;
void tuoluoyi()
{
if (Serial_GetRxFlag() == 1)
{
TH_H=Serial_RxPacket[16];
TL_H=Serial_RxPacket[15];
HWT_DAT = (((short)TH_H<<8) | TL_H); // 高8位低8位
HWT_Z = ((float)HWT_DAT/32768)*180; // 把0°至360°
if(HWT_Z>180&&HWT_falg==0)
{
HWT_Z-=360;
}
//OLED_ShowSignedNum(1, 1, HWT_Z, 4 );
}
}
三 总结
参加完广东省工科赛后,看到了现场很多队伍的作品都是没有避障功能的,而且也有很多队伍是没有到达区域的定位功能的,我选择的这套方案这两个功能都具有,避免了小车运行中遇到了障碍物或者没完全到达区域内的问题。
谈谈自己的感受吧,参加完了电赛和车赛后拥有了一定的比赛经验,广东省工科赛近几年的题目都大差不差,网上开源的资料非常丰富,备赛时间长,在这么多有利的条件下我觉得完成本次比赛的难度较小,非常适合大一大二的同学去参加锻炼,我跟我的队友参加本次比赛做了两套方案,两台车子,一台车子花个十几天从搭结构到编写代码调试就能够完成,期间模拟了很多比赛的特殊状况防止决赛中遇到难以解决的问题,可惜的是决赛内容跟初赛内容完全没变。
以上为我本次参赛的一些简短的分享,欢迎各位大佬指出错误和分享经验。
四 工程获取
过一段时间整理完后会进行分享。