简 介: 本文主要介绍了第十六届智能车竞赛智能视觉组的相关设计思想。此车系统由i.mx8处理器为上位机,RT1064为下位机。通过摄像头传感器检测赛道。使用光电编码器采集车轮速度。结合车模赛道物理模型对行车最优路径进行规划,利用PID等控制算法调节双电机输出,舵机输出,达到对四轮车的转向路径和速度的闭环控制。识别方面采用深度学习mobilenetv3模型的人工智能算法识别图片。

关键词 imx8pid控制差速深度学习

 

学 校:哈尔滨工程大学
队伍名称:济海追风 0 队  
参赛队员:王彦斌    
张弛     
李烨     
带队教师:许德新 唐墨   

 


  全国大学生智能汽车竞赛是以“立足培养、重在参与、鼓励探索、追求卓越” 为指导思想,鼓励创新的一项科技竞赛活动。竞赛要求在规定的汽车模型平台上, 使用恩智浦半导体公司的微控制器作为核心控制模块,通过增加道路传感器、电机驱动模块以及编写相应控制程序,制作完成一个能够自主识别道路的模型汽车。参赛队员的目标是模型汽车需要按照规则以最短时间完成单圈赛道。

  该竞赛以恩智浦半导体公司为协办方,得到了教育部相关领导、恩智浦公司领导与各高校师生的高度评价,已发展成全国 30 个省市自治区 400 余高校的全国大学生智能汽车竞赛。

  在这份报告中,我们小组通过对小车设计制作整体思路、电路、算法、调试、车辆参数的介绍,详尽地阐述了我们的思想和创意,具体表现在电路的创新设计, 以及算法方面的独特想法,而对单片机具体参数的调试也让我们付出了艰辛的劳 动。这份报告凝聚着我们的心血和智慧,是我们共同努力后的成果。

  在准备比赛的过程中,我们小组成员涉猎控制、模式识别、传感技术、汽车电子、电气、计算机、机械等多个学科,这次磨练对我们的知识融合和实践动手能力的培养有极大的推动作用,所有队员都为此次智能汽车竞赛付出了艰苦的劳动。

 

第一章 统总体设计


1.1 系统概述

  智能车主要由三个部分组成:检测系统,控制决策系统和动力系统。其中检测系统采用摄像头,控制决策系统采用i.mx8作为上位机,RT1064作为下位机。动力系统主要控制直流电机的转速。整体的流程为,通过摄像头来检测前方的赛道信息以及采集图片,并将赛道信息发送给上位机。同时,通过光电编码器构成的反馈渠道将车体的行驶速度信息通过下位机发送给上位机。根据所取得的赛道信息和车体当前的速度信息,由上位机做出决策,并通过与下位机通信将PWM信号控制直流电机进行相应动作,从而实现车体的转向控制和速度控制。
  根据智能车系统的基本要求,我们设计了系统结构图,如图 1.1 所示。

▲ 图 1 系统框图

▲ 图 1 系统框图

 

第一章 统总体设计


1.2 整车布局

  (1)电池放于车模中部,合理分配重心,方便速度控制。
  (2)舵机直立放置,以提高舵机响应速度。
  (3)铜柱结合3D打印材料固定摄像头减小摄像头的晃动。

▲ 图 2 车模布局

▲ 图 2 车模布局

 

第二章 赛任务及机械结构设计


2.1 智能视觉组比赛任务

2.1.1 比赛任务以及要求

  (1)车模
  车模使用 c 型车模,车模作品尺寸不限。

  (2)微控制器与传感器
  车模微控制器指定使用 NXP 系列单片机,推荐使用 i.MX RT 系列的任意一款单片机。
  允许使用摄像头、电磁、红外、激光传感器等。

  (3)比赛赛道
  a.六种标准元素
  b.车库
  c.视觉识别元素:数字,动物, 水果

  (4)比赛任务
  a.循迹任务:车模在赛道上运行,计算积分值,规则及赛道要求与基础四轮组一致,只是每次运行的限定时间变为两分钟;
  b.识别任务:车模在固定位置,两分钟内对固定位置的图片内容进行循环识别并作出相应动作来获得积分值,动作要求请查看图片识别得分标准里的备注栏描述;

 

第二章 赛任务及机械结构设计


