51寻迹小车基础代码

    网上的寻迹小车代码千奇百怪,多数代码功能不全或是逻辑不清晰。为方便大家更快上手寻迹小车, 我找了一篇逻辑相对清晰的基础循迹代码,并自己加了些注释供大家参考。

    【此代码不能完全契合每个人的小车,不能优秀的完成180°转向或是多元赛道等题目。仅给大家提供一个相对清晰的代码编写思路。想要完成所有赛题还需在此基础上补充完善】

#include<reg52.h>
typedef unsigned int u16;
typedef unsigned char u8;


/******************************/
此处六个端口对应L298N的六条信号线
/******************************/

sbit ENA = P2^0;   //右点机使能,输出pwm
sbit IN1 = P2^1;   //为0右轮反转
sbit IN2 = P2^2;   //为0右轮正转
sbit IN3 = P2^3;   //为0左轮正转
sbit IN4 = P2^4;   //为0左轮反转
sbit ENB = P2^5;   //左电机使能,输出pwm

/*******************************/
此处四个端口对应循迹模块的四条信号线
/*******************************/

sbit left1 = P1^3;
sbit left2 = P1^2;
sbit right1 = P1^1;
sbit right2 = P1^0;

u8 PWMCnt1 = 0;
u8 PWMCnt2 = 0;
u8 cntPWM1 = 0;
u8 cntPWM2 = 0;

void Timer0Init();
void XunJi();

void main()
{
	Timer0Init(); //定时器0初始化
	while(1)
	{
		XunJi(); 主循环持续循迹

	}	
}

/*******************************/
延时函数(备用)本代码暂时没用到
/*******************************/
// i = 1时, 大概延时10us(最大65535)
//void delay(u16 i)
//{
//    while (i--);
//}

void Timer0Init()//定时器初始化函数,直接复制不用看懂
{
	TH0 = 0xFF;
	TL0 = 0xA3;
	TMOD &= 0xF0;
	TMOD |= 0x01;
	EA = 1;
	ET0 = 1;
	TR0 = 1;
}

void TurnRight1()		   //右转
{
	IN1 = 0;	//右轮反转
	IN2 = 1;

	IN3 = 0;	//左轮正转
	IN4 = 1;
	cntPWM1 = 70;//pwm设置用于调节转速(下边代码同理)
	cntPWM2	= 55;
}

void TurnRight2()		   //右转
{
	IN1 = 0;	//右轮反转
	IN2 = 1;

	IN3 = 0;	//左轮正转
	IN4 = 1;
	cntPWM1 = 50;
	cntPWM2	= 40;
}

void TurnLeft1()				//左转
{
	IN1 = 1;
	IN2 = 0;   	//右轮正转

	IN3 = 1;
	IN4 = 0;   	//左轮反转
	cntPWM1 = 55;
	cntPWM2	= 70;
}			  	

void TurnLeft2()				//左转
{
	IN1 = 1;
	IN2 = 0;   	//右轮正转

	IN3 = 1;
	IN4 = 0;   	//左轮反转
	cntPWM1 = 40;
	cntPWM2	= 50;
}	
	
void Forward()				 //前进
{
	IN1 = 1;
	IN2 = 0;   	//右轮正转

	IN3 = 0;   	//左轮正转
	IN4 = 1;

	cntPWM1 = 40;
	cntPWM2	= 40;
}

//void Backward()					 //后退
//{
//	IN1 = 0;	//右轮反转
//	IN2 = 1;
//
//	IN3 = 1;
//	IN4 = 0;	//左轮反转
//	cntPWM1 = 30;
//	cntPWM2	= 30;
//}

void Stop()					  //停止
{
	IN1 = 0;
	IN2 = 0;

	IN3 = 0;
	IN4 = 0;
}
void XunJi()//此处代码是需要重点理解的,内涵循迹逻辑,根据实际情况自行增补

