1 背景
辅助驾驶目前已经被广泛应用于车辆和飞行器的自动安全控制。比如车辆的自动牵引力控制,可以在车辆发生打滑时自动反打方向和刹车,防止汽车进入漂移或甩尾状态;飞行器的自动攻角控制可以在飞机攻角过大时自动推杆降低攻角,防止飞机进入失速状态。我们今天要聊聊的一种辅助驾驶是让小车直行时能自动避让障碍物。
我去年在社区得到了一台自动循迹和避障的小车,来自慧净电子。小车前方的左右各有一个红外避障模块。
慧净的小车本身有一块STM32F103开发板作为控制器和一块基于293D芯片的电机驱动板。小车的固件可以实现几种功能:1、 自动黑线循迹,2、 前进和避障(小车不能控制,上电后就不断向前开,遇到障碍物就转向),3、蓝牙和WIFI遥控(通过蓝牙转串口或WIFI转串口接口输入控制信号,但是避障功能就没了)。
慧净的STM32F103控制板已经做出了串口控制接口。所以,我们只要通过串口输入相应的命令就可控制电机运动了。具体的串口控制协议如下图所示:
硬石F4工控板带有网络功能,可以通过网络给硬石F4板子前进、转弯或后退的指令,以此操作小车。
当小车靠近障碍物的时候,再前进就会撞车。
WIFI转串口模块可以实现遥控功能,但是没有任何辅助驾驶控制。然而,当我们使用硬石F4工控板代替WIFI模块以后,可以实现的功能就多啦。
今年初的时候,我得到了社区的硬石F4工控板的试用资格。试用时间有限制,很快就要归还给社区了,于是我赶紧做了这应用——硬石F4辅助驾驶控制器。
原理上,硬石F4实现网络TCP控制,然后通过串口总线与慧净的小车控制板通讯。也就是说,硬石F4做控制器,而把慧净的小车控制主板当电机驱动板来用了。
2 要实现的功能
网络TCP服务,这个使用硬石F4的教程里有个历程,我们可以基于它的框架来做。我们可以自创个个小车的网络控制协议解析代码,比如用W A S D表示前后左右方向。
用硬石F4的UART4(PC10和PC11)实现异步通讯,给慧净的板子发指令。其中慧净的接口协议在第一章已经给了。我们需要根据TCP解析到的WASD来确定前进后退还是转向。其中,当要前进时,要先检测一下是否有障碍物。左边有障碍物的话,用右转替代前进。
其中,UART4在CN10接口上,如下图所示。
自动避障的思路是这样的,当使用硬石F4的通用输入接口INPUT1和INPUT2读取小车的左右红外避障传感器信号,如果有障碍物就自动转弯(即使收到向前的信号)。硬石的输入接口有光耦隔离,非常安全。我们分别使用下图中CN22接口上的3-4和5-6端口连接左右避障传感器的输出,如下图所示。要用到的GPIO是PG1和PG2。
3 具体的开发过程
网络TCP服务的建立和数据接收,这部分在硬石的历程里本来就有,我们就不说了,我们只说说增量的工作。工程文件非常巨大,所以这里我不提供完整的工程文件了。这篇文章主要是聊聊代码的写法和算法思路。
首先,添加UART和GPIO的板级的BSP驱动文件到TCP Server例程。分别把c和h文件添加到src和inc目录。然后在工程里添加BSP驱动代码,如下图所示。
UART4的定义在bsp usart文件,如下定义了引脚和波特率:
当避障传感器给光耦输入信号时,光耦输出高电平(后来调试时候发现反了)。我们使用PG1引脚检测左边的避障传感器,PG2检测右边的。所以我没这样定义PG1和PG2两个引脚。GPIO的设置代码如下。(后来实际调试中又把INPUT IDLE 改成1了)
GPIO读取时候为了防止信号抖动干扰,我们设计一个延时算法来读取GPIO。下图展示了PG1的代码,PG2具有相同的形式。间隔1毫秒读两次,如果都是读到有信号,就表明有障碍物,输出GPIO_ON。
GPIO PG1和PG2的初始化代码,还有UART4的初始化代码都要添加到主函数里去,如下图所示:
有了板级支持以后,我们就可以添加各种花里胡哨的用户代码了。
要上重点了!
下面我们来添加一个辅助驾驶程序carctrl文件,放到用户代码目录,如下图
这个mycar函数会从tcp程序里接收字符。当接收到A S D时,相应地进入左转、后退或右转程序。但是当收到w时,具体动作要根据是否有障碍,所以进入一个叫car test的自动避障函数。避障函数名叫test是因为这个函数目前还处于测试阶段,具体的参数还要不断调试优化。
carctrl文件里写入了车辆行走控制的代码,这个是根据慧净板子的数据接口写的。举个例子,前进的代码如下图所示。转向和后退函数与前进有相同的形式。这是直接把慧净板子当电机驱动板进行控制的函数。
自动避障算法car test函数的具体形式如下图所示。当收到W时候,会进入car test函数。没有障碍就正常进入CarGo函数,也就是前进。如果左边有障碍,就控制小车右转,反之亦然。如果左右同时检测到障碍物,可能就要发生正碰了,所以让车轮倒转100毫秒(不然刹不住车),然后右转弯。大家会发现,我的if else做了好几次,这是因为写这个代码时候我没有打草稿,边写变改造成的(原来以为只有一两个状态)。而且代码飞流直下三千尺却一行注释也没有。这是个不好的示范,请大家尽量规避这种写法。当if else较多的时候,我比较建议用switch语句。
把mycar函数写进tcp echoserver文件里,并做个接口。tcp echoserver是硬石的tcp服务例程里本来就有的。把recdata数组收到的字节赋值给mycar函数的输入变量,如下图所示。
在主函数的头文件里定义一下USE DHCP宏,定义TCP服务的端口号,如下图。可以让路由器给硬石F4分配IP。
好了,大功告成,可以编译了。如果像下图这样没有报错也没有警告,就可以上传到板子上跑了。
编译并上传到板子上,程序就开始跑了。当然,后续调试过程中,我后来发现GPIO部分的代码写反了。实际触发时候,GPIO是低电平,这个只要代码上把idle状态电平的定义改一下就可以解决。
4展望
在网络连接上,我们这次的设计使用了以太网,小车最后拖着网线到处跑,实在是很不方便,所以还有提高的空间。如果再在车上加个无线路由器,就可以实现WIFI控制了。
控制器会根据障碍物位置用左或右的命令替代人发出的前进命令。这么一来,即使命令它撞墙,它也不撞墙,表现上似乎有些“不听话”。也许我们可以改进一下自动避障,比如先询问一下看看驾驶员是否愿意让机器来接管(好像也不太靠谱,等问完就撞上了)。
一个操作,到底是让机器自动执行,还是让它询问,然后让人来确定是否执行,这是个很深奥的哲学问题。以人为中心,还是以机器为中心,这个问题也许将伴随整个自动驾驶的发展历程。
原创作品,未经权利人授权禁止转载。详情见转载须知。 举报文章
我要举报该内容理由
×