2.1.2 第十六届赛道特殊元素

  (1) 三岔路口
  三岔路口尺寸要求如下图所示:

  两个三岔路口之间距离: 两个相邻三岔路口之间的距离大于等于 1.5 日;
  三岔路口支路直道长度: 三岔路口三条支路的长度大于等于 45 厘米; 连接两个三岔路口之间的赛道形状与距离没有任何要求。

  完成一次三岔路口任务标准:

  从一个三岔路口直道进入,并行驶超过 45 厘米的直道;从另外一个三路口直道行驶并驶出三叉路口驶出;
  前后两次通过相同三叉路口必须从不同岔路行进;对于双车接力组则允许前后两次通过相同的路口。
  对于全向行进组,要求车模在通过三岔路口时必须更换运行模式; 对于车模是否在三岔路口转圈,三岔路口冲出赛道等均不作判罚。

  (2) 十字路口
  十字路口没有任何限制,在十字路口中心店两条相交的赛道中心线是垂直即可。两个十字路口中心距离,以及十字路口距离三岔路口中心的距离不小于45 厘米。

  完成十字路口任务标准:
  从十字路口一侧进入,直线通过十字路口;不允许直接左拐与右拐; 车模通过同一十字路口有两种情况:
  如果车模从十字路口通过后,没有途径其它赛道元素(坡道、环岛、三岔路口)直接回到十字路口(这种情况称为十字圆环路口);

  如果从十字路口通过后,途径其它赛道元素(坡道、环岛、三岔路口)之后又回到同一十字路口通过;

  以上两种都被视作通过十字路口两次。

  (3) 环岛

  要求环岛赛道中心线的直径大于等于 50 厘米。环岛中心线与赛道中心线是相切关系。
  完成环岛任务标准:进入环岛绕行至少一周以上驶出环岛;
  对于在环岛内多次绕行不进行判罚。不允许车轮进入环岛内侧区域,否则认为是比赛任务失败。

  (4) 坡道
  只规定坡道的最高定点距离地面不小于 15 厘米。对于坡道的宽度、长度、形状以及制作材质不做任何要求。
  通过坡道任务标准:车模在通过坡道最高点时,车轮必须距离地面超过 15 厘米。

  在满足上述要求的同时,车模是否从坡道上掉落不进行判罚。

  (5) 车库

  车库允许放置在赛道任意位置。对于车库的形状没有任何限制。只要保证车模在发车时,车模的中心线垂直与赛道中中心线,车模车轮在赛道边缘之外即可。

  完成车库发车任务标准:车模从车库出发并在赛道上行驶超过 1 米的距离。

  (6) 识别
  图片识别积分任务分为“积分”和相应“扣分”环节,积分也是在两分钟内可以多轮次一直识别累计积分,直到两分钟倒计时结束。“扣分”是当识别错误做出错误动作或不做动作时的惩罚手段。
  扣分规则为:当屏幕上出现相应图片时,小车不能进行相应动作或动作错误,则扣除本次任务对应的分值。比如屏幕出现水果图片时,小车未能完成识别和打靶,则扣 10 分;出现偶数数字图片时,小车未能按要求前行进大约 30
  厘米,然后退回到原地,则扣 5 分;

  最终得分为赛道运行的积分+AI 识别的积分。赛道运行任务和图片识别任务是分别倒计时的 2 分钟,两个任务之间不允许调整时间,即便放弃某一项任 务,另一项任务的时间也只有 2 分钟。

  AI 视觉组赛道各元素积分分值、图片识别得分标准见下表:

2.2 机械结构设计

2.2.1 摄像头安装与调试

  为了识别赛道以及图片,采用双摄像头,摄像头投影位于车模中心。摄像头支架采用铜柱和3D打印件相结合的方式制作。

  识别用摄像头高度 17.8cm,符合比赛规则要求。

  搜线用摄像头高度 14.0cm, 符合比赛规则要求。如图 2.2.2。

2.2.2 编码器的安装

  为了更为精确的获得电机转速的返回值,本次车模上安装的是逐飞 1064 线编码器,及其套件。编码器安装直接使用车模上的编码器安装孔。如图 2.2.3。

