寻线式电脑鼠的设计
人工智能电脑鼠搜迷宫实验

北京科技大学实验报告学院:自动化学院专业:智能科学学技术班级:姓名:学号:实验日期:2017年11月6日实验名称:人工智能电脑鼠搜迷宫实验实验目的:掌握电脑鼠的基本操作及智能搜索算法操作。
实验仪器:KEIL MDK、电脑鼠、J-Link、VS实验原理:所谓“电脑鼠”,英文名叫做Micromouse,是一种具有人工智能的轮式机器人,是由嵌入式微控制器、传感器和机电运动部件构成的一种智能行走装置的俗称。
当电脑鼠放入起点,按下启动键之后,他就必须自行决定搜索法则并且在迷宫中前进,转弯,记忆迷宫墙壁资料,计算最短路径,搜索终点等功能。
电脑鼠更结合了机械、电机、电子、控制、光学、程序设计和人工智能等多方面的科技知识。
本实验中,通过红外传感器检测电脑鼠所处位置状态,通过智能算法保存地图并实现地图的搜索,通过pid等控制算法控制电机,达到电脑鼠搜索迷宫并计算最短路径等功能。
实验内容与步骤:实验内容1)KEIL MDK的安装2)电脑鼠硬件的检查及调整3)智能搜索算法的编写4)算法的调试与优化5)实验结果实验步骤(一)KEIL MDK的安装1双击运行Ke i l MDK 4.12 安装程序,出现软件安装界面,如图所示:2点击Next,勾选安装协议;3选择安装路径,建议安装在C 盘,运行速度快些4 填入用户信息,个人用户随意填入即可;点击Next 就进入实质的安装过程了,Wait for a Whle…5点击Finish,Keil MDK 就完成安装了,可以发现桌面上生成了名为“Keil uVis ion4”的可执行文件快捷方式。
(二)检查和调整电脑鼠的硬件1.电机检查:在电脑鼠程序文件中找到Motor.c文件,直接为两侧电机赋相同的速度值,用G-link连接电脑鼠和电脑,传入程序,打开电脑鼠放在地面上,如果电脑鼠能正常直线行进,即证明两侧电机正常工作。
如果有电机有问题,拆下原来的电机换新的再次进行电机检查即可。
2.传感器检查:用G-link连接电脑鼠和电脑,打开传感器查询模式,用手逐渐靠近每一个传感器,如果相应的传感器值由小变大,那么此传感器工作正常。
一种人工智能迷宫穿梭电脑鼠

一种人工智能迷宫穿梭电脑鼠作者:龙行杜强王宁杨荃文来源:《现代信息科技》2021年第01期摘要:作為微型轮式机器人,电脑鼠能够自主地求解迷宫。
文章对电脑鼠车身结构进行了研究,通过加入新型双层吸盘装置增大压力,提高电脑鼠在迷宫穿梭时的速度,降低电脑鼠高速运行下打滑的风险;对算法控制等方面的研究与改进,电脑鼠能够在迷宫中找到从起点到终点的最佳路径。
在当今智能社会的发展趋势下,电脑鼠具有广泛的实用价值,其技术可以推广到自动导航和避障机器人等多个行业。
关键词:轮式机器人;电脑鼠;结构设计;算法控制中图分类号:TP301.6;TP242.6 文献标识码:A 文章编号:2096-4706(2021)01-0168-04An Artificial Intelligence Maze of Shuttle MicroMouseLONG Hang,DU Qiang,WANG Ning,YANG Quanwen(School of Information Science and Engineering,Tianshi College,Tianjin 301700,China)Abstract:As a micro-wheeled robot,micromouse can solve maze independently. In this paper,the body structure of the micromouse is studied. By adding a new double-layer sucker device to increase the pressure,the speed of the micromouse in the maze shuttle is improved,and the risk of the micromouse slipping at high speed is reduced;through the research and improvement ofalgorithm control,the micromouse can find the best path from the beginning to the end in the maze. Under the trend of today’s intelligent society,the micromouse has a wide range of practical value,and its technology can be extended to industries such as automatic navigation and obstacle avoidance robots.Keywords:wheeled robot;micromouse;structure design;algorithmic control0 引言电脑鼠是一个基于微处理器控制的、集传感器与控制于一体的、能够自动穿梭迷宫的智能微型机器人[1]。
鼠标设计课程设计

