智能车竞赛技术报告 | 智能车视觉 - 西安邮电大学 - AI小布丁

举报
tsinghuazhuoqing 发表于 2021/12/26 02:01:57 2021/12/26
【摘要】 学 校:西安邮电大学    队伍名称:AI小布丁      参赛队员:张展鹏 徐军其 杜博林带队教师:亢红波 蔡秀梅                 第一章 引...

学 校:西安邮电大学    
队伍名称:AI小布丁      
参赛队员:张展鹏 徐军其 杜博林
带队教师:亢红波 蔡秀梅    
          

 

第一章


  国大学生智能车竞赛是从 2006 开始,由教育部高等教育司委托高等学校 自动化类教学指导委员会举办的旨在加强学生实践、创新能力和培养团队精神 的一项创意性科技竞赛,至今已经成功举办了十四届。在继承和总结前十四届 比赛实践的基础上,竞赛组委会努力拓展新的竞赛内涵,设计新的竞赛内容, 创造新的比赛模式,使得围绕该比赛所产生的竞赛生态环境得到进一步的发展。

  为了实现竞赛的"立足培养、重在参与、鼓励探索、追求卓越"的指导思想, 竞赛内容设置需要能够面向大学本科阶段的学生和教学内容,同时又能够兼顾 当今时代科技发展的新趋势。比赛形式包括有竞速比赛与创意比赛两大类。竞 速比赛中包含不同的组别,难度适合本科不同年级本科生学生参赛。在竞速赛 基础上,适当增加挑战性,形成创意比赛的内容,适合部分有条件、能力强的 本科生和研究生参加创意比赛。

  本文采用第十六届全国大学生智能车竞赛的汽车模型作为研 究平台,以 32 位单片机 i.MX RT1064 作为主控制单元,。道路信息检测模块普 遍采用简单、速度快的数字类摄像头。本模块采 MT9V034 芯片,该芯片具有全 局快门,高动态成像,红外透视等优点。MT9V034 芯片最高分辨率为 752H x 480V,以每秒 60 帧(fps)的形式输出。本届车模后置双电机,因此需要对两个电 机分别进行速度、方向检测,以及 PID 控制,车模转向采用 S3010 官方指定伺 服舵机。

  本篇技术报告将从智能车对整体方案、机械结构、硬件电路、图像处理、图像识别、 控制算法等方面详细介绍整个准备过程。

 

第二章 统设计方案


2.1 系统结构框图

  光电智能车系统的总体工作模式为:CMOS 图像传感器拍摄赛道,输出 8 位灰度信号及行场像素中断,主控制器检测各中断信号进行图像采集,同时使用伺服器和电机对于车模姿态和行进进行控制,并通过速度传感器等不同传感器获取车模姿态,进行闭环控制。

▲ 图2.1 系统框图

▲ 图2.1 系统框图

  系统框图如上图1所示,该系统总共包括6个子系统:电源模块、主控制器模块、赛道采集模块、伺服器(舵机)控制模块、电机控制模块、调试模块。

2.2 主要设备选型

2.2.1 主控制器模块:

  使用NXP公司的MIMXRT1064DVL6A单片机(以下简称RT1064)作为智能车系统的主控制器。该单片机采用NXP先进的ARM高性能实时处理Cortex-M7内核,运行速度高达600MHz。可实现较高的CPU性能和出色的实时响应。512KB SRAM可以灵活配置为TCM或通用片上RAM,而另一个512KB SRAM是通用片上RAM。设有ADC、ACMP和TSC等模拟接口,充分满足智能车设计需要。

2.2.2 赛道采集模块

  使用逐飞科技提供的MT9V032(总钻风)摄像头作为光电传感器进行赛道图像采集,该摄像头通过一块51单片机与主控制器进行通信,进而配置摄像头的相关信息,通过使用场中断触发主控制器开始图像采集、像素中断控制采集速度。

2.2.3伺服器(舵机)控制模块

  使用Futaba S3010舵机进行车模转向控制。

2.2.4 电机控制模块

  使用RS-380电机进行车模的速度控制。

2.2.5 调试模块

  调试模块由OLED屏幕、组合按键、无线透传串口组成。

  OLED屏幕采用逐飞科技的1.8寸TFT彩屏,满足图像参数显示的需要;组合按键分为加、减、保存共3个按键,满足对于参数的微调需要;另外同时采用八路拨码开关,用于控制显示内容;无线透传串口使用逐飞科技的无线透传模块,可以在智能车运行中实时传输控制参数和赛道信息;

 