2.2.3 电池安装

  电池可以采用两串两并 21700 锂电池。锂电池放电性能优越,质量轻。电池自带保护板,由于展示需要拆卸,这里不予体现。电池图片2.2.4

  电池安装如图 2.2.5

2.3 本章小结

  本章主要介绍了小车的安装制作和调试过程中机械方面的具体的问题。我们 从开始比赛以来,一直坚持机械结构和算法是同样重要的原则,在更新算法的同时也在提高相应的机械和硬件结构来适应。上面的介绍是我们最稳定的小车版本的经验。而在刚开始做小车到现在,对机械结构方面我们做了许许多多各种各样的尝试和实验,收获了一些效果,但是目前这版是能够适应算法并且最稳定的机械结构系统。

 

第三章 件设计


3.1 硬件设计方案

  整个智能车控制系统是由三部分组成的:i.mx8上位机、RT1064下位机、电机驱动电路板以及摄像头处理集成板。最小系统板可以插在主板上组成信号采集、处 理和电机控制单元。同时为了减小下位机以及电机驱动电路给上位机带来的干扰,我们把上位机,下位机和电机驱动分开来。

  上位机主要电路包括如下:USB电路、最小系统板插座、(UART、SPI、I2C、JTAG)接口、稳压电路、电源接口、指示灯、拨码开关、电源开关、复位按键、硬件时钟等。

  下位机主要电路包括如下:电源稳压电路、最小系统板插座、电机驱动器接口、测速接口、OLED、电源接口、指示灯、五向按键、开关等。

3.2 传感器选择

  本设计中,传感器分为两部分:摄像头传感器、速度传感器。

3.2.1 摄像头

  摄像头的工作原理是:景物通过镜头(LENS)生成的光学图像投射到图像传感器表面上,然后转为电信号,经过A/D(模数转换)转换后变为数字图像信号,再送到数字信号处理芯片(DSP)中加工处理,再通过一定的传输方式给其他设备,

  由于加入识别这个任务,再加上赛道环境在一定程度上是未知,所以我们采用摄像头识别的识别方式。
  市面上常见的摄像头主要是分为两种:数字摄像头和模拟摄像头,数字摄像头主要有ov7725,ov2640,ov5640,ov7670,MT9V032 等,模拟摄像头主要有
  ov5116,BF3003,MT9V136。数字摄像头通常会有DVP 接口,其数据口通信电压一般为
  3.3v 远低于一般模拟摄像头需要的 12v,采用模拟摄像头会大大增加电路的安全性, 就算是操作失误,也不会造成大范围的硬件损坏。

  事实证明智能车对于图像的分辨率要求并不是很高,但是对于其动态性能要求十分高,特别是在小车高速行驶时,图像变化会很大,再加上赛场环境的复杂的光照条件,过亮过暗,有无阳光直射,灯光的颜色和强度都会影响到摄像头的成像,所以选择一款满足条件摄像头就显得尤为重要。

  KS2A543是一款彩色全局曝光摄像头,作为一个低压的COMS能通过USB2.0接口提供图像。

3.2.2 编码器

  本小车使用编码器由LM2596S为其提供 5V 工作电压。处理器通过读取编码器脉冲数来实现小车速度的检测,通过读取编码器旋转方向脚的高低电平来检测电机的正反转。编码器原则上轻小为好,选逐飞编码器较好,所以最终选用1024线逐飞编码器。

3.3 下位机

  单片机最小系统板使用逐飞RT1064系统板,为减少电路板空间,主板上仅将本系统所用到的引脚引出,包括信号接口、外部中断接口、若干普通 IO 接口等。

3.3.1 电源管理部分

  电源部分使用一片LM2596-ADJ、2 片 TPS7333转 3.3V 为单片机、OLED供电,一片LM2596转5.0V为编码器及逻辑芯片供电,一片LM2596转7V为舵机供电,一片LM2596转7V为上位机供电电源部分电路图如图 11 所示:

▲ ▲ 图 11 电源电路

▲ ▲ 图 11 电源电路

3.3.2 辅助调试部分

  为了减轻负担方便现场调试我们加入了五向按键、OLED。大大的节省了我们时间,避免了经常用电脑下程序的麻烦。调节按键、拨码开关用 OLED 来显示各个参数。也方便我们观看图像和各项参数。