图13 草图方案1
图14 草图方案2
10
《产品设计》 课程设计
草图绘制
方案3:设计的想法来源于轨迹球鼠 标的设计,由于轨迹球鼠标可以不 用移动鼠标底座,不受距离的影响 ,因此可以当遥控器使用,对其进 行了功能改进,可以设计多个快捷 按钮,让鼠标实现多种功能的智能 鼠标;如图15所示。 方案4:想法来源于拟态仿生设计方法, 模拟青蛙的造型,设计不对称得直立鼠 标的形态,使用的舒适性也很强;如图 16所示。
产品设计课程设计基于以上的分析我们把消费人群定位为年龄为1635岁的年轻人因为他们年轻有活力喜欢个性张扬的东西易于接受新事物也易于学会使用技术含量高的新产品因此在造型上要新颖有个性和吸引力色彩可以艳丽张扬一点在结构上也可以推陈出新无需担心他们会不会使用给我们的设计提供了一个广阔的空间可以天马行空任意发挥这样有利于提高我们的想象力创造出很多新的设计想法来
1
《产品设计》 课程设计
市场调查
资料收集
鼠标是一种移动光标和实现选择操作的计算机输入设备。随着“所见即 所得”的环境越来普及,使用鼠标的场合越来越多。它的基本工作原理是: 当移动鼠标器时,它把移动距离及方向的信息转换成脉冲送到计算机,计算 机再把脉冲转换成鼠标器光标的坐标数据,从而达到指示位置的目的。 目前市场上流行的鼠标主要有三种,机械鼠标(半光电鼠标)、轨迹球 鼠标和光电鼠标。每种鼠标的特点、用途和选购上都稍有不同。
图3 遥控式轨迹球
图4 轨迹球鼠标
4
《产品设计》 课程设计
市场调查
(3)光电式鼠标: 光电鼠标产品按照其年代和使用的技术可以分为两代产品,其共同的特点 是没有机械鼠标必须使用的鼠标滚球。如图5和图6所示。 第一代光电鼠标由 光断续器来判断信号,最显著特点就是需要使用一块特殊的反光板作为鼠标 移动时的垫。
迷宫电脑鼠的硬件设计简介

单独翘囊两者缀合成不阏性能的交换黼络结构来实现。根据交换网络入端 信道数与出端倍道数的不同,可以把交换网络分成集线器、扩线器和分配 嚣。
基于ARM的电脑鼠控制系统研究

L S 0 、L S 0 、L S 1 或 者 单 片 机 微 控 制 M3 1 1 M3 1 2 M3 6 5 器 ,其 红 外 检 测 模 块 采 用 了 一 体 式 红 外 传 感 器 ,
迷 宫 的信息 以有效 的数 据结构 存储 ,微 控制器 根据 这 些记 录信息 运用迷 宫 高效算 法找 到一 条最优 化路 径 ,从 而实现从起 点到终 点的最 大化 冲刺 。
2 硬 件 电路 设 计
为 完 成 迷 宫 探 测 和 冲刺 任 务 。 电脑 鼠需 具 备 以下 各 功 能模 块 :A M微 处 理 器 作 为控 制 核 心 协 R 调 各 功 能 模 块 正 常 工 作 : 电机 及 驱 动模 块 实 时 控
播 距 离 相 对 越 远 ,在 本 设 计 中 由于 迷 宫 墙 壁 之 间
图4 红 外 检 测 电路
3 软 件 系 统 设 计
软 件 模 块 是 系统 的重 要 组 成 部 分 。 电脑 鼠通
距 离 1 .c ( 68m 单元 格 1c 8 m,墙 壁厚 度 1 c ,而 电 . m) 2 脑 鼠 的宽 度 一 般 为 1c 0 m左 右 ,车 体 距 两 边 墙 体 的 距 离 只有 3 m左右 。所 以正左 方 和正 右 方发 射 频 率 c 选 择 为3 k z 3 H ,左 前 方 和 右 前 方 发 射 3 k z 5 H ,正 前 方 距离 最远 ,发射 频率 为3 k z 8 H 。具体 如 图3 所示 。
正 前 、 正 左 、正 右 以及 正 前 方 两 个 4 度 斜 角 外 , 5
频 率 为7 MHz 2 ,内置 高速存 储 器 f 高达 1 8 字 节 的 2K
基于STM32的电脑鼠机器人设计与开发

基于STM32的电脑鼠机器人设计与开发作者:蒙飚严健平来源:《电子技术与软件工程》2016年第06期摘要电脑鼠是一种四轮车形状且具有人工智能的小型机器人,针对电脑鼠体积小、实时性要求高等特点,采用高性能的ARM Cortex-M3架构内核的STM32系列处理器作为电脑鼠硬件控制核心,优化机器人行走和搜寻迷宫控制算法,通过精密红外传感器和执行电机,实现了电脑鼠性能的极大提升。
【关键词】STM32 电脑鼠机器人电脑鼠机器人是一种能够在迷宫中行进、位置记忆、搜寻终点和优化路径等功能,按照电脑鼠竞赛规则,机器人必须在陌生与未知的迷宫环境中以最快速度及最短时间到达终点完成比赛任务以获得胜利。
本文研究的电脑鼠机器人选择了高性能的32位ARM Cortex-M3架构内核的处理器作为控制核心设计了电脑鼠机器人的软硬件系统,实现了电脑鼠机器人系统的稳定快速行走能力、记忆迷宫搜寻轨迹能力和优化最短执行路径能力,相比传统基于8位单片机的电脑鼠系统,极大提升了系统整体性能,同时能够借助本文研究的电脑鼠系统设计案例,进而研究与发明更加复杂的机械控制系统。
1 电脑鼠机器人整体设计方案电脑鼠机器人软硬件系统由基于STM32的核心处理器、电源稳压电路系统、传感器系统、行走电机执行系统、液晶显示系统和无线网络系统六个子模块组成,其中基于STM32的核心处理器子模块是整个电脑鼠机器人的控制中心,负责与其它五个子模块的信息传输,并运行整体系统的软件程序,实现电脑鼠的流程控制、运算优化和数据存储;电源稳压电路系统负责给系统硬件提供稳定可靠的电源,传感器系统让电脑鼠机器人能够感知迷宫周围环境,行走电机执行系统能让电脑鼠机器人快速直行或转弯,液晶显示系统可以通过屏幕让人们获得机器人的各种状态信息,无线网络系统能实现电脑鼠机器人与远程计算机的联网。
电脑鼠机器人整体结构示意图如图1所示。
2 电脑鼠机器人硬件设计电脑鼠机器人的硬件系统核心处理器采用ST公司的STM32F103R8T6,它的时钟频率最高可达72MHz,内置64K的Flash、20K的RAM、12位AD、4个16位定时器、3路USART 通讯口等多种资源,具有极高的性价比。
电脑鼠走迷宫竞赛ppt教材