第三章 统硬件设计


3.1 总体硬件设计及电路图和说明

▲ 图 3.1.1 总体硬件电路图

▲ 图 3.1.1 总体硬件电路图

▲ 图3.1.2 电源管理模块总体框图

▲ 图3.1.2 电源管理模块总体框图

3.2 各模块介绍及硬件电路图

3.2.1 RT1064核心板最小系统

  • 晶振电路

  • 复位电路

  • SWD下载电路

  • BOOT MODE按键电路

  从串行设备启动:
  按住MODE按键,按复位再松开复位,最后松开MODE,即可进入串行设备启动模式。若单片机锁住,用串行下载模式可以进行芯片解锁等操作。

3.2.2 电源管理模块

  整辆小车都是用2000mAh的镍铬电池提供,但是各种元器件所需的电压不同,这就需要我们用不同的电源芯片来生成不同的电压。

3.2.3 拨码开关

  为了调参方便,我们用三路按键开关搭配八路拨码开关。

3.2.4 蜂鸣器电路

  我们用三级管驱动蜂鸣器来实现判元素可视化。

3.2.5 编码器电路

  测速模块我们采用龙邱科技的MINI512线编码器。此编码器10000rpm,与高速电机配套不丢步。

3.2.6 无线转串口电路

  本串口采用高性能cortex-M3单片机(72MHz主频)来进行数据转发,转发速度更快。

3.2.7摄像头电路

  总钻风摄像头是一款基于 MT9V032 芯片设计的传感器模块,适合在高速情况下采集图像的全局快门摄像头。具有高动态性能、自动曝光、曝光时间随时可调等优点。集合内部 AD 摄像头采集模块与视频信号处理模块,极大地简洁使用该摄像头硬件电路的设计。

3.2.8 TFT屏电路

  为使软件上参数调节方便,且兼顾硬件上的简洁与美观,我们特意将这部分设计在主板上,我们使用TFT显示模块。TFT体积上小,分辨率高,功耗低。

  调试中,这个模块对参数的调试带来了极大的方便,可以减少烧录程序的次数而提高调试效率。

3.2.9 ADC电路

  此电路为电磁采集模块与单片机的接口电路。采用1MM 8P FPC接线端子,大大地缩小了电路板面积。

3.2.10 电磁采集电路

  我们采用2片OPA4377运算放大器搭建6路电磁采集模块。OPA4377运放是宽带CMOS放大器,它是轨到轨运放,拥有5.5MHz增益带宽积,压摆率为2V/us,低噪声。

3.2.11 驱动电路

  电机驱动电路的作用指通过控制电机的旋转角度和运转速度,以此来实现对占空比的控制,来达到对电机变速控制的方式。

  我们此次使用的是 BTN7971驱动电路。BTN7971B是一个集成的大电流半桥电机驱动应用。它包含一个p沟道高边MOSFET和一个n沟道低边MOSFET,在一个封装中集成了驱动电路。由于p沟道高边开关,因此无需电荷泵,从而最大限度地减少了EMI。该BTN7971B提供了一个成本优化的解决方案,保护大电流PWM电机驱动器与非常低的板空间消耗。并同时采用74hc244隔离。

3.2.12 整车布局

  舵机位置在前,立式安装,既保证响应速度又大多数符合阿克曼转角原理;电池用扎带固定在后方,平衡重心;CMOS摄像头通过碳杆、金属支架固定在主板后方,有效的采集赛道信息;两个水平电感,两个八字电感,两个中间电感,充分利用电磁前瞻,更好地进行电磁赛道识别。

 

第四章 统循迹软件设计


4.1软件控制程序的整体思路

  软件编写的目的,是控制车模在既定规则前提下,以最快的速度,跑完整个赛道。不论上哪种方案,软件的总体框架总是相似的,我们追求的就是稳定至上,兼顾速度。软件上大类分为图像采集、图像处理识别黑线,电感采集, 电磁控制,速度控制以及速度反馈。

4.2灰度图像处理思路

  通过 MT9V032 摄像头传输回来的图像是 188*120 大小的灰度图像,而处理图像的第一步就是如何处理灰度图像,主要有以下两种思路:

4.2.1二值化图像

  通过给定一个阈值,将每个像素点与之进行比较,从而确定出来这个像素点是黑或白,之后的图像处理就使用这个二值化后的数组进行处理。

  这种方法在图像处理的过程中仅仅有黑白两种元素,可以使图像处理更加简 单。但由于摄像头高度较低,在实际的运行中当小车运行到不同的区域中的由于光线不均匀使得设定的单一阈值不同。