3.3.3 电机驱动电路

  BTN7971 是用于电机驱动应用的集成高电流半桥。 它是 NovalithIC™系列的一部分,包含一个 p 沟道高边 MOSFET 和一个 n 沟道低边 MOSFET,在一个封装中集成了驱动 IC。 由于 p 沟道高边开关,消除了对电荷泵的需求,从而最大限度地降低了 EMI。 集成驱动器 IC 可轻松连接微控制器,具有逻辑电平输入, 电流检测诊断,转换速率调整,死时间生成以及针对过温,欠压,过流和短路的保护。 BTN8982TA 为受保护的大电流 PWM 电机驱动器提供了成本优化的解决方案,并且电路板空间消耗非常低。

▲ 图 13 电机驱动电路

▲ 图 13 电机驱动电路

3.4 上位机

  上位机最小系统板采用NXP i.MX 8M Mini 应用处理器。其内置高性能、高能效的 14 FinFET 技术。上位机主板含有稳压电源并将USB接口以及通信接口引出。

3.4.1 稳压电源部分

  首先接入8.4V的电池电压,通过TPS5430将其稳压至5V。为保证系统板的安全,使用FDS4435芯片将电源5V和供电5V分开,只有接入系统板后才可导通。再将导通后的5V稳压供至接口使用,再稳压至3.3V供DB连接器和USB使用。

▲ 图 14 电源电路

▲ 图 14 电源电路

3.4.2 USB接口部分

  5V电源(VCC5V)通过 P 沟道场效应管构成的电子开关给 USB 插座供电,该电子开关的使能端是OTG_PWRON,OTG_PWRON为高电平时,电子开关导通,反之则截止。三极管的作用是,当底板无电时,不会检测到来自USB口的电压。

▲ 图 15 USB电路

▲ 图 15 USB电路

 

第四章 件系统设计


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

  软件的控制,就是让控制车模在符合比赛规则前提下,以最快最稳定的速度跑完整个赛道。不论上哪种方案,软件的总体框架总是相似的,我们追求的就是稳定至上,兼顾速度,以我们的方案,软件上就是图像采集、图像处理识别横断,速度控制以及速度反馈以及计算偏差。

4.2 图像处理

  采用opencv对采集回来的图像进行处理。主要分为以下步骤:
  1. 图像的灰度化以及二值化。
  2. 图像的最大连通域的选取。
  3. 图片的中线求取,中心扩散搜索,找到黑点记录黑点当前列值;两边都有直接求和平均求出中心值;只找到一边时,根据图像修正值确定中心值。

▲ 图 16 图像处理

▲ 图 16 图像处理

4.3 电机以及舵机控制

  PID 控制主要有三部分组成,比例、积分、微分。比例控制是一种最简单的控制方式。其控制器的输出与输入误差信号成比例关系。偏差一旦产生,调 节器立即产生控制作用使被控量朝着减小偏差的方向变化,控制作用的强弱取 决于 KP。 当仅有比例控制时系统输出存在稳态误差( Steady-stateerror)。

4.4 识别任务处理

  MobileNet v3发表于2019年,该v3版本结合了v1的深度可分离卷积、v2的Inverted Residuals和Linear Bottleneck、SE模块,利用NAS(神经结构搜索)来搜索网络的配置和参数。我们设计了一种水果,动物,奇数,偶数,奇数TAG,偶数TAG,空白,七分类的模型,数据集大小为7万张,通过手动采集图片完成。训练时间3小时。TOP1精确度99.92%。

4.5 本章小结

  本章主要介绍了智能车比赛中所用到的图像处理,电机控制算法等软件程序。这些程序是赛车检测系统的核心,我们一次又一次的找问题后优化,优化后找问题。不断尝试新的控制算法,学习新的知识,并把新的知识应用于智能车上。
  智能车比赛的程序不是一时半会就能写好的,也不是一些好就能直接使用的,它需要经过一次次的调试,找问题调参数,直到到达最佳状态。并且我们要想更近一步,要不断去尝试新的算法,从其他角度经行寻找解决方案,对比之下选最优。

 

录 C:部分代码


