嵌入式设备——如何实现主车前进?

举报
holo.yh 发表于 2021/06/11 11:43:23 2021/06/11
【摘要】 【任务介绍】要想完成路线任务,需要将以下的指令结合:前进、后退、左转90°、右转90°、循迹、左转45°、右转45°,每个任务都需要通过编写一个函数来实现,我们这篇文章来编写前进函数【代码解释】 void Car_Go(uint8_t speed,uint16_t temp)// 主车前进函数 参数:速度/码盘{ Roadway_mp_syn(); //码盘同步函数 Stop_Flag...

【任务介绍】

我们这篇文章来编写前进函数

【代码解释】


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°函数同理。


【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。