4.2.2灰度图像处理

  在处理灰度图像中,我们尝试了使用苏泊尔算子将图像进行卷积运算,运算之后的图像在黑白跳变处会呈现一个很明显的高值。

  这种方法虽然在处理的过程中比较复杂,但是在对于虚线会车区、颠簸路段等元素的识别上更加容易。

▲ 图 4.2.2.1 原灰度图像

▲ 图 4.2.2.1 原灰度图像

▲ 图 4.2.2.2 苏泊尔算子卷积图像

▲ 图 4.2.2.2 苏泊尔算子卷积图像

4.2.3 动态阈值二值化处理

  通过之前的尝试,我们在上位机仿真的过程中发现,使用最大协方差阈值法能够有效的计算出一幅图像的最佳阈值,实现对于图像前景与背景的分离。这样使用动态阈值二值化之后的图像能够像普通二值化图像一样处理,但在颠簸等黑白跳变不大的元素让需要借助灰度图像进行处理。

4.3 基本循迹扫线思路

4.3.1 中心扫线

  中心扫线是指每行图像的起始扫线都是从上一行图像的中线位置开始的,从白点向左向右扫到黑点及寻找到所需要的边界线,进而拟合出赛道中心线。

  • 优点:对于环境光线依赖比较小,如由于光线不均匀造成的反光仅仅会影响反光存在的几行,而不会对整幅图像之后的边界线提取造成干扰;

  • 缺点:比较消耗时序,需要遍历图像中大多数像素点才能够找到赛道的边界线,同时由于环岛等特殊元素的存在,使我们寻找的边界线与环岛的特征点有一定的差距,不利于元素的识别。

4.3.2 边缘扫线

  边缘扫线是指每行图像的起始扫线根据左右边界线分别根据上一行左右边界线开始的,根据上一行的边界线在这行中同样位置的像素点黑白确定向左向右扫线,并找到黑白的切换点作为实际的赛道边界线。

  • 优点:能够较少的利用时序,同时克服赛道中间白色区域中产生的噪点, 同时可以较好的寻找环岛等元素的特征点;

  • 缺点:若外界光线不均匀造成部分行的扫线错误,将一直影响之后整幅图像的扫线,同时不利于提取(斜入)十字等元素的特征。

4.3.3 根据不同的赛道元素类型,指定每行的扫线起始点

  根据不同的赛道元素类型,指定每行的扫线起始点”是指在每行扫线的过程中,同时对元素类型进行区分,根据先前确定下来的赛道元素类型明确扫线的方向及起始点。

  如在正常扫线可以将下一行的扫线起点指定为本行的左右边线,在十字的判断中可以将扫线的起点通过十字前拐点下的直线斜率确定,方便寻找十字远

  处的跳变点,而环岛扫线可以通过环岛阶段确定需要扫到的特征点进而确定扫线方向与扫线起始。
  由此看来,这种方式的扫线可以最大限度的简化程序执行流程,同时我们可以在扫线的应用“搜索”中“剪枝”的思想。
  如在扫线的过程中判断是否已经扫到了赛道外,如果已经扫出赛道即停止扫线,体现了“可行性剪枝思想”;在对十字和环岛的判断中,可以根据之前图像找到的特征点具体位置寻找这场图像的特征点,体现了“记忆化搜索思想”。

4.4 赛道中线的拟合

  因为是双边的黑线赛道,所以我们在正确提取黑线信息的基础上,外加赛道中心拟合函数模块,其具体思想有以下几种。

4.4.1 已知左右线求边线

  在已知左右线的基础上的处理最为简单,仅仅取每行左右线的中心位置即可得到近似的赛道中心线。

4.4.2 一边丢线的中线拟合

  如果一侧的边线丢失,我们在最初的基础上使用最近一行能够找到的赛道宽度作为之后丢线区域的赛道宽度,之后的丢线区域就将已知边线平移该宽度的一半作为近似的赛道中心线。

4.4.3 丢线不严重区域的中线拟合

  如果在丢线过程中全部按照 3.4.2 节中的思路进行拟合中心线,会导致在一些连续变向的弯道中有超调的问题,导致路径不太流畅。我们首先将正常直道的赛道宽度保存在一个数组中,之后再丢线不严重的区域寻找丢线边线的恢复行,计算恢复行的宽度相较正常直道赛道宽度的比值,再丢线区域按照这个比值,平移已知边线,拟合出需要的赛道中心线。

  下图为上位机上的处理效果图。

