这种方法呢实现起来是最简单的,对于0基础的可以尝试一下,障碍物检测距离一般在20cm左右,在车速不太快,而且在室内(也就是无阳光直射)时是可行的,也可以很好的实现避障。
缺点呢或者说不足之处,也就很明确了,在室外(或者阳光直射时)传感器受阳光干扰可能不能正常工作,检测距离20cm左右,车速过快时,在检测到障碍物时,不能直接转弯(因为车速过快,还没来得及转弯可能就撞上了),需要往回倒一下,再转弯。
这种方法呢,避障思路跟利用4路红外寻迹避障传感器模块实现避障是相同的,只是换了传感器类型而已,但是漫反射光电传感器抗阳光干扰能力强,克服了4路红外寻迹避障传感器模块在室外(或者阳光直射时)传感器受阳光干扰可能不能正常工作的缺点。
缺点呢或者说不足之处,检测距离也在20cm附近,依然没能克服车速过快时,在检测到障碍物时,不能直接转弯的不足,而且呢漫反射光电传感器模块体积、重量、价格都要高一些。
这种方法呢,利用超声波模块测距远,一般常见的超声波模块测距最远在4.5米左右,完全不用担心车速过快来不及反应的情况,而且基本不受阳光干扰(当环境温度升高时,声音的传播速度会加快,对测距产生一定的误差,但是误差很小很小,对于超声波模实现避障来说完全可以忽略)也就是说超声波模块很好的解决了以上两个问题
缺点呢或者说不足之处,也很明确,从避障思路我们可以看出这种方案小车不能连续的运动,当遇到障碍物时,小车就会停下来判断下一步该往哪个方向转弯,除此之外,超声波模块用起来比前两种难一些
这种思路结合了这两种传感器的优点,互补了他们的不足,即同时克服阳光直射时传感器不能正常工作、车速过快时,在检测到障碍物时,不能直接转弯、遇到障碍物需要停车判断 这三种不足可以说是一种比较理想的方案。唯一的缺点呢,就是超声波模块本身用起来难度要大一些,当然对富有挑战精神的人,也就不算缺点了
sbit Trig= P1^4; //产生脉冲引脚
sbit Echo= P1^5; //回波引脚
void StartModule() //启动超声波模块
{
Trig=1;
_nop_(); //此语句是空语句,用来延时,也就是满足高电平持续10us以上的要求
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
Trig=0;
}
void Timer0Init() //定时器0初始化函数
{
TMOD|=0X01;//选择为定时器0模式,工作方式1,仅用TR0打开启动。
TH0=0XFC; //给定时器赋初值,定时1ms
TL0=0X18;
ET0=1;//打开定时器0中断允许
EA=1;//打开总中断
TR0=1;//打开定时器
}
void timer0()interrupt 1 using 2 //定时器0中断函数
{
TH0=0XFC; //给定时器赋初值,定时1ms
TL0=0X18;
time++;
pwm_val_left++;
pwm_val_right++;
pwm_out_left_moto();
pwm_out_right_moto();
//以下内容是新加的:
HC_SR04_time++;
if(HC_SR04_time>=250) //250ms 启动一次超声波测距
{
HC_SR04_time=0;
StartModule();
}
}
void Timer1Init() //定时器1初始化
{
TMOD|=0X10;//选择为定时器1模式,工作方式1,仅用TR1打开启动。
TH1=0;
TL1=0;
ET1=1;//打开定时器1中断允许
EA=1;//打开总中断
TR1=1;//打开定时器
}
void Timer1() interrupt 3 //定时器1溢出中断
{
flag=1; //若定时器1溢出则flag置1
}
void Conut(void) //计算障碍物距离函数
{
measure_time=TH1*256+TL1;
TH1=0;
TL1=0;
S=(measure_time*1.87)/100; //这就是计算距离的公式,参数1.87根据实际情况调节,算出来是CM
if(flag==1||S>50) //超出测量或者超出设定的距离
{
flag=0;
LED=1; //此处是测试用的,我用的单片机在P00上接了个LED
}
else
LED=0;
}
void main() //主函数
{
Timer0Init();
Timer1Init();
Left_Speed_Ratio=5; //设置左电机车速为最大车速的50%
Right_Speed_Ratio=5; 设置右电机车速为最大车速的50%
while(1)
{
if(Echo==1)
{
TH1=0;
TL1=0;
TR1=1; //开启计数
while(Echo); //当RX为1计数并等待
TR1=0; //关闭计数
Conut(); //计算
}
// run();
// delay1s(); delay1s(); delay1s(); delay1s(); delay1s();
}
}
if(M_sensor==1)
{ run(); }
else
{
if(L_sensor==1)
{ left(); }
else if(R_sensor==1)
{ right() ; }
else
{ back(); }
}
void left(void) //小车左转
{
push_val_left =Left_Speed_Ratio;
push_val_right =Right_Speed_Ratio;
Right_moto_go();
Left_moto_back();
}
void right(void) //小车右转
{
push_val_left =Left_Speed_Ratio;
push_val_right =Right_Speed_Ratio;
Right_moto_back();
Left_moto_go();
#include
extern unsigned char Left_Speed_Ratio;
extern unsigned char Right_Speed_Ratio;
unsigned int time=0;
unsigned int HC_SR04_time=0;
extern unsigned char pwm_val_left;
extern unsigned char pwm_val_right;
bit flag =0;
extern char M_sensor;
void delay1s(void)
{
unsigned char a,b,c;
for(c=167;c>0;c--)
for(b=171;b>0;b--)
for(a=16;a>0;a--);
_nop_();
}
void delay1ms(void)
{
unsigned char a,b,c;
for(c=1;c>0;c--)
for(b=142;b>0;b--)
for(a=2;a>0;a--);
}
void Timer0Init()
{
TMOD|=0X01;//选择为定时器0模式,工作方式1,仅用TR0打开启动。
TH0=0XFC; //给定时器赋初值,定时1ms
TL0=0X18;
ET0=1;//打开定时器0中断允许
EA=1;//打开总中断
TR0=1;//打开定时器
}
void Timer1Init()
{
TMOD|=0X10;//选择为定时器1模式,工作方式1,仅用TR1打开启动。
TH1=0;
TL1=0;
ET1=1;//打开定时器1中断允许
EA=1;//打开总中断
TR1=1;//打开定时器
}
void timer0()interrupt 1 using 2
{
TH0=0XFC; //给定时器赋初值,定时1ms
TL0=0X18;
time++;
pwm_val_left++;
pwm_val_right++;
pwm_out_left_moto();
pwm_out_right_moto();
HC_SR04_time++;
if(HC_SR04_time>=300) //300ms 启动一次超声波测距
{
HC_SR04_time=0;
StartModule();
}
}
void Timer1() interrupt 3
{
flag=1; //若定时器1溢出则flag置1
}
void main()
{
Timer0Init();
Timer1Init();
Left_Speed_Ratio=6; //设置左电机车速为最大车速的50%
Right_Speed_Ratio=6; 设置右电机车速为最大车速的50%
while(1)
{
if(Echo==1)
{
TH1=0;
TL1=0;
TR1=1; //开启计数
while(Echo); //当RX为1计数并等待
TR1=0; //关闭计数
Conut(); //计算
}
if(M_sensor==1)
{ run(); }
else
{
if(L_sensor==1)
{ left(); }
else if(R_sensor==1)
{ right() ; }
else
{ back(); }
}
}
}
#include
unsigned char pwm_val_left =0;
unsigned char push_val_left =0;
unsigned char pwm_val_right =0;
unsigned char push_val_right=0;
unsigned char Left_Speed_Ratio;
unsigned char Right_Speed_Ratio;
bit Left_moto_stop =1;
bit Right_moto_stop =1;
void Left_moto_go() //左电机正转
{p34=0;p35=1;}
void Left_moto_back() //左电机反转
{p34=1;p35=0;}
void Left_moto_stp() //左电机停转
{p34=1;p35=1;}
void Right_moto_go() //右电机正转
{p36=0;p37=1;}
void Right_moto_back() //右电机反转
{p36=1;p37=0;}
void Right_moto_stp() //右电机停转
{p36=1;p37=1;}
void pwm_out_left_moto(void) //左电机PWM
{
if(Left_moto_stop)
{
if(pwm_val_left<=push_val_left)
Left_moto_pwm=1;
else
Left_moto_pwm=0;
if(pwm_val_left>=10)
pwm_val_left=0;
}
else
Left_moto_pwm=0;
}
void pwm_out_right_moto(void) //右电机PWM
{
if(Right_moto_stop)
{
if(pwm_val_right<=push_val_right)
Right_moto_pwm=1;
else
Right_moto_pwm=0;
if(pwm_val_right>=10)
pwm_val_right=0;
}
else
Right_moto_pwm=0;
}
void run(void) //小车前行
{
push_val_left =Left_Speed_Ratio;
push_val_right =Right_Speed_Ratio;
Left_moto_go();
Right_moto_go();
}
void back(void) //小车后退
{
push_val_left =Left_Speed_Ratio;
push_val_right =Right_Speed_Ratio;
Left_moto_back();
Right_moto_back();
}
void left(void) //小车左转
{
push_val_left =Left_Speed_Ratio;
push_val_right =Right_Speed_Ratio;
Right_moto_go();
Left_moto_back();
}
void right(void) //小车右转
{
push_val_left =Left_Speed_Ratio;
push_val_right =Right_Speed_Ratio;
Right_moto_back();
Left_moto_go();
}
void stop(void) //小车停止
{
push_val_left =Left_Speed_Ratio;
push_val_right =Right_Speed_Ratio;
Left_moto_stp();
Right_moto_stp();
}
void rotate(void) //小车原地转圈
{
push_val_left =Left_Speed_Ratio;
push_val_right =Right_Speed_Ratio;
Left_moto_back();
Right_moto_go();
}
#include
float S=0;
extern bit flag;
unsigned int measure_time;
char M_sensor;
void StartModule() //启动超声波模块
{
Trig=1;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
Trig=0;
}
void Conut(void)
{
measure_time=TH1*256+TL1;
TH1=0;
TL1=0;
S=(measure_time*1.87)/100; //算出来是CM
if(flag==1||S>50||S<2) //超出测量
{
flag=0;
LED=1;
M_sensor=1;
}
else
{
LED=0;
M_sensor=0;
}
}
#ifndef __car_H
#define __car_H
#include
#include
sbit Left_moto_pwm=P1^6 ;
sbit Right_moto_pwm=P1^7;
sbit p34=P3^4;
sbit p35=P3^5;
sbit p36=P3^6;
sbit p37=P3^7;
sbit Trig= P1^4; //产生脉冲引脚
sbit Echo= P1^5; //回波引脚
sbit LED=P0^0;
sbit L_sensor=P2^0;
sbit R_sensor=P2^1;
void Left_moto_go() ;
void Left_moto_back() ;
void Left_moto_stp() ;
void Right_moto_go();
void Right_moto_back();
void Right_moto_stp();
void delay(unsigned int k) ;
void delay1s(void) ;
void delay1ms(void);
void pwm_out_left_moto(void) ;
void pwm_out_right_moto(void);
void run(void);
void back(void);
void left(void);
void right(void);
void stop(void);
void rotate(void);
void StartModule() ;
void Timer1Init();
void Timer0Init();
void Conut(void);
#endif
本文到这里就结束了,本文介绍的内容的完整的keil文件会放在附件里,需要者自取,我放的时候都是免费的,但是过段时间它会自己涨…需要的在评论区留言我可以直接发给你,欢迎大家继续阅读本系列的后续文章“详细介绍如何从零开始制作51单片机控制的智能小车(四)———通过蓝牙模块实现数据传输以及对小车状态的控制”
欢迎大家积极交流,本文未经允许谢绝转载