无人机的RC部分

一直没能仔细看的几个文件就是DT(数据传输)、RC(遥控器控制)和flight_ctrl,一是长,二是难,不直观,太多flag啊什么的,与总体控制有关。今晚就看完这些然后对代码做一个更加全面的整理,后面就要去试飞机和自己写控制了。

需要逐个函数进行分析。

void Remote_Control_Init()
{
	RC_IN_MODE = Ano_Parame.set.pwmInMode;
	if(RC_IN_MODE == SBUS)
	{
		Drv_SbusInit();
	}
	else
	{
		Drv_PpmInit();
	}
}

看名字,遥控控制初始化。
有关通信协议的东西,ppm和subs,应该不是我们需要关心的内容。

后面还有两个看门狗函数,不知道在搞什么。。。

然后有一个很长的函数,其实也就这个比较长,又有好多判断,一点一点看:

void unlock(u8 dT_ms)

解锁的意思

if( flag.power_state <=2 && para_sta.save_trig == 0)//只有电池电压非最低并且没有操作flash时,才允许进行解锁
{
	if(sens_hd_check.acc_ok && sens_hd_check.gyro_ok)
	{
		if(sens_hd_check.baro_ok)
		{
			if(flag.sensor_imu_ok  )//imu传感器正常时,才允许解锁
			{
				flag.unlock_err = 0;	//允许解锁标志位

			}
			else
			{
				flag.unlock_err = 1;//imu异常,不允许解锁

			}
		}
		else
		{
			LED_STA.errBaro = 1;
			flag.unlock_err = 2;//气压计异常,不允许解锁。
		}
	}
	else
	{
		LED_STA.errMpu = 1;
		flag.unlock_err = 3;//惯性传感器异常,不允许解锁。
	}
}
else
{
	flag.unlock_err = 4;//电池电压异常,不允许解锁
}

这个很多层的代码块其实逻辑并不复杂,依次对电源、陀螺仪加速度计、气压计、imu、进行有效检验,只有全部ok,解锁错误标志位才为0,否则都为1、2、3等等,非0也就是解锁错误。同时如果有问题,相应的指示灯会亮。
这里的unlock_err,要记住,有关解锁的标志位应该有好几层。

if(flag.unlock_sta == 0)
{
	if(flag.unlock_cmd != 0)
	{		
		if(flag.unlock_err == 0)
		{
			//
			flag.unlock_sta = flag.unlock_cmd;
			//
			ANO_DT_SendString("Unlock OK!");
			
		}
		else 
		{
			//reset
			flag.unlock_cmd = 0;
			//
			if(flag.unlock_err == 1)
			{
				ANO_DT_SendString("Unlock Fail!");
			}
			else if(flag.unlock_err == 2)
			{
				ANO_DT_SendString("Unlock Fail!");
			}
			else if(flag.unlock_err == 3)
			{
				ANO_DT_SendString("Unlock Fail!");
			}
			else if(flag.unlock_err == 4)
			{
				ANO_DT_SendString("Power Low,Unlock Fail!");
			}
			else
			{
			
			}
		}
	}
	else
	{
	
	}
}

也是好多层逻辑,但貌似也不复杂:
如果unlock_sta等于0,也就是没有解锁,那么如果unlock_cmd=1,也就是解锁命令有效,而且unlock_err=0,解锁没有错误,那么将解锁置一。
否则如果前面条件满足,但解锁有错误,就将unlock_cmd置0,清楚解锁命令,并给出错误的原因。

else
{
	if(flag.unlock_cmd == 0)
	{
		ANO_DT_SendString(" FC Output Locked! ");
	}		
	flag.unlock_sta = flag.unlock_cmd;
}

如果unlock_sta等于1,也就是已经解锁了,那么再判断当前解锁命令unlock_cmd是否有效,如果解锁命令无效,就说明此时需要锁定,把unlock_cmd赋给unlock_sta。
也就是说,对于解锁或者上锁,我们只要去调整unlock_cmd,而不需要去调整unlock_sta。
接下来又很长:

