这是我大学毕业做的毕业设计,本人是学计算机专业,这个项目应该算嵌入式入门,这个最后展示的效果也不错。在这里写出来,是为了方便想做这个的朋友提供一些帮助。主要涉及到软硬件设计与搭建平台,我是觉得挺有意思的。
- 嵌入式硬件系统概要设计
选择常见的电机模型车为机械平台,通过细化设计要求, 结合传感器技术和电机控制技术相关知识来实现小车的各种功能[15]。
3.1. 智能小车系统层次结构
图3-1 层次图
图3-1为基于C54单片机的智能小车控制系统层次图,系统主要有4层组成:导航逻辑层、小车控制层,传感和执行层以及小车机械层,导航逻辑层和小车控制层运用C语言开发的应用软件,导航逻辑层,进行计算获取下一个操作的指令发给小车控制层,小车控制层把获取到的位置信息和行驶信息给导航逻辑层进行计算。小车传感层和执行层,起到采集信息和执行小车运动操作。导航逻辑层主要包括决策树算法,也是本设计的重要部分。
3.2. 系统软硬件组成
图3-2 系统图
智能小车控制系统软硬件组成如图 所示。系统由两部分组成,控制系统层,硬件部分。
硬件部分有STC89C54单片机,电机模块、舵机模块、GPS模块、电源模块、LCD模块、电子罗盘模块。GPS模块通过解调获取经纬度,处理后的数据通过串口来传输给单片机、车方向角度数据则通过IIC协议与单片机通信。
4. 智能小车控制系统硬件平台
4.1. 总体设计
图4-1 硬件图
自动行驶小车控制系统硬件平台架构如图所示。智能小车的硬件是控制系统的基础,硬件主要以STC89C54单片机作为控制核心,用GPS模块获取经纬度信息,单片机接收到GPS信息和用电子罗盘模块获取小车方向角度,一方面在LCD1602模块上进行显示,另一方面控制舵机的转向和调节电机驱动模块,然小车可以到达预设定终点
4.2. 智能小车控制系统硬件电路设计
- 智能小车核心板设计
(1) 微处理器的选型
系统的控制器选用STC89C54RD+单片机。8位STC89C54RD+单片机是STC 公司生产的一款增强型51 单片机,具有低功耗、存储容量大、运行稳定、价格便宜等特点。其支持的最高时钟为80MHz.内部包括16 KB 的Flash程序存储器ROM、1 kB 的数据存储器RAM,具有ISP 在线编程功能,大大减少了开发复杂度,同时可节省购买编程器的额外投入。STC89C54RD + 单片机的开发环境与51 单片机的开发环境兼容.
(2) 单片机最小系统设计
最小系统是处理器能够运行的基本系统。在嵌入式控制系统的开发中,最
小系统起着至关重要的作用。因此构建一个嵌入式控制系统,第一步,必须是要让系统核心部分–嵌入式处理器,可以运行起来,这样才可以逐步增加系统的功能,如外围扩展、软件及程序设计、增加各种接口等,最终形成符合需求的完整系统。该最小系统组成,采用11.0592M晶振,复位电路,如图4-1所示:
图4-1 最小系统图
(3) GPS模块
GPS模块是自动行驶小车系统的关键模块之一,其经纬度的获取和性能是选择的一个重点。模块采用U-BLOX NEO-6M模组,体积小巧,性能优异。 其中该电路设计增加放大电路,有利于无源陶瓷天线快速搜星。模块可通过串口进行各种参数设置,并可保存在EEPROM,使用方便。模块自带SMA接口,可以连接各种有源天线,适应能力强。 该设计模块兼容3.3V/5V电平,方便连接各种单片机系统。其设计原理图4-2如下:
图4-2 GPS图
(4) 电源驱动模块
其中电源模块有两部分,一个型号为78M05电源稳压模块给电机驱动供电的,其需要7.2v的电压如图4-3,一个电源稳压模块给舵机供电,其输出5v电源给舵机进行供电如图4-4。
图4-3 78M05图
图4-4
(5) 电机驱动模块
L298N是ST公司生产的一种高电压、直流电机驱动控制芯片。该芯片采用15脚封装。内含两个H桥的高电压大电流全桥式驱动器,主要功能驱动直流电动机和步进电动机、继电器线圈等感性负载;采用标准逻辑电平信号控制;具有两个控制端,最多去控制两个直流电机。在这里使用L298N芯片驱动电机,驱动两台后轮直流电机。如图4-5所示
图4-5 L298N图
(6) 电子罗盘模块
霍尼韦尔 HMC5883L 是一种表面贴装的高集成模块,并带有数字接口的弱磁
传感器芯片,应用于低成本罗盘和磁场检测领域。HMC5883L 只要使用最先进的高分辨率 HMC118X 系列磁阻传感器。还包括有放大器、自动消磁驱动器、偏差校准、能使罗盘精度控制在 1°~2°的 12 位模数转换器、简易的 I2C 系列总线接口。如图4-6。
图4-6 HMC5883L图
- 智能小车控制系统软件
整个GPS导航的软件部分从总体上说是一个反馈系统,根据小车的目前形式情况和目前的经度纬度信息,控制小车调整行驶方向,每次做完小的调整后,直走2秒钟。再次处理数据判断当前位置是否是目标位置[16]。
其中智能小车控制算法采用决策树算法。根据小车当前位置建立一个直角坐标系,
以正北方向为0度角,角度旋转方向以顺时针方向为正方向,在计算中得到小车方向角度,路径方向角度。然后预先建立一个决策树,依据决策树,对输入的小车方向和路线方向进行逐次判断,从而得到结果。
5.1. 电机控制代码
主要有三个函数,分别控制前进,后退,电机制动。其使能和转动方向,分别有对应引脚控制。
//函数或者变量声明
sbit INENL = P2^0;
sbit IN1 = P2^1;
sbit IN2 = P2^2;
sbit INENR = P2^3;
sbit IN3 = P2^4;
sbit IN4 = P2^5;
void forward(){
//L左电机正转
INENL=1;
IN1=1;
IN2=0;
//R右电机正转
INENR=1;
IN3=0;
IN4=1;
}
//电机反转
void reverse(){
//L左电机正转
INENL=1;
IN1=0;
IN2=1;
//R右电机正转
INENR=1;
IN3=1;
IN4=0;
}
//电机制动
void stop(){
//L左电机正转
INENL=1;
IN1=0;
IN2=0;
//R右电机正转
INENR=1;
IN3=0;
IN4=0;
}
5.2. 舵机控制代码
其主要是通过PWM解调方式进行舵机控制,通过在一个控制周期内,占空比不同,确定舵机左转、右转、归中。本控制代码采用定时器0。其函数控制代码主要包括初始化,时间控制器函数,舵机状态函数,三个转向函数。信号端口有其对应管脚。
sbit ControlPort = P0^2; //舵机信号端口
//初始化定时器
void InitialTimer ( void ){
TMOD|=0x01; //定时/计数器0工作于方式1
TH0 = 0xff;
TL0 = 0x33;
EA=1; //开总中断
ET0=1; //允许定时/计数器0 中断
TR0=1; //关闭定时/计数器0 中断
}
//定时器中断函数
void Timer0 ( void ) interrupt 1 //定时器中断函数{
TH0 = 0xff; //0.25ms
TL0 = 0x33;
TimeOutCounter ++;
switch ( LeftOrRight )
{
case 0 : //为0时,舵机归位,1.5ms脉宽
{
if( TimeOutCounter <= 6 )
{
ControlPort = 1;
}
else
{
ControlPort = 0;
}
break;
}
case 1 : //为1时,舵机左转,1.25ms脉冲
{
if( TimeOutCounter <= 5 )
{
ControlPort = 1;
}
else
{
ControlPort = 0;
}
break;
}
case 2 : //为2时,舵机右转,1.75ms 脉冲
{
if( TimeOutCounter <= 7 )
{
ControlPort = 1;
}
else
{
ControlPort = 0;
}
break;
}
default : break;
}
if( TimeOutCounter == 80 ) //周期20ms(理论值),比较可靠,最好不要修改
{
TimeOutCounter = 0;
//TR1=0;
}
}
//读取舵机状态
unsigned char readState(){
return LeftOrRight;
}
//舵机向右转
void turnRight(){
if(readState()==2)
{ return ;}
else{
LeftOrRight = 2;
}
}
//舵机向左转
void turnLeft(){
if(readState()==1)
{ return ;}
else{
LeftOrRight = 1;
}
}
//舵机归为位
void turnMin(){
if(readState()==0)
{ return ;}
else{
LeftOrRight = 0;
}
}
5.3. GPS模块控制代码
其主要通过串口进行数据接收。代码主要启动定时器1,采用中断4进行数据接收,函数主要包括:初始化函数、数据接收函数、数据存储函数(且显示)、获取经、纬度函数。
串口对应引脚为txd为p3.0、rxd为p3.1。
//串口初始化
void Uart_Init()
{
SCON = 0X50; //UART方式1;8位UART
REN = 1; //允许串行口接收数据
PCON = 0x00; //SMOD=0;波特率不加倍
TMOD |= 0x20; //T1方式2,用于产生波特率
TH1 = 0xFD; //装初值
TL1 = 0xFD;
TR1 = 1; //启动定时器1
EA = 1; //打开全局中断控制
ES = 1; //打开串行口中断
}
//接受数据
void RECEIVE_DATA(void) interrupt 4 using 3
{
unsigned char temp = 0;
ES=0;
temp = SBUF;
RI = 0;
// LED1 = ~LED1;
if(temp == '$')
{
RX_Count = 0;
Flag_GPS_OK = 0;
}
RX_Buffer[RX_Count++] = temp;
if(RX_Count >= 59)
{
RX_Count = 59;
Flag_GPS_OK = 1;
}
ES=1;
}
//gps信息获取
void recieveLatLng()
{
unsigned char i = 0;
unsigned char gps_time[9]={‘0’,‘0’,‘0’,‘0’,‘0’,‘0’,‘0’,‘0’,’\0’};
unsigned char gps_altitude[5]={‘0’,‘0’,‘0’,‘0’,’\0’};
unsigned char gps_date[10]={‘0’,‘0’,‘0’,‘0’,‘0’,‘0’,‘0’,‘0’,‘0’,’\0’};
unsigned char gps_speed[6]={‘0’,‘0’,‘0’,‘0’,‘0’,’\0’};
if(Flag_GPS_OK == 1 && RX_Buffer[4] == ‘G’ && RX_Buffer[6] == ‘,’ && RX_Buffer[13] == ‘.’) //确定是否收到"GPGGA"这一帧数据
{
for( i = 0; i < 68 ; i++)
{
Display_GPGGA_Buffer[i] = RX_Buffer[i];
}
Hour= (Display_GPGGA_Buffer[7]-0x30)*10+(Display_GPGGA_Buffer[8]-0x30)+8; //UTC时间转换到北京时间 UTC+8 //0x30为ASCII转换为数字
if( Hour >= 24) //溢出
{
Hour %= 24; //获取当前Hour
Flag_OV = 1; //日期进位
}
else
{
Flag_OV = 0;
}
Min_High = Display_GPGGA_Buffer[9];
Min_Low = Display_GPGGA_Buffer[10];
Sec_High = Display_GPGGA_Buffer[11];
Sec_Low = Display_GPGGA_Buffer[12];
Flag_Calc_GPGGA_OK = 1;
}
if(Flag_Calc_GPGGA_OK == 1)
{
Flag_Calc_GPGGA_OK = 0;
LCD1602_write_com(0x80); //设置指针
//记录下时间
gps_time[0]=Hour/10+0x30;
gps_time[1]=Hour%10+0x30;
gps_time[2]=':' ;
gps_time[3]=Min_High;
gps_time[4]=Min_Low ;
gps_time[5]=':' ;
gps_time[6]=Sec_High ;
gps_time[7]=Sec_Low ;
//记录下海拔
gps_altitude[0]=Display_GPGGA_Buffer[54];
gps_altitude[1]=Display_GPGGA_Buffer[55];
gps_altitude[2]=Display_GPGGA_Buffer[56];
gps_altitude[3]=Display_GPGGA_Buffer[57];
//显示经纬度信息
if(1){
LCD1602_write_data(Display_GPGGA_Buffer[28]); //N 或者 S
LCD1602_write_data(Display_GPGGA_Buffer[17]); //纬度
LCD1602_write_data(Display_GPGGA_Buffer[18]); //纬度
LCD1602_write_data(0xdf); //度
LCD1602_write_data(Display_GPGGA_Buffer[19]); //纬度
LCD1602_write_data(Display_GPGGA_Buffer[20]); //纬度
LCD1602_write_word("'"); //秒
LCD1602_write_data(Display_GPGGA_Buffer[42]); //E 或者 W LCD1602_write_data(Display_GPGGA_Buffer[30]); //经度
LCD1602_write_data(Display_GPGGA_Buffer[31]);
LCD1602_write_data(Display_GPGGA_Buffer[32]);
LCD1602_write_data(0xdf);
LCD1602_write_data(Display_GPGGA_Buffer[33]);
LCD1602_write_data(Display_GPGGA_Buffer[34]);
LCD1602_write_word("'");
LCD1602_write_data(Display_GPGGA_Buffer[36]);
LCD1602_write_data(Display_GPGGA_Buffer[37]);
LCD1602_write_data(Display_GPGGA_Buffer[38]);
LCD1602_write_data(Display_GPGGA_Buffer[39]);
}
else if(Page==1){ //显示日期和速度
}
second_lat=((int)(Display_GPGGA_Buffer[22]-0x30))*0.1+ ((int)(Display_GPGGA_Buffer[23]-0x30))*0.01+((int)(Display_GPGGA_Buffer[24]-0x30))*0.001+((int)(Display_GPGGA_Buffer[25]-0x30))*0.0001;
second_lat=second_lat*60;
second_lng=((int)(Display_GPGGA_Buffer[36]-0x30))*0.1+ ((int)(Display_GPGGA_Buffer[37]-0x30))*0.01+((int)(Display_GPGGA_Buffer[38]-0x30))*0.001+((int)(Display_GPGGA_Buffer[39]-0x30))*0.0001;
second_lng=second_lng*60;
//测试gps经度精确代码 ,调试时执行
// gpstest=(int)(second_lng*10);
// gps_display[0]=Display_GPGGA_Buffer[30];
// gps_display[1]=Display_GPGGA_Buffer[31];
// gps_display[2]=Display_GPGGA_Buffer[32];
// gps_display[3]= 0xdf;
// gps_display[4]=Display_GPGGA_Buffer[33];
// gps_display[5]=Display_GPGGA_Buffer[34];
// //display[6]=’’’ ;
// gps_display[7]=gpstest/100+0x30;
// gps_display[8]=(gpstest%100)/10+0x30;
// gps_display[9]=gpstest%10+0x30;
// LCD1602_write_com(0x80);
// LCD1602_write_word(gps_display);
//当前经度 当前纬度 当前经度
cur_lat=(Display_GPGGA_Buffer[17]-0x30)*10+ (Display_GPGGA_Buffer[18]-0x30)+ (Display_GPGGA_Buffer[19]-0x30)*0.1+(Display_GPGGA_Buffer[20]-0x30)*0.01 +second_lat/10000;
cur_lng=(Display_GPGGA_Buffer[30]-0x30)*100+ (Display_GPGGA_Buffer[31]-0x30)*10+ (Display_GPGGA_Buffer[32]-0x30)+ (Display_GPGGA_Buffer[33]-0x30)*0.1+ (Display_GPGGA_Buffer[34]-0x30)*0.01+ second_lng/10000;
}
/*******************************************************************
获取小车行驶速度
*******************************************************************/
if(Flag_GPS_OK == 1 && RX_Buffer[4] == 'M' && RX_Buffer[52] == ',' && RX_Buffer[59] == ',')//确定是否收到"GPRMC"这一帧数据
{
for( i = 0; i < 68 ; i++)
{
Display_GPRMC_Buffer[i] = RX_Buffer[i];
}
Year_High = Display_GPRMC_Buffer[57];
Year_Low = Display_GPRMC_Buffer[58];
Month_High = Display_GPRMC_Buffer[55];
Month_Low = Display_GPRMC_Buffer[56];
Day_High = Display_GPRMC_Buffer[53];
Day_Low = Display_GPRMC_Buffer[54];
if(Flag_OV == 1) //有进位
{
UTCDate2LocalDate(); //UTC日期转换为北京时间
}
Flag_Calc_GPRMC_OK = 1;
}
//第一阶段不记录
if(0 && Flag_Calc_GPRMC_OK == 1)
{
Flag_Calc_GPRMC_OK = 0;
LCD1602_write_com(0x80); //设置指针
LCD1602_write_word("20");
//记录下当前日期
gps_date[0]='2';
gps_date[1]='0';
gps_date[2]=Year_High;
gps_date[3]=Year_Low;
gps_date[4]='-';
gps_date[5]=Month_High;
gps_date[6]=Month_Low;
gps_date[7]='-';
gps_date[8]=Day_High;
gps_date[9]=Day_Low;
//记录下小车当前速度
gps_speed[0]=Display_GPRMC_Buffer[46];
gps_speed[1]=Display_GPRMC_Buffer[46];
gps_speed[2]=Display_GPRMC_Buffer[46];
gps_speed[3]=Display_GPRMC_Buffer[46];
gps_speed[4]=Display_GPRMC_Buffer[46];
}
}
//获取维度
float getLat(){
return cur_lat;
}
//获取经度
float getLng(){
return cur_lng;}
5.4. HMC5883电子罗盘控制代码
其主要功能为获取小车方向与正北方向的夹角,以后简称小车方向角度,要获取值,要管脚要与单片机对应以来。主要函数有初始化函数,获取角度,和IIC通信函数。其中为电子罗盘添加修正角度。
sbit SCL=P0^0; //IIC时钟引脚定义
sbit SDA=P0^1; //IIC数据引脚定义
//初始化HMC5883****
void Init_HMC5883()
{
Single_Write_HMC5883(0x02,0x00); //
}
//获取偏移角度
double getAngle(){
Multiple_Read_HMC5883(); //连续读出数据,存储在BUF中
angle=-1; //每次置零
//---------显示X,y,z轴
x=BUF[0] << 8 | BUF[1]; //Combine MSB and LSB of X Data output register
z=BUF[2] << 8 | BUF[3]; //Combine MSB and LSB of Z Data output register
y=BUF[4] << 8 | BUF[5]; //Combine MSB and LSB of Y Data output register
angle= atan2((double)y,(double)x) * (180 / 3.14159265) + 180; // angle in degrees
angle=angle+correctCompass; //添加电子罗盘校准
angle*=10;
angle=((int)angle)%3600;
conversion(angle); //计算数据和显示
LCD1602_write_com(0x80+0x40); //设置指针
LCD1602_write_word("angle ");
LCD1602_write_data(wan);
LCD1602_write_data(qian);
LCD1602_write_data(bai);
LCD1602_write_data(shi);
LCD1602_write_data('.');
LCD1602_write_data(ge);
return angle/10;
}
/**************************************
起始信号
**************************************/
void HMC5883_Start()
{
SDA = 1; //拉高数据线
SCL = 1; //拉高时钟线
Delay5us(); //延时
SDA = 0; //产生下降沿
Delay5us(); //延时
SCL = 0; //拉低时钟线
}
/**************************************
停止信号
**************************************/
void HMC5883_Stop()
{
SDA = 0; //拉低数据线
SCL = 1; //拉高时钟线
Delay5us(); //延时
SDA = 1; //产生上升沿
Delay5us(); //延时
}
/**************************************
发送应答信号
入口参数:ack (0:ACK 1:NAK)
**************************************/
void HMC5883_SendACK(bit ack)
{
SDA = ack; //写应答信号
SCL = 1; //拉高时钟线
Delay5us(); //延时
SCL = 0; //拉低时钟线
Delay5us(); //延时
}
/**************************************
接收应答信号
**************************************/
bit HMC5883_RecvACK()
{
SCL = 1; //拉高时钟线
Delay5us(); //延时
CY = SDA; //读应答信号
SCL = 0; //拉低时钟线
Delay5us(); //延时
return CY;
}
5.5. LCD1602控制代码
其主要功能为对获取到的GPS数据进行显示,管脚要与单片机对应以来。其中函数主要包括:初始化函数,写多个字符函数,写单个字符函数,写指令函数。
//LCD1602 IO设置
#define LCD1602_PORT P1
sbit LCD1602_RS = P0^5;
sbit LCD1602_RW = P0^4;
sbit LCD1602_EN = P0^3;
//****************************************************
//写指令
//****************************************************
void LCD1602_write_com(unsigned char com)
{
LCD1602_RS = 0;
LCD1602_delay_ms(1);
LCD1602_EN = 1;
LCD1602_PORT = com;
LCD1602_delay_ms(1);
LCD1602_EN = 0;
}
//****************************************************
//写数据
//****************************************************
void LCD1602_write_data(char dat)
{
LCD1602_RS = 1;
LCD1602_delay_ms(1);
LCD1602_PORT = dat;
LCD1602_EN = 1;
LCD1602_delay_ms(1);
LCD1602_EN = 0;
}
//****************************************************
//连续写字符
//****************************************************
void LCD1602_write_word(unsigned char *s)
{
while(*s>0)
{
LCD1602_write_data(*s);
s++;
}
}
//初始化函数
void Init_LCD1602()
{
LCD1602_EN = 0;
LCD1602_RW = 0; //设置为写状态
LCD1602_write_com(0x38); //显示模式设定
LCD1602_write_com(0x0c); //开关显示、光标有无设置、光标闪烁设置
LCD1602_write_com(0x06); //写一个字符后指针加一
LCD1602_write_com(0x01); //清屏指令
}
5.6. 主程序控制代码
其功能是程序的入口,运行程序的逻辑功能。,其中包括初始化个个功能模块、与小车行驶控制算法。其中小车自己驾驶控制算法包括了两个功能,1.通过前后获取两次经纬度的值对比出小车行驶方向,与小车的行驶倾角(正北为y轴,正东为x轴)。2.通过设定的经纬度与当前经纬度进行对比,判断是否终点在小车方向与当前和终点的倾角。中和以上进行判断是否需要进行转向。
void main()
{
InitMoudle();
//check();
while(1){
navigation();
}
}
//初始化模块
void InitMoudle(){
/初始化lcd/
Init_LCD1602();
LCD1602_write_com(0x80); //指针设置
LCD1602_write_word(“Welcome to use!”);
delay200ms();
/gps串口初始化/
Uart_Init();
/舵机初始化/
InitialTimer(); //舵机初始化时间器
turnMin();//舵机归中
delay200ms();
//forward(); //电机前进
//电子罗盘初始化
Init_HMC5883();
}
//电子罗盘和gps定位
void navigation(){
//m_lat=30.4656;
//m_lng=103.5740; //103.5725
recieveLatLng();
m_angle=getAngle();
m_lat= getLat(); //当前纬度
m_lng= getLng(); //当前经度
if(m_lat==0||m_lng==0){
return ;
}
//判断电子罗盘是否正常运行
if(m_angle==-1){
return;
}
//以小车当前位置为原点,正北方向为y轴正方向,正东方向为x轴正方向
if((my_lng-m_lng)0){
stop();
return;
}
m_route =(my_lat -m_lat)/(my_lng-m_lng); //小车斜率 tan函数的值
if(m_route>0){//终点在一、三象限
forward();
if(my_lng-m_lat>0){ //终点在一象限
m_routeAngle =90- atan (m_route) * 180 / PI;
}
else if(my_lng-m_lat<0){ //终点在三象限
m_routeAngle =270- atan (m_route) * 180 / PI;
}
}
else if(m_route<0){ //终点在二、四象限
forward();
if(my_lng-m_lat>0){ //终点在一象限
m_routeAngle =90+ atan (m_route) * 180 / PI;
}
else if(my_lng-m_lat<0){ //终点在三象限
m_routeAngle =270+ atan (m_route) * 180 / PI;
}
}
else if (m_route0){ // 终点在坐标原点
stop();
return;
}
//计算小车方向和路线方向的关系,计算小车方向转动
//其中改进过程中增加了修正角度,在这个修正角度里 小车不采取操作 if((m_angle-m_routeAngle)<-180&&(m_angle-m_routeAngle)>(-360+corrected)){
turnLeft() ;
delay200ms();
delay200ms();
delay200ms();
delay100ms();
turnRight();
delay200ms();
delay200ms();
turnMin();
}else if((m_angle-m_routeAngle)<(0-corrected)&&(m_angle-m_routeAngle)>=-180){
turnRight();
delay200ms();
delay200ms();
delay200ms();
delay100ms();
turnLeft();
delay200ms();
delay200ms();
turnMin();
}
else if((m_angle-m_routeAngle)>(0+corrected)&&(m_angle-m_routeAngle)<180){
turnLeft();
delay200ms();
delay200ms();
delay200ms();
delay100ms();
turnRight();
delay200ms();
delay200ms();
turnMin();
} else if((m_angle-m_routeAngle)>180&&(m_angle-m_routeAngle)<(360-corrected)){
turnRight();
delay200ms();
delay200ms();
delay200ms();
delay100ms();
turnLeft();
delay200ms();
delay200ms();
turnMin();
} else{ //在修正角度里 小车不采取操作
turnMin();
}
delay200ms();
delay200ms();
delay200ms();
delay200ms();
delay200ms();
delay200ms();
delay200ms();
delay200ms();
delay200ms();
delay200ms();
m_lat= 0; //重置当前纬度
m_lng= 0; //重置当前经度
}
- 系统测试
系统测试与性能分析在程序最后成为一个可交付产品的过程中占有很大的地位。这章会测试的过程、方法在本系统中的应用。其中主要包括系统模块的测试(白盒测试),和系统集成测试(黑盒测试)。
6.1. 模块测试
测试环境:对程序单个模块进行测试,主要有5个模块:GPS模块、电子罗盘模块、舵机控制模块、电机驱动模块、LCD显示模块。
- GPS模块
测试方法:调用电子罗盘显示函数,观察LCD1602。
测试结果:LCD1602模块显示经纬度信息,测试成功。 - 电子罗盘模块
测试方法:调用电子罗盘显示函数,观察LCD1602。
测试结果:LCD显示小车方向角度,测试成功。 - 舵机控制模块
测试方法:调用左转、右转、归中函数,看小车行驶方向。
测试结果:小车分别左转,右转,归中,测试成功。 - 电机驱动模块
测试方法:调用小车正转、反转、制动函数,小车前进、后退、停止。
测试结果:小车分别向前,向后,制动到终点位置,测试成功。 - LCD显示模块
测试方法:调用显示函数,观察LCD1602显示。
测试结果:成功显示“welcome to use” ,测试成功。
测试总汇,如图5-2。
6.2. 系统测试
测试环境:程序组装完成。以智能小车为平台,搭载5个模块。
测试方法:预先设定小车目的地经纬度,这里设定小车目的地为西华大学东门,经纬度为103.970196,30.785864。小车放在任意位置。
测试结果:小车经过自动调整后,朝着目的地方向行驶,成功到达目的地,测试成功。
qq邮箱:741515962@qq.com