寻线式电脑鼠的设计.docx
《寻线式电脑鼠的设计.docx》由会员分享,可在线阅读,更多相关《寻线式电脑鼠的设计.docx(40页珍藏版)》请在冰豆网上搜索。
![寻线式电脑鼠的设计.docx](https://file1.bdocx.com/fileroot1/2022-11/27/d2137599-d646-45c5-95a2-3cc2ddb22152/d2137599-d646-45c5-95a2-3cc2ddb221521.gif)
寻线式电脑鼠的设计
一、任务和总体设计
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)LM339
LM393是四电压比较器集成电路。
该电路的特点如下:
工作电源电压范围宽,单电源、双电源均可工作,单电源:
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类似。
内部结构:
6、元件清单
元件名称
数量
元件名称
数量
L9110
100uF电容
0.1uF电容
104电容
1N914
Header5
IR_LED红外发射
Header2
LED红色发光管
ST256
Header2H
LCD5110
20K电阻
10K电阻
2K电阻
2
3
1
6
1
1
5
1
7
2
2
1
5
6
10
360R
1K电阻
5.1K电阻
300R
510R
2K电位器
SW-PB
STC15W413AS
TL413B
SGPT324BL
LM339
LM393
74HC00
干电池盒
7
2
1
1
1
1
2
1
1
5
1
1
2
2
三、软件设计
程序总流程图:
中断返回
中断
Y
Y
Y
Y
N结束
N结束
N结束
N结束
结束
是否冲刺到终点?
是否检测到终点?
是否回到起点?
是否等待出发?
开始
软件部分主要是由以下三个部分组成。
(1)、电机驱动部分
PWM产生函数驱动电机,通过调节占空比进行调速,通过控制四个I/O口来控制电机的正反转以及停转。
根据芯片以及PCB板控制单片机的CCP_S0,CCP_S1为0X20和0X10。
电脑鼠转弯和直走时用不同速度进行控制。
同时在转弯和直线时,采用不同的占空比调速,使得电脑鼠在行走过程中速度能在快的同时达到稳定的效果。
//------------------PWM初始化函数---------------------//
voidPWM_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;
}
//------调整速度函数-----------//
voidspeed(bita,bitb,bitc,bitd)
{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)、中断产生部分
中断用于测速盘测速,用两个中断源进行控制,分别用于左轮计数和右轮计数。
根据测速盘转过的圈数,中断计数的数字判断电脑鼠是否走过一格,根据走过的格子进行坐标的加减。
//----------------外部中断初始化函数---------------//
voidExti_InterruptInit()
{//----------INT0--------------------------//
IT0=1;
EX0=1;
//----------INT1-------------------------//
IT1=1;
EX1=1;
EA=1;//所有中断开放
}
//--------------外部中断0左轮计数器------------//
voidExit0_LeftWheel()interrupt0
{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灯进行坐标的测试标定,运用右轮计数器以及中断进行坐标测定。
但最终由于硬件原因无法精准计数,由于时间原因,最终没能实现最短路径。
在制作电脑鼠过程中,花费了许多的时间与精力。
在每一个部分都遇到了十分多的问题。
但每一次解决问题的欣喜都让我们受益匪浅。
在课程设计过程中,更加深了我们对于单片机的了解,在实践中学会了硬件设计与硬件设计。
深入学习和掌握了如何运用AltiumDesigner设计原理图和PCB图,如何运用Keil软件进行单片机的编程,如何在出现问题时,对软件和硬件进行问题的排除。
虽然最后我们没能实现最短时间,但对于这一功能也做了十分大的努力,最后发现硬件问题难以解决,这也为以后的设计积累了经验。
在这过程中深入了解了迷宫算法,坐标的确定以及调整。
总之,最后我们较好地完成了课程设计任务,在设计过程中受益匪浅。
,
六、附录
1、原理图
2、PCB图
3、代码
#include"reg51.h"
#include"intrins.h"
//-------------------------变量声明---------------------------------------//
typedefunsignedcharBYTE;
typedefunsignedintWORD;
typedefunsignedcharu8;
typedefunsignedintu16;
#defineFOSC33177600L
#defineF38_4KHz(256-FOSC/2/12/40000)
#defineSYSCLK33177600L
#defineTIMSEND65536-SYSCLK/12/1000
#defineTIMKEEP65536-SYSCLK/12/1000
#defineCCP_S00x20
#defineCCP_S10x10
sfrP5=0XC8;
sbitLeft_Detector=P1^7;
sbitRight_Detector=P1^3;
sbitLeft_Front_Detector=P1^6;
sbitRight_Front_Detector=P1^4;
sbitFront_Detector=P1^5;
staticbitcomeback;//为0时搜索为1时返回
staticbitsenddir;//senddir=0发送左右前ORsenddir=1发送左前右前
staticbitstartkey;
staticu8mouseface;//车的面向方向
u16left_count;
u16right_count;
u8adflg;//调整标志位当adflg=0时没有调整过当adflg=1时有调整过
staticu8leftbuf;//保存车左面是否有障碍
staticu8frontbuf;//保存车前面是否有障碍
staticu8rightbuf;//保存车右面是否有障碍
enum{
IDLE=0,
SEARCH=1,
RETURN=2,
ADJUST=3,
OVER=4
}task,taskbuf;
struct{
signedcharcX;
signedcharcY;
}mouselocate,mousenext;//micromouse当前位置
u8map[8][8];//保存地图信息表
constbitENABLE=1;
constbitDISABLE=0;
#defineSPEED_INIT0x9c//电机最初速度
#defineFACE_NORTH0//车头部面向北边
#defineFACE_SOUTH2//车头部面向南边
#defineFACE_WEST3//车头部面向西边
#defineFACE_EAST1//车头部面向东边
#defineMOUSERIGHT1//车右边
#defineMOUSEFRONT2//车前边
#defineMOUSELEFT3//车左边
sbitI1=P1^0;
sbitI2=P2^7;
sbitI3=P2^4;
sbitI4=P2^3;
sbitRstart_Key=P5^5;
sbitStart_Key=P5^4;
sbitled1=P5^4;
sbitled2=P5^5;
//------------------公有寄存器定义-------------//
sfrAUXR=0X8E;
sfrWAKE_CLKO=0X8F;
//------------------PWM数据类型----------------//
typedefenum{
PWM0=0,
PWM1=1,
PWM2=2
}pwmx;
/************************************************************************************************************
*functionname:
voidTimer1_Cmd(bitcmd)
*param:
1bitcmd
*returnvalue:
none
*description:
enableordisablethetimer1counter
************************************************************************************************************/
voidTimer1_Cmd(bitcmd)
{
if(cmd==ENABLE)
{
TR1=1;
}
elseif(cmd==DISABLE)
{
TR1=0;
}
}
/************************************************************************************************************
*functionname:
voidTimer1_Interrupt_Init()
*param:
none
*returnvalue:
none
*description:
configurethetimer1interrupt
************************************************************************************************************/
voidTimer1_Interrupt_Init(void)
{
ET1=1;
PT1=0;
EA=1;
}
/************************************************************************************************************
*functionname:
voidTimer1_Rload(u16count)
*param:
16bitscountnumber
*returnvalue:
none
*description:
updatetheTimerTH1andTL1register
************************************************************************************************************/
voidTimer1_Reload(u16count)
{
TL1=count;
TH1=count>>8;
}
//---------------PWM寄存器定义-----------------//
sfrP_SW1=0xA2;
sfrCCON=0xD8;
sbitCCF0=CCON^0;
sbitCCF1=CCON^1;
sbitCR=CCON^6;
sbitCF=CCON^7;
sfrCMOD=0xD9;
sfrCL=0xE9;
sfrCH=0xF9;
sfrCCAPM0=0xDA;
sfrCCAP0L=0xEA;
sfrCCAP0H=0XFA;
sfrCCAPM1=0xDB;
sfrCCAP1L=0xEB;
sfrCCAP1H=0xFB;
sfrCCAPM2=0xDC;
sfrCCAP2L=0xEC;
sfrCCAP2H=0xFC;
sfrPCA_PWM0=0xf2;
sfrPCA_PWM1=0xf3;
sfrPCA_PWM2=0xf4;
//------------------PWM初始化函数---------------------//
voidPWM_Init()
{
ACC=P_SW1;
ACC&=~(CCP_S0|CCP_S1);
ACC|=CCP_S0;
P_SW1=ACC;//CCP_S0,CCP_S1[0,1]→[P3.5.CCP0_2,P3.6.CCP1_2,P3.7.CCP2_2]//其余I/O口详见芯片手册
CCON=0;
CL=0;
CH=0;
CMOD=0x02;
CR=1;
}
//------调整函数----f_pwm=PCA_clk/256-------//
voidspeed(bita,bitb,bitc,bitd)
{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占空比zuo
CCAPM1=0x42;
}
voidspeed2(bita,bitb,bitc,bitd)
{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;
}
voidspeed3(bita,bitb,bitc,bitd)
{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模式使能函数----------------//
voidPWM_Cmd(bitcmd)
{
if(cmd==ENABLE)
CR=1;
elseif(cmd==DISABLE)
CR=0;
}
//----------------------延时函数-------------------//
voidDelay(u16count)
{
u16i;
for(i=0;i}
//----------------外部中断初始化函数---------------//
voidExti_InterruptInit()
{
//----------INT0--------------------------//
IT0=1;
EX0=1;
//----------INT1-------------------------//
IT1=1;
EX1=1;
EA=1;//所有中断开放
}
voidadjust2()
{
if(Left_Front_Detector==0)
{
speed(1,0,0,1);
}
elseif(Right_Front_Detector==0)
{
speed(0,1,1,0);
}
else
{speed(0,1,0,1);}
}
voidGo()
{
speed(0,1,0,1);
}
//------------------小车右转函数------------