暑假阳光下训练的傻孩子们
电赛的训练最早是暑假就开始了,为了参加集训我甚至一个暑假没有回家。食堂真是太难吃了
但是令人没想到的是今年学校对于自控队伍的训练约等于没有,所以在训练期间我们一直在做一些往年的题目来提高技术水平。
这期间不得不提的就是:还好我们试着做了板球控制系统。在做这道题目的时候我们发现树莓派处理图像有很大的时延,并不满足板球控制系统的要求,因此迫使我们学习了OpenMV。而OpenMV在正式的电赛中也确实发挥了很大的作用。
除了OpenMV之外还有点小收获就是控制器:
我们采用了TM4作为主控,用以防止电赛自控题目出现限制单片机的情况。为了使用方便,我在使用过程中对一些外设功能进行了二次封装,虽然写的代码很屎,但是还是很好用的,已经开源在了我的GitHub中的TM4C123G_UserInterface仓库中,代码中含有详尽的注释,无论是别人使用还是我自己后面再看都有很大帮助。
就在当时所谓的电赛前两天,我们整个队伍搬家到了比赛的教室,结果熟悉了一天环境后得知了电赛推迟的消息:
就这样,在暑假阳光下训练的傻孩子们被电赛放了鸽子。
不过虽然大部分同学都回家了,我们队伍仍然没有回家。不是因为想留下训练,实在是因为再没有比暑假更适合做自己的项目的时间了,因此我们三个人分别开始玩起了自己的东西:sjj的平衡车、yqy的独轮车还有我自己的无人机(虽然至今未完成),项目进度我写在了这篇文章里面,现在开学应该是龟速更新,只能等到寒假的时候才能接着玩自己的项目了(叹气
对第二次延期习以为常的傻孩子们
有了第一次延后的经验,大家开始对于电赛延期习以为常了,也就是在这样的心情下,我们对于得到的电赛延期消息其实十分平静,然后继续做手中没做完的项目。
带着平静心情打电赛的傻孩子们
日子一点一点地过,我们当时对于电赛的执着其实已经被磨得不能更平了。
从一开始的见到材料清单疯狂猜题,比赛前一晚睡不着觉,到后来的见到比赛赛题内心毫无波动,平静的开始进行分工,相信无论是队友还是我自己,我们都有了很大的提升。
电赛开始,看到赛题我们几乎毫不犹豫地选择了F题:智能送药小车。
题目太长就不放图了,可以点进超链接去看。
另:单片机工程上传到了蓝奏云,需要自取吧:
写这段内容的时候我们已经完成了电赛的测评,结果还算满意。下面的内容大概是对这四天三夜的一些回顾、吐槽还有反思(都是废话):
第一天 - 昼
拿到赛题,秒选F题,我立刻开始新建工程担任了单片机程序的撰写任务。
与此同时,yqy负责硬件开始搭建两辆小车,sjj负责视觉开始撰写代码。
此时的方案选择是:
硬件:四轮小车
单片机平台:STM32
视觉:OpenMV
小惊喜:其实我自己有一辆小车不过两个队友一直不知道,电赛了想着拿来作为备用小车,可谁知道最后竟然刚好要用两辆小车,我们三人直接狂喜。
单片机平台选择是我们最熟悉的STM32,在工程中使用了一些我自己平时写的库:
调试信息输出库:DebugLogger
时间片轮询框架:TimePiece
其中时间片轮询框架在电赛后我自行进行了一些功能上的完善,上传的是完善后的版本,这部分后面再说。
在队友搭车的同时,我将电机、舵机的底层驱动以及速度环、转向环PID调节算法全部撰写完毕,刚好这时队友将第一辆车搭完了,开始简单的软硬件联调+调节速度环PID。
接着和视觉队友沟通了一下两边的通信协议,完成了通讯协议的解析程序;
为了将OpenMV装上车子,yqy专门3D建模量身定做了一个支架;
接着sjj完成了红线循迹程序,于是开始将OpenMV装到车上开始进行初步联调。
大概一天就这么结束了。
第一天 - 夜
有关晚上的内容大概仅限于对睡觉环境的吐槽吧...
第一题天在活室睡觉,我打开了活动室内的一张折叠床(据说是某学长留下的)打算美美的睡一觉:
我在早上两点美美的入睡了,但是却收到了反噬:有一只蚊子在我身边飞来飞去(/(ㄒoㄒ)/~~
以为会做个美梦,但是这次睡觉经历我见到人就会这样吐槽:就像睡在楼梯上面一样
四点钟我醒了一次,是被冻醒的,然后翻了个身接着睡,早上六点就实在忍不住,起来了。
这绝对是我主动起床最早的一次了。
就这样,第二天开始了。
第二天 - 昼
后面几天的内容其实并没有什么好说的,基本都是软硬件在联调,然后发现各种各样的问题并且解决各种各样的问题
依照之前的四轮小车的方案,我们大概做了第一个要求,此时就发现四轮车在行进的时候还要进行倒车和复杂的路线规划,这样整个系统的稳定性会直线降低,同时时间上也会有很大程度的浪费。
虽然但是我们仍在努力克服这些问题。联调的时候顺便确定了一些视觉任务的细节,比如:对十字的识别、对于T形路口的识别以及对于赛道终点(虚线)的识别。
同时还有一个遗留问题一直在困扰着我们:如何检测200g药品被放上了车子,暂时还没有明确的方案。
刚好有同一个实验室的同学和我们同时想到了两轮加万向轮的方案,于是我们立即更换方案:
yqy开始更改整辆车的硬件,sjj继续写视觉代码,我则将原来代码中用不到的底层驱动删除并且将PID算法稍作修改以适应双驱动车的循迹。
最终大概搭出了一辆简单的三轮小车(图片下方正面向前方的):
这个时候其实已经大概下午了,视觉那边遇到了数字识别的难点,于是我们三个人一起研究了很久,一天大概也就这样结束。
对了,必须要说的是谢谢指导教师送我们的披萨,真的很好吃!
第二天 - 夜
调车到大概四五点钟,我和队友都回去睡觉了。
有了第一天的教训,我绝对坚决拒绝再睡在那张床上面。我天真地以为趴在桌子上应该能获得比在床上更好的睡眠效果,但是事实是我完全错了:
穿着厚厚的马夹,戴着帽子,我睡了一小时就醒了,醒来的时候肚子里面鼓鼓的,感觉全是气体......
睡眠不足的虚弱感不断冲击着大脑,整个脑子浑浑噩噩的,整个人大概处于一个行尸走肉的状态:
站起来到外面走了一圈,看到了我未曾看到过的南邮日出。内心没有狂喜,没有紧张,不如说是什么都没有。转身回到活动室,队友们还在睡觉,听着大家的呼吸声,我意识到我才睡了一小时多应该再睡会,于是趴在桌子上闭上了眼,一会之后仍无法入睡,于是再次起身到走廊走了一圈......
上面的过程被我像一块单片机一样执行了记不清多少次(我知道这种比喻很奇怪),我不知道自己在干什么,只是走的次数多了整个人就会变得更清醒一点。直到再晚些sjj醒过来了,大概我的神智才恢复了一些,没过多久yqy也醒了于是我们商量了下决定去吃早饭。
吃早饭的路上我提出下午想回宿舍好好的睡一觉,因为我意识到我个人的消耗已经太大了,队友也同意了。
不过吃完饭之后(也可能是生物钟到了),我整个人开始变得精神起来。
就这样,第三天开始了。
第三天 - 昼
到了这时候,已经能够为车子实装上数字识别了,并且开始真正意义上的软硬件全面联调。
判断药品有了一个很好的方案:使用装满螺丝的大试管作为药品,并且由yqy为其量身建模一个试管架,在试管架下面放上微动开关,即可通过开关的闭合与否来判断是否有药品放入(这应该是电赛期间我们的一个高光设计了);
送药的过程中发现一些小问题:有些本应转弯的地方被循迹算法影响导致没法表现出我们想要的转弯效果,于是在程序的状态机结构中添加了循迹算法的屏蔽框架;
后续的测试中发现仅仅屏蔽循迹算法然后阻塞延时是不够的,因此又添加了一点简单的非阻塞延时代码;
视觉方面则是发现了一些会相互之间误识别的元素,并对他们做了一些处理。
虽然说着不多,但是中间过程非常艰辛,仅仅发现上述问题就花了很长时间,毕竟问题表现出来的现象往往是无原因的不正常,我们只能在一堆代码中一点一点找问题出在了哪里。
大脑转着转着,一天就这样结束了。
第三天 - 夜
白天的时候听了yqy推荐,我发现了一个良好的睡觉地方:一张黑色的大椅子
只要整个人躺在上面然后把jio伸出去再找一张矮一些的椅子来垫jio就可以了。
最后一天肯定是要冲刺一下的嘛,所以一直肝到了早上。
早上五点钟,我尝试了一下之前说的方法,不得不说这种方法睡得比前两天都要舒服,不过到了早上六点我还是准时醒了过来(作息规律了属于是),整个人还是一种浑浑噩噩的状态,但是比前一天的行尸走肉应该好多了(大概
依然是等队友醒过来然后出去吃了早饭,接着开始了这最后一天。
第四天 - 昼
最后一天了,整体的功能已经成型了,不过还有一些小细节需要完善。
大概是视觉上提高了T字路段的识别率,机械结构上进一步做了一些优化,单片机程序上对一些特殊情况做了一点处理。
解决完这些之后,我们开始搭起第二辆车。开始第二辆车调试的时候其实大概已经下午了,不过好在发挥题目对第二辆车子的要求不是很高,因此我只是在第一辆车的状态机上面稍微改改就获得了第二辆车的代码。
晚上八----点~(请自行脑部大姨的声线
收工!
吐槽题目
对于F题甚至是对于整个今年的电赛题目,我相信肯定会有很多人想要吐槽一些什么。我只做了F题,对于其他题目也不好信口开河,就来吐槽一下F题的槽点吧:
- 图像在整个题目中起着决定性作用
- 题目的区分点在单片机上
单纯的看这两点其实都不是一个良好的槽点,但是这两点同时出现就成为了最大的槽点:
明明图像在整个题目中起着决定性作用但是题目的区分点却在单片机上,与此同时单片机的内容又十分简单,并没有什么区分度。
这就直接导致了绝大部分参赛队伍只有两种结果:要么全部做完,要么一个题目都做不了。
单片机程序
懒得再开一篇博客来讲这东西了(主要是还有一堆东西还没写完,所以就顺手一起写了),所以就在这里大概讲一下参赛作品的单片机程序框架吧(写的挺屎的,欢迎大佬提出宝贵建议)
首先需要的功能显而易见:点灯、按键检测、电机驱动、串口通信还有编码器使用。
为了使程序更有条理使用了一些常见的代码框架(或者说程序设计方式?):状态机、时间片轮询还有数据流处理(我也不知道是不是这么叫
首先显而易见的是主循环里面一直在跑小车的状态机,然后在一个1kHz的定时器中断回调函数中部署了时间片轮询架构以对其进行时分复用,实现一种类似OS的效果。
在时间片轮询框架中执行了4个任务:
- PID控制(10ms
- 状态检测(2ms
- 日志输出(10ms
- 非阻塞延时的计时(2ms
PID控制是需要有实时性保证的,这点用过的大家都知道。
与OpenMV的通信是用串口接收中断来做的,中断里面放入了使用流处理方式的协议解析程序,每次运行完解析程序都会对所需的变量进行赋值,状态检测任务其实就是实时检测这些变量以便获得当前的路况信息,方便状态机进行跳转。
日志输出任务看名字其实就很容易理解了,就是在调试的时候把一些需要输出的数据进行输出,当然最后realease版本的时候是要删除的。
非阻塞延时计时任务仅对一部分有非阻塞延时需求的代码服务,为其提供计时功能,以便能够实现非阻塞延时。
也正是电赛期间发现了对于非阻塞延时和任务屏蔽的硬性需求,我才在自己的时间片轮询框架中添加了单任务和多任务的非阻塞延时功能以及任务屏蔽的功能。
测评时一句话都不敢乱说的~傻孩子们~
真的是第一次参加电赛测评,整个人紧张的不行不行的。
测评前有半小时的时间给我们进行准备和尝试,我和队友商量了一下大概整个流程应该怎么进行,包括但不限于谁发车、谁放置药品、谁录像以及谁取下药品等等。但是真的等到专家接入我们的测评会议室的时候真的是一切从简,之前的流程完全抛到脑后,唯一脑子里面还记得的就是把jio离车子远一点。
PS:测评当天我没脑子的穿了一双红色的鞋子,会造成图像的误识别,好在最终并没有什么影响。
测评基础第一题,第一次我们的车子跑的还好,只是有一些出线,测评的专家好心的让我们又测评了一次,至于第二次是什么结果我只记得跑完了,似乎还是有点压线来着。
测评基础第二题,同样是第一次有点压线,不过第二次跑的很完美,于是专家记录了我们的最好成绩。
测评基础第三题,两次都冲出赛道了,后面分析了一下觉得可能是因为贴数字的时候把数字贴的鼓起来了,导致摄像头没法看到数字。
测评发挥第一题,第一次就能够完整的跑下来,不过压线的现象有点严重,第二次两辆车都很完美的完成了题目,看到两辆车停下来的时候真的整个人都松了一口气。
不得不说上面的测评我们的运气都非常好,因为我们的数字识别其实有那么几个数字会以极高的概率(几乎是100%)被误识别,但是专家在选择数字的时候完全避开了我们的问题数字。所以其实能够到这一步我们就很满足了。
继续平静生活的~傻孩子们~
写下这段话的时间是2021年的12月13号,差点忘记了手头还有这么一篇文章等着完结。
比赛完之后就是等待时间,好在等待时间也不是很漫长。
11月26日出了省奖名单,我们运气还不错,获得了一等奖A的推优资格,但是我们学校的推优人数有点多,所以我们本来就已经满意的准备拿省一了。不巧的是,12月3号最终还是发出了国奖的名单,我们惊喜的发现我们通过了复测,拿到了国二的成绩。
也没有多么多么的振奋人心,我们依然继续着之前平静的生活。
继续玩着自己想玩的东西,仍然日常在给学弟学妹们讲课的时候翻车,唯一不同的是:
下次参加比赛的我们将抱着必拿国一的决心。