▲ 图4.4.3.1 原图像

▲ 图4.4.3.1 原图像

▲ 图4.4.3.2 左右边线和赛道中心线

▲ 图4.4.3.2 左右边线和赛道中心线

4.5 十字识别与赛道中心线修补

  十字元素是智能车光电组别近几年已知存在的赛道元素,我们创新了十字识别的思路,针对 20cm 高度摄像头图像进行一些调整。我们将十字分为斜入十字、直入十字、中入十字三种情况。

4.5.1 斜入十字

▲ 图 4.5.1 斜入十字图像

▲ 图 4.5.1 斜入十字图像

  以上图举例具体说明斜入十字的识别思想:

  1) 在右边界线过程中计算每两行边界线的差值,寻找边界线向外的跳变点并记录;
  2) 从这个跳变点开始向上的扫线起始点就改为通过这个点下面一段线的斜率延伸上去;
  3) 向上几行判断这个跳变点上下直线的斜率夹角,满足直角的范围;
  4) 之后的扫线继续按照之前的斜率延伸上去,直到寻找到黑色像素点,即跳出了十字,便可确定下来斜入十字远端的行数;
  5) 在补线的过程中确定斜入十字起始点和终点的位置,将赛道中心线改为这两个点相连接即可完成斜入十字的补线操作。

4.5.2 直入十字

▲ 图 4.5.2 直入十字图像

▲ 图 4.5.2 直入十字图像

  以上图举例具体说明直入十字的识别思想:
  1) 在左右边界线依次寻找边界线向外的跳变点,并且跳变点的上一行的边线在接近图像外边缘的位置,即边界线呈现近似垂直于镜头上前方向丢线, 记录下来左右边线出现这种情况的行;
  2) 在之后的扫线过程中,先确定出现边线在左右边界线附近同时丢线,再确定赛道宽度恢复正常直道情况的行;
  3) 最后通过寻找边界线的恢复行产生直入十字的结束行,将中心线与起始行的中心线相连,即得出直入十字的赛道中心线。

4.5.3 中入十字

▲ 图 4.5.3 中入十字图像

▲ 图 4.5.3 中入十字图像

  以上图举例具体说明中入十字的识别思想:
  1) 首先的识别前提条件在于前面存在直入十字或者斜入十字的情况,图像的显著特征在于图像下方有很大的左右边界线同时丢线的区域,当丢线达到一定的条件的时候可以确定这是中入十字;
  2) 之后寻找边界线向内收缩并且赛道宽度恢复到正常直道范围的行数,确定出十字的结束行;
  3) 由于 10cm 高度摄像头前瞻较短,不利与分析出十字之后赛道中心线的前进方向,我们直接将出中入十字行的中心线竖直地拉下来作为赛道的中心
线。

4.6 赛道类型的分离

4.6.1 直道计算算法

  赛道分离主要是将直道和弯道分离开,其关键在于将直道识别出来。

  我们逐行处理赛道的中心线,连接每行赛道的中心线和第一行赛道的中心线,并计算这行以下图像拟合出来的赛道中心线与这行直线举例的差值,如果差别很大,就跳出这个循环,而这行就作为图像的直道有效行,可以认为第 1 行到这行是直道。

4.6.2 直道弯道分离思路

  计算第 1 行中心线到之前计算出来的直道有效行的斜率,与直道有效行数一起参与直道弯道分离的协同计算。
  其中,直道有效行非常高且直线较直的作为“长直道”,直道有效行较高且直线较直的作为“短直道”,直道有效行不高(仍存在一段直道)且斜率较小的作为“直入弯 ”,其他基本作为“弯道”。

  按照上述完成对于赛道元素的分离,根据元素的不同采用不同的控制策略。

4.7伺服器(舵机)转向打角控制策略

4.7.1 舵机整体控制思路

  舵机通过一个由 FTM 灵活定时器模块输出的 PWM 波控制,通过各种参数的对比之后,我们确定使用 50Hz 的 PWM 波能够使舵机响应最快同时使舵机工作稳定。

  在每个控制周期中,每当图像处理完成,我们根据不同的赛道类型和速度传感器返回的实际转速综合分析得出最佳的舵机打角行,计算这一行的中线偏离差值,带入到舵机位置式 PD 的计算中,在舵机中值的基础上经过舵机上下限的限幅计算得到实际的舵机值。

