个人项目分享——基于51单片机寻迹避障运输小车的制作

       寒假无聊,总结下目前所学到,做过的项目。这是第一篇博客,就从一个简单的项目(大二做的课程设计)51单片机寻迹避障运输小车开始说起。。。。。好!转回正题。

小车主要实现的功能:(1)当有物品放上小车上时,小车开动掉头进行循迹,去到目的地停下;(2)当拿走物体时,小车自动掉头循迹回到初始位置。(3)在途中如果遇到障碍物时,会停止前进等待障碍物撤除后再继续前进。

视频演示1          视频演示2   

因为当时是课程设计,用的时间比较短,也比较紧凑。程序编写方面还是会有一些BUG,所以这篇博客仅用作给需要的朋友参考。。谢谢

①首先列举下本项目使用到的模块以及传感器:

       所使用到的传感器都是从某宝买回来的,比较廉价,对于我们初学者来说也算是比较实用。说一些比较主要的模块。

循迹功能需要使用到的传感器主要是红外传感器。传感器原理很简单,每个探头都有一个发送红外线端,一节接收端,上电后,白色探头会不停发送红外光,当没遇到黑线时,红外光会反射回来给接收探头接收;当遇到黑线时,黑线会将红外线吸收,就不会有反射光反射回来给接收端接收,相应地与单片机接收端也会有相应的高低电平返回。利用这些高低电平就可以判断小车当前的位置。以便给单片机作处理。

                                                            个人项目分享——基于51单片机寻迹避障运输小车的制作_第1张图片

 

避障功能需要用到超声波模块。

基本工作原理:

(1)采用 IO 口 TRIG 触发测距,给最少 10us 的高电平信呈。

(2)模块自动发送 8 个 40khz 的方波,自动检测是否有信号返回;

(3)有信号返回,通过 IO 口 ECHO 输出一个高电平,高电平持续的时间就是超声 波从发射到返回的时间。测试距离=(高电平时间*声速(340M/S))/2;

如右图接线,VCC 供 5V 电源,GND 为地线, TRIG 触发控制信号输 入,ECHO 回响信号输出等四个接口端的。

                                                                       个人项目分享——基于51单片机寻迹避障运输小车的制作_第2张图片              

车上是否有物品判别:压力传感器    (电阻式薄膜+转换模块) 根据压力大小输出模拟值(电压值)或数字值(0或1)                                                                   

                                          个人项目分享——基于51单片机寻迹避障运输小车的制作_第3张图片 

电机驱动模块、电源稳压模块这些都是小车的驱动必不可少的拉

                                  个人项目分享——基于51单片机寻迹避障运输小车的制作_第4张图片                                                   个人项目分享——基于51单片机寻迹避障运输小车的制作_第5张图片

②再看看这里面的小算法(调速算法)。当然你也可以尝试使用光码盘测速,再去用pid算法进行调速。。。

当你着手去做这个项目时,你会发现单单几个传感器和单片机自身,他们的处理能力和精度是很有限的,而直接驱动小车电机会使得车速过快,单片机处理不过来而做不到循迹这个功能。

这里就要引入PWM波来对电机的转速进行调速了。

PWM(脉宽调制)基本原理:控制方式就是对逆变电路开关器件的通断进行控制,使输出端得到一系列幅值相等的脉冲,用这些脉冲来代替正弦波或所需要的波形。也就是在输出波形的半个周期中产生多个脉冲,使各脉冲的等值电压为正弦波形,所获得的输出平滑且低次谐波少。按一定的规则对各脉冲的宽度进行调制,即可改变逆变电路输出电压的大小,也可改变输出频率。

然而在单片机怎样实现呢??单片机虽然比较低端,但是还是会有定时器这些基本功能。我们可以通过设定两个比较值,当push_value(设定值)>pwm_value(定时器计数值)则将io口置1否则置0。当计数值>设定值再重新置0重新计数。就可达到pwm的可调输出了。PWM生成具体实现代码如下:

//左轮PWM函数
void pwm_left(void){
	if(push_value_left!=0){
		if(pwm_value_left20)
			pwm_value_left=0;
	}
}
//右轮PWM函数
void pwm_right(void){
	if(push_value_right!=0){
		if(pwm_value_right20)
			pwm_value_right=0;
	}
}
//实现PWM的中断函数
void timer0() interrupt 1 using 2{
	TH0=0XFC;  //重新赋初值
    TL0=0X66;
    pwm_value_left++;
    pwm_value_right++;
    pwm_left();
    pwm_right();
}

③说得差不多了。。。搭建小车

                                                            个人项目分享——基于51单片机寻迹避障运输小车的制作_第6张图片

④最后,贴下完整代码:

#include 
#include	
#define unint unsigned int		  
unsigned int  time=0;			 //定时器时间
unsigned long distance=0;	     //计算距离
bit flag =0;				     //忙标记位
int S;//距离计算变量

//超声波和蜂鸣器引脚
sbit Trig = P1^6;
sbit Echo = P1^7;
sbit led=P0^0;
sbit kaiguan=P3^7;
sbit yali=P1^4;
//传感器引脚
sbit left = P2^0;
sbit middle = P2^1;
sbit right = P2^2;

//电机驱动模块引脚定义,zh:正,fu:负
sbit leftzh = P1^0; 
sbit leftfu = P1^1; 
sbit rightzh = P1^2;
sbit rightfu = P1^3;
//PWM和push值以及临时变量定义
unint pwm_forward_left = 0;
unint pwm_forward_right = 0;
unint push_forward_left = 0;
unint push_forward_right = 0;
unint pwm_back_left = 0;
unint pwm_back_right = 0;
unint push_back_left = 0;
unint push_back_right = 0;
unint num,num1= 0;
unint start = 0;
//延时x毫秒
void delay(unint xms){
	unint i,j;
	for(i=xms;i>0;i--)
		for(j=110;j>0;j--);
}
//正常前进函数,普通速度
void run(void){
	rightfu=0;
	leftfu=0;
	push_forward_left=7;
	push_forward_right=7;
	push_back_left=0;
	push_back_right=0;
}
//停止函数
void stop(void){
	push_forward_left=0;
	push_forward_right=0;
	push_back_left=0;
	push_back_right=0;
	leftzh=1;
	leftfu=1;
	rightzh=1;
	rightfu=1;
}  

//右直角转弯函数
void right_90(void){
	push_forward_right=0;
	push_back_left=0;
	push_forward_left=8;
	push_back_right=8;
	leftfu=0;
	rightzh=0;
}
//前左转函数
void turn_left(void){
	rightfu=0;
	push_forward_left=0;
	push_forward_right=8;
	push_back_left=0;
	push_back_right=0;
	leftzh=0;
	leftfu=0;
} 
//前右转函数
void turn_right(void){
	leftfu=0;
	push_back_left=0;
	push_back_right=0;
	push_forward_right=0;
	push_forward_left=8;
	rightzh=0;
	rightfu=0;
}
void back_right()
 {
    push_back_left=0;
	push_back_right=0;
	push_forward_right=0;
	push_forward_left=0;
	leftzh=0;
	leftfu=0;
	rightzh=0;
	rightfu=1;
 }
 void back_left()
 {
    push_back_left=0;
	push_back_right=0;
	push_forward_right=0;
	push_forward_left=0;
	leftzh=0;
	leftfu=1;
	rightzh=0;
	rightfu=0;
 }
//左轮前进PWM函数	 PWM一个周期为20,push值是用来决定占空比
void pwm_left_forward(void){
	if(push_forward_left!=0){
		if(pwm_forward_left20)
			pwm_forward_left=0;
	}
}
//右轮前进PWM函数
void pwm_right_forward(void){
	if(push_forward_right!=0){
		if(pwm_forward_right20)
			pwm_forward_right=0;
	}
}

