/*小车采用五组红外寻迹对管,排成一排装在小车前面,经测量黑线轨道约1.7cm,两个相邻红外对管间隔设置为1.5cm左右(有效寻迹),根据轨道大致设定小车各个状态的速度占空比(需要自己慢慢调整)。
本小车使用L298N模块,带有两路驱动,
*/
# include
typedef unsigned int uint; //对数据类型进行声明定义
typedef unsigned char uchar;
uchar Duty_left,Duty_right,j=0,i=0;//左右占空比标志,取1-100
uchar daihao;
//电机驱动IO口,ENA,ENB为使能端,1,2控制左边电机,3,4控制右边电机,自己查L298n驱动表
sbit IN1=P2^0;
sbit IN2=P2^1;
sbit IN3=P2^2;
sbit IN4=P2^3;
sbit ENA=P1^0;
sbit ENB=P1^1;
//寻迹口,五组红外对管,从左往右,12345
sbit left1=P1^6;
sbit left2=P1^5;
sbit mid3=P1^4;
sbit right4=P1^3;
sbit right5=P1^2;
//void delay(uint k)//k=1时,大约延时10us
//{
// while(k--);
//}
/*定时器0初始化,通过定时器中断设置PWM调速,可以节省cpu,(当时间未到0.1ms时,cpu执行其他命令,等时间到了,在停止执行中断里命令)
*/
void time0init()
{
TMOD|=0x01;//定时器T0,,工作方式都为方式1
TH0=0xff;//定时ff9c0.1ms fe0c0.5ms
TL0=0x9c;
EA=1; //开启总中断
ET0=1;//开启中断允许
TR0=1;//开启定时器中断
}
//向左矫正(用于left2检测到黑线)
void correct_left()
{
IN1=1;//电机控制小车前行
IN2=0;
IN3=1;
IN4=0;
Duty_left=11;
Duty_right=20;
}
//向右校正(用于right4检测到黑线)
void correct_right()
{
IN1=1;//电机控制小车前行
IN2=0;
IN3=1;
IN4=0;
Duty_left=20;
Duty_right=11;
}
//小车左转赋值(用于left1检测到黑线)
void Left_turning()
{
Duty_left=18;
Duty_right=20;
IN1=0; //转弯时一个正转一个反转
IN2=1;
IN3=1;
IN4=0;
}
//小车右转赋值(用于right5检测到黑线)
void Right_turning()
{
Duty_left=18;
Duty_right=20;
IN1=1;
IN2=0;
IN3=0;
IN4=1;
}
//小车直走前行,不拐弯速度赋值
void forward_move()
{
Duty_left=15;
Duty_right=17;
IN1=1;
IN2=0;
IN3=1;
IN4=0;
}
//红外寻迹检测,走直线时小车最多两个相邻红外对管能同时检测到黑线(10011和11001和00111和11100)
void detect_infrared() //reentrant//函数名后加reentrant可以递归调用
{
uchar qq=0,ww=0;
if((right5==1)&&(right4==1)&&(mid3==0)&&(left2==1)&&(left1==1))//11011
daihao=8;
else if((left1==1)&&(left2==1)&&(mid3==1)&&(right4==0)&&(right5==1))//11101
daihao=7;
else if((left1==1)&&(left2==0)&&(mid3==1)&&(right4==1)&&(right5==1))//10111
daihao=6;
else if((left1==0)&&(left2==1)&&(mid3==1)&&(right4==1)&&(right5==1))//01111
daihao=5;
else if((left1==1)&&(left2==1)&&(mid3==1)&&(right4==1)&&(right5==0))//11110
daihao=4;
else if((left1==1)&&(left2==0)&&(mid3==0)&&(right4==1)&&(right5==1))//10011
daihao=3;
else if((left1==1)&&(left2==1)&&(mid3==0)&&(right4==0)&&(right5==1))//11001
daihao=2;
else if((right5==1)&&(right4==1)&&(mid3==0)&&(left2==0)&&(left1==0))//00011直角弯左转
daihao=1;
else if((right5==0)&&(right4==0)&&(mid3==0)&&(left2==1)&&(left1==1))//11000直角弯右转
daihao=0;
switch(daihao)
{
case 0: Right_turning();break;//11000
case 1: Left_turning();break;//00011
case 2: correct_right();break;//11001
case 3: correct_left();break;//10011
case 4: Right_turning();break;//11110
case 5: Left_turning();break;//01111
case 6: correct_left();break;//10111
case 7: correct_right();break;//11101
case 8: forward_move();break;//11011
}
}
void main()
{
time0init();
while(1)
{
detect_infrared();
/*
数码管显示程序编写
*/
}
}
/*
*/
void time0() interrupt 1
{
TH0=0xff;
TL0=0x9c;
i++;
j++;
// q++;
if(i<=Duty_left)//设置左轮占空比,即左轮速度,
ENA=1;
else
ENA=0;
if(j<=Duty_right)
ENB=1;
else
ENB=0;
if(i==100) //设置pwm周期=0.1ms*100=10ms,这样开头定义的变量正好表示占空比数值
{
i=0;//加到100后变为0,重新计数
}
if(j==100) //设置pwm周期=0.1ms*100=10ms,这样开头定义的变量正好表示占空比数值
{
j=0;
}
}
/*寻迹程序其实主要找全各种情况,在加以调整速度,基本能实现寻迹。
若还有不懂,可留言
2018年9月23日