4.7.2 舵机PD计算式

  舵机控制采用位置是 PID,经过尝试我们认为 I 项(积分项)不适用与舵机的控制中,便将 PID 简化为舵机的 PD 控制,控制公式如下:

  PID_out = dir_P * dir_err + dir_D * (dir_err - dir_l_err);

4.7.3 动态打角行的选取

  由于车模不是处于匀速的运动中,不能够通过固定的打角行来计算偏差。我们采用根据编码器的速度返回值计算出来当前打角行的高度,其策略是速度越快打角行越高,目的是使不同的速度下小车的路径相近,达到小车整体的闭环控制。

4.7.4 不同元素的舵机PD 选取

  当车模行进到不同赛道元素的时候,如果同样的舵机 PD 会造成在直道上抖动和弯道上的转向不连续的问题,由此我们根据不同的赛道类型选取了不同的舵机控制 PD,使得能够在直道跑的直,在弯道流畅,同时在 S 型弯道能够基本沿着中线行进。

  其中不同元素的 PD 选取有以下的规律:直道 PD 小,弯道 PD 大,S 型弯道 P 小 D 略大。

4.7.5 电磁舵机PD控制表达式

  电磁舵机控制我们依旧采用位置式 PID,经过尝试我们认为 I 项(积分项)不适用与舵机的控制中,便将 PID 简化为舵机的 PD 控制,此外我们加入了陀螺仪控制,以此解决了 C 车电磁短前瞻下车模控制抖动问题。控制公式如下:
  PID_out = dir_P * dir_err + dir_D * (dir_err - dir_l_err);

4.7.6 电磁舵机PD模糊控制

  电磁舵机控制由于前瞻限制,为达到更好的转向效果,我们编写了模糊算法,采取PD模糊控制。综合考虑之后,我们选取了偏差和偏差的偏差进行二阶模糊,最后调出的P项模糊表参考下表:

FuzzyStruct C_Induct_P_Fuzzy =  
{ 
 	Fuzzy_Rank7, 
 	0, 
 	0, 
 	{30,60,80,90,110,130,170}, //e 
 	{0,2,4,6,8,10,14}, //ec 
 	{0,0.05,0.1,0.2,0.3,0.45,0.55}, //P 
 	{ 
//error 0, 1, 2, 3, 4, 5, 6 // d_error 
 	 	 { 1, 2, 3, 4, 5, 6, 6 }, // 0    
 	 	 { 1, 2, 3, 4, 5, 6, 6 }, // 1      
 	 	 { 0, 1, 2, 3, 4, 5, 6 }, // 2    
 	 	 { 0, 1, 2, 3, 4, 5, 6 }, // 3    
 	 	 { 0, 1, 2, 3, 4, 5, 6 }, // 4   
 	 	 { 0, 0, 1, 2, 3, 4, 5 }, // 5     
 	 	 { 0, 0, 0, 1, 1, 2, 3 },    //    6    	 
	} 	
}; 
 

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

4.8 电机转向差速控制策略

4.8.1 不同元素的速度控制策略

  通过对智能车的调试我们发现,在直道使用较高的转速,在弯道使用稍慢一些的转速能够很流畅的跑完整个赛道,其中在直道(长直道、短直道)的加速能够非常关键的决定车模的整体速度,而弯道的速度能够提升车模的稳定 性。
  针对直道入弯的过程我们采取了特定的减速策略,即先根据车模当前速度给出减速场数,当减速场数较高的时候设定速度较低,当减速场数较少的时候设定速度较高,并随着减速场数的减少设定速度逐渐接近弯道速度使车模能够流畅的进入弯道,避免出现“猛加猛减”的情况。

4.8.2 C1 型车模的差速策略

  C1 型车模有两个电机驱动,这两个电机可以通过主动差速来辅助车模的转向,因此我们采用了阿克曼模型。

  推导得出:V_left=V*(1-Btanα/2L);V_right=V(1+B*tanα/2L);

4.8.3 C1 型车模的电机 PI 控制

  C1 型车模电机使用增量式 PID 控制,其中 I 项能够加快电机响应,P 项能够减少稳态误差,控制公式如下:
  MotorL_Out += MotorL_Ki * MotorL_Error[2]; MotorL_Out += MotorL_Kp * (MotorL_Error[2] - MotorL_Error[1]);
  其中 MotorL_Out 作为加在电机输出占空比上的增量,针对不同元素,我们给出不同的 PI,规律大概是“直道 PI 大,弯道 PI 小”,能够使车模长直道加速更快,弯道更顺畅。

 

