本人是在参加完蓝桥杯比赛(省赛)之后才知道这个比赛的,当时由于蓝桥杯比赛成绩并不理想,没有进入全国总决赛;我的指导老师鼓励我说:没关系,咱们之后“干一票大的”。
本着对此次比赛抱有是不特别自信的心理,我在今年4月初开始准备这场比赛。
最初得到的消息是我们就按照国际灭火机器人的比赛规则来备赛,由于我大一的时候自己动手制作过一个红外遥控控制的遥控车,因此对于有轮子的机器人的控制来说算是有了一部分经验。大一的时候我采用的一个电机驱动是L298N,而我现在手头上有的是板载的L293d,不过这两个芯片使用方式基本相同,这也为之后的工作提供了一定的基础。
另外,我阅读完这个比赛之后,决定采用最基本的51芯片,也可以考虑用增强型的51(因为当时的我就会使用这一种单片机),灭火机器人比赛主要就是让机器人遍历4个房间,每个房间都有可能有火,之后才是灭火等操作(以下是灭火机器人的地图其中H是起点,屋子的入口有白线,H区域是一个白色的范围,整个场地地面是黑色):
那么问题就来了,如何遍历4个房间?当时拿到这个图纸的时候,我直接就想到了一个方法:寻墙。但是考虑到中间的房间无法通过寻墙进入,我就索性直接打消了这个念头。
在苦思冥想了几天之后,我想到了自认为的一个绝妙的主意,我把它叫做“右手定则”,
也就是当右面有路口的时候,右转90°进入路口,依次类推,当不得不左转的时候,再左转,最后会回到H点,然后切换“左手定则”模式,第二次检测到H时停车。对应的我写了一个出屋函数,因为进屋的时候,地下会检测到白线。
有了思路之后我就开始了机器人制作过程,基本上用了3天时间,成品如下:
基本上就是这个样子,用到的器件主要有:光电开关*6,L298N,电机传动80:1,超声波模块*3,继电器,5路火焰传感器,PCF8591,18650电池*2,自制风扇,寻迹模块*3,舵机一个,霍尔元件*2、磁铁若干、51单片机最小系统。
光电开关*6:前左、前右、左、有、后左、后右。前左和前右用于行进过程中避障,左右用于判断路口,后左、后右暂时备用。
L298N:电机驱动,PWM波调速,他的调速方式我没有用控制使能端的方法调速,而是让他输出两端同时为低电平或者高电平的方式让他停止,而两端高低电平不一的时候运动,依次来调速。
超声波模块:机器人左右快要蹭墙的时候的微调。(备用)
继电器+自制风扇:灭火
5路火焰传感器+PCF8591:用于判断火焰位置
舵机:用于控制风扇吹风高低
霍尔元件+测速模块:测速
车体做好之后,就开始根据思路码程序了。首先现在的思路是一种基于数学模型的思路,他的每一步运转都是直线以及旋转90度处理的,因此我所面临的第一个问题就是走直线的问题。走直线说起来简单做起来难,如果要走一个非常直的直线,其中涉及到了PID算法。我最开始的时候用了Visual C++ 6.0 模拟了一下PID精确控制的算法。感觉效果还可以,但是把它放到这个小车上的时候,却跑的一塌糊涂。没有进展的我在那几天陷入了思考。以下是PID算法的软件模拟:
}
在有一次我和一位学长的谈话中了解到:PID算法的反馈系统也相当的重要,然而我的反馈就仅仅依靠着一个直流电机,和霍尔元件+一个轮子4个磁铁,这个的反馈是达不到一种取样的线性水平的。他给我的建议是要么换编码电机,要么换思路。。。
但是对于当时的我依然“头铁”,抛弃了自动走直线的思路以及自动调节转90度的思路,硬着头皮靠着延时以及手动调程序的方法完善着我的程序,对此我唯一的收获是:尽量少用或者不用延时控制小车转弯,因为在延时的过程中,MCU除了会进入中断子函数之外,什么也没有干,在延时的过程中,你并不能确定你的电机输出是出于一种什么样的状态,如果确定,也会带来极大的麻烦。因此我建议用do{ }while(); 来代替delay(); 因为do{ }while();里面有括号,你可以控制在此段时间内,你的设备是出于一个可控的环境。
在过了一段时间之后,我已经可以保证这个机器人可以走3个房间了,并且有50%的几率(在误差范围之内)走完全程,并且耗时3min左右。至此我对我的成果还是稍稍满意的。
在我的满意的心里还没有充斥我整个细胞的时候,我们学校的另一个队伍制作的机器人以1min左右的时间跑完的全程,而且他们用到的思路正是寻墙。当时对于我的打击还是极大的。
原来,他们队并没有PID算法,仍然实现了寻墙。其中有5个光电门,除去中间一个是前方避障外,左2,右2,用于左右寻墙,而2个光电开关一个是检测远处障碍,一个检测近处,当车身出于2个之间的时候是直走,而远近另个光电开关限制了机器人与墙的距离进行调整,从而实现寻墙。在回到起点之后再切换与其反方向的寻墙,就实现了全部遍历。
我不得不佩服他们队伍的想法。我也开始自己反思。经过了一天左右的时间,我对我之前的思路方法进行全盘否定,并且也开始用起了寻墙的方法,但是我并非抄袭,因为了用了一种更加便捷的方法,让传感器的数量直接下降到了3个。除去前方避障以及反方向的传感器,仅仅用了一个红外避障或者光电开关实现寻墙的控制。
如何用一个光电开关实现寻墙呢,这个方法的实现或许很简单,大概是迄今为止最简单的方法,但是要想到这个主意可是需要灵感的。
我采用的方法是:当右寻墙时,将左轮PWM占空比调节至100%(全速),而右轮占空比为10%,这就导致了车体在正常过程中根本无法前进,只会右转。而此时在车体右部装上光电开关,当有物体阻挡时向左避障,而没有物体时继续左100% 右10%,采用这个方法之后你会发现你的车非常鬼畜,但是他却达到了寻墙的目的。并且用时40秒!
(此方法采用了微分的思路直行,他的速度主要取决于左避障右轮的PWM占空比以及平时行走的左轮PWM占空比)
经历了这些,我收获了很多,包括PID算法,超声波测距的子程序设计等等。但是最让我印象深的是,身为一个开发者,要有全盘否定的精神,所谓磨刀不误砍柴工,解决问题之前多多思考 ,解决一个问题的时候,解决问题的方法并不一定是越复杂就越好。
在临近比赛的时候遇到了一些小插曲,本届机器人比赛并没有灭火项目,我当时心里是崩溃的。但是我们发现有个走迷宫的项目对于灭火机器人遍历屋子的方法同样适用。不过我们唯一要改动的是尽量缩小车身,于是就有了我的小车2.0 和 3.0 (要求车身不超过14CM)
在最后,我们只用考虑如何在终点停止的问题了,在终点,裁判会拿一个有颜色的板子挡住,当机器人识别到时会停止,当裁判抽出挡板时机器人再前进到指定位置。对于这个,我们用了一个颜色传感器,颜色传感器的使用要用到一个定时器和一个计数器,然而对于51系列的单片机捉襟见肘的资源如果这样的话就无法用定时器PWM调速了,因此我们用了两片STC12 20P引脚的小单片机,最小系统自己制作。如图:
由于临近6月比赛就剩一个星期了,全部都是手工打造,其中为了缩小体积,3.0的小车用了两个STC12的20P引脚的芯片。 一个控制行走,一个控制颜色传感器以及OLED屏幕。车身长宽10CM。在比赛之前我们进行了无数的测试。终于在比赛当天表现良好,以1分钟左右的时间(最快速度)走出迷宫,取得了第五届河南省大学生机器人大赛迷宫组一等奖的成绩。
在这次比赛中,我也深刻认识到了自己能力的不足,以及51系列单片机的局限性,因此我决定立即学习更高级别的单片机,并且提升自己的编程思维。在日后我会在有硬件机会的时候亲自尝试变积分精确PID算法控制速度的可行性。并且之后我会尝试用电子罗盘的形式控制小车旋转90度。其中电子罗盘数据采集的程序已经写出。日后会尝试。
PS.其中红外避障和光电门是有障碍输出低电平,无障碍输出高电平。火焰传感器相反。相关传感器细则请参考使用手册。