{
	unsigned char flag = 0;
    //flag变量用于存储小车行进状态(行进状态由对四路传感器妆台的判断而来)

	if((left1 == 0)&&(left2 == 0)&&(right1 == 0)&&(right2 == 0))   //四路传感器状态:0 0 0 0
		flag = 0;

	if((left1 == 0)&&(left2 == 0)&&(right1 == 0)&&(right2 == 1))   //0 0 0 1
		flag = 1;

	if((left1 == 0)&&(left2 == 0)&&(right1 == 1)&&(right2 == 0))   //0 0 1 0
		flag = 0;

	if((left1 == 0)&&(left2 == 0)&&(right1 == 1)&&(right2 == 1))   //0 0 1 1
		flag = 1;

	if((left1 == 0)&&(left2 == 1)&&(right1 == 0)&&(right2 == 0))   //0 1 0 0
		flag = 0;

	if((left1 == 0)&&(left2 == 1)&&(right1 == 0)&&(right2 == 1))   //0 1 0 1
		flag = 4;

	if((left1 == 0)&&(left2 == 1)&&(right1 == 1)&&(right2 == 0))   //0 1 1 0
		flag = 0;
	
	if((left1 == 0)&&(left2 == 1)&&(right1 == 1)&&(right2 == 1))    //0 1 1 1
		flag = 1;
	
	if((left1 == 1)&&(left2 == 0)&&(right1 == 0)&&(right2 == 0))   //1 0 0 0
		flag = 3;
	
	if((left1 == 1)&&(left2 == 0)&&(right1 == 0)&&(right2 == 1))   //1 0 0 1
		flag = 0;
	
	if((left1 == 1)&&(left2 == 0)&&(right1 == 1)&&(right2 == 0))   //1 0 1 0
		flag = 2;
	// ?
	if((left1 == 1)&&(left2 == 0)&&(right1 == 1)&&(right2 == 1))   //1 0 1 1
		flag = 0;
	
	if((left1 == 1)&&(left2 == 1)&&(right1 == 0)&&(right2 == 0))   //1 1 0 0
		flag = 3;
	 //?
	if((left1 == 1)&&(left2 == 1)&&(right1 == 0)&&(right2 == 1))   //1 1 0 1
		flag = 0;

	if((left1 == 1)&&(left2 == 1)&&(right1 == 1)&&(right2 == 0))   //1 1 1 0
		flag = 3;
	
	if((left1 == 1)&&(left2 == 1)&&(right1 == 1)&&(right2 == 1))   //1 1 1 1
		flag = 5;
	
	switch(flag)//根据“状态flag”改变小车行进模式
	
{
		case 0:Forward();break;
		
		
		case 1:TurnRight1();break;
		
		
		case 2:TurnRight2();break;
		
		
		case 3:TurnLeft1();break;
		
		
		case 4:TurnLeft2();break;


		default:Stop();break;
	}
}

void InterruptTime0() interrupt 1//定时器相关函数(不用读懂直接粘贴)
{
	PWMCnt1++;
	PWMCnt2++;
	
	if(PWMCnt1  >= 200)
	{
		PWMCnt1 = 0;
	}
	if(PWMCnt1 <= cntPWM1)
	{
		ENA = 1;
	}
	else
	{
		ENA = 0;
	}

	if(PWMCnt2 >= 200)
	{
		PWMCnt2 = 0;
	}
	if(PWMCnt2 <= cntPWM2)
	{
		ENB = 1;
	}
	else
	{
		ENB = 0;
	}

	TH0 = (65536 - 50)/256;
	TL0 = (65536 - 50)%256;
}

【 附加讲解】

如果想要根据赛道调试小车,主要需要从两方面着手修改代码逻辑:

1、修改或增加TurnRight1()、TurnRight2()、TurnLeft1()、TurnLeft2()等控制行进模式的代码,调节里边的点机正反转逻辑或者左右速度差(pwm参数)

2、着重修改XunJi()函数,适当增加对各种情况判断语句,各种适应赛题的要求。

最后祝大家小车比赛顺利,起飞!!!

---TZ

51循迹小车通常指的是使用基于51单片机控制的一种玩具或实验项目,通过四个直流电机驱动轮子,通过编码器或者红外传感器来感知前方道路的信息,然后通过程序调整电机的速度和转向,让小车跟随预设的轨迹线行驶。具体的代码实现会涉及以下几个步骤: 1. **硬件连接**:连接4路电机、编码器或红外接收模块到单片机,如8051系列。 2. **数据采集**:编写程序读取电机转速或红外传感器的数据,判断小车当前的位置与目标路径的关系。 3. **PID控制**:如果是PID(比例积分微分)控制,需要计算出修正角度,根据误差大小调整电机的方向和速度。 4. **中断处理**:利用中断机制处理传感器数据,实时响应并调整小车运动。 5. **编码器或红外算法**:解析编码器脉冲或红外信号,计算出小车相对于直线的偏移,并据此调整控制指令。 6. **主循环**:在主程序中不断读取输入、更新状态、执行控制决策,实现小车的持续追踪。 以下是一个简化版的示例代码片段(仅用于演示,实际应用需要更复杂的错误检查和调试): ```c #include <reg52.h> #define motor_a P1^2 #define motor_b P1^3 #define motor_c P1^4 #define motor_d P1^5 void move_left(int speed) { motor_a = speed; motor_b = -speed; } void move_right(int speed) { motor_c = speed; motor_d = -speed; } void track_line() { // 算法略... if (error > 0) { // 偏左 move_left(-angle_correction); } else if (error < 0) { // 偏右 move_right(angle_correction); } else { // 正好对齐 stop_motors(); } } int main() { while (true) { track_line(); } } ```
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值