写在前面:
写完《我是如何连续两年获得吉林省机器人大赛一等奖的(上) 》一文后,很荣幸受到了面包板论坛管理和各位网友的肯定与支持,很开心。你们的支持与鼓励就是我学习的动力!再次感谢面包板论坛和各位网友。欢迎大家指教!
Wo先唠点:
这篇文章主要记录2017年参加吉林省机器人大赛时,Wilsin是如何用履带型全地形小车进行控制,并跑下来全场的一圈的。由于场地地图上有不同的障碍物,我将按照小车过障碍时的先后顺序进行记录。
先说路线循迹:
可以看到“S”型的场地,对于循迹来说是很重要的。我用的循迹原理很简单,就是在小车前端安装两个红外线传感器,两个传感器的距离要是场地线宽的1.5倍左右,这是针对于履带型小车我自己试验出来的一个最佳循迹模块安装距离。(第二年用的大轮子车,车速太快,因而两个传感器的距离就加大了,所以这个宽度还是需要对不同的场地进行实际测试)
正常行驶时,左右两个循迹模块是分布在线路的两边的,也就是小车骑着线路走的。场地上的黄色部分都会反光,只有当小车走歪了,使得循迹模块发出的红外光到黑线上,这样循迹模块就会发生信号给单片机。
单片机检测信号,如果是左边的循迹模块发来信号,则说明小车往右边偏了,则调节小车的履带转动方向。让左边的履带倒转,让右边的履带正转才能使得小车左转。我一开始以为如果想左转的话,让左面的履带正转但是慢点,右边的履带也正转但是快些,就可以让小车左转,但是实测时发现,履带车左转需要好长一段距离才能转过来,也就是拐弯十分不及时。后来,我在网上查了一些履带坦克行驶时的视频,才发现履带型的车要拐弯的话,都是一个履带正转,一个反转才可以及时的拐弯。
履带车的拐弯和第二年用的大轮子车拐弯还是有比较大的区别的。由于大轮子速度快,如果采用一个正转一个反转的方法去拐弯的话,会看到拐弯的角度太大,所以对于速度较快的大轮子车就采用了PWM进行控制,左边两个轮子给全速,右边两个轮子给半速,就可以往右转,左转也是类似。
可以看到,地图上在障碍物A,C,E的前面都有一条横着的黑线。当小车走到这个横着的黑线时,左右两个循迹模块会同时给单片机信号,单片机判断当左右都为有效信号时说明是要开始进行翻越障碍物了。由于三个障碍物不同,我在写程序时,就设置了一个标志位,专门记录是第几次检测到双黑线(左右两个循迹模块同时检测到黑线),如果是1,就执行第一个任务,爬坡。如果是2,就进行爬楼梯。如果是3,就进行栅格地行驶。如果是4,就全速直线前进,冲过终点线。哈哈,就是这样分任务执行的。
循迹模块的选取:
还可以看到场地上的B和D是由亚克力玻璃做的隧道,这就在相当于在黑线上加了一块玻璃,会反射一定的红外光,造成循迹不灵敏,有的甚至失效。但我用的这个红外寻迹模块是强度可以调节的,我在调试时,就把车放到隧道的玻璃上,调节模块上的可调电阻,使得红外强度可以实现在玻璃上正常识别黑线。由于没有玻璃的地方黄色反光和黑色不反光效果较为明显,所以在玻璃上可以正常工作时,在没有玻璃的地方也就可以正常工作了。
所以要选取对于玻璃反射影响较小的红外循迹,两次比赛中看到跑得最好的是用的激光循迹模块,对于普通红外线循迹模块也可以实现,但是受玻璃反射问题影响太大。另外见的比较多的是摄像头循迹,去年长春工业大学用的摄像头循迹,到正式比赛时由于现场光线与实验室光线强度不同,出现了不能循迹的问题。今年长春工业大学的学生采用了自带补光灯,就是在车的前方装了几个LED白光用来补光,以达到摄像头循迹稳定的效果。由于摄像头循迹的程序较为麻烦,我没有进行深入研究。还有我特别说明下漫反射光电开关传感器,就是下面的这种东西,在没有玻璃的地方循迹效果特别好,一旦碰到玻璃就失效了,所以以后这东西还是不适合用于循迹了:
希望卖这个的商家不要打我!
我在比赛时看到用激光传感器的循迹效果都特别好,比普通的红外寻迹在玻璃上循迹的时候要灵敏。
我在淘宝上也查到了激光循迹传感器,如果再有循迹的比赛,就首选这个了,但是激光模块好贵呀:
另外,现在想如果在车的左右两侧加上超声波传感器模块,就可以在过玻璃弯道的时候关闭红外循迹,靠超声波判断距离隧道玻璃两边的距离进行转弯,这样会比较可靠,程序会麻烦一些,在比赛现场没有见到类似的设计。
比赛的时候甚至见一些在车的两边安装导轮的,也就是说车完全是撞着隧道玻璃墙走出来的。哈哈,都是被玻璃反光给坑的,想的这怪招儿。
总之一句话,循迹模块的选取要考虑玻璃的反光,另外就是要买强度可调的那种,这样很方便现场调试,适应不同的场地。
再说程序控制思想:
关于单片机的选取,我第一年用的stm32,主要是觉得功能多些,用的单片机档次低了不够用。不过现在看来,一般的单片机都可以拿来用,只要有PWM就行,由于第一年用的的履带,其速度较慢,左右电机偏差不是太大,还有左右转时是靠一个正转一个反转执行的,所以第一年也没有用上PWM。第二年的大轮子是靠一个左右转速差来进行转弯的,因而用的PWM控制车速。
我设计的车进行循迹控制思想如下:车在正常前进时直行,设置一个20ms溢出中断的定时器,每过20ms进入中断,判断下循迹模块时候有跳变信号(也就是看看车有没有走歪)。如果没有走歪,赶紧退出中断,继续直行20ms,等再次进入下一个20ms进行循迹判断。如果在中断中循迹发现车偏转了,就让小车拐弯,拐弯的时间大约10ms就够了。这个数据值是我一点点测试出来的。基本上小车直行的时间和循迹时需要拐弯的时间控制在2:1即可。也就是说车即使需要拐弯,也要往前直行20ms,左拐或者右拐10ms,这样连续执行起来,才会有比较理想的拐弯角度,车在过弯道时的拐弯效果最好。这个数据很难得到,两年都是一点点测试得到的,但最终结论就是如果你要拐弯,也要往前走2下,拐1下。
先看下主函数:
主函数很简单,就是初始化,开中断,让小车开始的状态是直行,并将让舵机平放,这样摩擦力较大,车就跑的比较快些。主函数大循环里,就是一直在直行,每次循环都判断下左右循迹是否都是无效信号(也就是小车正好骑着线路),如果是继续直行。如果检测到左右循迹有跳变信号了(也就是小车压线了),那我就不走了,反正20ms又不是太长,等着20ms中断来了,到中断里执行拐弯。哈哈,主程序简单吧,就一个执行,所有的拐弯和任务都在中断执行。
再看下中断函数:(20ms定时器溢出中断)
20ms进入中断,先进行循迹判断任务执行(我待会儿进到tracking();循迹任务里给大家看),然后就是清中断标志,出中断。看看tracking();循迹任务里都干了点啥:
看起来有点长,我说下它干的活儿。就是进到这个函数里面先判断是左边的循迹模块有效了还是右边的循迹模块有效了(也就是看看小车往哪里偏了)。假如左偏了,右拐10ms【delay(5)】,然后就退出去中断了去直行然后再循环进中断,直到车走正了。如果车一直是正的,即使进到中断里进入tracking();循迹函数,也会判断得到没有任何跳变,然后赶紧出中断继续直行,走正道。
这样一来就可以在普通的线路上直行或者拐弯了。看程序会发现,我在拐弯10ms后还有一个循迹判断,就是if(LC!=0&&RC!=0),这主要用来判断是不是走到横着的任务黑线上了。
我们想下,车走的不可能是标准的直线,在过横着的任务黑线时,肯定是左边或者右边的一个循迹先发生有效跳变,这样我首先可以进到这个拐弯函数里,也就是不管左边还是右边碰到黑线了,我先轻轻拐一下,过10ms我再判断是不是两边都是有效跳变,如果是的话,说明真实是碰到任务线了,我就要开始执行任务了,而不是光拐弯就完事了。
可以看到有个line++,这个就是我设置的任务标志位,记录是第几次碰到双黑线,接下来直接判断任务标志位,去执行对应的过障碍的任务,直到这一个任务完全执行完成,我在退出中断,进行正常直行和循迹循环。
好了,程序大体框架就是这样,主函数直行,20ms进一次中断循迹。对于各个障碍任务如何控制小车我会在下篇文章中记录。
我的循迹思想就是这样,欢迎大家在评论中分享你们的循迹思想!
作者: wilsin, 来源:面包板社区
链接: https://mbb.eet-china.com/blog/uid-me-3880669.html
版权声明:本文为博主原创,未经本人允许,禁止转载!
wilsin 2018-5-26 22:25
用户1658788 2018-5-26 21:13
中断函数中只作相应标志位的置位操作即可。如定义20MS时间标志Flag_20ms
tracking()放入主程序中,当查询到Flag_20ms置位,就执行tracking(),
写程度多采用时间片轮询。
wilsin 2018-5-25 11:56
eeNick 2018-5-25 10:17
wilsin 2018-5-25 05:39
moniqiuwen 2018-5-24 11:22