第五章 别部分代码软件设计


  本次智能车竞赛中,采用了NXP系列视觉模块–OpenArt Mini并搭载神经网络模型进行识别分类。

5.1控制思想:

  在比赛中,识别与赛道寻迹任务分不开,因此,主要以总钻风摄像头寻迹判断元素,判断遇到三叉路口后,主控MCU向Openart以串口形式发送相应数据,激活openart进行寻找矩形并用相应分类模型对矩形内图像内容分类。 判断到Tag码时,主控MCU向openart发送数据激活其相应功能,并将openart识别判断所得结果发送回主控MCU,并做出相应动作。

5.2模型核心思想:

  在图像分类方面,其本质就是对获取的图像进行二分类,我们采用了基于TensorFlow-Keras搭建的卷积神经网络模型,采用了类似传统的VGG模型分类模式。在合适曝光率下,其准确率可达95.49%
  分类模型如下:

▲ 图5.2 分类模型

▲ 图5.2 分类模型

 

第六章


  制作智能车期间,我们遇到过很多问题,从最初的传感器选型与方案确定,到后来的软硬件联合调试。在解决一个个问题之后,我们发现,我们技术上在不断成长,思想上在不断成熟。而在这过程中,离不开我们自己的努力与不放弃,更离不开学校, 老师和同学的支持。在每次我们发现问题解决后,都能够及时总结自己的问题,这使得我们进步更明显,并且能够在赛道的跑的越来越快。在次比赛我们组成员都进步了很多

 

考文献


  1】孙同景,陈桂友 Freescale 9S12 十六位单片机原理及嵌入式开发技术, 北京-机械工业出版社,2008

  【2】邵贝贝. 单片机嵌入式应用的在线开发方法. 北京-清华大学出版社,2004 年10月第1版

  【3】卓晴,黄开胜,邵贝贝 学做智能车 北京-北京航空航天大学出版社,2007

  【4】王威 HCS12 微控制器原理及应用 北京-北京航空航天大学出版社,2007

  【5】李宁,刘启新 电机自动控制系统 北京-机械工业出版社,2003

  【6】潘松,黄继业 现代数字电路基础教程 北京-科学出版社 ,2008

  【7】魏彪,盛新志 激光原理及应用 重庆-重庆大学出版社, 2007

  【8】赵先奎 汽车前轮定位 黑龙江 黑龙江出入境检验检疫局,2008

  【9】姚领田 精通 MFC 程序设计 人民邮电出版社,2006

■ 附录:

  重要部分源代码:

