移动机器人设计与制作设计一智能循迹小车.docx
《移动机器人设计与制作设计一智能循迹小车.docx》由会员分享,可在线阅读,更多相关《移动机器人设计与制作设计一智能循迹小车.docx(19页珍藏版)》请在冰豆网上搜索。
移动机器人设计与制作设计一智能循迹小车
开放性实验报告
智能循迹小车
姓名:
党树林
学号:
06124143
专业:
电气工程及其自动化
指导老师:
赵勇
时间:
2013.9.17--2013.12.02
目录
1.系统功能介绍2
2.设计要求与任务2
3.系统硬件设计2
3.1舵机模块2
3.2数码管计数3
3.3循迹接收模块3
3.4避障模块3
3.5单片机硬件最小系统3
4.实验演示结果4
5.实验总结4
附录一4
1.系统功能介绍
本设计采取以单片机为最小系统,小车内部电路结构由舵机模块,数码管计数模块,遥控接收模块,循迹模块、避障这五大部分组成。
舵机模块主要是利用脉冲信号控制舵机进行360度旋转。
数码管计数模块通过以秒为单位进行计数显示。
遥控接收模块通过遥控控制小车进行各个方位的行进。
循迹模块主要是小车可以自主沿着黑色的轨迹行进。
避障模块当检测到障碍物之后主动改变原来方向,避开障碍物后继续前进。
2.设计要求与任务
熟悉51系列单片机的使用原理及操作方法。
掌握基本电路设计技巧和C程序设计。
掌握数码管、舵机等器材的基本使用方法并了解其原理。
设计并灵活调试小车的各方面行进功能。
3.系统硬件设计
3.1舵机模块
PWM信号进行控制,获得一个直流偏置压。
该输出的PWM波以驱动电机正反转。
利用占空比的变化改变舵机的位置。
给它提供一定的脉宽,它的输出轴就会保持在一个相对应的角度上,无论外界转矩怎样改变,直到给它提供一个另外宽度的脉冲信号它才会改变输出角度到新的对应的位置上。
舵机内部有一个基准电路,产生周期20ms,宽度1.5ms的基准信号,有一个比较器,将外加信号与基准信号相比较,判断出方向和大小,从而产生电机的转动信号。
3.2数码管计数
数码管分为共阴极和共阳极两种类型,其实共阴极就是将八个LED的阴极连在一起,让其接地,这样给任何一个LED的另一端高电平,它便能点亮。
而共阳极就是将八个LED的阳极连在一起。
3.3循迹接收模块
迅即模块主要通过ST188光电传感器,当没有物体反射红外线时,ce之间截止,无电流流过,输出电压为电源电压,高电平。
当有物体反射红外线时,be饱和导通ce也就导通了,输出端就相当于接地。
输出电压为低电平。
设置检测电路,当检测到黑显示输出低电平,否则输出高电平且控制舵机转向,熟悉掌握ST188的引脚功能,设计电路
3.4避障模块
检测距离可以根据要求进行调节。
该传感器具有探测距离远、受可见光干扰小、价格便宜、易于装配、使用方便等特点,可以广泛应用于机器人避障、流水线计件等众多场合。
前方无障碍输出高电平
(1),有障碍输出口(黄色)电平会从高电平变成低电平(0),工作原理已经标在图上了。
背面图有一个电位器可以调节障碍的检测距离。
3.5单片机硬件最小系统
试验的控制器件是AT89C51系列单片机,它在整个实验中起了核心作用,采用内部时钟方式,给它的引脚外接晶振,这样就构成了自激振荡器并在单片机内部产生时钟脉冲信号,给晶振的每个角又接了一个30PF的电容,让晶振快速起振并可以达到12M稳定频率,给单片机的RST口按键开关使之构成复位电路。
4.实验演示结果
当开启循迹时,小车放在跑道上,打开电源后,沿着跑道行进,在转弯处能根据跑道拐弯等动作前进。
开启遥控时,用遥控指挥小车的各个方向运动及停止行走过程。
加上避障后,在距离障碍物20厘米左右小车会自动改变方向,避开障碍物后再次沿着原来的方向前进,从而达到集循迹、遥控、避障为一体的智能小车。
5.实验总结
这次实验完成了循迹遥控避障的功能,我从开始的单片机C程序及相关软件学习到后来的电路设计,在关于实验的学习的过程中,获得一定的实验知识储备。
在实验中掌握了一定的知识,也遇到了问题:
比如避障模块,当遇到障碍物时,小车回多转动360度后才能沿着原来的方向继续前进,我认为应该是C程序定义之间有冲突,导致运行时发生混淆,从而使显示发生错误。
经过反复试验和努力到目前为止也没能解决这个问题,所以只能在以后的时间继续进行思索和改进。
在实际实验中才发现,理论和实际有一定的差距,所以在实际中要不断理解深入,只有进行实际的操作才能切实掌握知识的精华和作用所在,并巩固自己的理论知识,在解决问题中深化自己。
附录一
循迹遥控代码
#include
#defineucharunsignedchar
#defineuintunsignedint
voiddelay1(intms);
voiddelay2(ucharx);
sbitleft=P1^0;//左舵机控制信号
sbitp1_1=P1^1;//工作指示灯
sbitright=P1^2;//右舵机控制信号
sbitleft_s=P1^3;//左传感器信号
sbitmiddle_s=P1^4;//中传感器信号
sbitright_s=P1^5;//右传感器信号
sbiteye=P3^5;//红外接近传感器信号
sbitIN1=P2^4;
sbitIN2=P2^5;
sbitIN3=P2^6;
sbitge_w=P2^2;
sbitshi_w=P2^1;
sbitbai_w=P2^3;
uinta=2700,c=0;//舵机信号变量
uintcount=0,flag=0,ge,shi,bai,num;//计时变量
ucharIRCOM[7];
ucharcodenumber[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x7f};//数码管编码表
voiddelay(uinta)
{
ucharx;
uinty;
for(y=a;y>0;y--)
for(x=110;x>0;x--);
}
voidDelay(void)//舵机控制延时函数
{
uintt=2222;
while(t--)
{
}
}
voidtime1()interrupt3//定时器T1中断
{
TH1=(65536-50000)/256;
TL1=(65536-50000)%256;//50ms
flag++;
if(flag==20)
{
flag=0;
num++;
if(num==1000)
num=0;
ge=num%10;
shi=num/10%10;
bai=num/100;
}
}
voiddisplay(ucharge,ucharshi,ucharbai)//数码管显示函数
{
shi_w=0;
P0=number[shi];
delay(5);
//P0=0x00;
shi_w=1;
bai_w=0;
P0=number[bai];
delay(5);
//P0=0x00;
bai_w=1;
ge_w=0;
P0=number[ge];
delay(5);
//P0=0x00;
ge_w=1;
}
voidtimer0(void)interrupt1//定时器T0中断
{
left=0;
right=0;
c=10000-c;
TH0=-(c/256);
TL0=-(c%256);
c=a;
}
voidservo(uintb,uintd)//舵机控制函数
{
left=b;
right=d;
c=a;
TH0=-(a/256);
TL0=-(a%256);
ET0=1;//定时器T0中断允许
TR0=1;//定时器T0启
PT0=0;//定时器T0低优级
}
voidgo_forward(void)//前进函数
{
servo(1,1);
Delay();
ET0=0;
TR0=0;
}
voidgo_left(void)//左转函数
{
servo(0,1);
Delay();
ET0=0;
TR0=0;
}
voidgo_right(void)//右转函数
{
servo(1,0);
Delay();
ET0=0;
TR0=0;
}
voidstop(void)//停止函数
{
servo(0,0);
Delay();
ET0=0;
TR0=0;
}
voidturn_head(uintl,uintr)
//转向函数,参数为(1,0),左转;为(0,1),右转
{
uintaa=360;
while(aa--)
{
servo(r,l);
Delay();
ET0=0;
TR0=0;
display(ge,shi,bai);
if(middle_s==0)
{
break;
}
}
}
voidmain(void)//主函数
{
uinti=0;
p1_1=0;//工作状态显示
IN1=1;
IN2=1;
IN3=1;
EA=1;
ET1=1;
TR1=1;
PT1=1;
TMOD=0x11;//定时器工作方式为1
//IE=0x81;//允许总中断中断,使能INT0外部中断
//TCON=0x01;//触发方式为脉冲负边沿触发
while
(1)
{
display(ge,shi,bai);//调用显示函数,各判断中也或有调用以保持显示的连续性
if(eye==0)//检测到障碍物,转向
turn_head(1,0);
elseif(left_s==0&&middle_s==0&&right_s==0)//遇到障碍物回来后检测到节点,转向
{
i=6;
while(i--)
{
go_forward();
}
turn_head(0,1);
}
/*
elseif(LEFT_S1==1&&RIGHT_S1==0)//前进途中遇到转向节点,转向
{
turn_head(0,1);
}
*/
elseif((middle_s==0)||(IN1==1&&IN2==0&&IN3==1))//前进
go_forward();
elseif((left_s==0&&right_s==1)||(IN1==0&&IN2==1&&IN3==1))//左转
go_left();
elseif((left_s==1&&right_s==0)||(IN1==1&&IN2==1&&IN3==0))//右转
go_right();
elseif((left_s==1&&middle_s==1&&right_s==1)||(IN1==1&&IN2==1&&IN3==0))//停止
go_forward();
elseif(IN1==1&&IN2==1&&IN3==1)
stop();
ET0=0;
}
//以下为状态清零
TR0=0;
ET1=0;
TR1=0;
EA=0;
while
(1)//显示系统用时
{
display(ge,shi,bai);
}
}
2数码管代码
#include
#include
#defineNOP()_nop_()/*定义空指令*/
#defineucharunsignedchar
#defineuintunsignedint
#definedelayNOP();{_nop_();_nop_();_nop_();_nop_();};
voiddelay(ucharx);//x*0.14MS
voiddelay1(intms);
voidbeep(void);
sbitIRIN=P3^2;//红外接收器数据线
ucharIRCOM[7];
sbitIN1=P2^4;
sbitIN2=P2^5;
sbitIN3=P2^6;
voidTurn_left(void)
{
IN1=0;
IN2=1;
IN3=1;
}
voidTurn_right(void)
{
IN1=1;
IN2=1;
IN3=0;
}
voidGo(void)
{
IN1=1;
IN2=0;
IN3=1;
}
voidStop(void)
{
IN1=1;
IN2=1;
IN3=1;
}
unsignedcharY0;
/*******************************************************************/
main()
{
IE=0x81;//允许总中断中断,使能INT0外部中断
TCON=0x01;//触发方式为脉冲负边沿触发
IRIN=1;//I/O口初始化
delay1(10);//延时
IN1=1;
IN2=1;
IN3=1;
while
(1);
}//endmain
/**********************************************************/
voidIR_IN(void)interrupt0//外部中断服务程序
{
unsignedcharj,k,N=0;
EX0=0;
delay(15);
if(IRIN==1)
{EX0=1;
return;
}
//确认IR信号出现
while(!
IRIN)//等IR变为高电平,跳过9ms的前导低电平信号。
{delay
(1);}
for(j=0;j<4;j++)//收集四组数据
{
for(k=0;k<8;k++)//每组数据有8位
{
while(IRIN)//等IR变为低电平,跳过4.5ms的前导高电平信号。
{
delay
(1);
}
while(!
IRIN)//等IR变为高电平
{
delay
(1);
}
while(IRIN)//计算IR高电平时长
{
delay
(1);
N++;
if(N>=30)
{
EX0=1;
return;
}//0.14ms计数过长自动离开。
}//高电平计数完毕
IRCOM[j]=IRCOM[j]>>1;//数据最高位补"0"
if(N>=8){IRCOM[j]=IRCOM[j]|0x80;}//数据最高位补"1"
N=0;
}//endfork
}//endforj
if(IRCOM[2]!
=~IRCOM[3])
{EX0=1;
return;}
IRCOM[5]=IRCOM[2]&0x0F;//取键码的低四位
IRCOM[6]=IRCOM[2]>>4;//右移4次,高四位变为低四位
if(IRCOM[5]>9)
{IRCOM[5]=IRCOM[5]+0x37;}//十进制转Ascall的值
else//Ascall码‘0’到‘9’对应的十六进制是0x30--0x39'A'-'F'对应的0x41--0x46
IRCOM[5]=IRCOM[5]+0x30;
if(IRCOM[6]>9)
{IRCOM[6]=IRCOM[6]+0x37;}
else
IRCOM[6]=IRCOM[6]+0x30;
switch(IRCOM[2])
{
case0x45:
;break;
case0x46:
;break;
case0x47:
;break;
case0x44:
;break;
case0x40:
;break;
case0x43:
;break;
case0x07:
;break;
case0x15:
;break;
case0x09:
;break;
}
if(IRCOM[2]==0x45)
{
Turn_left();
delay
(1);
}
if(IRCOM[2]==0x46)
{
Go();
delay
(1);
}
if(IRCOM[2]==0x47)
{
Turn_right();
delay
(1);
}
if(IRCOM[2]==0x40)
{
Stop();
delay
(1);
}
EX0=1;
}
/**********************************************************/
/**********************************************************/
voiddelay(unsignedcharx)//x*0.14MS
{
unsignedchari;
while(x--)
{
for(i=0;i<13;i++){}
}
}
/**********************************************************/
voiddelay1(intms)
{
unsignedchary;
while(ms--)
{
for(y=0;y<250;y++)
{
_nop_();
_nop_();
_nop_();
_nop_();
}
}
}
/*