资源描述
综合课程设计报告
题目: 迷宫电脑鼠的设计
二级学院 计算机科学与工程学院
专 业 计算机科学与技术
班 级
学生姓名 学号
指导教师
时 间 2015 01 17
II
重庆理工大学综合课程设计报告
III
目 录
目 录 I
摘 要 II
1、课程设计的目的及要求 1
1.1 课程设计目的 1
1.2课程设计要求 1
2、题目分析 1
2.1 功能分析 1
2.2 性能需求分析 1
2.3 算法分析 1
3、系统设计 2
3.1系统整体设计 2
3.2硬件设计 3
3.2.1 硬件结构设计 3
3.2.2 传感器组设计 4
3.2.3 电机驱动电路设计 7
3.3软件设计 8
3.3.1 电脑鼠正常行走程序设计 8
3.3.2 电脑鼠找终点程序设计 11
3.3.3 程序设计 12
4 总结 27
4.1 所遇问题及解决办法 27
4.2 心得体会 28
摘 要
“电脑鼠”是使用单片机微控制器,传感器和机电运动部件构成的一种智能行走装置。一只电脑鼠是具有机电知识整合的基本构架,本身就像是一个智能的机器人。要在指定的迷宫中比赛,就像是一个人置身竞赛中一样,必须要靠自己的判断力,敏捷动作及正确探查周边坏境。一般来说一只电脑鼠具备有以下两个基本能力:拥有稳定且快速的行走能力;正确判断能力。
重庆理工大学综合课程设计报告
1、课程设计的目的及要求
1.1 课程设计目的
(1)了解并熟悉电子元器件焊接技术与方法。
(2)了解并熟悉电子元器件工作原理和功能特性。
(3)掌握单片机对编码电机的控制与红外发射与接收的控制。
(4)熟练运用keil软件进行单片机的C语言编程。
1.2课程设计要求
走有一定弯度、曲折度、路线单一的迷宫。
2、题目分析
2.1 功能分析
(1)迷宫电脑鼠能够在迷宫中随意穿行。
由于迷宫中有很多挡板,要使电脑鼠能够在迷宫中随意穿行,就要让电脑鼠遇到挡板的时候能够转弯找到一条可通行的路,所以就要用到用来检测挡板的传感器。还要电脑鼠能够左转、右转和前进,所以必须要写出这四个功能函数,不然电脑鼠就不能在迷宫中行走。
2.2 性能需求分析
1、迷宫电脑鼠外形合理,符合8×8迷宫场地需求。
2、迷宫电脑鼠运行稳定,能够正常在迷宫中随意穿行。
2.3 算法分析
此次迷宫电脑鼠主要用到了这几个算法:左手法则、右手法则和车头方向、转弯算法、修正算法。
转弯算法:当遇到障碍物向左转90度或者右转90度或者向后转。
修正算法:当在迷宫中走偏后能够自动修正方向。
左手法则:小车在搜过程中有两个以上的搜索方向时,优先选择向左转,其次是向前行进,最后才考虑向右转弯。
右手法则:小车在搜过程中有两个以上的搜索方向时,优先选择向右转,其次是向前行进,最后才考虑向左转弯。
车头方向:迷宫机器鼠的车头有绝对方向和相对方向之分。绝对方向:以小车刚开始运行的时候车头面向的方向作为“上”,其它方向类推。相对方向:顾名思义,相对于当前小车所朝向的方向的方向。机器鼠转弯时要修整方向为绝对方向。用数字0,1,2,3分别表示上,右,下,左,修正公式为:转弯后的绝对方向=(转弯前的绝对方向+转弯数值)% 4,如图所示。
绝对方向
转弯前的方向
转弯方向
转弯后的方向
0(上方)
向左(+3)
向左(0+3)%4 = 3
0(上方)
向右(+1)
向右(0+1)%4 = 1
0(上方)
向后(+2)
向后(0+2)%4 = 2
1(右方)
向左(+3)
向上(1+3)%4 = 0
1(右方)
向右(+1)
向下(1+1)%4 = 2
1(右方)
向后(+2)
向左(1+2)%4 = 3
2(下方)
向左(+3)
向右(2+3)%4 = 1
2(下方)
向右(+1)
向左(2+1)%4 = 3
2(下方)
向后(+2)
向上(2+2)%4 = 0
3(左方)
向左(+3)
向下(3+3) %4 = 2
3(左方)
向右(+1)
向上(3+1)%4 = 0
3(左方)
向后(+2)
向右(3+2) %4 = 1
3、系统设计
3.1系统整体设计
系统的功能函数:
延时函数功能:延时
电机驱动函数功能:启动和停止左右电机
电机初始化函数功能:初始化电机
中断函数功能:T0、T1用来计数左右电机的脉冲数;T2用来产生红外信号
系统初始化函数功能:初始化整个系统
红外传感器函数功能:当遇到障碍物时点亮LED灯
转弯函数1功能:左转和右转任意角度
转弯函数2功能:左转90度,右转90度,向后转
前进一步函数功能:电脑鼠在迷宫前进一个方格距离
主程序流程图:
3.2硬件设计
3.2.1 硬件结构设计
硬件电路部分主要由单片机最小系统电路、传感器电路、电机驱动电路构成。如图所示,是硬件电路部分结构框图。
单片机
传感器组5
传感器组4
传感器组3
传感器组2
传感器组1
38KHz载波发生器
3-8译码选择器
显示器
蜂鸣器
电机1
电机2
驱动电路1
驱动电路2
操作按键
1、微控制器
微控制器是电脑鼠的核心,可以选择单片机,若RAM需求量大或者算法复杂或者性能要求高时,需要使用ARM等高性能的微处理器。
2、传感器
传感器的作用是用来感知环境,探测电脑鼠的左、前、右是否有路可走。本设计中采用的是红外线方式,发射和接收分别受微控制器控制。由硬件电路部分结构框图可知,在电脑鼠的前、左、右、左前、右前方共有5组,其中左、右、前三组传感器是用于探测电脑鼠在当前迷宫格左、右、前三个方向上是否有支路的,左前、右前两组传感器呈45度安装,用于电脑鼠行进过程中进行姿态矫正,防止电脑鼠走偏而撞到迷宫墙。
3、显示器
显示器是用来显示当前位置等相关信息的,是电脑鼠的可选部分。
4、电源
电源用来为单片机供电,选择哪种电池,这也将影响电路的设计。
5、蜂鸣器
当电脑鼠到底终点、或是返回到起点,可以用蜂鸣器来提示,是电脑鼠的可选部分。
3.2.2 传感器组设计
(1)传感器的选择
电脑鼠有5组传感器。这5组传感器分别安装于电脑鼠的左、左前、前、右前、右5个不同的方向,其中左、右、前三组传感器是用于探测电脑鼠在当前迷宫格左右前三个方向上是否有支路的,左前、右前两组传感器呈45度安装,用于电脑鼠行进过程中进行姿态矫正,防止走偏而撞到迷宫墙。如图所示,是用于电脑鼠环境感知的传感器组电路。传感器组电路由红外发射LED和红外一体化接收头HS0038构成,红外LED由前面载波发生器产生的CLOCK信号驱动产生38KHz红外调制光。RP1为可调电阻,通过调节RP1来调节红外LED发光强度,从而调整传感器组检测迷宫墙障碍物的距离,RP1电阻越大,检测距离越近,电阻越小,检测距离越远。irT1用于控制该组传感器是否工作,连接到3-8译码选择电路。红外调制光经障碍物反射由HS0038红外一体化接收头接收,进行放大滤波、解调等处理后由irR1输出,单片机通过识别irR1位的高低电平来判断传感器前面是否有障碍物。这里只给出了一组传感器,另外四组传感器也与该组传感器相同的。电脑鼠通过对这五组传感器信息的融合,实现环境感知功能。
(2)74HC138译码器
74HC138译码器可接受3位二进制加权地址输入(A0, A1和A2),并当使能时,提供8个互斥的低有效输出(Y0至Y7)。74HC138特有3个使能输入端:两个低有效(E1和E2)和一个高有效(E3)。除非E1和E2置低且E3置高,否则74HC138将保持所有输出为高。
1、74HC138的引脚如图所示:
2、74HC138的译码/真值表如下表所示:
译码/真值表
应用:
例如A0A1A2地址为000时,74HC138输出Y0有效,从而使第一组传感器工作,而其他组传感器处于没有工作的状态。这样就可以实现单片机的3个引脚控制5个或者更多的传感器组。如图所示,是硬件电路部分3-8译码选择器电路。
(3)载波发生器
传感器组是由38KHz的红外一体化接收头和红外发射管构成的障碍感测器。为了能够让传感器组正常工作,红外发射管需要一个38KHz的方波来驱动,使红外发射管发射出调制频率与接收头接收频率匹配的红外光。如图所示,是产生38KHz方波的载波发生器电路。
(4)传感器的调试
(主要写每组传感器如何进行调试。)
1、左右两边的传感器检测是否有墙壁。
2、左前和右前45°角的两组传感器用于电脑鼠在行走过程中的微调。
3、传感器上标的1、2、3、4、5对应led的1、2、3、4、5(里面往前数)。
4、传感器的测距是通过条对应的可调电阻来实现的,可调电阻顺时针转动调近,逆时针调远传感器的测试距离。
3.2.3 电机驱动电路设计
如图所示,是用来驱动电脑鼠伺服电机的驱动电路。由于单片机I/O口电流输出能力有限,不能直接驱动电机转动。为了能让单片机控制电机运转,需要使用电机驱动电路,将单片机I/O口弱电流放大到足以驱动电机的电流。
1、L9110器件的管脚图如图所示。
2、 管脚定义如下:
3、通过L9110驱动芯片IA、IB输入的逻辑值的组合,不同高低电平的输入输出,控制电机正转、反转、停转。L9110的逻辑关系表如下表所示:
L9110逻辑关系
IA
IB
OA
OB
H
L
H
L
正转
L
H
L
H
反转
L
L
L
L
停止
H
H
L
L
停止
3.3软件设计
3.3.1 电脑鼠正常行走程序设计
电脑鼠正常行走包括直走、左转弯、右转弯和向后转弯四个功能函数。这四个功能函数中要用到T0、T1定时/计数器;所以函数中首先初始化T0、T1。T0初始化:打开总开关EA=1;开T0中断ET0=1;设定T0模式2,8位自动重装值定时计数器TMOD&=0xf6; TMOD|=0x06; 设定T0计数初值,定义中断脉冲数TH0=256-ICP;TL0=256-ICP; //启动T0计数TR0=1;T1初始化也是一样的。
为了使左右电机的转速尽可能相同,我们可以设定一个值,在这个值内,如果T0的脉冲数Count0大于T1的脉冲数Count1,就停止左电机,转动右电机;当Count0<Count1,停止右电机,转动左电机。
在左转函数中,当Count0>Count1时,停止右电机,反转左电机;当Count0<Count1时,停止左电机,正转右电机。
右转函数中,当Count0>Count1时,停止右电机,正转左电机;当Count0<Count1时,停止左电机,反转右电机。
向后转函数可以通过两次左转来实现。
在直走函数中,当Count0>Count1时,停止右电机,正转左电机;当Count0<Count1时,停止左电机,正转右电机。在直走函数中还需要一个修正函数,以便电脑鼠在行走中走歪了后能够自动调整路线走正:当检测到左前方有障碍物时,停止两个电机,关闭T0、T1并将Count0、Count1保存到tmp0、tmp1中,利用一个循环while让电脑鼠向右转一小角度直到左前方没有障碍物为止,调整方向后把tmp0、tmp1中的值还给Count0、Count1并开启T0、T1。当检测到右前方有障碍物时,停止两个电机,关闭T0、T1并将Count0、Count1保存到tmp0、tmp1中,利用一个循环while让电脑鼠向左转一小角度直到右前方没有障碍物为止,调整方向后把tmp0、tmp1中的值还给Count0、Count1并开启T0、T1。
向前走一步函数程序框图:
右转函数程序框图:
左转函数程序框图:
3.3.2 电脑鼠找终点程序设计
电脑鼠通过右手法则来探寻前进的路径:当右方有路时优先向右转,右方没路则检测前方,当前方有路就向前走,前方没路再检测左方,左方有路则向左转,左方没路的话就只有向后转了,所以四个方向的优先级为右>前>左>后。
规定电脑鼠起点车头方向为北,顺时针依次为北、东、南、西,分别用0、1、2、3代表;在左转右转和后转中,每转一次向就更新一次当前的绝对方向,然后向前行进一步并更新当前坐标,然后将当前坐标与终点坐标比较,若当前坐标为终点坐标,则蜂鸣器响一声表示已到达终点坐标;否则继续用右手法则探路直到到达终点坐标为止。
右手法则:
3.3.3 程序设计
1.头文件
#include <reg52.h>
#define ICP 35
//位定义左右电机
sbit ML1=P2^0;
sbit ML2=P2^1;
sbit MR1=P2^2;
sbit MR2=P2^3;
//指示灯接口定义
sbit LED1=P0^0;
sbit LED2=P0^1;
sbit LED3=P0^2;
sbit LED4=P0^3;
sbit LED5=P0^4;
sbit LED6=P0^5;
sbit LED7=P0^6;
sbit LED8=P0^7;
//红外地址接口定义(74HC138译码器
sbit A0=P1^2;
sbit A1=P1^3;
sbit A2=P1^4;
//红外传感器接口定义
sbit irR1=P2^5;//左外
sbit irR2=P2^6;//中
sbit irR3=P2^7;//右外
sbit irR4=P3^6;//左
sbit irR5=P3^7;//右
//按键接口定义
sbit key=P1^0;
//蜂鸣器接口定义
sbit SPEAK=P2^4;
2.符号定义
#include"hys.h"
bit irL,irR,irZ,irZL,irZR; //依次为左、右、前、左前、右前
unsigned char endX,endY,X,Y,exchangeX,exchangeY,Count0,Count1;
unsigned char now_direct; //绝对方向
unsigned char arrived; //定义到达终点坐标时要用到的的一个符号
3.延时函数代码
//在24M晶振下,延时1ms,12M倍频
void delay(unsigned char ms)
{
unsigned char X;
while(ms--)
{
X=250;
while(--X);//延时250us
X=250;
while(--X);//延时250us
X=250;
while(--X);//延时250us
X=250;
while(--X);//延时250us
}
}
4.驱动配置代码
/****************************电机驱动函数*********************************/
//左电机停止
void STOPML()
{
ML1=0;
ML2=0;
}
//右电机停止
void STOPMR()
{
MR1=0;
MR2=0;
}
//启动左电机
void RUNML(bit i)
{
if(i)
{
ML1=1;
ML2=0;
}
else
{
ML1=0;
ML2=1;
}
}
//启动右电机
void RUNMR(bit i)
{
if(i)
{
MR1=1;
MR2=0;
}
else
{
MR1=0;
MR2=1;
}
}
/*******************************电机初始化函数******************************/
void init_motor()
{
ML1=0;
ML2=0;
MR1=0;
MR2=0;
}
5.中断函数代码
//T2中断周期设定函数,最大30ms
void set_Timer2(unsigned int m)
{
TH2=RCAP2H=(65535-m)/256;
TL2=RCAP2L=(65535-m)%256;//设定T2自动重装载寄存器和计数器初值
}
void init_Timer2(unsigned int m)//中断定时获取 传感器返回的值
{
EA=1;
ET2=1;
TH2=RCAP2H=(65535-m)/256;
TL2=RCAP2L=(65535-m)%256;//设定T2自动重装载寄存器和计数器初值///捕捉/自动重载寄存器
TR2=1;
}
/************************中断函数*************************************/
//T0中断函数//右电机
void timer0() interrupt 1//外部中断1
{
//工作模式2.自动重装初值
Count0++;
}
//T1中断函数//左电机
void timer1() interrupt 3 //外部中断2
{
//工作模式2.自动重装初值
Count1++;
}
//T2中断函数
void Timer2() interrupt 5
{
static unsigned char intC=1,irNo=1;
TF2=0;//软件清除溢出中断标志位
//中断服务代码
if(intC==1)
{
switch(irNo)
{
case 1:
{
A0=0;
A1=0;
A2=0;
intC=1;
set_Timer2(2000);//发射2us
break;
}
case 2:
{
if(irR1) //如果irR1为高电平
{
irZL=0; //没有障碍物 置低电平0
LED1=1; //熄灭LED灯
}
else //如果irR1低电平
{
irZL=1; //有障碍物 置高电平1
LED1=0; //点亮LED灯
}
A0=1;
A1=0;
A2=0;
intC=1;
set_Timer2(2000);
break;
}
case 3:
{
if(irR2)
{
irZ=0;
LED2=1;
}
else
{
irZ=1;
LED2=0;
}
A0=0;
A1=1;
A2=0;
intC=1;
set_Timer2(2000);
break;
}
case 4:
{
if(irR3)
{
irZR=0;
LED3=1;
}
else
{
irZR=1;
LED3=0;
}
A0=1;
A1=1;
A2=0;
intC=1;
set_Timer2(2000);
break;
}
case 5:
{
if(irR4)
{
irL=0;
LED4=1;
}
else
{
irL=1;
LED4=0;
}
A0=0;
A1=0;
A2=1;
intC=1;
set_Timer2(2000);
break;
}
case 6:
{
if(irR5)
{
irR=0;
LED5=1;
}
else
{
irR=1;
LED5=0;
}
A0=1;
A1=1;
A2=1;
intC=2;
set_Timer2(20000);
break;
}
}
if(irNo<6)irNo++;
else irNo=1;
}
else
{
intC--;
}
}
6.系统初始化函数代码
/*********************************************************************/
//系统初始化函数
void init_system()
{
//起点坐标初始化
X=0;
Y=0;
//设置终点坐标
endX=7;
endY=7;
//小车的当前方向初始化
now_direct=0;
//变量初始化
Count0=0;
Count1=0;
init_motor();
//初始化T2,自动传感器采样
init_Timer2(2000);
arrived=0;
key=0;
}
7.红外传感器
void ir_Test()
{
if(irZL)
{
LED1=0;
}
else
{
LED1=1;
}
if(irL)
{
LED4=0;
}
else
{
LED4=1;
}
if(irZ)
{
LED2=0;
}
else
{
LED2=1;
}
if(irZR)
{
LED3=0;
}
else
{
LED3=1;
}
if(irR)
{
LED5=0;
}
else
{
LED5=1;
}
//delay(100);
}
8.转弯函数
/*******************向左转函数(转的角度通过参数控制)********************/
void left(unsigned char m)
{
//T0初始化
EA=1; //打开总开关
ET0=1;//开T0中断
TMOD&=0xf6;
TMOD|=0x06;//设定T0模式2,8位自动重装值定时计数器
TH0=256-ICP;
TL0=256-ICP;//设定T0计数初值,定义中断脉冲数
TR0=1;//启动T0计数
//T1初始化
EA=1; //打开总开关
ET1=1;//开T1中断
TMOD&=0x6f;
TMOD|=0x60;//设定T1模式2,8位自动重装值定时计数器
TH1=256-ICP;
TL1=256-ICP;//设定T1计数初值,定义中断脉冲数
TR1=1;//启动T1计数
Count0=0;
Count1=0;
while((Count0<m)||(Count1<m))
{
if(Count0<Count1)
{
STOPML();//左轮停止
RUNMR(1);//右轮正转
}
else
{
STOPMR();//右轮停止
RUNML(0);//左轮反转
}
}
STOPML();
STOPMR();
}
/******************向右转函数(转的角度通过参数控制)****************/
void right(unsigned char m)
{
//T0初始化
EA=1; //打开总开关
ET0=1;//开T0中断
TMOD&=0xf6;
TMOD|=0x06;//设定T0模式2,8位自动重装值定时计数器
TH0=256-ICP;
TL0=256-ICP;//设定T0计数初值,定义中断脉冲数
TR0=1;//启动T0计数
//T1初始化
EA=1; //打开总开关
ET1=1;//开T1中断
TMOD&=0x6f;
TMOD|=0x60;//设定T1模式2,8位自动重装值定时计数器
TH1=256-ICP;
TL1=256-ICP;//设定T1计数初值,定义中断脉冲数
TR1=1;//启动T1计数
Count0=0;
Count1=0;
while((Count0<m)||(Count1<m))
{
if(Count0<Count1)
{
STOPML();//左轮停止
RUNMR(0);//右轮反转
}
else
{
STOPMR();//右轮停止
RUNML(1);//左轮正转
}
}
STOPML();
STOPMR();
}
/**********************************向左转、右转、转身*******************/
void turnleft()//左转90度并更新当前绝对方向
{
left(35);
now_direct=(now_direct+3)%4;//修正当前方向为绝对方向
}
void turnright()//右转90度并更新当前绝对方向
{
right(35);
now_direct=(now_direct+1)%4;//修正当前方向为绝对方向
}
void turnback()//向后转更并新当前绝对方向
{
left(72);
now_direct=(now_direct+2)%4; //修正当前方向为绝对方向
}
9.前进一步函数
/******************走一步函数(每走一步就判断是否到达终点)*************************************/
void Go_one_step()
{
unsigned char tmp0,tmp1;
//T0初始化
EA=1; //打开总开关
ET0=1;//开T0中断
TMOD&=0xf6;
TMOD|=0x06;//设定T0模式2,8位自动重装值定时计数器
TH0=256-ICP;
TL0=256-ICP;//设定T0计数初值,定义中断脉冲数
TR0=1;//启动T0计数
//T1初始化
EA=1; //打开总开关
ET1=1;//开T1中断
TMOD&=0x6f;
TMOD|=0x60;//设定T1模式2,8位自动重装值定时计数器
TH1=256-ICP;
TL1=256-ICP;//设定T1计数初值,定义中断脉冲数
TR1=1;//启动T1计数
Count0=0;
Count1=0;
while((Count0<86)||(Count1<86))
{
//修正函数
if(irZ)
{
break;
}
if(irZL) //如果向左偏
{
STOPML();
STOPMR();
TR0=0; //关闭T0计数
TR1=0; //关闭T1计数
tmp0=Count0; //将Count0中的值暂存在tmp0中
tmp1=Count1; //将Count1中的值暂存在tmp1中
while(irZL) //矫正
{
right(1);
}
Count0=tmp0; //将tmp0中的值还给Count0
Count1=tmp1; //将tmp1中的值还给Count1
TR0=1; //启动T0计数
TR1=1; //启动T1计数
}
if(irZR) //如果向右偏
{
STOPML();
STOPMR();
TR0=0; //关闭T0计数
TR1=0; //关闭T1计数
tmp0=Count0; //将Count0中的值暂存在tmp0中
tmp1=Count1; //将Count1中的值暂存在tmp1中
while(irZR) //矫正
{
left(1);
}
Count0=tmp0; //将tmp0中的值还给Count0
Count1=tmp1; //将tmp1中的值还给Count1
TR0=1; //启动T0计数
TR1=1; //启动T1计数
}
//前进
if(Count0>Count1)
{
STOPMR();//右轮停止
RUNML(1);//正转左轮
}
else
{
STOPML();//左轮停止
RUNMR(1);//正转右轮
}
}
xy_repair(); //更新当前坐标
arrive(); //判断是否到达指定坐标
init_motor(); //初始化电机
}
10.右手法则
/*****************************右手法则*************************************/
void righthand()
{
switch(now_direct)
{
case 0: // 当前方向向北
{
if(!irR) //如果右边没有障碍
{
turnright(); //先向右转并更新绝对方向
Go_one_step(); //再前进一步并且更新坐标并判断是否到达指定坐标
break;
}
if(!irZ) //如果前方没有障碍
{
Go_one_step(); //向前走一步并且更新坐标并判断是否到达指定坐标
break;
}
if(!irL) //如果左方没有障碍物
{
turnleft(); //先左转并更新绝对方向
Go_one_step(); //再前进一步并且更新坐标并判断是否到达指定坐标
break;
}
else //如果左、右、前方都有障碍物
{
turnback(); //先向后转并更新绝对方向
Go_one_step(); //再前进一步并且更新坐标并判断是否到达指定坐标
break;
}
}
case 1: //当前方向向东
{
if(!irR)
{
turnright();
Go_one_step();
break;
}
if(!irZ)
{
Go_one_step();
break;
}
if(!irL)
{
turnleft();
Go_one_step();
break;
}
else
{
turnback();
Go_one_step();
break;
}
}
case 2: //当前方向向南
{
if(!irR)
{
turnright();
Go_one_step();
break;
}
if(!irZ)
{
Go_one_step();
break;
}
if(!irL)
{
turnleft();
Go_one_step();
break;
}
else
{
turnback();
Go_one_step();
break;
}
}
case 3: //当前方向向西
{
if(!irR)
{
turnright();
Go_one_step();
break;
}
if(!irZ)
{
Go_one_step();
break;
}
if(!irL)
{
turnleft();
Go_one_step();
break;
}
else
{
turnback();
Go_one_step();
break;
}
}
}
}
11.主函数
void main()
{
char s1=key; //按键开关
init_system(); //初始化系统
if(s1) //按下开关键
{
delay(500);
while(1)
{
// ir_Test();//可以不调用这个函数
righthand(); //右手法则寻路
if(arrived==1) //到达终点
{
arrived=0;
turnba
展开阅读全文