📄 control_dir.c
字号:
#include"19#405.h"
#define ON_LINE 90 // 主红外踩到黑线的临界值
#define ON_LINE_LOW 20 // 从红外踩到黑线的临界值
#define LEFT 1
#define RIGHT 2
#define MIDLE 0
/*******当前状态记录值********/
char this_side = 0 ; // 当今偏离的程度记录
unchar side_cal = 0 ; // 在一段时间内的偏离程度的累计
unchar is_on_line = 1 ; // 黑线在可视范围内的标志
unchar is_on_line_low = 1 ;
unchar l_or_r = 0 ; // 上一个状态黑线是处于左边还是右边还是中间
unchar l_or_r_low = 0 ;
extern unchar led_show1 ;
extern unchar led_show2 ;
/*********起跑线的检测记录值***********/
//unchar status[ 7 ] = { 0, 0, 0, 0, 0, 0 } ; // 对于一段时间内起跑线的检测状态的记录
unchar start_line = 0 ; // 经过起跑线的记录
/***********指向舵机偏离值表的指针*******/
unchar* table_dir ;
void Control_dir( ATD atdget, unchar* dir )
{
//静态变量
static char num_lowest = 3 ; // 当前踩到黑线的对管的代号
static char pre_dir = DIR_MID ; // 上一个状态的舵机的偏转值的记录
unchar pre_is_on_line = 1 ; // 上一个状态的黑线是处于左边还是右边
unchar *ptr = &atdget.left3 ; // 指向数据结构的指针,便于循环判断查询
unchar counter ; // 循环辅助变量
unchar atd_lowest = 255 ; // 当前踩到黑线的对管采回的最小的AD值
char pre_num_lowest ; // 上一个状态踩到黑线的对管的编号
// 将上个状态的值记录下来
pre_num_lowest = num_lowest ;
pre_is_on_line = is_on_line ;
is_on_line = 0 ;
num_lowest = 3 ;
// 循环查找踩到黑线的红外对管的编号
for( counter = 0; counter < 7; counter ++ )
{
if( *ptr < ON_LINE )
{
is_on_line = 1 ;
if( *ptr < atd_lowest )
{
num_lowest = counter ;
atd_lowest = *ptr ;
}
}
ptr ++ ;
}
/********************************错误状况的判断及错误的解除*********************************/
// 当上一个状态离线而这个状态踩到黑线时,如果出现两极情况,认为仍然离线
if( ( 0 == pre_is_on_line ) && ( 1 == is_on_line ) )
{
/* if( 0 == is_on_line_low )
{
is_on_line = 0 ;
l_or_r = l_or_r_low ;
} */
if( 1 == l_or_r ) // 当上一个状态黑线处于左边,当今状态判断到右边
{
if( num_lowest != 0 )
is_on_line = 0 ;
}
else if( 2 == l_or_r ) // 当上一个状态黑线处于右边,当今状态判断到左边
{
if( num_lowest != 6 )
is_on_line = 0 ;
}
}
// 当相近的两个状态相差很大时,认为上一个状态正确
if( ( pre_num_lowest - num_lowest > 1 )
|| ( pre_num_lowest - num_lowest < -1 ) )
num_lowest = pre_num_lowest ;
/***********************************************************************************************************/
// 当认为采集的数据正确时,开始对舵机及各个记录值进行处理
if( is_on_line )
{
// 判断当前的黑线在左边还是右边
if( num_lowest < 3 )
l_or_r = LEFT ; // 在左边
else if( num_lowest > 3 )
l_or_r = RIGHT ; // 在右边
else
l_or_r = MIDLE ; // 在中间
switch( num_lowest )
{
case 0 :
{
if( atdget.left2 > ON_LINE )
*dir = table_dir[ 0 ] ;
else if( atdget.left2 > ( ON_LINE - 10 ) )
*dir = table_dir[ 1 ] ;
else
*dir = table_dir[ 2 ] ;
this_side = -6 ;
side_cal += 3 ;
break ;
}
case 1 :
{
if( atdget.left3 < ( ON_LINE - 10 ) )
*dir = table_dir[ 3 ] ;
else if( atdget.left3 < ON_LINE )
*dir = table_dir[ 4 ] ;
else if( atdget.left2 < ( ON_LINE - 10 ) )
*dir = table_dir[ 7 ] ;
else if( atdget.left2 < ON_LINE )
*dir = table_dir[ 6 ] ;
else
*dir = table_dir[ 5 ] ;
this_side = -2 ;
side_cal += 2 ;
break ;
}
case 2 :
{
if( atdget.left1 < ( ON_LINE - 10 ) )
*dir = table_dir[ 8 ] ;
else if( atdget.left1 < ON_LINE )
*dir = table_dir[ 9 ] ;
else if( atdget.mid < ( ON_LINE - 10 ) )
*dir = table_dir[ 12 ] ;
else if( atdget.mid < ON_LINE )
*dir = table_dir[ 11 ] ;
else
*dir = table_dir[ 10 ] ;
this_side = -1 ;
side_cal += 1 ;
break ;
}
case 3 :
{
if( atdget.left1 < ( ON_LINE - 10 ) )
*dir = table_dir[ 13 ] ;
else if( atdget.left1 < ON_LINE )
*dir = table_dir[ 14 ] ;
else if( atdget.right2 < ( ON_LINE - 10 ) )
*dir = table_dir[ 17 ] ;
else if( atdget.right2< ON_LINE )
*dir = table_dir[ 16 ] ;
else
*dir = table_dir[ 15 ] ;
this_side = 0 ;
break ;
}
case 4 :
{
if( atdget.mid < ( ON_LINE - 10 ) )
*dir = table_dir[ 18 ] ;
else if( atdget.mid < ON_LINE )
*dir = table_dir[ 19 ] ;
else if( atdget.right2 < ( ON_LINE - 10 ) )
*dir = table_dir[ 22 ] ;
else if( atdget.right2 < ON_LINE )
*dir = table_dir[ 21 ] ;
else
*dir = table_dir[ 20 ] ;
side_cal += 1;
this_side = 1 ;
break ;
}
case 5 :
{
if( atdget.right1 < ( ON_LINE - 10 ) )
*dir = table_dir[ 23 ] ;
else if( atdget.right1 < ON_LINE )
*dir = table_dir[ 24 ] ;
else if( atdget.right3 < ( ON_LINE - 10 ) )
*dir = table_dir[ 27 ] ;
else if( atdget.right3 < ON_LINE )
*dir = table_dir[ 26 ] ;
else
*dir = table_dir[ 25 ] ;
side_cal += 2 ;
this_side = 2 ;
break ;
}
case 6 :
{
if( atdget.right2 < ( ON_LINE - 10 ) )
*dir = table_dir[ 28 ] ;
else if( atdget.right2 < ON_LINE )
*dir = table_dir[ 29 ] ;
else
*dir = table_dir[ 30 ] ;
side_cal += 3 ;
this_side = 6 ;
break ;
}
}
if( 0 == is_on_line_low )
{
if( ( LEFT == l_or_r ) && ( RIGHT == l_or_r_low ) )
*dir += 3 ;
else if( ( RIGHT == l_or_r ) && ( LEFT == l_or_r_low ) )
*dir -= 3 ;
}
}
// 如果处于离线状态则进行最大便移量处理
else
{
if( LEFT == l_or_r )
{
*dir = DIR_LMAX ;
num_lowest = 0 ;
}
else if( RIGHT == l_or_r )
{
*dir = DIR_RMAX ;
num_lowest = 6 ;
}
else
*dir = DIR_MID ;
side_cal += 4 ;
}
led_show2 = num_lowest ;
led_show1 = l_or_r_low ;
}
void Check_StartLine( ATD atd_start )
{
unchar counter ;
unchar show_temp = 0 ; // 用于显示下排红外的踩线情况的临时变量
unchar *ptr = &atd_start.left3 ;
unchar deal_flag = 0 ;
is_on_line_low = 0 ;
/***********对起跑线的检测测试显示***************/
// PORTB |= 0x7F ;
for( counter = 0; counter < 7; counter ++ )
{
if( *ptr < ON_LINE_LOW )
{
//PORTB &= ~( 1 << counter ) ;
// show_temp |= ( 1 << counter ) ;
is_on_line_low = 1 ;
break ;
}
ptr ++ ;
}
// PORTB = ~show_temp ;
/********************************************************/
if( is_on_line_low )
{
if( counter < 2 )
l_or_r_low = LEFT ;
else if( counter > 4 )
l_or_r_low = RIGHT ;
else
l_or_r_low = MIDLE ;
// PORTB = ~( l_or_r_low << 4 ) ;
ptr = &atd_start.left3 ;
if( ON_CROSS != start_line )
{
unchar *ptr_last = &atd_start.right3 ;
unchar scan_temp = 0 ;
ptr = &atd_start.left3 ;
while( ptr < ptr_last )
{
if( *ptr < ON_LINE_LOW )
{
if( scan_temp )
{
start_line = ON_START ;
deal_flag = 1 ;
break ;
}
if( *( ptr + 1 ) > ON_LINE_LOW )
{
scan_temp = 1 ;
ptr ++ ;
}
}
ptr ++ ;
}
}
if( 0 == deal_flag )
{
for( counter = 0; counter < 5; counter ++ )
{
if( ( *ptr < ON_LINE_LOW )
&& ( *( ptr + 1 ) < ON_LINE_LOW )
&& ( *( ptr + 2 ) < ON_LINE_LOW ) )
start_line = ON_CROSS ;
ptr ++ ;
}
}
}
}
/***********************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -