超声波避障小车

摘要:介绍了使用一路超声波测距和两路红外测障的自动避障小车
##功能实现:
材料:51单片机,L298N模块,超声波模块HC-SR04,Sg90舵机,红外传感器,18650电池
###硬件连接:
###代码编写:
####马达运动:
调节L298N的IN接口,控制电机正反转,通过变量PWMA和PWMB调节占空比从而调节小车左右轮的速度。

#include <REGX51.H>
sbit IN1 = P2^4;
sbit IN2 = P2^3;
sbit IN3 = P2^2;
sbit IN4 = P2^1;
extern unsigned char PWMA,PWMB;
void straight()
{
IN1 = 1;
IN2 = 0;
PWMA = 25;
IN3 = 0;
IN4 = 1;
PWMB = 25;
}
void turnleft()
{
IN1 = 1;
IN2 = 0;
PWMA = 34;
IN3 = 1;
IN4 = 0;
PWMB = 21;
}
void turnright()
{
IN1 = 0;
IN2 = 1;
PWMA = 21;
IN3 = 0;
IN4 = 1;
PWMB = 35;
}
void back()
{
IN1 = 0;
IN2 = 1;
PWMA = 30;
IN3 = 1;
IN4 = 0;
PWMB = 30;
}
void stop()
{
IN1 = 1;
IN2 = 1;
PWMA = 0;
IN3 = 1;
IN4 = 1;
PWMB = 0;
}

####马达速度的调节:
分别为左,右两侧马达提供pwm调节,通过调节PWMA与PWMB,可以调整输出的占空比从而控制速度。

void  main()
{
TMOD|=0x11; //定时器0定时器1,工作方式1
TH0=0;
TL0=0;
TH1=0xFE; //定时器1 500us定时
TL1=0x33;
ET0=1; //定时器0中断使能
ET1=1; //定时器1中断使能
TR1=1; //定时器1开始计时
EA=1; //开启总中断
}
void Tmr1_isr() interrupt 3
{
TH1=0xFE; //500us
TL1=0x33;
i++;
j++;
//电机调速pwm
if(i < PWMA)
{
ENA = 1;
}
else
{
ENA = 0;
if(i >= 100)
{
i = 0;
}
}
if(j < PWMB)
{
ENB = 1;
}
else
{
ENB = 0;
if(j >= 100)
{
j = 0;
}
}
}

####舵机的控制:
每500微秒执行一次中断,每执行一次通过counter计数,执行40次清零,输出周期为20ms的波形,通过调节angle改变占空比,从而控制舵机的角度。angle为1,2,3,4时,角度分别为0,45,90,135度。

void Tmr1_isr() interrupt 3 
{
TH1=0xFE; //500us
TL1=0x33;
counter++;//中断次数,即:多少个0.5ms
//舵机角度
if(counter <= angle) //angle个0.5ms提供高电平
sg90 = 1;
if(counter > angle && counter <= 40) //40-angle个0.5ms提供低电平
sg90 = 0;
if(counter > 40) //清零counter
counter = 0;
}

####超声波测距:
先给Tirg大于10us的高电平作为触发信号,通过检测echo口输出高电平的时间,得到从发射到返回所用的时间。

#include <REGX51.H>
#include <intrins.h>
void delayms(unsigned int ms);
sbit Echo = P1^5;
sbit Trig = P1^6;
sbit sg90 = P1^7;
extern unsigned int time; //时间
extern unsigned int S; //距离
void hcsr04()
{
Trig=1;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_(); //大于10us的触发信号
Trig=0;
while(!Echo); //当Echo为零时等待
TR0=1; //开启计数
while(Echo); //当Echo为1时,计时并等待
TR0=0; //关闭计时
}
void count(void)
{
time=(TH0*256+TL0)*1.085; //计数器每加一次,1us
TH0=0;
TL0=0; //清零定时器0计数
S=time*0.017; //计算距离,单位CM
delayms(2); //一定要延迟,否则舵机和超声波运行不正常!
}

####小车的运行:
未命名文件-导出 (2).png
默认直行,若前方有障碍物,则优先右转,若右方也有障碍物,则向左转,若两侧都有障碍物,则后退并且优先向右转,若右侧有障碍物,再向左转。
若小车左侧或右侧被墙角卡住,则红外传感器发出低电平,小车后退并优先向右转。

#include <REGX51.H>
#include "motor.h"
void count();
void hcsr04();
void delayms(unsigned int ms);
void run();
extern unsigned int S;
extern unsigned char angle;
sbit left_d=P3^7;//红外测障
sbit right_d=P3^6;
void run()
{
if(right_d==0)
{
back();
delayms(500);
angle=2;
delayms(200);
hcsr04();
count();
}
if(left_d==0)
{
back();
delayms(500);
angle=2;
delayms(200);
hcsr04();
count();
if(angle ==3 && S >= 20)
{
straight();
hcsr04();
count();
}
else if(angle ==3 && S < 20)
{
stop();
angle = 2;
delayms(200);
hcsr04();
count();
}
if(angle == 2 && S >=20)
{
turnright();
delayms(500);
angle =3;
delayms(200);
hcsr04();
count();
}
else if(angle == 2 && S < 20)
{
angle = 4;
delayms(200);
hcsr04();
count();
}
if(angle == 4 && S >=20)
{
turnleft();
delayms(500);
angle =3;
delayms(200);
hcsr04();
count();
}
else if(angle == 4 && S <20)
{
back();
delayms(500);
angle =3;
delayms(200);
hcsr04();
count();
}
}