基于 RT-Thread智能车控制算法开发-河南科技大学ROCKET
队伍名称: ROCKET
参赛队员:王思杰、王磊
胡彧奇、程钟鑫
带队教师:王新勇、付江涛
§01 引言
在第 16届全国大学生智能汽车竞赛中,我们选择了双车接力组这一比赛项目。经过队员之间的团结协作与共同努力,完成了直立车和三轮车的设计与制作,并在华北赛区的比赛中取得了双车接力组的第 5名。直立车与三轮车的结构大致相似,三轮车只是前端多了一个万向轮。车模均使用 ICM20602陀螺仪,既可以控制直立,又可用来对转向进行辅助。采用以电磁为主,摄像头为辅的方式进行循迹,并将速度环与角度环进行串级处理,并上转向环,以完成车模的整体任务。
在裸机开发的基础上,比赛方又将国产操作系统 RT-Thread引入了此次大赛中。RT-Thread,是一个嵌入式实时多线程操作系统,基本属性之一是支持多任务,而允许多个任务同时运行并不意味着处理器在同一时刻真地执行了多个任务。事实上,一个处理器核心在某一时刻只能运行一个任务,由于每次对一个任务的执行时间很短,任务与任务之间通过任务调度器进行非常快速地切换,给人造成多个任务在同一时刻同时运行的错觉。在 RT-Thread系统中,任务是通过线程实现的,RT-Thread中的线程调度器也就是以上提到的任务调度器。RT-Thread内核是 RT-Thread的核心部分,包括了内核系统中对象的实现,例如多线程及其调度、信号量、互斥量、邮箱、消息队列、定时器等。
在智能车的制作中,我们使用了 RT-Thread,主要应用了其多线程(动态线程)的创建、信号量、临界区保护、邮箱、定时器等。
在后文中,主要针对车模的系统总体设计、硬件设计、软件设计以及RT-Thread的使用进行阐述。
§02 系统总体设计
2.1系统概述
智能车系统的总体工作模式为:5个电感采集赛道电磁信息,MT9V034拍摄赛道图像(灰度图像),经大津算法进行软件二值化,得到图像。将电磁信息与摄像头信息融合,得到准确的赛道信息;通过 1024线正交编码器来检测车速;通过与 ICM20602进行 SPI通信得到车模姿态信息;为防止电机对电磁信号产生干扰,采用 15KHZ的 PWM波对电机进行控制。采用串级+并级的控制方式,对车模循迹完成最终控制。
▲ 图2.1 系统结构图
2.2整车布局
车模的布局本着轻量化,低重心为原则,具有以下特点:
1. 主板与驱动板均围绕电机附近安装,以使得车模的重心靠后且在电机转动轴附近。
2. 采用强度高,质量轻的材料作为摄像头支架。
3. 电磁杆均采用最细的碳素杆,以减轻车体质量。
4. 摄像头位于车体的中部而不是车的最前方,将车的重心后移。
▲ 图2.2 直立车图
▲ 图2.3 三轮车图
§03 硬件设计
3.1硬件设计方案
我们主要从系统的稳定性、可靠性、高效性、实用性、简洁等方面来考虑硬件的整体设计。从最初方案设定到最终方案的敲定,我们经历各种讨论与大的改动才有了如下的硬件方案。
可靠性与稳定性是一个系统能够完成预设功能的最大前提。在原理图与PCB的设计过程中,我们考虑到各个功能模块的电特性以及之间的耦合作用。对易受干扰的模块做了电磁屏蔽作用,而其他部分则做了相应的接地、滤波、模拟与数字电路的隔离等。
3.2传感器的选择
3.2.1摄像头
智能车的摄像头对于图像的分辨率要求并不高,但是对于动态性能要求较高,特别是车模在高速运行时,图像变化较大,因此对摄像头的自动增益有较高的要求,最终选取了总钻风 MT9V034摄像头。
3.2.2陀螺仪
本届大赛对陀螺仪的型号没有限制,我们最终选择的是一款 6轴陀螺仪ICM20602,采用 SPI通信,比传统的 IIC通信快很多,将其竖着固定轮轴的位置处,即可准确采集车模的各种姿态信息。
3.2.3通信模块
在双车接力的比赛任务中,双车通信是必不可少的一个环节。考虑到传输距离的问题,我们没有选用传统的蓝牙模块进行双车通信,蓝牙传输的有效距离一般在 10米左右,不是能很好地胜任此任务,我们最终选择了无线转串口模块,有效传输距离在 100米左右。为了防止通信干扰,我们将两块无线转串口模块均配置在 2.511G频段。
3.3电路设计方案
3.3.1主控电路
车模的控制系统电路主要由 3部分组成:主板、驱动、电磁运放板。使用MM32F3277G9P最小核心板,直插在主板上,主板上预留了摄像头、电磁、无线转串口、四路 PWM、四轴按键等。
▲ 图3.1 主板原理图
3.3.2电机驱动电路
电机驱动电路是由 IR2104芯片组成的 H桥驱动电路,其功率元件由四支 N沟道 MOSFET组成,额定工作电流可达 60A以上。为了避免某些大电流回灌到最小系统而把最小系统烧毁,为此设计了隔离电路加以保护。
▲ 图3.2 电机驱动原理图
3.3.3电磁运放电路
使用三片 OPA235芯片组成 6路运放,配合电位计即可将采集到的电磁信号在一定范围内按照任意倍数放大。
▲ 图3.3 电磁运放原理图
§04 RT-Thread应用
4.1 RT-Thread的移植
1. 首先,在 git上找到逐飞科技的 MM32F3277的开源库,然后,在 RT-Thread的官网下载 RT-Thread的相关资料。
2. 接下来需要做的是把 RT-Thread移植到 MM32F3277的开源库下。首先把 rtthread_libraries文件夹放在 MM32F3277的 libraries文件夹下。然后,在 MDK平台下,打开逐飞科技所提供的 MM32F3277开源库。在该工程下建立几个分组: rtthread_src、 rtthread_inc、 rtthread_lib、rtthread_components。建立好之后,将 RT-Thread的相关原文件添加至以上分组中,并将 rtconfig.h文件加载到 user.h中,之后包含相关头文件的包含路径。
3. RT-Thread相关文件成功添加到开源库后,还需要对开源库做一定的修改,使之适用于 RT-Thread操作系统。首先,在 board.c中添加 rtthread.h的头文件,在使用了操作系统后,串口的使用方式也可以进行相应的优化,我们采用邮箱的方式进行串口的通信:创建 uart_mb邮箱控制块,串口通信方式变为串口中断内发送邮件,fish组件接收邮件。然后,修改 zf_systick.h文件,使用操作系统后,硬件延时不再使用,而是使用线程的延时,将开源库中的硬件延时删除掉,均改为线程延时。
▲ 图4.1 相关资料
▲ 图4.2 将rtt 移植到开源库
4. 最后,在 headfile.h文件中添加 rtthrad.h,以供其他文件调用。
经过以上 4个步骤以后,RT-Thread的移植就基本上完成了。
4.2 RT-Thread的应用
4. 2.1多线程的应用
在 RT-Thread中,线程是一个非常重要的概念。通俗地对线程的理解,就是把一个比较大型的任务,拆分成多个小型的任务,然后通过合理的调度方式,让这几个小型的任务“同时”运行。通过多线程,就可以把原本串行完成的任务改为并行完成,大大提高了工作效率。
线程一共有 5种状态:初始状态、运行状态、就绪状态、挂起状态、结束状态。线程又分为静态线程和动态线程,在智能车的应用中,我们大多使用动态线程。rt_thread_init()是创建一个静态线程;rt_thread_create()是创建一个动态线程。(静态线程需要事先定义好栈空间)其中,rt_thread是一个线程控制块,该线程控制块内包含了线程的各种信息,如:名字、优先级、时间片等,而 rt_thread_t是该线程控制块的指针。
在智能车的比赛任务中,我们创建了以下线程:
1.main线程
在 RT-Thread中,main不再单单只是一个函数,而是一个线程。并且在components.c中可以看到 main线程的创建。并且在 rtconfig.h中可以看到 main线程的优先级是 10。
▲ 图4.1 Main线程
在 main函数中,首先是各种外设的初始化,之后进入 while(1)循环,在循环中,每100ms翻转一下 LED灯的状态:
while(1) {
gpio_toggle(LED1);
gpio_toggle(LED2);
gpio_toggle(LED3);
rt_thread_mdelay(100);
}
- 1
- 2
- 3
- 4
- 5
- 6
这样,车模在运行时,就可以看到车上的 3颗 LED灯在不断地闪烁,一来可以达到一个比较炫酷的状态,二来可以指示程序在正常运行,没有跑飞,一举多得。
其中,rt_thread_mdelay(100)是一个非常重要的函数,它不再是裸机状态下的死等延时,而是以系统滴答定时器为周期的一种操作系统软件延时,当调用该函数时,当前正在执行的线程会转变为挂起状态,跳转到其他线程,极大程度地提高了 CPU的效率。
2.蜂鸣器线程
为了与后面的邮箱一起使用,我们在此建立一个蜂鸣器的线程,优先级为20。
▲ 图4.4 蜂鸣器线程创建
3.菜单线程
在智能车的制作中,菜单显得十分重要,尤其是在今年的赛事制度下,选手只有场上十分钟的时间调试车模,运用菜单可以使调试事半功倍。菜单的功能由按键与 IPS114屏幕共同完成,在此,我们先创建一个屏幕翻页显示的线程。由于菜单显示的实时性并不是太高,为了不过多占用资源,我们将菜单显示的线程优先级设置为 31。
关于线程栈大小的设置:可以先随便给一个大小,如 2048,然后在 PUTY中msh>list_thread查看线程栈大小的使用情况,再进行相应的调整。一般将线程最大使用量设置为 70%。
▲ 图4.5 菜单线程的创建以及菜单入口函数
4.2.2信号量的应用
针对 RT-Thread实时操作系统,线程间同步主要有三种方式:信号量,互斥量,事件集。
信号量可以由任何线程(以及中断)释放,它用于同步的时候就像交通灯,线程只有在获得许可的时候才可以运行,强调的是运行步骤。
互斥量只能由持有它的线程释放,即只有“锁上”它的那个线程才有“钥匙”打开它。它用于互斥的时候就像一把钥匙,只有获得钥匙的线程才可以运行,强调的是许可和权限。
使用信号量可能导致信号优先级反转,而互斥量可通过优先级继承的方法解决优先级反转问题。
经过反复体会信号量与互斥量的用法与差别后,我们总结出以下较容易理解的方式去使用信号量或互斥量:
使用获取信号量函数(rt_sem_take)后,信号量的值会减一,使用释放信号量函数(rt_sem_release)后,信号量加一。当信号量的值为 0时,所有试图通过他的线程都将处于等待状态。
互斥量是没有 value这个值的,即互斥量就相当于一把钥匙,是一个持久物品;而信号量是有 value这个值的,即信号量相当于一个消耗品,用一次少一个。
在智能车的比赛任务中,我们在以下方面用到了信号量:
- 摄像头信号量摄像头的一场图像采集完毕大约 4ms左右,为了使摄像头采集完毕一场完
整的图像后程序再做处理,我们使用信号量来解决这个问题。首先,创建一个信号量: rt_sem_t camera_sem; camera_sem = rt_sem_create(“camera”, 0, RT_IPC_FLAG_FIFO);
第一届全国大学生智能汽车邀请赛技术报告
摄像头每一次 DMA中断都代表一场图像采集完毕,因此,我们在摄像头的
DMA中断里添加释放信号量的语句。这样以后,在每次程序上对一幅图像进行处理前,先要获取一次信号量。经过这样的操作以后,可以有效避免摄像头采集与处理紊乱的现象。
▲ 图4.6 DMA中信号量释放
▲ 图4.7 摄像头处理
- 按键信号量创建 4个按键的信号量,在每次按键按下时,释放一个信号量。
  key1_sem = rt_sem_create("key1", 0, RT_IPC_FLAG_FIFO);
  key2_sem = rt_sem_create("key2", 0, RT_IPC_FLAG_FIFO);
  key3_sem = rt_sem_create("key3", 0, RT_IPC_FLAG_FIFO);
  key4_sem = rt_sem_create("key4", 0, RT_IPC_FLAG_FIFO);
