可调速蓝牙遥控避障循迹四合一小车
一.项目材料:
1.小车材料:
-
小车图片
-
小车底板*2
-
直流小黄电机*4
-
l298n驱动*2
-
杜邦线*n
-
车轮*4
-
12v电池*1
-
HC-SR04 超声波模块
-
红外对管*4
-
51单片机最小系统*1
-
51单片机芯片*1
-
自走开关*1
-
电烙铁*1 ,锡,
-
胶枪
-
铜柱*n
-
蓝牙*1
2.遥控器材料:
- 蓝牙*1
- 51单片机最小系统*1
- 51单片机芯片*1
- 12V电池*1
- 稳压器*1
- 洞洞板*2
- 杜邦线*n
- 按键
二.项目程序:
1.小车程序:
//程序特点:
// 51单片机只有2个定时器
// 而此程序可同时进行循迹,避障,蓝牙,调速,多功能的同时实现
#include <reg51.h>
#include <INTRINS.H>
unsigned char i;
#define h 7 //左右转速度
#define l 10
#define m 7 //左右转速度
#define n 11
#define o 5 //小车直行速度
#define p 30
sbit Trig=P2^3; //超声波模块
sbit Echo=P2^4;
unsigned int time=0;
unsigned int timer=0;
unsigned char posit=0;
unsigned long L=0;
sbit left1 = P0^4; //红外对管
sbit right1 = P0^6;
sbit left2 = P0^3;
sbit right2 =P0^5;
sbit IN1 = P2^1;
sbit IN2 = P2^0;
sbit IN3 = P0^0;
sbit IN4 = P0^1;
sbit ENA = P2^2;
sbit ENB = P0^2;
sbit IN5 = P3^7; //小车使能口
sbit IN6 = P3^6;
sbit IN7 = P1^1;
sbit IN8 = P1^0;
sbit ENA1 = P3^5;
sbit ENB1 = P1^2;
void count();
void bizhang();
void xunji();
void xunji2();
void Delay2(unsigned int xms) //@12.000MHz //延时函数
{
unsigned char i, j;
while(xms)
{
i = 2;
j = 190;
do
{
while (--j);
} while (--i);
xms--;
}
}
void Delay(unsigned int xms) //@12.000MHz
{
unsigned char i, j;
while(xms)
{
if(Echo==0)
{
next:
break;
}
i = 2;
j = 190;
do
{
while (--j)
{
if(Echo==0)
{
goto next;
}
}
}
while (--i);
xms--;
}
}
void count() //超声波模块检测
{
Trig = 1;
_nop_(); _nop_(); _nop_(); _nop_();
_nop_(); _nop_(); _nop_(); _nop_();
_nop_(); _nop_(); _nop_(); _nop_();
_nop_(); _nop_(); _nop_(); _nop_();
_nop_(); _nop_(); _nop_(); _nop_();
Trig = 0;
while( !Echo ); //µè'y·?éú??2¨
TR0 = 1;
while( Echo ) //µè'y?óêü??2¨
{
xunji();
}
TR0 = 0;
time = TH0 * 256 + TL0;
L = 0.17 * time;
TH0 = 0;
TL0 = 0;
if(L>270)
{
xunji2();
}
else
{
bizhang();
}
}
void forward( int a , int b )
{
IN1 = 1;
IN2 = 0;
IN3 = 1;
IN4 = 0;
IN5 = 1;
IN6 = 0;
IN7 = 1;
IN8 = 0;
ENA =1; ENB =1; ENA1=1; ENB1=1; Delay(a);
if(Echo==0)
{
goto flag;
}
ENA =0; ENB =0; ENA1=0; ENB1=0;
flag:
Delay(b);
}
void stop()
{
IN1 = 0;
IN2 = 0;
IN3 = 0;
IN4 = 0;
IN5 = 0;
IN6 = 0;
IN7 = 0;
IN8 = 0;
}
void turnright( int a , int b )
{
IN1 = 0;
IN2 = 1;
IN3 = 1;
IN4 = 0;
IN5 = 0;
IN6 = 1;
IN7 = 1;
IN8 = 0;
ENA =1; ENB =1; ENA1=1; ENB1=1; Delay(a);
if(Echo==0)
{
goto flag;
}
ENA =0; ENB =0; ENA1=0; ENB1=0;
flag:
Delay(b);
}
void turnleft( int a , int b )
{
IN1 = 1;
IN2 = 0;
IN3 = 0;
IN4 = 1;
IN5 = 1;
IN6 = 0;
IN7 = 0;
IN8 = 1;
ENA =1; ENB =1; ENA1=1; ENB1=1; Delay(a);
if(Echo==0)
{
goto flag;
}
ENA =0; ENB =0; ENA1=0; ENB1=0;
flag:
Delay(b);
}
void forward2( int a , int b )
{
IN1 = 1;
IN2 = 0;
IN3 = 1;
IN4 = 0;
IN5 = 1;
IN6 = 0;
IN7 = 1;
IN8 = 0;
ENA =1; ENB =1; ENA1=1; ENB1=1; Delay2(a);
ENA =0; ENB =0; ENA1=0; ENB1=0; Delay2(b);
}
void turnright2( int a , int b )
{
IN1 = 0;
IN2 = 1;
IN3 = 1;
IN4 = 0;
IN5 = 0;
IN6 = 1;
IN7 = 1;
IN8 = 0;
ENA =1; ENB =1; ENA1=1; ENB1=1; Delay2(a);
ENA =0; ENB =0; ENA1=0; ENB1=0; Delay2(b);
}
void turnleft2( int a , int b )
{
IN1 = 1;
IN2 = 0;
IN3 = 0;
IN4 = 1;
IN5 = 1;
IN6 = 0;
IN7 = 0;
IN8 = 1;
ENA =1; ENB =1; ENA1=1; ENB1=1; Delay2(a);
ENA =0; ENB =0; ENA1=0; ENB1=0; Delay2(b);
}
void xunji() //循迹函数 使小车在黑色轨道上循迹
{
if((left1 == 0)&&(left2 == 0)&&(right1 == 0)&&(right2 == 0)) //0 0 0 0
{
forward( o,p );
if(Echo==0)
{
goto labell;
}
}
if((left1 == 0)&&(left2 == 0)&&(right1 == 0)&&(right2 == 1)) //0 0 0 1
{
turnright( h,l );
if(Echo==0)
{
goto labell;
}
}
if((left1 == 0)&&(left2 == 0)&&(right1 == 1)&&(right2 == 0)) //0 0 1 0
{
turnright( h,l );
if(Echo==0)
{
goto labell;
}
}
if((left1 == 0)&&(left2 == 0)&&(right1 == 1)&&(right2 == 1)) //0 0 1 1
{
turnright( h,l );
if(Echo==0)
{
goto labell;
}
}
if((left1 == 0)&&(left2 == 1)&&(right1 == 0)&&(right2 == 0)) //0 1 0 0
{
turnleft( 9,11 );
if(Echo==0)
{
goto labell;
}
}
if((left1 == 0)&&(left2 == 1)&&(right1 == 0)&&(right2 == 1)) //0 1 0 1
{
turnright( h,l );
if(Echo==0)
{
goto labell;
}
}
if((left1 == 0)&&(left2 == 1)&&(right1 == 1)&&(right2 == 0)) //0 1 1 0
{
forward( o,p );
if(Echo==0)
{
goto labell;
}
}
if((left1 == 0)&&(left2 == 1)&&(right1 == 1)&&(right2 == 1)) //0 1 1 1
{
turnright( h,l );
if(Echo==0)
{
goto labell;
}
}
if((left1 == 1)&&(left2 == 0)&&(right1 == 0)&&(right2 == 0)) //1 0 0 0
{
turnleft( 9,11 );
if(Echo==0)
{
goto labell;
}
}
if((left1 == 1)&&(left2 == 0)&&(right1 == 0)&&(right2 == 1)) //1 0 0 1
{
forward( o,p );
if(Echo==0)
{
goto labell;
}
}
if((left1 == 1)&&(left2 == 0)&&(right1 == 1)&&(right2 == 0)) //1 0 1 0
{
turnleft( h,l );
if(Echo==0)
{
goto labell;
}
}
if((left1 == 1)&&(left2 == 0)&&(right1 == 1)&&(right2 == 1)) //1 0 1 1
{
forward( o,p );
if(Echo==0)
{
goto labell;
}
}
if((left1 == 1)&&(left2 == 1)&&(right1 == 0)&&(right2 == 0)) //1 1 0 0
{
turnleft( h,l );
if(Echo==0)
{
goto labell;
}
}
if((left1 == 1)&&(left2 == 1)&&(right1 == 0)&&(right2 == 1)) //1 1 0 1
{
forward( o,p );
if(Echo==0)
{
goto labell;
}
}
if((left1 == 1)&&(left2 == 1)&&(right1 == 1)&&(right2 == 0)) //1 1 1 0
{
turnleft( h,l );
if(Echo==0)
{
goto labell;
}
}
labell:
if((left1 == 1)&&(left2 == 1)&&(right1 == 1)&&(right2 == 1)) //1 1 1 1
forward( o,p );
}
//检测到黑色返回1
//检测到白色返回0
void xunji2()
{
if((left1 == 0)&&(left2 == 0)&&(right1 == 0)&&(right2 == 0)) //0 0 0 0
{
forward2( o,p );
}
if((left1 == 0)&&(left2 == 0)&&(right1 == 0)&&(right2 == 1)) //0 0 0 1
{
turnright2( m,n );
}
if((left1 == 0)&&(left2 == 0)&&(right1 == 1)&&(right2 == 0)) //0 0 1 0
{
turnright2( m,n );
}
if((left1 == 0)&&(left2 == 0)&&(right1 == 1)&&(right2 == 1)) //0 0 1 1
{
turnright2( m,n );
}
if((left1 == 0)&&(left2 == 1)&&(right1 == 0)&&(right2 == 0)) //0 1 0 0
{
turnleft2( 11,11 );
}
if((left1 == 0)&&(left2 == 1)&&(right1 == 0)&&(right2 == 1)) //0 1 0 1
{
turnright2( m,n );
}
if((left1 == 0)&&(left2 == 1)&&(right1 == 1)&&(right2 == 0)) //0 1 1 0
{
forward2( o,p );
}
if((left1 == 0)&&(left2 == 1)&&(right1 == 1)&&(right2 == 1)) //0 1 1 1
{
turnright2( m,n );
}
if((left1 == 1)&&(left2 == 0)&&(right1 == 0)&&(right2 == 0)) //1 0 0 0
{
turnleft2( 11,11 );
}
if((left1 == 1)&&(left2 == 0)&&(right1 == 0)&&(right2 == 1)) //1 0 0 1
{
forward2( o,p );
}
if((left1 == 1)&&(left2 == 0)&&(right1 == 1)&&(right2 == 0)) //1 0 1 0
{
turnleft2( m,n );
}
if((left1 == 1)&&(left2 == 0)&&(right1 == 1)&&(right2 == 1)) //1 0 1 1
{
forward2( o,p );
}
if((left1 == 1)&&(left2 == 1)&&(right1 == 0)&&(right2 == 0)) //1 1 0 0
{
turnleft2( m,n );
}
if((left1 == 1)&&(left2 == 1)&&(right1 == 0)&&(right2 == 1)) //1 1 0 1
{
forward2( o,p );
}
if((left1 == 1)&&(left2 == 1)&&(right1 == 1)&&(right2 == 0)) //1 1 1 0
{
turnleft2( m,n );
}
if((left1 == 1)&&(left2 == 1)&&(right1 == 1)&&(right2 == 1)) //1 1 1 1
forward2( o,p );
}
void bizhang() //避开障碍物的固定运动状态,可根据实际改变
{
int b;
for(b=1;b<30;b++)
{
turnright2( 7 , 3 );
}
for(b=1;b<85;b++)
{
forward2( 3 , 7 );
}
for(b=1;b<60;b++)
{
turnleft2( 7 , 3 );
}
xunji2();
}
void csbko( ) //超声波定时器t0初始化
{
TMOD |= 0x01;
TH0 = 0x00;
TL0 = 0x00;
IT0 = 1;
ET0 = 1;
EX0 = 1;
EA = 1;
}
void ko() // 蓝牙模块t1定时器初始化
{
SCON=0X50;
TMOD|=0X20;
PCON=0X00;
TH1=0Xfd;
TL1=0Xfd;
TR1= 1;
ES = 1;
EA = 1;
}
void main() //主函数
{
ko();
csbko();
while(1)
{
switch(i) // 遥控函数
{
case ('A'):
forward( 1,100);break;
case ('B'):
count() ;break;
case ('C'):
turnleft( 1,100 );;break;
case ('D'):
turnright( 1,100 );break;
case ('E'):
stop();break;
}
}
}
void Timer0( ) interrupt 1 //超声波定时器中断
{
if(TH0*256+TL0>300)
{
Echo = 1;
}
}
void bai() interrupt 4 // 蓝牙模块定时器中断 发射固定的波特率
{
EA = 0;
if(RI == 1)
{
RI=0;
i = SBUF;
}
EA = 1;
}
2.蓝牙遥控器程序:
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit key1 = P1^0;
sbit key2 = P1^1;
sbit key3 = P1^2;
sbit key4 = P1^3;
sbit key5 = P1^4;
sbit key6 = P1^5;
sbit key7 = P1^6;
sbit key8 = P1^7;
void delay(uint z)
{
uint x,y;
for(x = z; x > 0; x--)
for(y = 114; y > 0 ; y--);
}
void UART_init()
{
SCON=0X50;
TMOD|=0X20;
PCON=0X00;
TH1=0Xfd;
TL1=0Xfd;
TR1= 1;
ES = 1;
EA = 1;
}
void main()
{
UART_init();
while(1)
{
if(!key1||!key2||!key3||!key4||!key5)//if(!key1||!key2||!key3||!key4||!key5||!key6||!key7||!key8)
TI = 1;
}
}
void UART() interrupt 4
{
char key;
if(TI)
{
TI = 0;
if(!key1)SBUF = 'B';
if(!key2)SBUF = 'D';
if(!key3)SBUF = 'C';
if(!key4)SBUF = 'A';
if(!key5)SBUF = 'E';
delay(10);
}
if(RI)
{
RI=0;
key=SBUF;
if(key=='1')
key1=0;
else
key1=1;
}
}
三. 注意事项
1.蓝牙配对
2.材料挑选
大家在买材料的时候,不要挑便宜的元气件,我们组在元器件超声波上就换花费了很多时间。大家尽量从正规的渠道买,不要买太便宜的。
3.调节红外对管
灵敏度:
当光敏三极管未导通时(发射的红外线遇到黑线被吸收),经过比较器OUT输出为1,当光敏三极管导通时(红外线被反射回来),OUT输出为0。
位置:
一共需要4个红外对管,2个红外对管(A,B)放在车最前,2个(C,D)放在车头靠后一点的地方,C, D两个之间的间距要大于A B两个之间的间距且C D两个红外对管,头要斜向车外,成八字此种方案可以流畅通过循迹路线的十字路口和直角弯,D形弯,
4.电池:
小车的电池电压对小车在运动过程中的影响,影响小车的运行速度,影响小车在循迹中转弯的速度。在比赛前要及时测量小车电池电压并记录。
四.项目心得
在小车制作中,团队的合作是至关重要的,我们小队在项目进行中经常会在一起讨论,在项目初期,我们小组分成两部分同时进行,硬件制作和程序实现,我们开始的时候将小车避障想的很复杂,用舵机,辅助避障,但在编写中,由于51单片机的定时器少,用软件延时来启动超声波,没有实行,这在比赛的时候,给我们小组带来了一些遗憾。在红外循迹实现的过程中,小车在初期用的是pwm定时器在进行调速,用pwm定时器来进行调速的时候,可以对小车的4个轮子分别实现不同的速度,在循迹中小车的姿态良好,我们小组在项目初期的进度很快,在项目中期 ,蓝牙遥控,超声波舵机辅助避障,红外对管巡线, 已经实现,我们进行总程序的合成,我们开始用分块法将程序进行分块,但小车的各功能实现的不理想,我又对程序进行的拆改,终于改出了最后的程序,由于编程水平有限,我们将避障功能中的舵机去除。在避障和巡线同时进行中,超声波,蓝牙,pwm,三者出现了冲突,我们将小车中pwm去除,改用软件延时函数来对小车进行调速,在实现中,延时函数对程序整体,压力过大,同时电池电量对小车的状态产生的影响加大。这不得不让我们随时记录小车电池的电压(小车运行良好的电压为11.3~11.6)。在巡线初期中,红外对管的位置,不是最理想的位置,我们对小车的红外对管的灵敏度进行的很多的调整,中间出了很多的麻烦。在比赛的时候小车的电量不是很理想,在巡线中,速度过低,小车完成蓝牙遥控,红外循迹加避障的总时间为1分59秒,获得了三等奖,这对我们小组成员来说还不是很理想,但重要的是过程。在小车这个项目中,我学到了很多,团队协作,交流,耐心,一个人并不能完成所有的事情,这不能搞个人主意,提高编程实力,还要理论联系实际。
乱糟糟的桌面 :