初学者的第一个项目:基于51单片机循迹小车

       准备工作

1)控制芯片:

由于刚学完51基础课程,所以这里直接用51学习板(STC89C52RC)。

2)车身:

可以直接在某宝购买,一般都会直接配齐(亚克力车身,电机,轮胎以及固定螺丝)。

3)L298N电机驱动模块:

L298N模块可以驱动 电机正反转,并且能直接给单片机供电(L298N接入12V)。

输出 A/B:         分别接 左/右 电机 (电机接法如上图所示)

通道A/B使能:    当把帽子拔下就可以通过PWM对电机进行调速 

逻辑输入:        IN1/2 控制 输出A 端 电机的正反转

                          IN3/4 控制 输出B 端 电机的正反转  

 电机的正反转 与 电机和输出A/B的接线有关,接线之后应当先调试判断是否方向正确,若方向不对因把电机与输出A/B的接线换序

        接线:按照上图进行接线,输出A/B 接电机,逻辑输入接单片机I/O口

4)红外循迹模块

           推荐使用TCR5000循迹模块(单个的循迹模块可以根据自己的实际情况进行调整扫描位置)

       

 

 

     

        循迹原理: 利用红外线对于不同颜色具有不同的反射性质的特点。在小车行驶过程中传感器的红外发射二极管不断发射红外光,当红外光遇到白色地面时发生漫反射,红外对管接收管接收反射光;如果遇到黑线则红外光被吸收,则红外管接收不到信号。
红外对管采集回来的信号通过2路循迹传感器模块里面的LM339比较器后输出高或低电平,从而实现信号的检测。

        接线:(A0可以不接)D0为输出信号接单片机I/O口

        注意:有的厂商设置的是红外管接收不到信号  输出高电平,有的厂商设置的则是红外管接收不到信号  输出低电平。故在接线后一定要调试(这里是输出高电平)

5)电源

        强烈建议用 12V锂电池,之前自己用的是9V碱性电池,虽然电压有9V左右,但电流严重不足。

所以可以直接用12V2000ma左右的锂电池 就可以直接驱动L298N而且还能通过L298N直接给单片机供电,而且锂电池还能 充电反复使用。

功能介绍

        根据TCR5000循迹模块的工作原理,用单片机I/O口接收TCR5000循迹模块发出的信号,当单片机I/O口接收到低电平/高电平时就表示检测到轨道(黑线),然后给L298N的逻辑输入脚信号,让电机做出相应的动作。

        小车转弯可以通过一侧轮胎正转另一侧不动实现,但这样小车移动的角度就很大,所以一般不推荐;另一种方法则是通过一侧轮胎正转另一侧反转,这样小车移动角度就会小很多,甚至于原地打转都行。

源码(仅供参考)

主函数(采用模块化编程,后续头文件自己补充啦)

#include <REGX52.H>
#include "trac.h"
#include "pwm.h"


int main ()
{

	Timer0_PWM_Init();
	P0=0XFF;
	while(1)
	{
	
		Trac();
	}
}

PWM函数

#include <REGX52.H>

sbit ENA=P2^0;		//ENA使然口
sbit ENB=P2^5;	//ENB使然口
unsigned char compare_ENA,compare_ENB;//PWM比较值
unsigned char count_ENA,count_ENB;    //PWM计数值

/***********************************************************************************
  * @brief  	定时器0初始化
  * @param  
  * @retval 
  */
void Timer0_PWM_Init(void)		//100微秒@11.0592MHz
{


	TMOD &= 0xF0;		//设置定时器模式
	TMOD |= 0x01;		//设置定时器模式
	TL0 = 0xA4;		//设置定时初值
	TH0 = 0xFF;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	ET0=1;
	EA=1;
	
}

/***********************************************************************************
  * @brief  	PWM比较值赋值函数
  * @param  	
  * @retval 
  */
void PWM_Compare( unsigned char Date1,Date2)
{
	compare_ENA=Date1;
	compare_ENB=Date2;
}