- 1
- 2
- 3
- 4
之后,只需要在使用按键的地方获取信号量,并执行相应的操作即可。
- 编码器积分信号量在智能车比赛的过程中,经常有地方需要编码器积分或者陀螺仪积分的地
方,为此,我们创建一个编码器积分的信号量。
  BM_sem = rt_sem_create("I_bmq", 0, RT_IPC_FLAG_FIFO);
- 1
创建一个专门关于编码器积分的线程,在该线程中首先将获取编码器信号量,这样在不需要编码器积分的时候,该线程就始终处于挂起状态,并不会浪费 CPU的资源,只需要在需要编码器积分的时候,释放编码器积分的信号量,编码器积分的线程在获取到该信号量时,就会进入编码器积分状态。
4.2.3定时器的应用
RT-Thread的定时器提供两类定时器机制:第一类是单次触发定时器,这类定时器在启动后只会触发一次定时器事件,然后定时器自动停止。第二类是周期触发定时器,这类定时器会周期性的触发定时器事件,直到用户手动的停止,否则将永远继续执行下去。
在智能车的制作中,定时器是不可或缺的一个功能,智能车的许多任务大都需要周期定时执行,所以大部分功能函数都在中断中。我们选择了两个定时器,一个周期为 5ms的定时器,一个周期为 1s的定时器。5ms的定时器用于执行智能车的主要任务,1s的定时器用于为程序计时,在相应的时间执行相应的操作。
▲ 图4.8 定时器的创建
4.2.4邮箱的应用
RT-Thread操作系统的邮箱用于线程间通信,特点是开销比较低,效率较高。邮箱中的每一封邮件只能容纳固定的 4字节内容(针对 32位处理器系统,指针大小即为 4个字节,所以一封邮件恰好能够容纳一个指针)
- 邮箱在串口通信中的应用在 RT-Thread中,串口调试多使用 PUTY组件,为了提高通信效率,采用邮箱的方式进行串口通信。
首先,创建邮箱的控制块:rt_mailbox_t uart_mb;
在串口 1的中断中,由于我们使用到了操作系统的相关函数,所以需要加入临界区保护,并在接收中断中发送邮件,finsh组件接收邮件,完成串口通信。其中,fish组件的初始化在 shell.c中,有一个初始化的宏定义: INIT_APP_EXPORT(finsh_system_init);
所以不需要用户去调用,上电后自动初始化 finsh组件。
▲ 图4.9 串口中断函数
- 邮箱在双车通信中的应用
在双车接力组的比赛任务中,双车通信是一个及其重要的环节。我们采用无线转串口模块进行双车通信,其实本质与串口通信一致,只需稍作修改即可。类似地,我们创建邮箱控制块 rt_mailbox_tcommunicate_mb;无线转串口使用的是串口 4,所以需要在串口 4的中断函数中加入临界保护,并添加接收邮件的函数,即可完成双车通信。
§05 总结
自报名参加全国大学生智能汽车竞赛以来,我们小组成员从查找资料、设计结构、组装车模、编写程序、学习 RT-Thread操作系统、改善程序一步一步的进行,最后完成了最初设定的目标,定下了现在这个设计方案。
历时 8个月的时间,我们最终完成了两辆车模的设计与制作,且车模的技术指标均符合比赛方的各项要求,并获得了华北赛区一等奖的成绩。
从 2021年 5月份开始,我们开始学习了 RT-Thread操作系统,并在学习中不断完善了对 RT-Thread的各方面理解,领悟了操作系统开发与裸机开发的重大区别,最终完成了 RT-Thread的学习,并将其应用在了此次全国大学生智能汽车竞赛中。
我们主要将 RT-Thread中的多线程、动态内存、信号量、互斥量、临界区保护、邮箱、定时器等知识应用在了智能车的制作中,其中,我们深入研究了信号量与互斥量的应用,得知信号量是一个多值量,而互斥量是一个二值量;且信号量会使优先级反转,而互斥量可通过优先级继承的方法解决优先级反转问题。
在备战过程中,场地和经费方面都得到了学校和学院的大力支持,在此特别感谢一直支持和关注智能车比赛的学校和学院领导以及各位指导老师、指导学长,同时也感谢比赛组委会能组织这样一项有意义的比赛。
参考文献
[1]卓晴,黄开胜,邵贝贝.学做智能车 [M].北京:北京航空航天大学出版社.2007.
[2]王淑娟,蔡惟铮,齐明.模拟电子技术基础 [M].北京:高等教育出版社.2009
[3]张文春.汽车理论 [M].北京.机械工业出版社.2005.
[4]李宁,刘启新电机自动控制系统北京-机械工业出版社,2003
[5]邵贝贝.嵌入式实时操作系统[LC/OS-Ⅱ(第 2版)[M].北京.清华大学出版社.2004
[6]童诗白,华成英.模拟电子技术基础[M].北京.高等教育出版社.2000
[7]沈长生.常用电子元器件使用一读通[M].北京.人民邮电出版社.2004
[8]殷剑宏,吴开亚.图论及其算法 [M].中国科学技术大学出版社,2003.
[9]蔡述庭.“飞思卡尔”杯智能汽车竞赛设计与实践 [M].北京:北京航空航天大学出版社. 2012.
[10]竞赛秘书处,电磁组竞赛车模路径检测设计参考方案(版本 1.0).2010.1.
[11]张昊飏,马旭,卓晴.基于电磁场检测的寻线智能车设计.北京:清华大学,2009.11.09.
[12]李仕伯,马旭,卓晴.基于磁场检测的寻线小车传感器布局研究.2009.12.10.
● 相关图表链接:
- 图2.1 系统结构图
- 图2.2 直立车图
- 图2.3 三轮车图
- 图3.1 主板原理图
- 图3.2 电机驱动原理图
- 图3.3 电磁运放原理图
- 图4.1 相关资料
- 图4.2 将rtt 移植到开源库
- 图4.1 Main线程
- 图4.4 蜂鸣器线程创建
- 图4.5 菜单线程的创建以及菜单入口函数
- 图4.6 DMA中信号量释放
- 图4.7 摄像头处理
- 图4.8 定时器的创建
- 图4.9 串口中断函数
文章来源: zhuoqing.blog.csdn.net,作者:卓晴,版权归原作者所有,如需转载,请联系作者。
原文链接:zhuoqing.blog.csdn.net/article/details/119697454
- 点赞
- 收藏
- 关注作者
评论(0)