智能寻迹(循迹)小车项目思路 + 代码

说是智能循迹小车,其实一点也不智能,仅仅是几个判断语句而已。更高级的可以使用PID算法控制小车双轮的转速,从而实现智能小车控制。

作为一个项目作业,完成后想删掉的,但是感觉有些可惜,故发布于博客上以便于其他人参考。

使用两个红外线接收器接受红外线探测到的黑色轨迹,实现转大小弯,直角(因为直角处轨迹宽度超过了探测器的宽度,所以有一些额外处理),但是无法通过锐角。
遇到转弯的时候就将直行的速度降低到最高速度的slow%,以防止小车冲出弯道。保持直行状态达到speedUp时间后,在fullGear-speedUp时间内将速度提升到最高,用来提升小车平均速度。每时每刻保存前一个转向状态,在传感器全为黑时执行保存的转向,以达到通过直角弯道的目的。

流程图如下
智能寻迹(循迹)小车项目思路 + 代码_第1张图片

完整代码如下

#include
#include
#define uint unsigned int
#define uchar unsigned char

// 电机部分
sbit P00 = P0^0;
sbit P01 = P0^1;
sbit P02 = P0^2;
sbit P03 = P0^3;
sbit P04 = P0^4; // 左电机使能
sbit P05 = P0^5; // 右电机使能
// 显像器部分
sbit P20 = P2^0;
sbit P21 = P2^1;
sbit P22 = P2^2;
sbit P23 = P2^3;
sbit P24 = P2^4;
sbit P25 = P2^5;
sbit P26 = P2^6;
sbit P27 = P2^7;
// 红外部分
sbit P33 = P3^3;
sbit P35 = P3^5; // 左边红外
sbit P36 = P3^6; // 右侧红外
uint num; // 计数器
uint pwmR;
uint pwmL;
// 其它参数
uint speedUp = 5000; // 开始加速的直行时间
uint fullGear = 8000; // 加速到满速的时间
uint slow = 60; // 遇到转弯时的直行速度
uint delayMs = 0; // 转弯延迟时间
unsigned long count = 0;
uchar status = 'F';
uchar pstatus = 'F';
int flag = 0; // 为0时代表全速,为1时代表转弯


void init();
void leftFdw();
void leftBack();
void rightFdw();
void rightBack();
void back();
void forward();
void turnLeft();
void turnRight();
void stop();
void closeLight();
void delayms(uint);
void printChar(uchar x);
void motorsWrite(int speedL, int speedR);

/*************************** 车轮控制基本程序 ***************************/
void leftFdw(){
	// 左轮前进
	P00 = 1;P01 = 0;
}

void leftBack(){
	// 左轮后退
	P00 = 0;P01 = 1;
}

void rightFdw(){
	// 右轮前进
	P02 = 1;P03 = 0;
}

void rightBack(){
	// 右轮后退
	P02 = 0;P03 = 1;
}

/*************************** 方向控制程序 ***************************/
void turnLeft(){
	// 左转
	status = 'L';
	printChar('L');
	motorsWrite(0, 90);
}

void turnRLeft(){
	// 左转
	status = 'L';
	printChar('L');
	motorsWrite(-70, 100);
}

void turnRight(){
	// 右转
	status = 'R';
	printChar('R');
	motorsWrite(90, 0);
}

void turnRRight(){
	// 右转
	status = 'R';
	printChar('R');
	motorsWrite(100, -70);
}

void forward(){
	// 前进
	status = 'F';
	printChar('F');
	if(flag){ // 转弯
		motorsWrite(slow,slow);
	} else { // 直线加速
		uint dSpeed = slow;
		motorsWrite(dSpeed,dSpeed);
	}
}

void back(){
	// 后退
	status = 'B';
	printChar('B');
	motorsWrite(-100,-100);
}

void stop(){
	// 停车
	status = 'S';
	printChar('S');
	motorsWrite(0,0);
}

/********************** 延时程序 **********************/
void delayms(unsigned int xms){
		unsigned int i,j;
		for(i=xms;i>0;i--)
			for(j=110;j>0;j--);
}

/********************** 数码管显示程序 **********************/
void closeLight(){
	P21 = 1;P22 = 1;P23 = 1;P24 = 1;P25 = 1;P26 = 1;P27 = 1;
}

void printChar(uchar x){
	closeLight();
//	if(x == 'L'){
//		P22 = 0;P23 = 0;P24 = 0;
//	} else if(x == 'R'){
//		P22 = 0;P23 = 0;P27 = 0;
//	} else if(x == 'F'){
//		P21 = 0;P22 = 0;P23 = 0;P27 = 0;
//	} else if(x == 'B'){
//		P21 = 0;P22 = 0;P23 = 0;P24 = 0;P25 = 0;
//	} else if(x == 'S'){
//		P21 = 0;P24 = 0;P27 = 0;
//	}
}

/********************** 电机控制程序 **********************/
void motorsWrite(int speedL, int speedR){
	// 电机控制
	if(speedL > 100) speedL=100;
	if(speedR > 100) speedR=100;
	if(speedL < -100) speedL=-100;
	if(speedR < -100) speedR=-100;
	
	if(speedL < 0) {
		pwmL = -speedL;
		leftBack();
	} else {
		pwmL = speedL;
		leftFdw();
	}
	if(speedR < 0){
		pwmR = -speedR;
		rightBack();
	} else {
		pwmR = speedR;
		rightFdw();
	}
}

void init(){
	// PWM控制程序
	// 100us计时器
	TMOD = 0x01; // 定时器0模式1
	TH0 = 0x0FF; // 定时器0的高八位
	TL0 = 0x0A4;
	//TF0;// 如果定时器中断(溢出),则TF0=1;
	EA = 1;
	ET0 = 1;
	TR0 = 1; // 表示开启定时器0
}

void main(){
	init();
	while(1){
		if(P35 == 0 && P36 == 0){
			forward();
		} else if(P35 == 0 && P36 == 1){
			turnRight();
			flag = 1;
			pstatus = 'R';
		} else if(P35 == 1 && P36 == 0){
			turnLeft();
			flag = 1;
			pstatus = 'L';
		} else if(P35 == 1 && P36 == 1){
			if(pstatus == 'F'){
				forward();
			} else if(pstatus == 'R'){
				turnRRight();
				delayms(delayMs);
			} else if(pstatus == 'L'){
				turnRLeft();
				delayms(delayMs);
			}
		}
	}
}

void Timer0Interrupt(void) interrupt 1
{
	TH0 = 0x0FF;
	TL0 = 0x0A4;
	if(num <= pwmL)P04 = 1;
	else P04 = 0;
	if(num <= pwmR)P05 = 1;
	else P05 = 0;
	num++;
	if(num >= 100)num=0;
	
	if(status == 'F') {
		count++;
	} else {
		count = 0;
	}
	if(count == speedUp && status == 'F') {
		flag = 0;
	}
}

你可能感兴趣的:(智能小车,寻迹小车,循迹小车)