/*
*函数:初始化函数
*作者:LXJSWD
*日期:2021/6/12
*版本:第一版
*备注:C3,C27
*/
void init(void)
{
		systick_delay_ms(300);												//延时
	/*================初始化TFT屏幕=====================*/
	  lcd_init();     															
		lcd_clear(GREEN);
    lcd_showstr(0,0,"Initializing...");  				  //如果屏幕没有任何显示,请检查屏幕接线			  
	/*================初始化蜂鸣器引脚==================*/
    gpio_init(BEEP_PIN,GPO,0,GPIO_PIN_CONFIG);  	//

	/*================拨码开关和按键初始化==============*/
    gpio_init(SW1,GPI,0,GPIO_PIN_CONFIG);   			
    gpio_init(SW2,GPI,0,GPIO_PIN_CONFIG);
		gpio_init(SW3,GPI,0,GPIO_PIN_CONFIG);
		gpio_init(SW4,GPI,0,GPIO_PIN_CONFIG);
		gpio_init(SW5,GPI,0,GPIO_PIN_CONFIG);
		gpio_init(SW6,GPI,0,GPIO_PIN_CONFIG);
		gpio_init(SW7,GPI,0,GPIO_PIN_CONFIG);
		gpio_init(SW8,GPI,0,GPIO_PIN_CONFIG);

    gpio_init(K1,GPI,0,GPIO_PIN_CONFIG);					//按键
		gpio_init(K2,GPI,0,GPIO_PIN_CONFIG);
		gpio_init(K3,GPI,0,GPIO_PIN_CONFIG);
	/*================电磁==============================*/
		adc_init(ADC_1,ADC1_CH5_B16,ADC_8BIT);//
		adc_init(ADC_1,ADC1_CH6_B17,ADC_8BIT);
		adc_init(ADC_1,ADC1_CH7_B18,ADC_8BIT);;//
		adc_init(ADC_1,ADC1_CH8_B19,ADC_8BIT);
		adc_init(ADC_1,ADC1_CH10_B21,ADC_8BIT);
		adc_init(ADC_1,ADC1_CH12_B23,ADC_8BIT);
	/*=================舵机=============================*/
		pwm_init(S_MOTOR_PIN,50,807);  //初始化转向舵机
//		pwm_init(PWM4_MODULE3_CHA_C31,50,807);  //初始化云台舵机
	/*=================编码器===========================*/
		qtimer_quad_init(QTIMER_1,ENCODER1_A,ENCODER1_B);  //编码器zuo
    
qtimer_quad_init(QTIMER_1,ENCODER2_A,ENCODER2_B);  //you
	/*=================电机============================*/
		pwm_init(MOTOR1_A,15000,0);
    pwm_init(MOTOR1_B,15000,0);
    pwm_init(MOTOR2_A,15000,0);
    pwm_init(MOTOR2_B,15000,0);
	/*=================摄像头===========================*/
    mt9v03x_csi_init();	//初始化摄像头 使用CSI接口
			  //如果屏幕一直显示初始化信息,请检查摄像头接线
			  //如果使用主板,一直卡在while(!uart_receive_flag),请检查是否电池连接OK?
			  //如果图像只采集一次,请检查场信号(VSY)是否连接OK?
  /*================无线透传模块初始化================*/
//		seekfree_wireless_init();  
	/*=================串口通信初始化===================*/
		uart_init (USART_1, WIRELESS_UART_BAUD,WIRELESS_UART_TX,WIRELESS_UART_RX);	//初始换串口    
		NVIC_SetPriority(LPUART1_IRQn,0);         //设置串口中断优先级 范围0-15 越小优先级越高
    uart_rx_irq(USART_1,1);
		//配置串口接收的缓冲区及缓冲区长度
		extern uint8 example_rx_buffer;
    example_receivexfer.dataSize = 1;
    example_receivexfer.data = &example_rx_buffer;
    uart_set_handle(USART_1, &example_g_lpuartHandle, example_uart_callback, NULL, 0, example_receivexfer.data, 1);
    lcd_showstr(0,0,"     OK...     ");
	/*================中断==============================*/
		pit_init();                     //初始化pit外设
		pit_interrupt_ms(PIT_CH0,1); 		 //初始化pit通道0 周期
		NVIC_SetPriority(PIT_IRQn,15);  //设置中断优先级 范围0-15 越小优先级越高 
    systick_delay_ms(500);
}

/*
*函数:主动差速增量式PID
*作者:LXJSWD
*时间:2021/5/7
*参数:target,目标速度,dir0为左轮,1为右轮
*功能:单电机控制
*
*/

void INC_PID(void)
{
	/*=======*/
			l_err_l = err_l;
			err_l = target_L - car_speed_L;
			Dspeed_L += INC_KP * (err_l - l_err_l) + INC_KI * 			
if(Dspeed_L >5000)
				Dspeed_L  = 5000;
			if(Dspeed_L < -8000)
				Dspeed_L  = -8000;
	/*======*/
			l_err_r = err_r;
			err_r = target_R - car_speed_R;
			Dspeed_R += INC_KP * (err_r - l_err_r) + INC_KI * err_r;
			if(Dspeed_R >5000)
				Dspeed_R  = 5000;
			if(Dspeed_R < -8000)
				Dspeed_R  = -8000;
}
/*=====================================================================================================*/

/*
*函数:速度采集
*作者:LXJSWD
*日期:2021/6/16
*备注:
*/
/*****************************/