if(CH_N[CH_THR] < -UN_THR_VALUE  )
{
	//判断用户是否想要上锁、解锁
	if(ABS(CH_N[CH_YAW])>0.1f*UN_YAW_VALUE && CH_N[CH_PIT]< -0.1f*UN_PIT_VALUE)
	{
		if(flag.locking == 0)
		{
			flag.locking = 1;
		}
	}
	else
	{
		flag.locking = 0;
	}

	//飞控上锁、解锁检测
	if(CH_N[CH_PIT]<-UN_PIT_VALUE && CH_N[CH_ROL]>UN_ROL_VALUE && CH_N[CH_YAW]<-UN_YAW_VALUE)
	{
		stick_fun_0 = 1;
		flag.locking = 2;
	}
	else if(CH_N[CH_PIT]<-UN_PIT_VALUE && CH_N[CH_ROL]<-UN_ROL_VALUE && CH_N[CH_YAW]>UN_YAW_VALUE)
	{
		stick_fun_0 = 1;
		flag.locking = 2;
	}
	else
	{
		stick_fun_0 = 0;
	}
		
	
	u8 f = 0;		
	if(flag.unlock_sta)
	{
		//如果为解锁状态,最终f=0,将f赋值给flag.unlock_sta,飞控完成上锁
		f = 0;
		unlock_time = 1000;
	}
	else
	{
		//如果飞控为锁定状态,则f=2,将f赋值给flag.unlock_sta,飞控解锁完成
		f = 2;
		unlock_time = 200;
	}
	//进行最终的时间积分判断,摇杆必须满足条件unlock_time时间后,才会执行锁定和解锁动作
	stick_function_check_longpress(dT_ms,&unlock_f,unlock_time,stick_fun_0,f,&flag.unlock_cmd);
}

如果油门值低于-300,也就是油门拉低,就进入判断。
先判断pitch和yaw,如果yaw绝对值大于那个啥,pitch值小于那个啥,且此时locking等于0,表示没锁,就令locking=1,表示正在上锁(?还并不知locking是啥),否则,如果不满足这个条件,locking等于0,就是没有在上锁(?)

接下来再判断:外八和内八,都会使locking为2,stick_fun_0为1(虽然不知道这是个啥),如果不是外八或者内八,那么不需要管locking,把stick_fun_0置为0(orz)

再判断:如果为解锁状态,f = 0,unlock_time = 1000
如果为上锁状态,f = 2,unlock_time = 200
然后判断:如果stick_fun_0有效(1),那么计时,如果计时超过时间unlock_time,就把f赋值给unlock_cmd。

也就是说,如果内八或者外八,那么stick_fun_0为1,如果此时是解锁状态,且状态维一定的时间,那么就把f=0赋值给unlock_cmd,也就是锁定。如果此时是上锁状态,那么f=2赋值给unlock_cmd,表示要解锁。
如果没有内八或者外八,说明不要锁定,stick_fun_0清零,后面不会计时,也不会对unlock_cmd赋值。

else
{
	flag.locking = 0; //油门高
	if(flag.unlock_cmd == 2)
	{
		flag.unlock_cmd = 1;
	}
}

如果油门值没有低于-300,那么locking=0,表示没有在上锁,如果unlock_cmd=2,那么就把它赋值为1(暂时还不知道unlock_cmd2和1有什么区别)

if(CH_N[CH_THR]>-350)
{
	flag.thr_low = 0;//油门非低
}
else
{
	flag.thr_low = 1;//油门拉低
}

很清楚,就是不知道有啥用。
整个函数就是有关解锁的。。。再总结的时候会说。

接下来

void RC_duty_task(u8 dT_ms) //建议2ms调用一次

是轮询函数之一。
如果start_ok=1,则进入判断。

if(RC_IN_MODE == PPM || RC_IN_MODE == PWM)
	{
		for(u8 i=0;i<CH_NUM;i++)
		{
			if(chn_en_bit & (1<<i))//(Rc_Ppm_In[i]!=0)//该通道有值
			{
				CH_N[i] = ((s16)RC_PPM.Captures[i] - 1500); //1000 -- 2000us,处理成大约+-500摇杆量
			}
			else
			{
				CH_N[i] = 0;
			}
			CH_N[i] = LIMIT(CH_N[i],-500,500);//限制到+—500
		}		
	}

如果RC_IN_MODE是ppm或者pwm,那么对chn_en_bit每个位进行判断,如果该位有效,说明有值,那么处理该通道的值,否则该通道的值设为0.

