遥控器数据解析

遥控器数据解析

本章以乐迪AT9S(已停产)为代表举例,如有不同,请根据所持遥控器查看厂商说明书。
遥控器数据解析_第1张图片

文章目录

  • 遥控器数据解析
    • 一、遥控器简介
    • 二、遥控器通道
    • 三、遥控器协议解析
    • 四、遥控器数据解析
      • 1、得到遥控器数据上一次接收到的和这一次接收到数据的间隔(freertos版,也可以通过定时器来获取)
      • 2、遥控数据单位化和去除死区
      • 3、主要数据处理
      • 4、封装遥控数据单位化和加死区后的数据
      • 5、返回一个通过检测接收机与遥控器连接状态或接收数据是否异常来判断接收遥控器数据线程是否健康的函数

一、遥控器简介

遥控器是一种用于控制无人系统操作的设备。它通常由一个手持的控制器和一个接收器组成。遥控器上配有各种按钮、摇杆和滑块,用于控制无人系统的各种功能,如起飞、降落、悬停、前进、后退、左转、右转等。

无人系统遥控器使用无线信号将操作指令传输给无人系统的接收器。接收器将信号解码后发送给无人系统的飞行控制系统,从而实现用户的指令

二、遥控器通道

遥控器一般具有多个通道,具体数量取决于遥控器的设计和用途。
AT9S有十个通道,其中前四个通道对应摇杆,5通道以上为拨扭开关,可以自定义。其自定义概念为可以将任意拨扭开关映射到5通道以上任意通道上。

三、遥控器协议解析

遥控器协议分为SBUS、PPM等
SBUS协议详见另一篇文章:遥控器协议解析—SBUS篇

四、遥控器数据解析

接收机接收到遥控器数据后进行处理后会得到各个通道值,不同协议接收机接收到的数据范围是不一样的,比如SBUS传来的每个通道值的数据大概范围为300~1700,PPM传来的每个通道值的数据大概范围为500~1500等。其具体的通道值数据范围可以通过将数据读出来查看。

1、得到遥控器数据上一次接收到的和这一次接收到数据的间隔(freertos版,也可以通过定时器来获取)

_Bool get_rc_sbus_health()
{
	//rc_connect_flag为接收机接收到的数据中标志着遥控器和接收机是否失去连接
    if( (xTaskGetTickCountFromISR() - last_sbus_update_ms > 100) || rc_connect_flag == false){
        return  false;
    }
    else  return  true;
}

2、遥控数据单位化和去除死区

死区(deadband)有时也称为中性区(neutral zone)或不作用区,是指控制系统的传递函数中,对应输出为零的输入信号范围。

float data_to_deadzone(float x,float ref,float zoom)
{
    float t;
    if(x>ref)
    {
        t = x - zoom;   //x不管在ref~ref+zoom之间怎么变,输出t始终为ref
        if(t<ref)
        {
            t = ref;
        }
    }
    else
    {
        t = x + zoom;
        if(t>ref)
        {
            t = ref;
        }
    }
	return (t);
}

static float data_to_unit_dead(int16_t rawData, int16_t deadband)
{
    float norm = ((float)data_to_deadzone(rawData,0,deadband) / (float)(500-deadband));
    return norm;
}

3、主要数据处理

enum
{
    ROL ,
    PIT ,
    THR ,
    YAW ,
    AUX1 ,
    AUX2 ,
    AUX3 ,
    AUX4 ,
    //其实可以更多,根据遥控器通道和所需多少通道来设置
    CH_NUM
};

typedef enum
{
    LO = 0,
    CE = 1,
    HI = 2,
    //拨扭开关有的为两档,有的为三档,这里分为三个档位来标志开关位置
}CH_Pos;
/* 结构体数组,指示每个通道低中高三种状态 */
CH_Pos channelPos[CH_NUM];      			//辅助通道位置状态
int16_t rc_original[CH_NUM] = {0};          //储存遥控器原始数据
float rc_value_unit[3];                     //遥控器原始数据加死区后单位化
uint16_t rc_sbus_in[18];
int sbus_data_update(void)
{
    for (uint8_t i = 0; i < CH_NUM; ++i) {
		//使数据在1000~2000之间,原始数据在300~1700之间
        rc_sbus_in[i] = 1000 + (int)((sbus.ch[i]-300)*((float)1000/(1700-300)));	
    }
    return HAL_OK;
}

void main_channel_value_update(void)
{
	rc_health = get_rc_sbus_health();
    for(uint8_t i=0; i<CH_NUM; ++i)
    {
        if(rc_sbus_in[i] >= 1000)                                           //如果该通道有值,处理通道数据
        {
            if (rc_sbus_in[1]<910||rc_sbus_in[2]<910) {
            	rc_health = false;
            }
 //           else  rc_health = true;
 
            rc_original[i] = 1.1f *(rc_sbus_in[i] - 1500);    //处理成+-500摇杆量,1.1是为遥控器做的适配
            rc_original[i] = (int16_t)limit(rc_original[i],-500,500);   //限制到+—500
			if(
        }
        /*接收机掉落仍进不去此判断,如果之前_rc_health已经为ture则此时_rc_health仍为ture*/
        else
        {
            rc_original[i] = 0;      //没值全部默认设为中位(1500)//遥控器不开相当于遥控器输入0
            rc_health = false;
        }

        if(rc_original[i] < (-300))
        {
            channelPos[i] = LO;        //处理通道 档位
        }
        else if(rc_original[i] > (300))
        {
            channelPos[i] = HI;         //高档
        }
        else
        {
            channelPos[i] = CE;         //中档
        }
    }

    /*遥控数据单位化和加死区*/
    rc_value_unit[ROL] =  data_to_unit_dead(rc_original[ROL], 40);
    rc_value_unit[PIT] =  data_to_unit_dead(rc_original[PIT], 40);
    rc_value_unit[YAW] =  data_to_unit_dead(rc_original[YAW], 50);
    rc_value_unit[THR] =  data_to_unit_dead(rc_original[THR], 100);
}

4、封装遥控数据单位化和加死区后的数据

/*遥控数据单位化和加死区后的数据*/
float get_channel_roll_control_in()  //线性数据 -1 to 1
{
    return  rc_value_unit[ROL];
}

/*遥控数据单位化和加死区后的数据*/
float get_channel_pitch_control_in()  //线性数据 -1 to 1
{
    return  rc_value_unit[PIT];
}

/*遥控数据单位化和加死区后的数据*/
float get_channel_yaw_control_in()   //线性数据 -1 to 1
{
    return  rc_value_unit[YAW];
}

/*遥控数据单位化和加死区后的数据*/
float get_channel_thr_control_in()   //线性数据 -1 to 1
{
    return  rc_value_unit[THR];
}

/*遥控数据单位化和加死区后的数据*/
float get_one_way_throttle()   //线性数据 0 to 1  一般用于手动控制油门
{
    if(rc_original[THR] == 0) return 0;

    return  (rc_original[THR]+500)*0.001f;
}

5、返回一个通过检测接收机与遥控器连接状态或接收数据是否异常来判断接收遥控器数据线程是否健康的函数

_Bool get_rc_health(void)
{
   return  (_rc_health && rc_connect_flag);
}

你可能感兴趣的:(遥控器相关,c语言,stm32,单片机)