嵌入式设备——如何实现主车前进?
【任务介绍】
我们这篇文章来编写前进函数
【代码解释】
void Car_Go(uint8_t speed,uint16_t temp)// 主车前进函数 参数:速度/码盘
{
Roadway_mp_syn(); //码盘同步函数
Stop_Flag = 0; //运行状态标志位
Go_Flag = 1; //前进标志位
wheel_L_Flag = 0; //左转标志位
wheel_R_Flag = 0; //右转标志位
wheel_Nav_Flag = 0; //码盘旋转标志位
Back_Flag = 0; //后退标志位
Track_Flag = 0; //循迹标志位
temp_MP = temp; //码盘值赋值
Car_Spend = speed; //速度值赋值
Control(Car_Spend ,Car_Spend); //调用电机驱动函数
while(Stop_Flag != 0x03);//等待前进完成
}
函数类型:void ,无需返回值
参数:速度、码盘值(通过协议:0X02代表前进,对应的副指令有速度和码盘两项参数;或者通过概念:前进就是小车以一定的速度行驶一定的码盘(路程)值)
函数名:Car_Go ,采用大驼峰命名法(每个单词首字母大写,其余小写)
函数体:前进函数体共有12条语句,下面对其依次进行解释。
Roadway_mp_syn(); //码盘同步函数
作用:获取小车当前的码盘值(指当前小车走了多少路程,在小车显示屏上可以看到该数值)。
Q:不写该函数可不可以?
A:不可以,小车的码盘值只在电机驱动板上记录,核心板是不知道的,要通过此函数,把该数据传给核心板,以便进行数据处理,执行后续任务。
Stop_Flag = 0; //运行状态标志位
作用:判断小车是否完成行驶任务。
Go_Flag = 1; //前进标志位
作用:Go_Flag = 1,代表小车前进;Go_Flag = 0,代表小车不前进
Q:如何判断小车当前处于什么状态呢呢?
A:打开通讯协议→四、竞赛平台运行状态表 (如下),运行状态就是通过给Stop_Flag的值判断的,如果Stop_Flag == 0x03 ,说明小车前进任务完成了。
wheel_L_Flag = 0; //左转标志位
wheel_R_Flag = 0; //右转标志位
wheel_Nav_Flag = 0; //码盘旋转标志位
Back_Flag = 0; //后退标志位
Track_Flag = 0; //循迹标志位
同前进标志位。
temp_MP = temp; //码盘值赋值
将我们自定义的码盘值变量“temp” 传递给小车默认(即设备厂商定义的)的码盘值变量“temp_MP”
Car_Spend = speed; //速度值赋值
将我们自定义的速度值变量“speed” 传递给小车默认的(即设备厂商定义的)码盘值变量“Car_Spend”
Control(Car_Spend ,Car_Spend); //调用电机驱动函数
电机驱动函数:一个控制小车左、右两轮子方向及速度的函数,
我们将鼠标移动到函数名上右击,选择Go To Definition Of 'Control' ,跳转到了“my_lib”文件夹下的“roadway_check.c”文件里,来查看该函数的代码。
该函数代码如下:
/***************************************************************
** 名字: 电机控制函数
** 功能: 控制左、右两轮子转动的方向和速度
** 参数: L_Spend:电机左轮速度
** R_Spend:电机右轮速度
** 返回值: 无
****************************************************************/
void Control(int L_Spend,int R_Spend) //函数名→Control:控制 参数1→L_Spend:左轮速度 参数2→R_Spend:右轮速度
{
if(L_Spend>=0) //如果左轮速度是正值(代表左轮向前转)
{
if(L_Spend>100)L_Spend=100;if(L_Spend<5)L_Spend=5; //作用:限制左轮速度在[5,100]内
}
else //要不然左轮速度就是负值(代表左轮向后转)
{
if(L_Spend<-100)L_Spend= -100;if(L_Spend>-5)L_Spend= -5; //作用:限制左轮速度在[-100,5]内
}
if(R_Spend>=0) //如果右轮速度是正值(代表右轮向前转)
{
if(R_Spend>100)R_Spend=100;if(R_Spend<5)R_Spend=5; //作用:限制右轮速度在[5,100]内
}
else //要不然右轮速度就是负值(代表右轮向后转)
{
if(R_Spend<-100)R_Spend= -100;if(R_Spend>-5)R_Spend= -5; //作用:限制右轮速度在[-100,5]内
}
Send_UpMotor(L_Spend ,R_Spend); //调用真正的电机驱动函数(底层的电机驱动函数),右击可查看
}
我们将鼠标移动到上述代码第27行的函数名上右击,选择Go To Definition Of 'Send_UpMotor',跳转到了“CAN”文件夹下的“roadway_check.c”文件里,来查看该函数的代码。
该函数代码如下(知道这些语句是控制轮子转速的底层代码就行,无需深入了解):
/**
函数功能:发送电机转速。知道这些语句是控制轮子转速的底层代码就行,无需深入了解
参 数:x1 左侧电机速度 x2 右侧电机转速
返 回 值:无
*/
void Send_UpMotor( int x1, int x2)
{
u8 txbuf[4];
txbuf[0] = x1;
txbuf[1] = x1;
txbuf[2] = x2;
txbuf[3] = x2;
//CanDrv_WhaitTxEmpty();
if(CanDrv_TxEmptyCheck())
{
CanDrv_TxData(txbuf,4,CAN_SID_HL(ID_MOTOR,0),0,_NULL);
CanP_Cmd_Write(CANP_CMD_ID_MOTO,txbuf,0,CAN_SID_HL(ID_MOTOR,0),0);
}
else
CanP_Cmd_Write(CANP_CMD_ID_MOTO,txbuf,4,CAN_SID_HL(ID_MOTOR,0),0);
}
while(Stop_Flag != 0x03);//等待前进完成
Q:如何判断小车前进完成了呢?
A:我们通过代码来了解其原理
首先,通过Ctrl+F查询Go_Flag,跳转到my_lib目录下roadway_check.c文件的“前进、后退监测函数”(第96行左右),如下:
/**
函数名:前进完成、后退完成监测函数
函数功能:当小车完成前进或后退指令后,使小车轮子速度降为0,停止运行
*/
void Go_and_Back_Check(void)
{
if(Go_Flag == 1) //如果前进标志位等于1
{
if(temp_MP <= Roadway_mp_Get()) //如果我们给定的码盘值 <= 小车当前码盘值(通过调用Roadway_mp_Get()函数获取)(代表前进完成)
{//前进完成之后执行下列操作:
Go_Flag = 0; //给前进标志位赋值为0
Stop_Flag = 3; //给运行状态标志位赋值为3;赋值为多少要与通讯协议的四、竞赛平台运行状态表对应
Send_UpMotor(0,0); //调用底层驱动代码,让小车左右轮子转速都为0,从而停止前进
}
}
else if(Back_Flag == 1)
{
if(temp_MP <= Roadway_mp_Get())
{
Back_Flag = 0;
Stop_Flag=3;
Send_UpMotor(0,0);
}
}
}
右击第9行的Roadway_mp_Get(),进入该被调函数(同文件下第39行左右),代码如下:
/*
函数名字:码盘值获取函数
函数功能:获取码盘值,并返回码盘值。无需深入了解
**/
uint16_t Roadway_mp_Get(void)
{
uint32_t ct;
if(CanHost_Mp > Roadway_cmp)
ct = CanHost_Mp - Roadway_cmp;
else
ct = Roadway_cmp - CanHost_Mp;
if(ct > 0x8000)
ct = 0xffff - ct;
return ct;
}
Q:如何让小车左转90°,右转90°?
A:左转90°的原理是让小车以一定速度向左旋转,同时寻找地图的黑线,由于地图的交叉黑线是90°夹角,所以当小车识别到黑线时,小车停止,此时正好转了90°。所以小车左转90°的函数需要一个参数:速度
右转90°函数同理。
- 点赞
- 收藏
- 关注作者
评论(0)