//左轮后PWM
void pwm_left_back(void){
	if(push_back_left!=0){
		if(pwm_back_left20)
			pwm_back_left=0;
	}
}
//右轮后PWM函数
void pwm_right_back(void){
	if(push_back_right!=0){
		if(pwm_back_right20)
			pwm_back_right=0;
	}
}
//中断产生PWM
void timer0() interrupt 1 using 2{
	TH0=0XFC;
    TL0=0X66;
    pwm_forward_left++;
    pwm_forward_right++;
    pwm_left_forward();
    pwm_right_forward();
	pwm_back_left++;
    pwm_back_right++;
    pwm_left_back();
    pwm_right_back();
}
//计算距离
int Conut(void)	 
	{
	 time=TH1*256+TL1;
	 TH1=0;
	 TL1=0;
	 distance=(time*1.7)/100;    
	 return distance;	
	}
//启动模块
 void  StartModule() 		         
  {
	  Trig=1;			                     
	  _nop_(); 
	  _nop_(); 
	  _nop_(); 
	  _nop_(); 
	  _nop_(); 
	  _nop_(); 
	  _nop_(); 
	  _nop_(); 
	  _nop_(); 
	  _nop_(); 
	  _nop_(); 
	  _nop_(); 
	  Trig=0;
  }
//超声波中断
void timer1() interrupt 3 		 
  {
    flag=1;							 //中断溢出标志
  }
 //循迹函数
void xunji()
{
 //为单片机引脚赋变量
        unint l,m,r;
		l=left;
		m=middle;
		r=right;
		//传感器检测到黑线就会给单片机返回高电平,1
	
		if(l==0&&m==1&&r==0){
			run();
			num=0;
		}
		else if(l==1&&m==0&&r==0){
			turn_left();	    
		}
		else if(l==0&&m==0&&r==1){
			turn_right();	    
		}
		else if(l==0&&m==1&&r==1){
			turn_right();
			num=0;	    
		}
		else if(l==1&&m==1&&r==0){
			turn_left();
			num=0;	    
		}
		else if(l==0&&m==0&&r==0)
		{	
			turn_left();		    
		}
		else if(l==1&&m==1&&r==1){
			stop();
			num=0;	    
		}
			       
}
void CSB()
{
  StartModule();
  while(!Echo);		//当RX为零时等待
  TR1=1;			    //开启计数
  while(Echo);		 //当RX为1计数并等待
  TR1=0;				//关闭计数
  S=Conut();
}

//主函数
void main(void){
	yali=1;		   //无源蜂鸣器pwm		  
	leftzh = 0;
	leftfu = 0;
	rightzh = 0;
	rightfu = 0; 
	TMOD=0X11;	  //两个定时器
    TH0= 0XFC;
    TL0= 0X66;
    TR0= 1;
    ET0= 1;
	TH1=0;
	TL1=0;          
	ET1=1;          
	EA=1;			      	
	while(1){
		if(kaiguan==0)	 //模式一
		{ 
		    xunji();
			if(yali==0)
			{	right_90();
		        delay(500);
		        while(!(left==0&&middle==1&&right==0));
		        while(!yali)
		    {          
				CSB(); 
			  if(S<=20)
			   {
			    led=0;
			    stop();//如果距离小于xxcm ,电机停止 
			  }
			  else if(S>20||flag==1) 
			  {
			    flag=0;
			    led=1;
			    xunji();
			  }
			 }
		}
		else if(yali==1)
		{
		 right_90();
		 delay(500);
		 while(!(left==0&&middle==1&&right==0));
		 while(yali)
		 {
		    	CSB();
			  if(S<=20)
			   {
			    led=0;
			    stop();//如果距离小于xxcm ,电机停止		 
			  }
			  else if(S>20||flag==1)	 
			  {
			    flag=0;
				led=1;
			    xunji();
			 }
		 }
		}
	}
	else //模式2
	{
	    CSB();
	  if(S<=35)
	 {
	    led=0;
		num1++;
		if(num==1)
		{
	    back_right();
		delay(20); 
		}
		else
		{
		back_left();
		delay(5);
		num=0;
		}	
	 }
	  else if(S>35||flag==1)	 
	  {
	   flag=0;
	   led=1;
	   run();
	   delay(20);
	 }
	}
	}           			
}   

 

你可能感兴趣的:(单片机,嵌入式,51,51单片机,避障小车,循迹小车)