电脑鼠 |基于LM3S615微控制器
电脑鼠走迷宫竞赛
• 电脑鼠迷宫竞赛的计分规则说明
启动
迷宫时间
运行时间 返回到起点
迷宫时间:电脑鼠激活到每次运行开始的那段时间 运行时间:电脑鼠从起点走到终点的时间
! 碰成触绩:=电迷脑宫鼠时在间运÷行30过+程运中行若时要间手-动奖辅励助时,间则
为碰触(,非此碰次触运)行将失去 10s的奖励时间。电脑鼠 能从终点自动返回到起点,若要手动放回起点, 也视为“碰触”,按碰触的规则进行处理。
电脑鼠 |基于LM3S615微控制器
电脑鼠的简介
LM3S615 ARM cortex-M3内核
• 功耗低 • 具有门数目少 (价格低) • 调试成本低 • 中断延迟短 • 中断响应快速且支持多级中断嵌套 • 处理器采用先进的ARMv7-M架构
电脑鼠 |基于LM3S615微控制器
• 传感器
– 位置传感器 – 惯性传感器 – 距离传感器
MicroMouse615迷宫电脑鼠
——基于Cortex-M3
1234567
电脑鼠 电脑鼠 电脑鼠 电脑鼠 简介 走迷宫竞赛 走迷宫演示 走迷宫算法
走迷宫 电脑鼠 电脑鼠 标准套件 调试例程 传感器校正
电脑鼠 |基于LM3S615微控制器
电脑鼠的简介
• 电脑鼠是一种具有人工智能的轮式机器人
» 它是多学科的交叉结合的结晶
• 光电接收管
– IRM8601S
• PSD器件
– GP2D12
• CCD • 超声波
电脑鼠的简介
电脑鼠 |基于LM3S615微控制器
• 电机
– 步进电机 – 直流电机
• 减速 • 速度反馈
电脑鼠的简介
迷宫电脑鼠控制系统设计

