声明在前:本系列以程序设计为主,适用于刚学会32,想完成一个基本项目却不知道怎么上手的小伙伴。想学习硬件方面如:电路、画板等内容的朋友请不要在本系列耽误您的时间,关闭即可。
经过 第一天.与第二天.的基础内容讲解,本系列终于迎来了最后一期:避障、磁铁、停车元素的方案设计,以及——如何让车跑得更好?
首选红外模块/光电对管。简单朴实不枯燥,又不像超声波花里胡哨。
左图为在第一期中,说到过一个平价版的红外模块;右图为光电对管(圆柱体,长得像个小号手电筒):
装车的时候只要让他们都朝前就能充当避障的传感器:(光电对管的距离更远一些,但速度没达到一定程度的话,没必要那么远就作出响应)
光电对管的用法和红外模块几乎是相同的:)
在没有障碍物的时候,红外模块返回值为“黑色”;当障碍进入检测范围时,返回值为“白”,而程序就对其返回值作出响应,这便是红外避障的原理。所以,如果用红外避障的话,障碍物不能是黑色,否则返回值永远都是“黑色”。
原理讲完,接下来我们看看程序:
最直接的方法就是用if else语句:
初始化balabala
while(1){
if(有障碍){
避障();}
else {
Run();}
}
外部中断,就是当特定引脚发生改变的时候,触发中断。
我们可以把连避障的引脚设置为外部中断,上升沿或下降沿触发,这里就不细讲了,感兴趣的可以自己回去研究
其实无论是用if else 还是外部中断,我们都希望把“避障”作为一个突发事件来优先处理的。避障程序该怎么写呢?
推荐一种最简单直接的方法:固定路线,最多分一下往左还是往右拐出两种情况:
即:(右转为例)
void Avoid(){
右转2S——怎么转在昨天文末写了,就不在这里浪费空间了
左转2s
}
这就是最基本的固定程序避障方案,但是在实际上,这种写法可能会产生以下几种结果:
第一种自然是我们最希望发生的,但是理想往往都只能是理想;
** 都包含一个问题:拐弯异常。**
我们可以适当增加拐出的角度与速度:(向右拐出,TIM4通道一连左电机,通道二连右电机)
TIM4->CCR1 = 56000
TIM4->CCR2 = 36000
High_Set = 右转大角度
delay_s(1.5)
我们可以适当减缓回归时的角度与速度:(向左回归,TIM4通道一连左电机,通道二连右电机)
TIM4->CCR1 = 36000
TIM4->CCR2 = 48000
High_Set = 左转小角度
delay_s(2.5)
通过以上方法,若是能让车的避障曲线达到这种效果是比较稳妥的:
(不排除有厉害的小伙伴能做到闪现的可能性)
除非速度快到每秒三四米,不要把检测距离提得太高,否则就是纯粹给别人找机会超越自己了。
磁铁检测同样提供两种方案:
电路如图:纽扣电池提供电源,干簧管为开关,唯一的用电器是蜂鸣器
这样就能够在周围有磁铁的时候直接触发了。
一般的干簧管都是没有磁场的时候断开,有磁场的时候闭合。而且还需要讲究放置方向的,如果可以的话,最好能多准备一些,在车上多装几个,互相垂直放置,再多留几个备用。(这是放在底盘的,想支出去也没问题)
因为干簧管本身比较娇贵,又特别小,如果一不小心没拿住掉地上了就不用找了:一是找不到,二是就算找到了十有八九也摔坏了。。。所以建议多准备一些留着备用。毕竟单独的干簧管非常便宜。
第一次感受到了鼠绘的艰辛,画出来这玩意我能吹一年
这是我曾用过的一种干簧管模块,在没有检测到磁铁时,返回值是0;在检测到磁铁时,返回值是1.。既然返回值只有0和1的分别,那用法就跟红外模块基本无二——或者说这都是一类的模块。
我们只需要把一个引脚初始化为输入后不断读取它的电平值就好了。
然后另一个引脚设为输出,连接蜂鸣器;甚至有想法的同学可以放一块屏幕+MP3播放器,当检测到磁铁的时候,来个互动。
——————————
我记得我学长当时做这个同样的比赛的时候,车上就是有一块彩屏,还有MP3播放器,每检测到磁铁或避障等元素就放个笑脸,还放不同的音乐,车跑得又比其他所有人都快,真是,节目效果拉满:) 这一点我还是远远不如当时的学长的。不过我们的车属于重量级寻迹车。大概是什么感觉?就像掠夺者,无法阻挡:)同样是寻迹车,一旦跟别的组的不小心接触了,一定是其他组的被我们的车撞飞或碾过,对,撞飞或碾过:)又撞不过,又追不上,节目效果同样爆炸:)
————————————
注:蜂鸣器是分有源跟无源的,这一点各位就根据需要自行决定选择哪一种好了。
我们再来回顾一下赛道:
我们看到:停车线比赛道线要粗一些,这就为我们的检测提供了极大的便利:我们可以再安置一个不和寻迹模块在同一水平线上的红外模块,让这个点到寻迹模块线的距离,小于停车线宽度,大于赛道线宽度就好。
然后让这个额外的电感和五个寻迹的一部分全都为“黑”时,立刻停车,PWMAB=0,舵机复位。
不过要注意的是:停车线和十字线都有可能触发停车条件,尤其是当停车线不够宽甚至本就跟赛道线一样宽的时候,更容易增加误判的几率,导致十字线停车。
对于这种情况,要考虑到停车线是否有别的条件,比如多条横线作为停车线时,可以用计数的方式,当计数达到一定数量,就停车;或者是停车线上有磁铁,这就要用干簧管模块+计数了——还有赛道上的磁铁呢等等等等,各位见招拆招即可。
接下来,终于到了最重要的一点:
实践出真知,斗争长才干。只有多调车,才能找到最适合于这辆车的PWM、舵机角度。有用到编码器的还有一组或多组pid,或者有实力的使用比pid更高级的模型控制方法等等,除非它能自己学习,当然学习也不是万能的,而且会学习的前提是有大量的数据积累。所以,还是要调车,调车,再调车。
高手过招,弯道超车。真正厉害的赛车手都是在弯道超过了对手——真正厉害的车不是直线快,而是过弯不减速。最能直接反映一辆车调得好不好的,就是弯道。
第一个直角弯和平滑直角弯的区别就会难住不少人,更何况后面的弯道了。如有雷同,不胜荣幸/斜眼笑
说实话如果明年是我出题,我倒挺想用这个的/doge
质量上乘的赛车不光要足够灵活,兼顾速度才是最重要的。放着好好的直线不加速,难道等着被超越吗?
直线加速的方案很简单,最基本的就是11011的时候加速。虽然有可能发生出赛道的情况,但这不就来了?
出赛道是很正常的事情,谁还没出个道了/doge。不过就算真出道了也不要怕,我们还有机会,先看图:
虽然它拐弯不及时,虽然它出道了,虽然它现在是11111,虽然程序里没有写这种情况怎么办。但是没事,它出道之前的状态是 01111,即左转大角度。那么,最直接的保持上一个状态的写法就是:
if(01111){
左转大角度
if(11111){
左转大角度}}
else if(10111){
左转小角度
if(11111){
左转小角度)
else if...
}
这就是最简单的保持上一个状态的方案,如此便能在发生意外的情况下力挽狂澜。
同为寻迹车,只有两个电感的和五个的肯定不一样。单论排列组合的话,双电感的组合多少,五电感的组合又是多少?每多考虑到一种情况,跑得稳-跑得快的几率就越大。
虽然我一直在用的都是一整块五电感的模块,完整的模块带来的好处也很多,但是,它也是限制我们的因素。因为它的左右宽度是限定的,只能检测到一小块范围,如果我们再在其两边各加一个,或者在车身、车尾等,检测到的情况就更多了,车对赛道的判断力就更强了。
在第一期中写的Run函数只有5个条件,但很明显它是远远不够的,在实际开始跑车的时候,经常会发生除了这五个情况以外的事情,就比如刚刚说的出赛道,还有停车,总不能全都放到else 里面做相同处理吧,所以剩下的判断条件就需要各位在调车的时候自己完善了。
——————————————————————
到此为止,这个短篇系列就算是完结了。本系列只是为各位刚刚入门32的同学提供一个思考的方向,至于32,甚至嵌入式本身仍需要各位亲自深耕,而且32也不是三天就能精通的。而通过这三天的文章,如果大概知晓了一个工程从0到逐渐完善是怎样一个过程,就足够了:)若是您能从中吸取到了什么经验,并以此让您的车跑得更快更稳,那真是我的荣幸。
——————
我是康.,希望做一名能够帮助到各位的博主!除了这个短篇系列,我也在持续更新学Python的系列,欢迎感兴趣的小伙伴关注我的频道!在Python更新完后,根据时间安排,我会再开机器学习或者算法系列,随时欢迎各位与我共同学习,一起进步!