void GetSpeed (void) 
{
    static int index = 0;
		L_car_speed = car_speed;
    L_RealSpeed_R = RealSpeed_R;
    L_RealSpeed_L = RealSpeed_L;
    RealSpeed_R = qtimer_quad_get(QTIMER_1,QTIMER1_TIMER0_C0);
		qtimer_quad_clear(QTIMER_1,QTIMER1_TIMER0_C0 );
		RealSpeed_L=qtimer_quad_get(QTIMER_1,QTIMER1_TIMER2_C2);
    qtimer_quad_clear(QTIMER_1,QTIMER1_TIMER2_C2);
		
    RealSpeed_R = (int) (0.7 * RealSpeed_R + 0.3 * L_RealSpeed_R);
RealSpeed_L = (int) (0.7 * RealSpeed_L + 0.3 * L_RealSpeed_L);
		
    Encoder_Speed_Filter_L[index++] = RealSpeed_L;
		Encoder_Speed_Filter_R[index] = RealSpeed_R;
    index %= 5;

    car_encoder_speed_L = 0;
    car_encoder_speed_R = 0;

    for (int i = 0; i < 5; i++)
    {
				//左
        car_encoder_speed_L += Encoder_Speed_Filter_L[i];
        if (Encoder_Speed_L_Max < Encoder_Speed_Filter_L[i])
            Encoder_Speed_L_Max = Encoder_Speed_Filter_L[i];

        if (Encoder_Speed_L_Min > Encoder_Speed_Filter_L[i])
            Encoder_Speed_L_Min = Encoder_Speed_Filter_L[i];
				//右
				car_encoder_speed_R += Encoder_Speed_Filter_R[i];
        if (Encoder_Speed_R_Max < Encoder_Speed_Filter_R[i])
            Encoder_Speed_R_Max = Encoder_Speed_Filter_R[i];

        if (Encoder_Speed_R_Min > Encoder_Speed_Filter_R[i])
            Encoder_Speed_R_Min = Encoder_Speed_Filter_R[i];
				
    }

    car_encoder_speed_L = (car_encoder_speed_L - Encoder_Speed_L_Max - Encoder_Speed_L_Min) / 3.0;
    car_encoder_speed_R = (car_encoder_speed_R - Encoder_Speed_R_Max - Encoder_Speed_R_Min) / 3.0;

		car_speed_L = car_encoder_speed_L * 0.035 * 100;
		car_speed_R = car_encoder_speed_R * 0.035 * 100;
		
		car_speed_L = 0.8 * car_speed_L + 0.2 * L_car_speed_L;
		car_speed_R = 0.8 * car_speed_R + 0.2 * L_car_speed_R;
		car_speed = (car_speed_L+car_speed_R)/2;

}

/*
*作者:LXJSWD
*时间:2021/6/5
*功能:位置式PID,
*待优化地方:*/
void dirction(void)
{
			dir_l_err = dir_err; //方向偏差

		dir_err = img_W / 2 - (mid_line[80]+mid_line[81]+2*mid_line[82]+2*mid_line[83]+3*mid_line[84]+3*mid_line[85]+
														4*mid_line[86]+4*mid_line[87]+5*mid_line[88]+5*mid_line[89])/30;

	if(R_flag > 2)
			PID_out = 1 * dir_err + 0  * (dir_err - dir_l_err);
//	else if( abs(dir_err) > 10)//弯道
//		PID_out = dir_P * dir_err + dir_D  * (dir_err - dir_l_err);
//	else
		PID_out = dir_P * dir_err + dir_D  * (dir_err - dir_l_err);

	if(abs(PID_out)< 5 || jun_flag == 1)
		PID_out = 0;
	PID_OUT = steer_mid + PID_out;
		if(PID_OUT > steer_left)
			PID_OUT = steer_left;
		if(PID_OUT < steer_right)
			PID_OUT = steer_right;
		pwm_duty(S_MOTOR_PIN, PID_OUT);
}

/*********************************************************************************************************************
 * @file       		main
 * @author     		LXJSWD
 * @date       		2021-06-10
 * @备注:按键0为发车键,按键1-,按键2+
					拨码开关:3为PID四个参数(增量式PI,位置式

PD)总开关;2 1开关:00为IP  01为Ii  10为Dd   11为DP
										4为速度调节:
										5为显示页数调节:
										6为是否识别数字等图像
* @版本说明: ********************************************************************************************************************/

int main(void)
{
	DisableGlobalIRQ();						
board_init();							
init();								    EnableGlobalIRQ(0);							
		systick_start();							    while (1)
    {
			debug_key();
			if(mt9v03x_csi_finish_flag)				
			{
				SysTick->VAL = 0x00;
				start_time = systick_getval_ms();		
				mt9v03x_csi_finish_flag = 0;			
//				AD_collect();					
				get_image();									img_filter();	
											
				get_line();														
//				chuku();
//				ruku();						

				roundabout();													
				road_junction();											
				buxian();															
				dirction();														
				differential();												
//				out_range();													
				display();														
			}
    }
}
/*===================================================================================== 

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236


● 相关图表链接:

文章来源: zhuoqing.blog.csdn.net,作者:卓晴,版权归原作者所有,如需转载,请联系作者。

原文链接:zhuoqing.blog.csdn.net/article/details/120105190

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。