方法文献标识码:B文章编号:1003—0492(2009)07—0080·03中图分类号:TP275迷宫电脑鼠控制系统设计DesignofMicro—mouseControlSystem曾璐(1983.)女,江西赣州人,江西理T大学应用科学学院教师,研究方向为过程控制和嵌入式系统。
摘要:电脑鼠实际上是集传感与控制于一体的,能够自动穿越迷宫的微型机器人。
本课题结合模拟电路、数字电路知识以及传感器知识,制作出一个性能优良的电脑鼠,在迷宫中找到一条最优路径,走出迷宫。
根据国际标准迷宫电脑鼠的比赛规则,通过各种方案的对比,确定在本文中采用NXP公司ARM7LPC2138作为控制核心,将新必的群智能算法运用到迷宫电脑鼠中。
关键词:最优路径、迷宫,电脑鼠,ARM、蚁群算法Abstract:Micro-mouseinfactbeingmicro-robotwithintegratedandcontroller,whichiscontrolledbythemicroprocessor,canautomaticallytraversemaze.Combiningwithanalogcircuits,digitalcircuitsandknowledge,weconstructfineperformancemicro-moosethatfindoptimalpathinthemaze.Inaccordancewithinternationalmazemicro-mousecompetitionstandards,comparedwithsomedifferentschemes,itmakescertainthatusingARM7LPC2138controlapplytheintelligentalgorithmsinmazemiero-mouse.Keywords:optimalpath;maze;micro-mouse;ARM;Antcolonyalgorithm智能机电鼠又称电脑鼠,电脑鼠(micromouse)是一只迷人的人工智慧鼠,它不但有锐利的眼睛和灵活的双脚,还有聪明的头脑来控制眼睛和双脚,使眼睛和双脚能够同心协力,互相配合,以达成唯~的目标——走出迷宫。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
一、任务和总体设计1、任务要求要求设计一个寻线型电脑鼠,能够在8×8的迷宫中搜索路径并且根据所搜寻的路线走出最短路径。
其中迷宫由25cm的黑线组成。
电脑鼠第一次进入迷宫和返回迷宫时,可以循着黑线走到终点并记录迷宫信息,第二次进入迷宫时,根据第一次所记录的迷宫信息选择最短路径冲刺到终点。
2、总体设计硬件部分主要由传感器,单片机,电机所组成。
传感器采用红外传感器,由发射管和接收管组成,可以探测迷宫中黑线。
单片机采用STC15W413AS芯片,用于编写程序。
电机由单片机产生的PWM以及L9110芯片进行驱动。
软件部分主要由产生占空比函数,电脑鼠在迷宫中搜寻路径法则,记录迷宫信息,测速盘计数组成。
电脑鼠搜寻迷宫时按照左手法则进行搜寻,根据测速盘的计数得到迷宫坐标,用8×8的数组对迷宫信息进行储存。
第一次搜寻时,对死路和走得通的路进行标定,第二次走时,仍然按照左手法则进行,但不走第一次标定的死路。
由此达到在迷宫中走最短路径的目的。
二、硬件设计1、设计步骤设计原理图后生成PCB板后进行布线。
根据PCB板将元件焊上。
将轮子,轴,轴承以及电机,齿轮进行组装,调整传感器角度。
测试电路。
2、主控模块包括STC15W413AS芯片以及连接电脑的下载部分。
原理图:STC15W413AS芯片中包括中央处理器(CPU)、程序存储(Flash)、数据存储器(SRAM)、定时器/计数器、掉电唤醒专用计时器、I/O口、高速A/D转换(30万次/秒)、比较器、看门狗、高速异步串行通信端UART、CCP/PWM/PCA、高速同步串行端口SPI、片内高精度R/C时钟以及高可靠复位等模块。
单片机内部结构:管脚图:3、电机驱动模块主要运用L9110芯片和两个74HC00芯片进行电机驱动。
原理图:(1)L9110:L9110 是为控制和驱动电机设计的两通道推挽式功率放大专用集成电路器件,将分立电路集成在单片IC 之中,使外围器件成本降低,整机可靠性提高。
该芯片有两个TTL/CMOS兼容电平的输入,具有良好的抗干扰性;两个输出端能直接驱动电机的正反向运动,它具有较大的电流驱动能力,每通道能通过800mA 的持续电流,峰值电流能力可达1.5A;同时它具有较低的输出饱和压降;内置的钳位二极管能释放感性负载的反向冲击电流,使它在驱动继电器、直流电机、步进电机或开关功率管的使用上安全可靠。
应用电路:管脚图:(2)74HC00:该芯片是输入端四与非门。
4、测速模块运用测速盘和两个侧向发射接收管。
原理图:实物图:5、传感器模块运用五个LED红外发射管和LM339和LM393芯片。
原理图:实物图:(1)LM339LM393是四电压比较器集成电路。
该电路的特点如下:工作电源电压范围宽,单电源、双电源均可工作,单电源: 2~36V,双电源:±1~±18V;消耗电流小, Icc=1.3mA;输入失调电压小,VIO=±2mV;共模输入电压范围宽, Vic=0~Vcc-1.5V;输出与TTL,DTL,MOS,CMOS 等兼容;输出可以用开路集电极连接“或”门;采用双列直插14 脚塑料封装(DIP14)和微形的双列14 脚塑料(SOP14)内部结构:(2)LM393与LM339类似。
内部结构:三、软件设计程序总流程图:软件部分主要是由以下三个部分组成。
(1)、电机驱动部分PWM产生函数驱动电机,通过调节占空比进行调速,通过控制四个I/O口来控制电机的正反转以及停转。
根据芯片以及PCB板控制单片机的CCP_S0,CCP_S1为0X20和0X10。
电脑鼠转弯和直走时用不同速度进行控制。
同时在转弯和直线时,采用不同的占空比调速,使得电脑鼠在行走过程中速度能在快的同时达到稳定的效果。
//------------------PWM初始化函数---------------------//void PWM_Init(){ ACC = P_SW1;ACC &= ~(CCP_S0|CCP_S1);ACC |= CCP_S0;P_SW1 = ACC;CCON = 0;CL = 0;CH = 0;CMOD = 0x02;CR=1;}//------调整速度函数-----------//void speed(bit a,bit b,bit c,bit d){ I1=a;I2=b;I3=c;I4=d;PCA_PWM0 = 0X00;CCAP0H = CCAP0L =46;CCAPM0 = 0x42;PCA_PWM1 = 0X00;CCAP1H = CCAP1L =51;CCAPM1 = 0x42;}(2)、中断产生部分中断用于测速盘测速,用两个中断源进行控制,分别用于左轮计数和右轮计数。
根据测速盘转过的圈数,中断计数的数字判断电脑鼠是否走过一格,根据走过的格子进行坐标的加减。
//----------------外部中断初始化函数---------------//void Exti_InterruptInit(){//----------INT0--------------------------//IT0=1;EX0=1;//----------INT1-------------------------//IT1=1;EX1=1;EA=1; //所有中断开放}//--------------外部中断0 左轮计数器------------//void Exit0_LeftWheel() interrupt 0{ EX0=0;if(left_count<38){ left_count++; }else{ left_count=0;}EX0=1;}(3)、探测路径部分电脑鼠沿着黑线走的同时,进行路径的记忆,将走过的路的坐标标记为0xfa,将死路标记为0xff。
没有走过的路标记为0x00。
将路径信息存储在一个8×8数组中,探测路径运用左手法则进行探路到终点后返回。
时间最短迷宫算法的基本思路:所谓时间最短是指电脑鼠在迷宫内前进,如果遇到交叉则按一定规则选择方向,如果是死路则回退,直到找到终点为止,这种方式的行走路径长度不一定是最短的,但是它的优点在于不必要遍历整个迷宫,只要找到终点就停止,所以这种算法所花费的时间是最短的。
电脑鼠从起点开始在单元格内行走,如果最后无路可走,则该路为死路,则退回并标记此路不通,然后在沿令一个方向行走。
电脑鼠在任一单元格内,可能的行走方向最多只有三个(前、左、右),如果有二个或二个以上的可能行走方向,称为交叉,遇有交叉时,由于有多个可以行走的方向,在行走方向的选择上用左手法则(遇有交叉时,以左边为优先的前进方向,然后是直线方向、右边方向)。
在第一遍探测结束之后,按下Rstar_Key,根据第一次探测之后的8×8矩阵走最短路径,标记为死路的地方不走。
走到终点之后停下来。
四、结果1、最终结果电脑鼠可以循着黑线按照左手法则走到终点,但是由于传感器的灵敏度以及光照影响,电脑鼠受外界光线影响很大。
光线强时,电脑鼠无法以比较快的速度进行寻线。
传感器受到外界红外光线的干扰,在转弯时会出现错乱。
由于电脑鼠的左右测速盘部分只有一个右测速盘正常工作。
运用右测速盘进行坐标的标定,发现在直路时,无法进行坐标的修改,所以会造成较大的误差。
2、实物图五、总结本次课程设计从原理图到PCB设计再到硬件设计然后软件设计,最后是软硬件的调试修改。
每一个步骤都认真仔细地参与完成。
在硬件部分遇到了许多问题,尤其是传感器部分的问题,原因是对各个元件以及芯片的不熟悉,导致走了许多弯路,犯了许多的错误。
在不断地调试,不断地发现问题以及解决问题过程中,不仅解决了鼠的问题,同时提升了自己的能力。
软件部分的调试是分开来各个部分进行调试,首先调试PWM的产生部分,测试电机的驱动情况。
在PWM程序测试时,调整鼠的机械部分,使得两轮的速度达到相对一致,能够基本走直线。
然后调整传感器部分,根据传感器输出信号写程序让鼠能够沿着黑线走,在转弯处能够按照左手法则进行转弯。
在这个过程中,出现了许多硬件方面的问题,尤其是传感器角度与灵敏度以及电机速度方面的问题。
在无数次地试验中最终得以让电脑鼠循着黑线前进。
在最短路径方面,运用两个LED灯进行坐标的测试标定,运用右轮计数器以及中断进行坐标测定。
但最终由于硬件原因无法精准计数,由于时间原因,最终没能实现最短路径。
在制作电脑鼠过程中,花费了许多的时间与精力。
在每一个部分都遇到了十分多的问题。
但每一次解决问题的欣喜都让我们受益匪浅。
在课程设计过程中,更加深了我们对于单片机的了解,在实践中学会了硬件设计与硬件设计。
深入学习和掌握了如何运用Altium Designer设计原理图和PCB图,如何运用Keil软件进行单片机的编程,如何在出现问题时,对软件和硬件进行问题的排除。
虽然最后我们没能实现最短时间,但对于这一功能也做了十分大的努力,最后发现硬件问题难以解决,这也为以后的设计积累了经验。
在这过程中深入了解了迷宫算法,坐标的确定以及调整。
总之,最后我们较好地完成了课程设计任务,在设计过程中受益匪浅。
,六、附录1、原理图2、PCB图3、代码#include "reg51.h"#include "intrins.h"//-------------------------变量声明---------------------------------------//typedef unsigned char BYTE;typedef unsigned int WORD;typedef unsigned char u8;typedef unsigned int u16;#define FOSC 33177600L#define F38_4KHz (256-FOSC/2/12/40000)#define SYSCLK 33177600L#define TIMSEND 65536-SYSCLK/12/1000#define TIMKEEP 65536-SYSCLK/12/1000#define CCP_S0 0x20#define CCP_S1 0x10sfr P5 = 0XC8;sbit Left_Detector = P1^7 ;sbit Right_Detector = P1^3 ;sbit Left_Front_Detector = P1^6 ;sbit Right_Front_Detector = P1^4 ;sbit Front_Detector = P1^5 ;static bit comeback; //为0时搜索为1时返回static bit senddir; //senddir=0 发送左右前OR senddir=1 发送左前右前static bit startkey;static u8 mouseface; //车的面向方向u16 left_count;u16 right_count;u8 adflg; //调整标志位当adflg=0时没有调整过当adflg=1时有调整过static u8 leftbuf; //保存车左面是否有障碍static u8 frontbuf; //保存车前面是否有障碍static u8 rightbuf; //保存车右面是否有障碍enum {IDLE=0,SEARCH=1,RETURN=2,ADJUST=3,OVER=4}task,taskbuf;struct {signed char cX;signed char cY;} mouselocate,mousenext; //micromouse 当前位置u8 map[8][8]; //保存地图信息表const bit ENABLE=1;const bit DISABLE=0;#define SPEED_INIT 0x9c //电机最初速度#define FACE_NORTH 0 //车头部面向北边#define FACE_SOUTH 2 //车头部面向南边#define FACE_WEST 3 //车头部面向西边#define FACE_EAST 1 //车头部面向东边#define MOUSERIGHT 1 //车右边#define MOUSEFRONT 2 //车前边#define MOUSELEFT 3 //车左边sbit I1=P1^0;sbit I2=P2^7;sbit I3=P2^4;sbit I4=P2^3;sbit Rstart_Key = P5^5 ;sbit Start_Key = P5^4 ;sbit led1=P5^4;sbit led2=P5^5;//------------------公有寄存器定义-------------//sfr AUXR = 0X8E ;sfr WAKE_CLKO = 0X8F;//------------------PWM数据类型----------------//typedef enum {PWM0=0,PWM1=1,PWM2=2}pwmx;/******************************************************************************************************** *****function name :void Timer1_Cmd(bit cmd)*param :1bit cmd*return value :none*description :enable or disable the timer1 counter********************************************************************************************************* ***/void Timer1_Cmd(bit cmd){if(cmd==ENABLE){TR1=1;}else if(cmd==DISABLE){TR1=0;}}/******************************************************************************************************** *****function name :void Timer1_Interrupt_Init()*param :none*return value :none*description :configure the timer1 interrupt********************************************************************************************************* ***/void Timer1_Interrupt_Init(void){ET1=1;PT1=0;EA=1;}/******************************************************************************************************** *****function name :void Timer1_Rload(u16 count)*param :16 bits count number*return value :none*description :update the Timer TH1 and TL1 register********************************************************************************************************* ***/void Timer1_Reload(u16 count){TL1=count;TH1=count>>8;}//---------------PWM寄存器定义-----------------//sfr P_SW1 = 0xA2;sfr CCON = 0xD8;sbit CCF0 = CCON^0;sbit CCF1 = CCON^1;sbit CR = CCON^6;sbit CF = CCON^7;sfr CMOD = 0xD9;sfr CL = 0xE9;sfr CH = 0xF9;sfr CCAPM0 = 0xDA;sfr CCAP0L = 0xEA;sfr CCAP0H = 0XFA;sfr CCAPM1 = 0xDB;sfr CCAP1L = 0xEB;sfr CCAP1H = 0xFB;sfr CCAPM2 = 0xDC;sfr CCAP2L = 0xEC;sfr CCAP2H = 0xFC;sfr PCA_PWM0 = 0xf2;sfr PCA_PWM1 = 0xf3;sfr PCA_PWM2 = 0xf4;//------------------PWM初始化函数---------------------//void PWM_Init(){ACC = P_SW1;ACC &= ~(CCP_S0|CCP_S1);ACC |= CCP_S0;P_SW1 = ACC;//CCP_S0,CCP_S1[0,1]→[P0_2,P1_2,P2_2]//其余I/O口详见芯片手册CCON = 0;CL = 0;CH = 0;CMOD = 0x02;CR=1;}//------调整函数----f_pwm=PCA_clk/256-------//void speed(bit a,bit b,bit c,bit d){ I1=a;I2=b;I3=c;I4=d;PCA_PWM0 = 0X00;CCAP0H = CCAP0L =46; //修改此处数值[0~255]可以调节CCP2_0占空比CCAPM0 = 0x42;PCA_PWM1 = 0X00;CCAP1H = CCAP1L =51; //修改此处数值[0~255]可以调节CCP2_1占空比zuoCCAPM1 = 0x42;}void speed2(bit a,bit b,bit c,bit d){ I1=a;I2=b;I3=c;I4=d;PCA_PWM0 = 0X00;CCAP0H = CCAP0L =60; //修改此处数值[0~255]可以调节CCP2_0占空比CCAPM0 = 0x42;PCA_PWM1 = 0X00;CCAP1H = CCAP1L =65; //修改此处数值[0~255]可以调节CCP2_1占空比CCAPM1 = 0x42;}void speed3(bit a,bit b,bit c,bit d){ I1=a;I2=b;I3=c;I4=d;PCA_PWM0 = 0X00;CCAP0H = CCAP0L =255; //修改此处数值[0~255]可以调节CCP2_0占空比CCAPM0 = 0x42;PCA_PWM1 = 0X00;CCAP1H = CCAP1L =255; //修改此处数值[0~255]可以调节CCP2_1占空比CCAPM1 = 0x42;}//-------------------PWM模式使能函数----------------//void PWM_Cmd(bit cmd){if(cmd==ENABLE)CR=1;else if(cmd==DISABLE)CR=0;}//----------------------延时函数-------------------//void Delay(u16 count){u16 i;for(i=0;i<count;i++);}//----------------外部中断初始化函数---------------//void Exti_InterruptInit(){//----------INT0--------------------------//IT0=1;EX0=1;//----------INT1-------------------------//IT1=1;EX1=1;EA=1; //所有中断开放}void adjust2(){if(Left_Front_Detector==0){speed(1,0,0,1);}else if(Right_Front_Detector==0){speed(0,1,1,0);}else{speed(0,1,0,1);}}void Go(){speed(0,1,0,1);}//------------------小车右转函数-------------------// void TurnRight(){// u8 flg=1;speed2(0,1,1,0); //左轮前转,右轮后转// left_count=right_count=0;/* while(flg==1){if(left_count==12|right_count==12){speed(0,0,0,0); //两轮停转left_count=0;right_count=0;flg=0;}}for(flg=0;flg<100;flg++){Delay(6000);}*/}//------------------小车左转函数-------------------// void TurnLeft(){// u8 flg=1;speed2(1,0,0,1); //左轮后转,右轮前转// left_count=right_count=0;}//------------------小车后转函数-------------------//void TurnBack(){u8 flg=1;// left_count=right_count=0;while(Front_Detector==1){speed2(0,1,1,0);} //左轮前转,右轮后转}//------------------小车停止函数-------------------//void Stop(){// u8 flg=1;// left_count=right_count=0;speed(0,0,0,0); //左轮后转,右轮后转}/******************************************************************************************************** *****function name :void Parameter_Init()*param :none*return value :none*description :初始化软件标志********************************************************************************************************* ***/void Parameter_Init(){task=SEARCH;// taskbuf=IDLE;left_count=0;right_count=0;frontbuf=rightbuf=leftbuf=0x01;startkey=1;adflg=0;led1=1;led2=1;map[8][8]=0;mouseface=FACE_NORTH;//车最开始是面向北边mouselocate.cX=0;mouselocate.cY=0;mousenext.cX=0;mousenext.cY=0;}/******************************************************************************************************** *****function name :u8 GetNextGridmap(u8 side)*param :MOUSERIGHT or MOUSELEFT or MOUSEFRONT*return value :下一格的8bit地图信息*description :根据车当前的方向和选择要走的支路返回该支路的地图信息********************************************************************************************************* ***/u8 GetNextGridmap(u8 side){mousenext.cX=mouselocate.cX;mousenext.cY=mouselocate.cY;switch(mouseface){case FACE_NORTH: //如果车面向北if(side==MOUSERIGHT) //选择右边的支路信息{mousenext.cX++;}else if(side==MOUSEFRONT) // 选择前边的支路信息{mousenext.cY++;}else if(side==MOUSELEFT) //选择右边的支路信息{mousenext.cX--;}break;case FACE_SOUTH:if(side==MOUSERIGHT){mousenext.cX--;}else if(side==MOUSEFRONT){mousenext.cY--;}else if(side==MOUSELEFT){mousenext.cX++;}break;case FACE_EAST:if(side==MOUSERIGHT){mousenext.cY--;}else if(side==MOUSEFRONT){mousenext.cX++;}else if(side==MOUSELEFT){mousenext.cY++;}break;case FACE_WEST:if(side==MOUSERIGHT){mousenext.cY++;}else if(side==MOUSEFRONT){mousenext.cX--;}else if(side==MOUSELEFT){mousenext.cY--;}break;}return map[mousenext.cX][mousenext.cY];}/******************************************************************************************************** *****function name :void rightMethod (void)*param :none*return value :none*description :右手法则优先级为:右-> 前-> 左并且存储即将行走的下一个格子的坐标********************************************************************************************************* ***/void LeftMethod (void){u8 leftmap,rightmap,frontmap;leftmap=GetNextGridmap(MOUSELEFT);rightmap=GetNextGridmap(MOUSERIGHT);frontmap=GetNextGridmap(MOUSEFRONT);/* if(mouselocate.cX==3&&mouselocate.cY==3) //判断当前的坐标是否为目标地点{comeback=1;Stop();TurnBack();mouseface=(mouseface+2)%4;Stop();left_count=35;right_count=35;return;} */if(Left_Detector==0&&(leftmap&0x0f)==0x00) // 未走过的之路{if(mouseface==FACE_NORTH){mouselocate.cY++;led1=!led1;}if(mouseface==FACE_SOUTH){mouselocate.cY--;led1=!led1;}mouseface=(mouseface+3)%4;TurnLeft();left_count=0;right_count=0;return;}if(Front_Detector==0&&((frontmap&0x0f)==0x00)) // 未走过的支路{ Go();return; //直走什么都不做}if(Right_Detector==1&&((rightmap&0x0f)==0x00)) // 未走过的支路{if(mouseface==FACE_NORTH){mouselocate.cY++;led1=!led1;}if(mouseface==FACE_SOUTH){mouselocate.cY--;led1=!led1;}mouseface=(mouseface+1)%4; //根据转向调整绝对方向TurnRight();left_count=0;right_count=0;return;}if(Left_Detector==1&&Right_Detector==0&&Front_Detector==1){TurnBack();mouseface=(mouseface+2)%4;map[mouselocate.cX][mouselocate.cY]|=0x0f; //将该支路标志为不通left_count=0;right_count=0;return;}if(Left_Detector==0){TurnLeft();mouseface=(mouseface+3)%4;map[mouselocate.cX][mouselocate.cY]|=0x0f;left_count=0;right_count=0;return;}if(Front_Detector==0){map[mouselocate.cX][mouselocate.cY]|=0x0f;return;}if(Right_Detector==1){TurnRight();mouseface=(mouseface+1)%4; //根据转向调整绝对方向map[mouselocate.cX][mouselocate.cY]|=0x0f;left_count=0;right_count=0;return;}}void LeftMethod2(){unsigned char i;if(Left_Detector==0&&Front_Detector==0&&Right_Detector==1){ Go();for(i=0;i<4;i++){ Delay(20000);}if(Left_Detector==0&&Front_Detector==0&&Right_Detector==1){speed3(0,0,0,0);led1=0;while(Rstart_Key==1);led1=1;}else{TurnLeft();}}if(Left_Detector==0){ TurnLeft();}else if(Front_Detector==0){Go();}else if(Right_Detector==1){TurnRight();}else if(Left_Detector==1&&Front_Detector==1&&Right_Detector==0){TurnBack();}}void LeftMethod3(){u8 leftmap,rightmap,frontmap;leftmap=GetNextGridmap(MOUSELEFT);rightmap=GetNextGridmap(MOUSERIGHT);frontmap=GetNextGridmap(MOUSEFRONT);if(mouselocate.cX==0&&mouselocate.cY==0) //判断当前的坐标是否为目标地点{task=OVER;return;}if(leftbuf==0&& // 左边有支路((leftmap&0x0f)==0x0a)) // 走得通的支路{TurnLeft();mouseface=(mouseface+3)%4;return;}if(frontbuf==0&& // 前方有支路((frontmap&0x0f)==0x0a)) // 走得通的支路{Go();return; //直走什么都不做}if(rightbuf==1&& // 右方有支路((rightmap&0x0f)==0x0a)) // 走得通的支路{Stop();TurnRight();mouseface=(mouseface+1)%4; //根据转向调整绝对方向return;}}void LeftMethod4(){if(Left_Detector==0){TurnLeft();}else if(Front_Detector==0){Go();}else if(Right_Detector==1){TurnRight();}else if(Left_Detector==1&&Front_Detector==1&&Right_Detector==0){TurnBack();}}/******************************************************************************************************** *****function name :void Dir_Trans()*param :none*return value :none*description :计算下一个到达的格子坐标********************************************************************************************************* ***/void DirTrans(){switch(mouseface) //计算下一个到达的格子坐标{case FACE_NORTH: //如果车的头部是向北的纵价标加1mouselocate.cY++;led1=!led1;break;case FACE_SOUTH: // 如果车的头部是向南的纵坐标减1 mouselocate.cY--;led1=!led1;break;case FACE_EAST: //如果车的头部是向东的横坐标加1mouselocate.cX++;// led2=!led2;break;case FACE_WEST: //如果车的头部是向西的横坐标减1mouselocate.cX--;// led2=!led2;break;}}/******************************************************************************************************** *****function name :void MapProcess()*param :none*return value :none*description :地图信息的保存********************************************************************************************************* ***/void MapProcess(){leftbuf=Left_Detector;rightbuf=Right_Detector;frontbuf=Front_Detector;/*switch(mouseface){case FACE_NORTH:map[mouselocate.cX][mouselocate.cY]=(frontbuf<<7)|(leftbuf<<5)|(rightbuf<<4);break;case FACE_EAST:map[mouselocate.cX][mouselocate.cY]=(frontbuf<<4)|(leftbuf<<7)|(rightbuf<<6);break;case FACE_WEST:map[mouselocate.cX][mouselocate.cY]=(frontbuf<<5)|(leftbuf<<6)|(rightbuf<<7);break;case FACE_SOUTH:map[mouselocate.cX][mouselocate.cY]=(frontbuf<<6)|(leftbuf<<4)|(rightbuf<<5);break;}*/map[mouselocate.cX][mouselocate.cY]&=0xf0;map[mouselocate.cX][mouselocate.cY]|=0xfa; //将该格标志为走过的路径}/******************************************************************************************************** *****function name :void ProcessData()*param :none*return value :none*description :在没有走完一格时调整行走方向,到达新的一格判断地图信息********************************************************************************************************* ***/void ProcessData(){if(left_count>=300) //前进一格{MapProcess();LeftMethod();adjust2();DirTrans();// Rstart_Key=~Rstart_Key;left_count=0;right_count=0;}}void ProcessData2(){LeftMethod();adjust2();if(right_count>=300) //前进一格{ MapProcess();DirTrans();// Rstart_Key=~Rstart_Key;left_count=0;right_count=0;}}void MouseBack(){if(right_count>=35){leftbuf=Left_Detector;rightbuf=Right_Detector;frontbuf=Front_Detector;Rstart_Key=~Rstart_Key;LeftMethod();DirTrans();left_count=0;right_count=0;}}void adjust(){if(adflg==1) //已经调整过{if(Left_Front_Detector==0||Right_Front_Detector==0){Go();adflg=0;}}if(Left_Front_Detector==1){speed(1,0,0,1);adflg=1;}if(Right_Front_Detector==1){speed(0,1,1,0);adflg=1;}}void main(){unsigned char i;Parameter_Init();Exti_InterruptInit();PWM_Init();PWM_Cmd(ENABLE);while(Start_Key==1);task=SEARCH;while(1){if(task==SEARCH){LeftMethod4();adjust2();if(Rstart_Key==0){task=IDLE;}}else{ LeftMethod2();adjust2();} }}//--------------外部中断0 左轮计数器------------// void Exit0_LeftWheel() interrupt 0{EX0=0;if(left_count<38){left_count++;}else{left_count=0;}EX0=1;}//------------外部中断1 右轮计数器--------------// void Exit1_RightWheel() interrupt 2{right_count++; }。