#include "headfile.h" 
#define key_up B23 
#define key_left B22 
#define key_down B27 
#define key_mid B24 
#define key_right B26 
int16 left_now_spd = 0; 
int16 right_now_spd = 0; 
int16 left_exp_spd = 0; 
int16 right_exp_spd = 0; 
int u_left_now = 0; 
int u_left_last = 0; 
int u_right_now = 0; 
int u_right_last = 0; 
int u_val = 0; 
float Kp_left = -20; //-3 
float Ki_left = -3; //-0.55 
float Kd_left = -0.5; 
float Kp_right = 20; //3 
float Ki_right = 3; //0.55 
float Kd_right = 0.5; 
uint8 mode = 0; 
int16 err_right[3] = {0,0,0}; 
int16 err_left[3] = {0,0,0}; 
int quad_distance = 0; 
int16 turn_servo_angle = 3985; 
int16 up_servo_angle = 3750; 
int16 down_servo_angle = 3550; 
int16 angle = 0; 
int dis1 = 0; 
int pic_pos = 0; 
uint8 imx8_rx_buffer[28] = {0}; 
lpuart_transfer_t   imx8_receivexfer; 
lpuart_handle_t     imx8_g_lpuartHandle; 
 
int serial_stop_flag = 0; 
int hit_stop_flag = 0; 
//uint8 imx8_uart_data[10] = {0xFF,0xFF,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
uint8 cam1_ok = 0; 
uint8 cam2_ok = 0; 
uint8 ser_ok = 0; 
uint8 bell_zz = 0; 
void motor_control(int num,int val) 
{ 
//0代表左边,1代表右边 
// u_val -50000----50000 
if(val>=50000) 
{ 
val = 50000; 
} 
else if(val<=-50000) 
{ 
val = -50000; 
} 
u_val = val; 
if(num == 0) 
{ 
if(u_val>=0) 
{ 
pwm_duty(PWM1_MODULE3_CHB_D1,u_val); 
pwm_duty(PWM1_MODULE3_CHA_D0,0); 
/*if(left_exp_spd ==0&&err_left[0]>500) 
{ 
pwm_duty(PWM1_MODULE3_CHB_D1,50000); 
pwm_duty(PWM1_MODULE3_CHA_D0,0); 
}*/ 
 
} 
else 
{ 
pwm_duty(PWM1_MODULE3_CHB_D1,0); 
pwm_duty(PWM1_MODULE3_CHA_D0,-u_val); 
 
} 
 
} 
else if(num == 1) 
{ 
if(u_val>=0) 
{ 
pwm_duty(PWM2_MODULE3_CHA_D2,u_val); 
pwm_duty(PWM2_MODULE3_CHB_D3,0); 
/*if(u_val>25000) 
{ 
pwm_duty(PWM2_MODULE3_CHA_D2,50000); 
pwm_duty(PWM2_MODULE3_CHB_D3,0); 
}*/ 
 
} 
else 
{ 
pwm_duty(PWM2_MODULE3_CHA_D2,0); 
pwm_duty(PWM2_MODULE3_CHB_D3,-u_val); 
/*if(right_exp_spd ==0&&err_right[0]>500) 
{ 
pwm_duty(PWM2_MODULE3_CHA_D2,0); 
pwm_duty(PWM2_MODULE3_CHB_D3,50000); 
}*/ 
 
} 
 
} 
 
} 
void uart1_callback(LPUART_Type *base, lpuart_handle_t *handle, status_t status, void *userData) 
{ 
if(kStatus_LPUART_RxIdle == status) 
{ 
for(int i = 0;i<14;i++) 
{ 
if(imx8_rx_buffer[i] == 0X2F) 
{ 
if(imx8_rx_buffer[i+13] == 0XFF) 
{ 
uint8 sum = 0; 
sum = imx8_rx_buffer[i+1] + imx8_rx_buffer[i+2] + imx8_rx_buffer[i+3] + imx8_rx_buffer[i+4] + imx8_rx_buffer[i+5] + 
imx8_rx_buffer[i+6] + imx8_rx_buffer[i+7] + imx8_rx_buffer[i+8] + imx8_rx_buffer[i+9] + imx8_rx_buffer[i+10] + imx8_rx_buffer[i+11]; 
if(sum == imx8_rx_buffer[i+12]) 
{ 
left_exp_spd = -(imx8_rx_buffer[i+1] << 8  | imx8_rx_buffer[i+2]); 
right_exp_spd = imx8_rx_buffer[i+3] << 8  | imx8_rx_buffer[i+4]; 
turn_servo_angle = imx8_rx_buffer[i+5] << 8  | imx8_rx_buffer[i+6]; 
down_servo_angle = imx8_rx_buffer[i+7] << 8  | imx8_rx_buffer[i+8]; 
up_servo_angle = imx8_rx_buffer[i+9] << 8  | imx8_rx_buffer[i+10]; 
bell_zz = imx8_rx_buffer[i+11]; 
 
} 
} 
 
} 
} 
serial_stop_flag = 0; 
 
} 
handle->rxDataSize = imx8_receivexfer.dataSize;  //还原缓冲区长度 
handle->rxData = imx8_receivexfer.data;          //还原缓冲区地址 
} 
uint8 key_scan(PIN_enum pin) 
{ 
if(!gpio_get(pin)) 
{ 
systick_delay_ms(100); 
if(!gpio_get(pin)) 
{ 
return 1; 
} 
} 
return 0; 
} 
//uint8 laser_flag = 0; 
void laser_run(uint8 flag) 
{ 
if(flag) 
{ 
gpio_set(B20,0); 
systick_delay_ms(4); 
gpio_set(B20,1); 
systick_delay_ms(4); 
} 
else 
{ 
gpio_set(B20,0); 
systick_delay_ms(4); 
} 
 
} 
int oled_cnt = 0; 
float Kp = 8; 
float Kd = 25; 
int16 Max_Vel = 3000; 
int16 Min_Vel = 3000; 
uint8 params_data[13] = {0,0,0,0, 
0,0,0,0, 
0,0,0,0,0};//Kp(4)Kd(4)v_max(2)v_min(2)garage(1) 
uint8 chk_sum = 0; 
uint8 pkg_head[2] = {0xfe,0xef}; 
uint8 pkg_tail[2] = {0x79,0x7e}; 
uint8 pkg_det[4] = {0x11,0x22,0xff,0xee}; 
union Kp_Union 
{ 
float Kp; 
unsigned char dat[4]; 
}Kp_Union; 
union Kd_Union 
{ 
float Kd; 
unsigned char dat[4]; 
}Kd_Union; 
 
