标题:
单片机黑线寻迹小车程序,如何快速识别黑线,无延迟切换转弯?
[打印本页]
作者:
aktuan007
时间:
2022-4-8 08:00
标题:
单片机黑线寻迹小车程序,如何快速识别黑线,无延迟切换转弯?
程序功能:红外寻迹小车,跑道为黑色,其他地方为白色。左右两个红外传感器,当传感器在黑线上时,没有反射光进入传感器,判断压线,左边压线就左转,反之右转。
实际效果:小车右边检测到黑线后不能马上右转,而是前进一下,前进后就脱离了跑道,不能再寻迹。
用KEIL单步调试时发现,如果直行时遇到了左右传感器检测到信号后,没有马上转弯,而是反复执行了上一个状态的前进函数,这就导致了在寻迹时不能马上转弯。请问一下如何快速检测、快速切换前进状态?主函数在下面
单片机源程序如下:
#include<AT89X52.H> //包含51单片机头文件,内部有各种寄存器定义
#include<ZY-4WD_PWM.H> //包含IO口定义等函数
#define uchar unsigned char
#define uint unsigned int
sbit pwm=P1^6;//PWM信号输出口 舵机信号输出口
unsigned char n,count,angle;//距离标志位,0.5ms次数,角度标识
uchar i;
void DelayUs2x(uchar t)
{
while(--t);
}
void DelayMs(uchar t)
{
while(t--)
{
//大致延时1mS
DelayUs2x(245);
DelayUs2x(245);
}
}
/*------------------------------------------------
定时器01初始化
//定时器1工作方式1 (舵机 ),定时器0 电机PWM调速控制信号
------------------------------------------------*/
void Time1_Int() interrupt 3//舵机
{
TH1=0xfe; //0.5ms初值
TL1=0x33;
if(count<angle)//判断0.5ms次数是否小于角度标识
pwm=1;//确实小于,pwm输出高电平
else
pwm=0;//大于则输出低电平
count++;//0.5ms次数加1
count=count%40;//次数始终保持为200即保持周期为20ms
//if(count>=20)count=0;
}
//主函数
void main(void)
{
angle=3;//舵机居中
count=0;
P0=0XF0; //关电机
/*
B: for(i=0;i<50;i++) //判断S4是否按下
{
delay(1); //1ms内判断50次,如果其中有一次被判断到K4没按下,便重新检测
if(P3_2!=0)//当S4按下时,启动小车前进.
goto B; //跳转到标号B,重新检测
}
*/
//本实验学习的知识蜂鸣器,注意要在HJ-4WD头文件里定义IO口
BUZZ=0; //50次检测K4确认是按下之后,蜂鸣器发出“滴”声响,然后启动小车。
delay(50);
BUZZ=1;//响50ms后关闭蜂鸣器
TMOD=0X11;
TH0= 0XFc; //1ms定时
TL0= 0X66;
TR0= 1;
ET0= 1;
EA = 1; //开总中断
TH1=0xfe; //0.5ms
TL1=0x33;
ET1=1;
TR1= 1;
while(1) //无限循环
{
//有信号为0 没有信号为1
//有信号为0 没有信号为1
if(Left_1_led==1&&Right_1_led==1)
{
run();
angle=3 ;
} //调用前进函数
else
{
if(Left_1_led==1 && Right_1_led==0) //左边检测到黑线
{
angle=4;
leftrun(); //调用小车左转 函数
for(time=0;time<100;time++);
}
if(Left_1_led==0 && Right_1_led==1) //右边检测到黑线
{
angle=2;
rightrun(); //调用小车右转 函数
for(time=0;time<100;time++);
}
}
}
}
复制代码
作者:
热度三分
时间:
2022-4-8 09:19
调一下传感器的灵敏度?试试用switch case?
作者:
aktuan007
时间:
2022-4-8 09:27
头文件:
#ifndef _LED_H_
#define _LED_H_
//定义小车驱动模块输入IO口
sbit IN1=P0^0;
sbit IN2=P0^1;
sbit IN3=P0^2;
sbit IN4=P0^3;
sbit EN1=P0^4;
sbit EN2=P0^5;
/***蜂鸣器接线定义*****/
sbit BUZZ=P0^6;
#define Left_1_led P3_5 // 左传感器
#define Right_1_led P3_6 //右传感器
#define PWMSD 5 ////速度调节变量 0-20。。。0最小,20最大
#define Left_moto_pwm P0_4 //PWM信号端 ,EN1
#define Right_moto_pwm P0_5 //PWM信号端,EN2
#define Left_moto_go {P0_0=1,P0_1=0;} //左电机向前走
#define Left_moto_back {P0_0=0,P0_1=1;} //左边电机向后转
#define Left_moto_Stop {P0_4=0;} //左边电机停转
#define Right_moto_go {P0_2=1,P0_3=0;} //右边电机向前走
#define Right_moto_back {P0_2=0,P0_3=1;} //右边电机向后走
#define Right_moto_Stop {P0_5=0;} //右边电机停转
unsigned char pwm_val_left =0;//变量定义
unsigned char push_val_left =0;// 左电机占空比N/20
unsigned char pwm_val_right =0;
unsigned char push_val_right=0;// 右电机占空比N/20
bit Right_moto_stop=1;
bit Left_moto_stop =1;
unsigned int time=0;
/************************************************************************/
//延时函数
void delay(unsigned int k)
{
unsigned int x,y;
for(x=0;x<k;x++)
for(y=0;y<2000;y++);
}
/************************************************************************/
//前速前进
void run(void)
{
push_val_left=PWMSD; //速度调节变量 0-20。。。0最小,20最大
push_val_right=PWMSD;
Left_moto_go ; //左电机往前走
Right_moto_go ; //右电机往前走
}
void stop(void)
{
Left_moto_Stop;
Right_moto_Stop;
}
//左转
void leftrun(void)
{
push_val_left=PWMSD;
push_val_right=PWMSD;
Right_moto_go ; //右电机往前走
Left_moto_back ; //左电机后走
}
//右转
void rightrun(void)
{
push_val_left=PWMSD;
push_val_right=PWMSD;
Left_moto_go ; //左电机往前走
Right_moto_back ; //右电机往后走
}
/************************************************************************/
/* PWM调制电机转速 */
/************************************************************************/
/* 左电机调速 */
/*调节push_val_left的值改变电机转速,占空比 */
void pwm_out_left_moto(void)
{
if(Left_moto_stop)
{
if(pwm_val_left<=push_val_left)
{
Left_moto_pwm=1;
}
else
{
Left_moto_pwm=0;
}
if(pwm_val_left>=20)
pwm_val_left=0;
}
else
{
Left_moto_pwm=0;
}
}
/******************************************************************/
/* 右电机调速 */
void pwm_out_right_moto(void)
{
if(Right_moto_stop)
{
if(pwm_val_right<=push_val_right)
{
Right_moto_pwm=1;
}
else
{
Right_moto_pwm=0;
}
if(pwm_val_right>=20)
pwm_val_right=0;
}
else
{
Right_moto_pwm=0;
}
}
/***************************************************/
///*TIMER0中断服务子函数产生PWM信号*/
void timer0()interrupt 1 using 2
{
TH0=0XFc; //1ms定时
TL0=0X66;
time++;
pwm_val_left++;
pwm_val_right++;
pwm_out_left_moto();
pwm_out_right_moto();
}
/*********************************************************************/
#endif
作者:
glinfei
时间:
2022-4-8 11:17
我一般根据情况使用下面方法:1、减慢车速,足够慢,就不会错过;2、加延时,其实你已经加了,就是加的太少了就是这句,for(time=0;time<100;time++);多加点,这个必须要调试的,而且跟电量有关,最好你能检测电源电压做个变量加到延时中。当然这种硬延时不大好,我喜欢加标志变量延时的,不影响路线检测;3、改控制策略,比如左压线后,要左转到右压线为止(记得要去掉上面的延时)。或者左压线左转到再次左压线等这个也要测一下的。4、我觉得你最应该的是多上几个红外,使用pid控制,就能跑得飞快,要不搞舵机干啥。
作者:
aktuan007
时间:
2022-4-8 11:25
感谢
PID控制是个好方法啊。
如果我把速度调慢,怎么调啊?调pwm=P1^6这个的占空比吗
作者:
glinfei
时间:
2022-4-8 12:08
aktuan007 发表于 2022-4-8 11:25
感谢PID控制是个好方法啊。
如果我把速度调慢,怎么调啊?调pwm=P1^6这个的占空比吗
你那个显然是舵机啊,你程序不全,感觉是count=count%40;在调占空比。看你的提问,觉得你先加延时,去试车比较好。
作者:
lkc8210
时间:
2022-4-8 13:12
if(Left_1_led==1 && Right_1_led==0) //左边检测到黑线
0=压线
Right_1_led==0 是右压线吧?
舵机是干什么用的?
中断内time为什么要++?
作者:
yzwzfyz
时间:
2022-4-8 13:44
比较一下:
你在黑夜开近光灯与开远光灯拐弯的情形,你远光灯会好一些!速度慢会好一些!
其实关键点是:有足够的预判时间!
假设从你决定拐弯开始到完成拐弯,需要两秒钟的时间。那么你的预判时间就是两秒!
所以,完成命题的需求是,传感器必须在2秒之前得到拐弯信息!
大多数人认为拐弯需要减速,看上去是对的。其实关键点是:以低于最小的安全拐弯速度拐弯就可以了。
你要注意以下几点:
1、最小拐弯速度。(道路环境条件相关)
2、完成拐弯的时间。(以当前速度、制动能力相关)
3、小车行进的速度。(与在何处开始起动拐弯程序相关)
4、依据1、2、3、计算出开始拐弯动作的起点在哪里。这个点,距拐弯点的距离,就是小车传感器必须能探知的点(提前预判)!
余下的事,可参考其它人支着。
作者:
glinfei
时间:
2022-4-8 14:49
aktuan007 发表于 2022-4-8 11:25
感谢PID控制是个好方法啊。
如果我把速度调慢,怎么调啊?调pwm=P1^6这个的占空比吗
之前没看到你后来发的程序。 你已经定义速度了啊,#define PWMSD 5 ////速度调节变量 0-20。。。0最小,20最大
改一下就行了,但这个不是线性调整的,太小估计就走不动了。我觉得你程序很奇怪,明明用了舵机转弯,为啥还要用电机差动转弯呢,电机转弯效率低啊。还有中断内的time要删掉,你应该增加主程序for循环产生的延时才对。你用的是什么底盘,配置的不太合理啊。
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1