else//sbus
	{
		for(u8 i=0;i<CH_NUM;i++)
		{
			if(chn_en_bit & (1<<i))//该通道有值
			{
				CH_N[i] = 0.65f *((s16)Rc_Sbus_In[i] - 1024); //248 --1024 --1800,处理成大约+-500摇杆量
			}
			else
			{
				CH_N[i] = 0;
			}
			CH_N[i] = LIMIT(CH_N[i],-500,500);//限制到+—500
		}					
	}

如果是sbus,那么仍然做该处理,只是处理方式不太一样,最终都是把各个通道的值处理为±500的油门量。

	//解锁监测	
	unlock(dT_ms);
	//摇杆触发功能监测
	stick_function(dT_ms);	
	//通道看门狗
	ch_watch_dog(dT_ms);
	//失控保护检查
	fail_safe_check(dT_ms);//3ms

接下来调用这些,也就是说这些函数会跟随RC_duty_task一起轮询。

接下来看关于fail_safe,也就是失控保护:

void fail_safe()
{
	for(u8 i = 0;i<4;i++)
	{
		CH_N[i] = 0;
	}

	if(CH_N[CH_THR]>0)
	{
		CH_N[CH_THR] = 0;
	}

	CH_N[CH_ROL] = 0;
	CH_N[CH_PIT] = 0;
	CH_N[CH_YAW] = 0;
	
	//切记不能给 CH_N[AUX1]赋值,否则可能导致死循环。(根据AUX1特殊值判断接收机failsafe信号)
	
	if(flag.unlock_sta)
	{
		if(switchs.gps_on ==0)
		{
			flag.auto_take_off_land = AUTO_LAND; //如果解锁,自动降落标记置位
		}
		else
		{
			flag.rc_loss_back_home = 1;
		}
		
	}
}

先看一下这个枚举里,通道和数字的对应关系:

enum
{
 CH_ROL = 0,
 CH_PIT ,
 CH_THR ,
 CH_YAW ,
 AUX1 ,
 AUX2 ,
 AUX3 ,
 AUX4 ,
 CH_NUM,//8
};

可以看出,这里对前四个值清零了两遍。
后面进行判断:如果此时是解锁状态,
那么如果没有gps,就flag.auto_take_off_land = AUTO_LAND,
如果有gps,就flag.rc_loss_back_home = 1;

也就是说,执行这个函数的时候,会启动自动降落。

再看失控保护检查,应该也就是判断何时调用fail_safe()函数的函数:

cnt += dT_ms;
if(cnt >= 500) //500*dT 秒
{

这个东西,500ms才会调用一次。

if((chn_en_bit & 0x0F) != 0x0F || flag.chn_failsafe ) //前4通道有任意一通道无信号或者受到接收机失控保护信号
{
	cnt2 ++;
}
else
{
	cnt2 --;	
}

如注释所说,前4通道有任意一通道无信号,或者受到接收机失控保护信号,那么对cnt2操作。

if(cnt2>=2)
{
	cnt2 = 0;
	
	flag.rc_loss = 1; //认为丢失遥控信号
	
	LED_STA.noRc = 1;
	
	fail_safe();		
}

如果cnt2大于等于2,说明至少连续进入函数两次,那么cnt2置零,rc_loss=1,即确认丢失了遥控信号,那么LED_STA.noRc = 1,用灯指示出来,并且执行fail_safe()。

else if(cnt2<=-2) //认为信号正常
{
	cnt2 = 0;
	
	if(flag.rc_loss)
	{
		flag.rc_loss = 0;
		LED_STA.noRc = 0;
		
			if(flag.taking_off)
			flag.auto_take_off_land = AUTO_TAKE_OFF_FINISH; //解除下降
	}		
}

如果cnt2<=-2,那么认为信号很正常,cnt2清零。如果上次是flag.rc_loss是1,那么改为0,灯也灭掉。如果起飞了,解除下降。

	test_si_cnt = signal_intensity;
	signal_intensity=0; //累计接收次数

不知道什么鬼。。。

最后就是这个什么stick_function()摇杆触发功能?
这个东西也跟随轮询。
不写了,内容就是在没有解锁的时候,会不停的检测遥感状态,不同的摇杆状态对应着罗盘、加速度计、陀螺仪的校准。

那遥控部分就完成了。。。。好长,但主要就只有四个量的接收转换、解锁、上锁、失控保护和失控保护检查。。比想象中简单一丢丢。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值