基于51单片机的扫地机器人设计报告文档格式.docx
《基于51单片机的扫地机器人设计报告文档格式.docx》由会员分享,可在线阅读,更多相关《基于51单片机的扫地机器人设计报告文档格式.docx(53页珍藏版)》请在冰豆网上搜索。
面向初学者来说LCD主要分为两种,1602和12864
(1)1602:
能够显示简单的字符,操作简单,屏幕相对较小,能够显示的信息数量有限
(2)12864:
能够显示简单字符也可以显示自定义的图片,操作相对困难,屏幕相对较大
能够显示较多的信息。
5.电源的选择
18650锂电池:
输出电压高,约为3.7v,负载能力强,能够驱动电机驱动模块和单片机和各模块。
只需要两块电池。
可充电,比较环保。
价格相对较高。
普通干电池:
输出电压较低,负载能力较低,要驱动电机驱动模块需要5块1.5v干电池,一般不能充电,调试过程易造成浪费。
价格相对较便宜。
升压模块:
能将3-5伏的电压升到12伏或更高,但是性能越好的价格越高,性能较低的承受电流不能过大。
6.储存模块的选择
(1)单片机自带EEPROM:
使用方便,可以节省IO口,操作简单
(2)AT24C02:
擦除写入速度快,可擦写次数达100万次,数据可保存达100年,功耗低
7.时钟模块的选择
(1)DS1302:
操作简单,IO口占用少,基础电路简单,可自行焊接
(2)DS12C887:
芯片集成度高,不需要外部基础电路,焊接方便,但IO占用多
8.最终选择方案
基于设计思路,由小组成员讨论决定选择同时选用锡板和铜板(降低开支的同时,保证焊接稳定),鉴于使用模块较多IO口不足的问题同时选用STC89C52RC芯片和STC12C5A60S2芯片,独立键盘(只需要4个功能按键,IO口占用与矩阵键盘相同,且矩阵键盘的焊接难度大),12864(根据需要显示的功能选择),单片机自带EEPROM(节省IO口,同时降低操作难度),选用电源为18650锂电池(输出电压较为稳定,且可以充电,环保实用),选用DS1302(降低操作难度,节省IO口)。
四、一些模块的选择及底盘的制作
1.电机驱动模块
采用专用芯片L298N作为电机驱动芯片。
L298N是一个具有高电压大电流的全桥驱动芯片,它相应频率高,一片L298N可以分别控制两个直流电机,而且还带有控制使能端。
用该芯片作为电机驱动,操作方便,稳定性好,性能优良。
我们采用现成的封装好的电机驱动模块,能将6-12伏的电压转化为5伏电压输出,给单片机和其他模块供电,操作简单功能强大。
2.红外传感器模块
该传感器模块对环境光线适应能力强,其具有一对红外线发射与接收管,发射管发射出一定频率的红外线,当检测方向遇到障碍物时,红外线反射回来被接收管接收,经过比较器电路处理之后,指示灯会亮起,同时信号输出接口输出一个低电平信号,可通过电位器旋钮调节检测距离,有效距离范围2~30cm,工作电压为3.3V-5V。
该传感器的探测距离可以通过电位器调节、具有干扰小、便于装配、使用方便等特点。
3.寻迹模块:
TCRT5000传感器的红外发射二极管不断发射红外线,当发射出的红外线没有被反射回来或被反射回来但强度不够大时,光敏三极管一直处于关断状态,此时模块的输出端为低电平,指示二极管一直处于熄灭状态;
被检测物体出现在检测范围内时,红外线被反射回来且强度足够大,光敏三极管饱和,此时模块的输出端为高电平,指示二极管被点亮
4.底盘的制作:
利用废弃的硬纸盒,通过钻孔来固定各个模块和轮子,同时也能将各种杜邦线和电路板包含在盒子里面,达到外形美观和节约材料变废为宝的目的。
五、设计与论证
程序流程图
六、理论分析与计算
1.基础设想分析
(1)单片机间的控制
由于是基于人机交互界面控制的扫地机器人,故可由两个单片机控制不同的模块(STC12C5A60S2控制显示模块,STC89C52RC控制小车模块)。
STC12IO口与STC89IO口相连,由显示模块(STC12)输出信号,小车模块(STC89)接受信号,从而实现单片机间的控制。
(2)背光灯及小车车轮控制
由STC12IO口输出一定的PWM信号,可调节背光灯的亮度。
由STC89控制电机驱动输出PWM信号小车电机转速,同时可通过对车轮输出不同的PWM信号实现车轮转速不同而实现小车的转向,可对电机驱动输入不同的使能信号使其电机实现正反转动,从而实现小车的前进后退。
(3)小车的避障功能
通过红外传感器测距,当红外传感器与障碍物距离缩短到一定距离时,红外传感器会给单片机传输一个电信号,单片机识别电信号后可控制小车转向,从而避开障碍物。
(4)扫地装置
通过电机驱动控制两个带毛刷电机以一定速度反向转动,将毛刷经过的区域的垃圾扫进小车底部设计的简易垃圾收集装置
(5)电量检测与显示
设计一简单的外围电路,通过STC12自带的AD功能,可实现对电池电压的检测。
再通过电池电压与容量的简易关系,设计简易程序实现在12864固定区域显示。
(6)时间显示
单片机对外部时钟芯片的数据进行读取,同时设置开启时间(ON)停止时间(OFF),通过单片自带EEPROM储存ON、OFF时间数据,再通过LCD12864显示。
(7)返回出发点
通过循迹模块对地面进行识别,若识别到黑线即会输出电信号,单片机识别电信号后行走一小段时间后便停止行动
2.整体框架分析
(1)主程序main函数开始执行初始化,初始化LCD等外部硬件,在LCD上显示固定数据
(2)进入while循环重复扫描按键,时间比较,显示电量,背光选择。
3.独立键盘检测分析
按键与GND相连,一旦按键被按下单片机便会接受到一个低电平信号。
由于单片机执行速度快,故按下按键的同时,单片机几乎同时执行按键扫描函数,对来自IO口的电平信号进行分析
。
4.LCD12864显示理论分析
初始化函数显示液晶屏固定显示部分,使用LCD自带字库,使现实速率提高,再通过对外部时钟数据进行读取,按键扫描程序数据更改的读取,局部改变液晶屏上数据的显示。
因LCD的执行速度很快,人眼存在视觉停留效果,故改变数据时,人不易察觉到这一过程。
5.算法计算分析
(1)更改时间:
DS1302对时间数据的存储是16进制,故读取时钟数据时需将其转化为10进制再分别取时分秒的十位数和个位数,分别显示在LCD上。
因此,在对DS1302时钟数据的更改时需将更改的时钟数据改变为16进制再进行储存。
(2)电量显示:
通过STC12的AD串口对电压进行读取(此时读取的电压值为电源电压的一半),再将读取的数据乘以2即得电源的电压值。
再通过对电压与电源电路的简易关系,判断电压属于哪个范围即显示相应的剩余电量。
七、电路原理图
八、测试方法和测试仪器
1、测试方法
(1)通过调节红外传感器模块上的可调电阻,调节模块的灵敏度,使其在一定距离下输出低电平。
表现为红外传感器指示灯亮起
(2)通过LCD显示AD串口检测到的电压,同时用万用表检测电源两端的输出电压,观察读取数据是否准确。
(3)通过调节PWM,调节旋转电机(扫地用)转速,使其能够较好的清扫垃圾,观察其是否能达到预估效果
(4)通过调节PWM。
调节行走电机的转速,使其实现转向,观察其是否能达到预估效果
(5)通过给电机驱动模块输入使能信号,控制行走电机转向,使其实现前行和后退,观察其是否能达到预估效果
(6)根据需要的功能设计程序,观察其在LCD上是否能够按预想状况进行
2、测试仪器:
万用表
九、测试数据与结果分析
1、测试数据
要求
测试内容
测试前
测试后
备注
基本要求1:
设计扫地机器人,自主完成前进、后退、转向等控制
前进
通过观测可知(能够前进)
后退
通过观测可知(能够后退)
转向
通过观测可知(能够转向)
基本要求2:
实现避障功能,能自主走完一个用围墙围起来2m*2m的区域
避障
通过观测可知(能够避障)
自主走完一个用围墙围起来2m*2m的区域
通过观测可知(能够走完待清扫区域)
基本要求3:
设计简易扫地装置,能够清扫小纸团
清扫小纸团
通过观测可知(能够清扫小纸条,部分有较小几率弹出垃圾收集装置
拓展功能1:
设计良好的人机界面,用于设置开启时间,显示电量等
设置时间
~为设置时间标志,ho,mi,se分别为时分秒设置标记
设置开启时间
设置关闭时间
显示电量
拓展功能2:
能够清扫更小的垃圾,如纸屑
清扫更小的垃圾
通过观测可知(能够清扫较小纸屑)
拓展功能3:
清扫之后能够回到用黑胶布围成的30cm*30cm的起点区域
回到起点
通过观测可知(能够回到起点)
其他拓展功能:
设置LCD背光亮度
测试前为直接接上电源后LCD背光灯亮度(亮度太大,耗能高,刺眼)
2、结果分析
基本要求
完成情况
1
完成
2
完成,小车在检测到前方障碍物时会自行转向
3
完成,通过两个反向旋转毛刷可以将小纸团收集进自制简易垃圾收集装置
拓展功能
完成,可以显示实时时间,开启时间,关闭时间,电量。
并可通过按键调节时间数据
完成,通过调试旋转毛刷的转速可以实现更小垃圾的清扫
完成,当达到关闭时间后,小车弱检测到黑色胶布传送的深色信号时将自动前进一小段距离便停止
4
设置LCD背光亮度、开关机动画
附录
#include<
reg52.h>
intrins.h>
#defineucharunsignedchar
#defineuintunsignedint
#defineRdCommand0x01//定义ISP的操作命令
#definePrgCommand0x02
#defineEraseCommand0x03
#defineError1
#defineOk0
#defineWaitTime0x01//定义CPU的等待时间
#defineADC_POWER0x80//ADCpowercontrolbit
#defineADC_FLAG0x10//ADCcompleteflag
#defineADC_START0x08//ADCstartcontrolbit
#defineADC_SPEEDLL0x00//420clocks
#defineFOSC11059200L
#defineBAUD9600
sbitLCD_PSB=P3^0;
sbitLCD_EN=P3^1;
sbitLCD_WR=P3^2;
sbitLCD_RS=P3^3;
sbitSCLK=P3^4;
sbitSDA=P3^5;
sbitRST=P3^6;
sbitkey=P2^0;
sbits1=P2^4;
sbits2=P2^5;
sbits3=P2^6;
sbits4=P2^7;
sfrISP_DATA=0xc2;
sfrISP_ADDRH=0xc3;
sfrISP_ADDRL=0xc4;
sfrISP_CMD=0xc5;
sfrISP_TRIG=0xc6;
sfrISP_CONTR=0xc7;
sfrADC_CONTR=0xBC;
sfrADC_RES=0xBD;
sfrADC_LOW2=0xBE;
sfrP1ASF=0x9D;
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;
sfrPCAPWM0=0xf2;
sfrPCAPWM1=0xf3;
ucharcount;
charmiao,shi,fen;
charnshi,nfen,nmiao,fshi,ffen,fmiao;
uchars1num,s2num;
ucharcodetable[]="
ON:
00:
00:
00"
;
ucharcodetable1[]="
扫地机器人"
ucharcodetable2[]="
OFF:
ucharcodetable3[]="
TIME:
voidInitUart();
voidInitADC();
voidSendData(uchardat);
intGetADCResult(ucharch);
voidDelay(uintn);
voidShowResult(ucharch);
floatAd_AV(ucharchannel);
//计算AD转换电压值
voiddelayus(uintz);
voiddelayms(uintz);
voidQ0(void);
voidcc(uintaddr);
voidxcx(uintaddr,uchardat);
uchardcx(uintaddr);
voidwrite_com(ucharcommand);
voidwrite_date(uchardate);
voidds1302writebyte(uchardat);
uchards1302readbyte();
uchards1302read(ucharcmd);
voidds1302write(ucharcmd,uchardat);
//初次初始化ds1302使用
//voidinit_ds1302(void);
voidinit();
voidkeyscan();
//设置时钟,开启时间,结束时间
//voiddi();
//蜂鸣器报警
voidclock();
voidcompare();
voidpowershow();
voidshow(intx,inty);
voidshow1(intx);
voidpwm(ucharx);
voidbeiguang();
voidmain()
{
init();
while
(1)
{
keyscan();
clock();
compare();
powershow();
beiguang();
}
}
voidbeiguang()
{
if(s1num==0)
if(s2==0)
{pwm(255);
}
if(s3==0)
{pwm(128);
if(s4==0)
{pwm(256);
voidpwm(ucharx)
CCON=0;
CL=0;
CH=0;
CMOD=0x02;
CCAP0H=CCAP0L=x;
CCAPM0=0x42;
CR=1;
floatAd_AV(ucharchannel)//计算AD转换电压值
floatVAL_AV=0;
ucharnum;
for(num=100;
num>
0;
num--)
VAL_AV+=GetADCResult(channel);
VAL_AV/=100.0;
VAL_AV*=2.0;
VAL_AV=VAL_AV*5.0/1024;
returnVAL_AV;
voidpowershow()//显示电量
floatdianya;
dianya=Ad_AV
(1);
if(dianya<
=7.16)
{show1(0);
elseif(dianya<
=7.18)
{show1
(1);
=7.22)
{show1(3);
=7.26)
{show1(5);
=7.28)
{show1(8);
=7.3)
{show(1,0);
=7.32)
{show(1,2);
=7.38)
{show(1,5);
=7.40)
{show(1,8);
=7.42)
{show(2,0);
=7.44)
{show(2,5);
=7.450523)
{show(2,8);
=7.46)
{show(3,0);
=7.47108)
{show(3,3);
=7.48)
{show(3,5);
=7.50)
{show(3,8);
=7.52)
{show(4,0);
=7.53)
{show(4,2);
=7.54)
{show(4,5);
=7.58)
{show(5,0);
=7.62)
{show(5,5);
=7.65)
{show(5,8);
=7.68)
{show(6,0);
=7.71)
{show(6,3);
=7.74)
{show(6,5);
=7.77)
{show(6,7);
=7.80)
{show(7,0);
=7.835)
{show(7,3);
=7.86)
{show(7,5);
=7.895)
{show(7,7);
=7.94)
{show(8,0);
=8.00)
{show(8,2);
=8.06)
{show(8,5);
=8.10)
{show(8,7);
=8.16)
{show(9,0);
=8.20)
{show(9,2);
=8.24)
{show(9,5);
=8.28)
{show(9,7);
=8.30)
{show(9,9);
elseif(dianya>
8.30)
write_com(0x80+6);
write_date(0x30+1);
write_date(0x30+0);
write_date('
%'
);
voidshow(intx,inty)
write_com(0x80+6);
write_date('
'
write_date(0x30+x);
write_date(0x30+y);
voidshow1(intx)
voiddelayus(uintz)
uin