目前大一新生,多数用的是数字式的循迹模块,当碰到黑线,发出一个1信号,碰到白线发出0信号。这个1和0是根据实际模块电路决定的,有些碰到黑线是0,有些是1,这个可以用万用表测试下,如果是信号引脚碰到黑线的时候,是5v电,那么就是黑线是1,如果碰到白线是5v,那么白线是1。有一个按钮调节灵敏度的,根据实际情况调节好。
后面熟练之后,可以用ADC模块进行黑白线检测。这个后面再了解。
其他模块也一样。
一般需要3-5个循迹模块。
布局很重要,可以设置中间三个距离近一点,边角远一点。
这个关系到循迹条件的判断。
从做到右叫做LS1,LS0,MS,RS0,RS1,这个名字自己起就可以了。
循迹的几种情况。(注意判断情况条件自己根据自己情况,适当修改,不能太死板哦。)
第一种,直线行走。两个轮子速度一样
1代表黑线,0代表直线。
MS黑线的时候;
00100
第二种,往左小偏转,右轮比左轮的速度快一点。
LS0黑线
01000
第三种,左大转。
右轮速度更加快一点,左轮干脆停止了。
LS11(黑线)
10000
大转弯到MS碰到黑线,就停止大转弯。
第四种,右边小转
RS01
00010
第五种,右边大转
00001
大转弯到中碰到黑线,就停止大转弯。
第六种,直角左转弯
11x00。
中间的那个x代表是0或者1都可以。
转弯到RS0碰到黑线,就停止转弯。
第七种,直角右转弯。
只需要最右边的两个是黑线就行。
00x11
转弯到LS0碰到黑线,就停止转弯。
四个或者5个都是1,碰到黑线,都调头
01111
11110
11111
前进1秒,
然后左轮后退,右轮前进,旋转调头,直到之间的MS碰到黑线停止调头。
第九种,检测不到线,就原地打圈,极端情况。
00000
由于使用几个模块,几个循迹模块都需要VCC和GND,都接杜邦线到控制板,会比较乱。
因此,最好用洞洞板焊接一个转接板。
实物看实验室的小车。
电机接线看上一个文章。
4、编程流程图
定义引脚,循迹,电机,按键。
写前进,停止子函数;
初始化。pwm初始化,端口初始化。
while(1)
{
1,按键按下吗?
,是
设置标记flag=1
2、标记flag==1吗?
是,开始循迹
{
第一种情况
。。。
第二种
。。。
第n中
。。。。。
}
}
//***************************************************************************下面是接线定义
//左电机
sbit LPWM=P2^0;//电机调节速度的信号
sbit LA2=P0^4;
sbit LA1=P0^5;
//右电机
sbit RPWM=P2^1;
sbit RA2=P0^6;
sbit RA1=P0^7;
//接传感器
sbit L1S=P1^0;
sbit L0S=P1^1;
sbit MS=P1^2;
sbit R0S=P1^3;
sbit R1S=P1^4;
sbit key=P3^4;//接按键,启动按键
void trackline0();
//这个是定义,不声明,后面main函数可以直接用,
//小车前进,根据速度两个轮子速度差,进行前进,转弯等
void qianjin(float vleft,float vright)
{
HPWM_Set(0,8000,vleft);
LA2=1;
LA1=0;
HPWM_Set(1,8000,vright);
RA2=1;
RA1=0;
}
//小车调头程序,左轮反转,右轮正转
void turnback(float vleft,float vright)
{
HPWM_Set(0,8000,vleft);
LA2=0;
LA1=1;
HPWM_Set(1,8000,vright);
RA2=1;
RA1=0;
}
//****************************************************************子函数3:void stop()
//小车停止
void stop()
{
LA2=0;
LA1=0;
RA2=0;
RA1=0;
}
//*******************************************主函数
void main()
{
bit startflag=0; //按键控制的启动标记
bit startflag2=0; //蓝牙控制的启动标记
//每个外设,比如按键,屏幕,PWM等内部资源的初始化,配置一下环境
//设置准双向口,和普通的51单片机一样
P0M1=0x00;P0M0=0x00;
P1M1=0x00;P1M0=0x00;
P2M1=0x00;P2M0=0x00;
P3M1=0x00;P3M0=0x00;
P4M1=0x00;P4M0=0x00;
P5M1=0x00;P5M0=0x00;
P6M1=0x00;P6M0=0x00;
delay_tms(200);
//屏幕初始化
OLED_Init();
//PWM模块初始化
HPWM_Init();
//*****************************************************************
//*********************************************正式执行程序
while(1)
{
//**************************************************************************按键来控制的
//*****************************
//检测按键是不是按下,开始启动
if(key==0)
{
delay_tms(10);//延时去抖动
if(key==0)
{
startflag=1;
stop();
delay_tms(1000);//延时,按下两秒之后,小车开始启动进行循迹
// delay_tms(2000);
}
}
//**********************如果开始标记等于1,说明按下启动键key,这时候小车才开始跑
if(startflag==1)
{
//开始循迹,请看这部分代码,太长了,单独拉出来写,方便看主程序逻辑
trackline0();
}
// //**************************************************************//函数定义trackline0();
// //**************************************************************功能:按键循迹;
void trackline0()
{
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++第1种情况
if(L1S==blackline &&L0S==whiteline && MS==whiteline && R0S==whiteline&& R1S==whiteline)//1 0 0 0 0
{
qianjin(vturnsmallM,vturnbigM);//左da转弯,转到碰到中线停止
while(1)
{
if(MS==blackline)break;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++第2种情况
else if(L1S==whiteline &&L0S==blackline && MS==whiteline && R0S==whiteline&& R1S==whiteline)//0 1 0 0 0
{
qianjin(vturnsmall,vturnbig);//左xiao转弯
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++第3种情况
else if(L1S==whiteline &&L0S==whiteline && MS==blackline && R0S==whiteline&& R1S==whiteline)//00 1 0 0
{
qianjin(vleftmove,vrightmove);//直走
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++第4种情况
else if(L1S==whiteline &&L0S==whiteline && MS==whiteline && R0S==blackline&& R1S==whiteline)//0 0 0 1 0
{
qianjin(vturnbig,vturnsmall);//左xiao转弯vturnbig vturnsmall
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++第5种情况
else if(L1S==whiteline &&L0S==whiteline && MS==whiteline && R0S==whiteline&& R1S==blackline)//0 0 0 0 1
{
qianjin(vturnbigM ,vturnsmallM);//左da转弯vturnbigM vturnsmallM,碰到黑线,不然一直大转弯,
while(1)
{
if(MS==blackline)break;
}
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++第6种情况
else if(L1S==blackline && L0S==blackline && R1S==whiteline )//11xx0 判断是左转90度
{
qianjin(vturnsmall,vturnbig);//左转弯
while(1)
{
if(R0S==blackline)break;
}
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++第7种情况
else if( L1S==whiteline &&R0S==blackline && R1S==blackline)//0xx11 判断是右转90度
{
qianjin(vturnbig,vturnsmall);//
while(1)
{
if(L0S==blackline)break;
}
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++第8种情况
else if(L1S==blackline &&L0S==blackline&& MS==blackline && R0S==blackline && R1S==whiteline)//1111x 判断是终点,调头,左轮反转,右轮正转,左转调头
{
stop();
delay_tms(1000);
qianjin(vleftmove,vrightmove);
delay_tms(1000);
stop();
delay_tms(1000);
turnback(vleftmove,vrightmove);
// delay_tms(1000);
while(1)
{
if(MS==blackline)break;
}
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++第8种情况
else if(L1S==whiteline &&L0S==blackline&& MS==blackline && R0S==blackline && R1S==blackline)//1111x 判断是终点,调头,左轮反转,右轮正转,左转调头
{
stop();
delay_tms(1000);
qianjin(vleftmove,vrightmove);
delay_tms(1000);
stop();
delay_tms(1000);
turnback(vleftmove,vrightmove);
// delay_tms(1000);
while(1)
{
if(MS==blackline)break;
}
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++第8种情况
else if(L1S==blackline &&L0S==blackline&& MS==blackline && R0S==blackline && R1S==blackline)//1111x 判断是终点,调头,左轮反转,右轮正转,左转调头
{
stop();
delay_tms(1000);
qianjin(vleftmove,vrightmove);
delay_tms(1000);
stop();
delay_tms(1000);
turnback(vleftmove,vrightmove);
while(1)
{
if(MS==blackline)break;
}
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++第9种情况 这是极端情况,放在最后面判断
//000找不到直线,如果前面是直走,就转360度,如果是之前右边,就左转,之前左偏,就右转
else if(L1S==whiteline &&L0S==whiteline && MS==whiteline && R0S==whiteline && R1S==whiteline)
{
qianjin(vturnbig,vturnsmall);//
}
}
下载,测试一下程序。