/***********************************************************************************
  * @brief  	定时器0执行函数
  * @param  
  * @retval 
  */


void Timer0_PWM_Run(void) interrupt 1
{
//	TL0 = 0xA4;		//设置定时初值
//	TH0 = 0xFF;		//设置定时初值
	TL0 = 0xE9;		//设置定时初值
	TH0 = 0xFF;		//设置定时初值
	
	count_ENA++;
	count_ENA%=100;		//控制范围0~99
	if(count_ENA<compare_ENA)
	{
		ENA=1;		
	}
	else if(count_ENA>compare_ENA)
	{
		ENA=0;		
	}
	
	count_ENB++;
	count_ENB%=100;		//控制范围0~99
	if(count_ENB<compare_ENB)
	{
		ENB=1;		
	}
	else if(count_ENB>compare_ENB)
	{
		ENB=0;		
	}
	
	
	
	
}

 循迹函数

#include <REGX52.H>
#include "pwm.h"

/***********************************************************************************
  * @brief 		红外对管从左至右返回信号脚

  */
sbit IR_1=P0^3;
sbit IR_2=P0^4;
sbit IR_3=P0^5;
sbit IR_4=P0^6;

/***********************************************************************************
  * @brief  L298N信号输出   10正转	   01反转
 
  */
sbit IN1=P2^1;
sbit IN2=P2^2;
sbit IN3=P2^3;
sbit IN4=P2^4;

/***********************************************************************************
  * @brief  	控制车轮旋转方向		10正转	   01反转
  * @param  	a,b,,c,d
  * @retval 
  */

void L298N_Init(unsigned char a,b,c,d)
{
		IN1=a;
		IN2=b;
		IN3=c;
		IN4=d;


}
/***********************************************************************************
  * @brief  	循迹模块执行函数
  * @param  	无
  * @retval 	无
  */
void Trac()
{
	if(IR_1==0 && IR_2==0 && IR_3==1 && IR_4==0 )	//中间检测到黑线,此时小车位置中间偏右
	{
		PWM_Compare( 20,20);		//左右轮都为20%
		L298N_Init(1,0,1,0);		//左右轮都正传
	}
	
	else if(IR_1==1 && IR_2==0 && IR_3==0 && IR_4==0 )	//最左边检测到黑线
	{
		PWM_Compare( 30,40);		//左轮为30%	右轮为40%
		L298N_Init(0,1,1,0);		//左轮反传	右轮正转
	}
	
	else if(IR_1==0 && IR_2==1 && IR_3==0 && IR_4==0 )	//中间检测到黑线,此时小车位置中间偏左
	{
		PWM_Compare( 23,23);		//左轮为23%	右轮为23%
		L298N_Init(1,0,1,0);		//左轮正传	右轮正转
	}
	

	
	else if(IR_1==0 && IR_2==0 && IR_3==0 && IR_4==1 )	//最右边检测到黑线
	{
		PWM_Compare( 40,30);		//左轮为40%	右轮为30%
		L298N_Init(1,0,0,1);		//左轮正传	右轮反转
		
	}
	
	else if(IR_1==0 && IR_2==0 && IR_3==0 && IR_4==0 )	//未检测到黑线
	{
		PWM_Compare( 0,0);
		L298N_Init(0,0,0,0);		//轮胎不运动
	}
	
	else if(IR_1==1 && IR_2==1 && IR_3==1 && IR_4==1 )	//四路都检测到黑线
	{
		PWM_Compare( 0,0);
		L298N_Init(0,0,0,0);		//轮胎不运动
	}
	
		else if(IR_1==0 && IR_2==1 && IR_3==1 && IR_4==0 )	//中间两路检测到黑线
	{
		PWM_Compare( 17,17);		//左轮为17%	右轮为17%
		L298N_Init(1,0,1,0);		//左轮正传	右轮正转
	}
	
	


}

物联沃分享整理
物联沃-IOTWORD物联网 » 初学者的第一个项目:基于51单片机循迹小车

发表评论