uint8 car_init(void) 
{ 
oled_p6x8str(20,0,"Mode:"); 
if(mode==0) 
{ 
oled_p6x8str(60,0,"SLOW_Track"); 
} 
else if(mode==1) 
{ 
oled_p6x8str(60,0,"FAST_Track"); 
} 
else if(mode==2) 
{ 
oled_p6x8str(60,0,"Detect"); 
} 
oled_p6x8str(50,1,"RUN"); 
oled_p6x8str(0,oled_cnt,">>"); 
 
if(key_scan(key_up)&&oled_cnt>0) 
{ 
oled_cnt--; 
oled_fill(0x00); 
} 
 
if(key_scan(key_down)&&oled_cnt<1) 
{ 
oled_cnt++; 
oled_fill(0x00); 
} 
 
if(oled_cnt==0) 
{ 
if(key_scan(key_left)&&(mode>0)) 
{ 
mode--; 
oled_fill(0x00); 
} 
else if(key_scan(key_right)&&(mode<2)) 
{ 
mode++; 
oled_fill(0x00); 
} 
} 
if(oled_cnt==1) 
{ 
if(key_scan(key_mid)) 
{ 
uart_putbuff(USART_1,pkg_head,2); 
uart_putchar(USART_1,mode); 
uart_putbuff(USART_1,pkg_tail,2); 
 
uart_putbuff(USART_1,pkg_head,2); 
uart_putchar(USART_1,mode); 
uart_putbuff(USART_1,pkg_tail,2); 
 
uart_putbuff(USART_1,pkg_head,2); 
uart_putchar(USART_1,mode); 
uart_putbuff(USART_1,pkg_tail,2); 
 
uart_putbuff(USART_1,pkg_head,2); 
uart_putchar(USART_1,mode); 
uart_putbuff(USART_1,pkg_tail,2); 
 
uart_putbuff(USART_1,pkg_head,2); 
uart_putchar(USART_1,mode); 
uart_putbuff(USART_1,pkg_tail,2); 
 
uart_putbuff(USART_1,pkg_head,2); 
uart_putchar(USART_1,mode); 
uart_putbuff(USART_1,pkg_tail,2); 
 
uart_putbuff(USART_1,pkg_head,2); 
uart_putchar(USART_1,mode); 
uart_putbuff(USART_1,pkg_tail,2); 
 
uart_putbuff(USART_1,pkg_head,2); 
uart_putchar(USART_1,mode); 
uart_putbuff(USART_1,pkg_tail,2); 
 
uart_putbuff(USART_1,pkg_head,2); 
uart_putchar(USART_1,mode); 
uart_putbuff(USART_1,pkg_tail,2); 
 
uart_putbuff(USART_1,pkg_head,2); 
uart_putchar(USART_1,mode); 
uart_putbuff(USART_1,pkg_tail,2); 
 
uart_putbuff(USART_1,pkg_head,2); 
uart_putchar(USART_1,mode); 
uart_putbuff(USART_1,pkg_tail,2); 
 
uart_putbuff(USART_1,pkg_head,2); 
uart_putchar(USART_1,mode); 
uart_putbuff(USART_1,pkg_tail,2); 
 
uart_putbuff(USART_1,pkg_head,2); 
uart_putchar(USART_1,mode); 
uart_putbuff(USART_1,pkg_tail,2); 
 
uart_putbuff(USART_1,pkg_head,2); 
uart_putchar(USART_1,mode); 
uart_putbuff(USART_1,pkg_tail,2); 
 
uart_putbuff(USART_1,pkg_head,2); 
uart_putchar(USART_1,mode); 
uart_putbuff(USART_1,pkg_tail,2); 
 
uart_putbuff(USART_1,pkg_head,2); 
uart_putchar(USART_1,mode); 
uart_putbuff(USART_1,pkg_tail,2); 
 
uart_putbuff(USART_1,pkg_head,2); 
uart_putchar(USART_1,mode); 
uart_putbuff(USART_1,pkg_tail,2); 
 
uart_putbuff(USART_1,pkg_head,2); 
uart_putchar(USART_1,mode); 
uart_putbuff(USART_1,pkg_tail,2); 
 
uart_putbuff(USART_1,pkg_head,2); 
uart_putchar(USART_1,mode); 
uart_putbuff(USART_1,pkg_tail,2); 
 
uart_putbuff(USART_1,pkg_head,2); 
uart_putchar(USART_1,mode); 
uart_putbuff(USART_1,pkg_tail,2); 
 
uart_putbuff(USART_1,pkg_head,2); 
uart_putchar(USART_1,mode); 
uart_putbuff(USART_1,pkg_tail,2); 
 
uart_putbuff(USART_1,pkg_head,2); 
uart_putchar(USART_1,mode); 
uart_putbuff(USART_1,pkg_tail,2); 
 
uart_putbuff(USART_1,pkg_head,2); 
uart_putchar(USART_1,mode); 
uart_putbuff(USART_1,pkg_tail,2); 
 
uart_putbuff(USART_1,pkg_head,2); 
uart_putchar(USART_1,mode); 
uart_putbuff(USART_1,pkg_tail,2); 
 
uart_putbuff(USART_1,pkg_head,2); 
uart_putchar(USART_1,mode); 
uart_putbuff(USART_1,pkg_tail,2); 
 
uart_putbuff(USART_1,pkg_head,2); 
uart_putchar(USART_1,mode); 
uart_putbuff(USART_1,pkg_tail,2); 
 
uart_putbuff(USART_1,pkg_head,2); 
uart_putchar(USART_1,mode); 
uart_putbuff(USART_1,pkg_tail,2); 
 
uart_putbuff(USART_1,pkg_head,2); 
uart_putchar(USART_1,mode); 
uart_putbuff(USART_1,pkg_tail,2); 
 
uart_putbuff(USART_1,pkg_head,2); 
uart_putchar(USART_1,mode); 
uart_putbuff(USART_1,pkg_tail,2); 
 
uart_putbuff(USART_1,pkg_head,2); 
uart_putchar(USART_1,mode); 
uart_putbuff(USART_1,pkg_tail,2); 
return 0; 
} 
 
} 
systick_delay_ms(5); 
return 1; 
} 
int action = 0; 
int main(void) 
{ 
DisableGlobalIRQ(); 
board_init();   //务必保留,本函数用于初始化MPU 时钟 调试串口 
/*串口初始化*/ 
uart_init (USART_1, 500000,UART1_TX_B12,UART1_RX_B13); 
NVIC_SetPriority(LPUART1_IRQn,0);         //设置串口中断优先级 范围0-15 越小优先级越高 
uart_rx_irq(USART_1,1); 
 
//配置串口接收的缓冲区及缓冲区长度 
imx8_receivexfer.dataSize = 28; 
imx8_receivexfer.data = imx8_rx_buffer; 
 
//设置中断函数及其参数 
uart_set_handle(USART_1, &imx8_g_lpuartHandle, uart1_callback, NULL, 0, imx8_receivexfer.data, 28); 
/*舵机电机初始化*/ 
pwm_init(PWM1_MODULE3_CHA_D0 , 7000, 0);//右前 
pwm_init(PWM1_MODULE3_CHB_D1 , 7000, 0);//左前 
pwm_init(PWM2_MODULE3_CHA_D2 , 7000, 0);//左后 
pwm_init(PWM2_MODULE3_CHB_D3 , 7000, 0);//右后转 
 
pwm_init(PWM4_MODULE2_CHA_C30 , 50, turn_servo_angle); 
pwm_init(PWM4_MODULE3_CHA_C31 , 50, down_servo_angle); 
pwm_init(PWM4_MODULE1_CHA_B25 , 50, up_servo_angle); 
qtimer_quad_init(QTIMER_1, QTIMER1_TIMER3_C24, QTIMER1_TIMER2_C2); 
qtimer_quad_init(QTIMER_2, QTIMER2_TIMER1_C4,QTIMER2_TIMER0_C3); 
gpio_init(D12, GPO,0, GPIO_PIN_CONFIG);//beel 
gpio_init(B20, GPO,0, GPIO_PIN_CONFIG);//laser 
gpio_init(key_up, GPI,1, GPIO_PIN_CONFIG);//上 
gpio_init(key_down, GPI,1, GPIO_PIN_CONFIG);//左 
gpio_init(key_left, GPI,1, GPIO_PIN_CONFIG);//下 
gpio_init(key_right, GPI,1, GPIO_PIN_CONFIG);//中 
gpio_init(key_mid, GPI,1, GPIO_PIN_CONFIG);//右 
oled_init(); 
while(car_init()); 
pit_init();                     //初始化pit外设 
if(mode==0) 
{ 
pit_interrupt_ms(PIT_CH0,1);  //初始化pit通道0 周期 
pit_interrupt_ms(PIT_CH1,5);  //初始化pit通道1 周期 
pit_interrupt_ms(PIT_CH2,10);  //初始化pit通道0 周期 
} 
if(mode==1) 
{ 
pit_interrupt_ms(PIT_CH0,1);  //初始化pit通道0 周期 
pit_interrupt_ms(PIT_CH1,5);  //初始化pit通道1 周期 
pit_interrupt_ms(PIT_CH2,10);  //初始化pit通道0 周期 
} 
if(mode==2) 
{ 
pit_interrupt_ms(PIT_CH0,1);  //初始化pit通道0 周期 
pit_interrupt_ms(PIT_CH1,5);  //初始化pit通道1 周期 
pit_interrupt_ms(PIT_CH2,10);  //初始化pit通道0 周期 
Kp_left = -40; //-3 
Ki_left = -4; //-0.55 
Kd_left = -0.5; 
Kp_right = 40; //3 
Ki_right = 4; //0.55 
Kd_right = 0.5; 
} 
NVIC_SetPriority(PIT_IRQn,15);  //设置中断优先级 范围0-15 越小优先级越高 四路PIT共用一个PIT中断函数 
EnableGlobalIRQ(0); 
while(1) 
{ 
////蜂鸣器zzz 
if(bell_zz==0) 
{ 
gpio_set(D12,0); 
} 
else if(bell_zz==1) 
{ 
gpio_set(D12,1); 
} 
if(up_servo_angle==4000) 
{ 
laser_run(1); 
} 
else 
{ 
laser_run(0); 
} 
} 
 
} 
 


● 相关图表链接:

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