基于FreeRTOS的STM32四轴飞行器: 八.遥控器摇杆
- 一.摇杆数据的扫描
- 二.处理摇杆数据
- 三.微调按键处理
一.摇杆数据的扫描
下面摇杆初始化时,启动了ADC-DMA进行了采集,已经开始转换直接将数据通过DMA存入buff数组中:
static uint16_t buff[4] = {0};
/**
* @description: 摇杆初始化
* @return {*}
*/
void Inf_JoyStickAndKey_Init(void)
{
debug_printfln("摇杆和按键数据的初始化 开始");
/* 1. ADC校准 */
HAL_ADCEx_Calibration_Start(&hadc1);
/* 2. 启动ADC转换 */
HAL_ADC_Start_DMA(&hadc1, (uint32_t *)buff, 4);
debug_printfln("摇杆和按键数据的初始化 结束");
}
扫描摇杆数据时,直接从缓冲区中扫描就行了:
注意取数据要根据配置的Rank。
定义摇杆数据:
com_config.h使用int16防止数据突变。
typedef struct
{
int16_t THR; /* 油门 */
int16_t PIT; /* 俯仰 */
int16_t ROL; /* 横滚 */
int16_t YAW; /* 偏航 */
uint8_t isPowerDown; /* 是否关机: 1:关机 0:不关机 */
uint8_t isFixHeight; /* 是否翻转定高的状态 */
} JoyStick_Struct;
扫描摇杆数据:
/**
* @description: 扫描摇杆数据
* @return {*}
*/
void Inf_JoyStickAndKey_JoyStickScan(void)
{
joyStick.THR = buff[0];
joyStick.YAW = buff[1];
joyStick.PIT = buff[2];
joyStick.ROL = buff[3];
}
创建摇杆处理任务:
先定义一些任务参数。
/* 4. 摇杆处理任务 */
void joyStickTask(void *args);
#define JOY_STICK_TASK_NAME "joy_stick_task"
#define JOY_STICK_TASK_STACK 256
#define JOY_STICK_TASK_PRIORITY 7
TaskHandle_t joyStickTaskHandle;
#define JOY_STICK_EXEC_CYCLE 4
/* 4. 摇杆处理任务 */
xTaskCreate(joyStickTask,
JOY_STICK_TASK_NAME,
JOY_STICK_TASK_STACK,
NULL,
JOY_STICK_TASK_PRIORITY,
&joyStickTaskHandle);
测试打印摇杆数据:
/* 4. 摇杆处理 */
void joyStickTask(void *args)
{
vTaskDelay(500);
debug_printfln("摇杆处理任务开始调度");
uint32_t preTime = xTaskGetTickCount();
while(1)
{
Inf_JoyStickAndKey_JoyStickScan();
Com_Config_PrintJoyStick("a");
vTaskDelayUntil(&preTime, JOY_STICK_EXEC_CYCLE);
}
}
观察打印数据全部为0:
因为要先启动ADC采集数据。
在启动任务前启动处理模块:
这时可以打印数据:
观察发现数据有一些极性相反。
二.处理摇杆数据
摇杆极性和范围的处理:
处理摇杆数据范围0-4095转换为0-1000。
/**
* @description: 处理摇杆数据的极性和范围
* @return {*}
*/
static void App_DataProcess_JoyStickPolarityAndRange(void)
{
/* 1. 处理极性 [4095, 0] => [0, 1000]
(4095 - [4095, 0]) / 4.095
(4095 - [4095, 0]) / (4095 / 1000)
(4095 - [4095, 0]) * 1000 / 4095
1000 - [4095, 0] * 1000 / 4095
*/
joyStick.THR = 1000 - joyStick.THR * 1000 / 4095;
joyStick.ROL = 1000 - joyStick.ROL * 1000 / 4095;
joyStick.PIT = 1000 - joyStick.PIT * 1000 / 4095;
joyStick.YAW = 1000 - joyStick.YAW * 1000 / 4095;
}
处理摇杆数据:
/**
* @description: 处理摇杆数据
* @return {*}
*/
void App_DataProcess_JoyStickDataProcess(void)
{
/* 1. 扫描摇杆 */
Inf_JoyStickAndKey_JoyStickScan();
/* 2. 极性和范围处理 */
App_DataProcess_JoyStickPolarityAndRange();
Com_Config_PrintJoyStick("2");
}
观察发现该数据在默认情况下会有误差值,需要进行校准:
摇杆数据校准:
想办法求出数据偏移量,长按按键减去偏移量进行校准。
在Config.c中定义存储摇杆偏移量的结构体:
计算偏移量:
/**
* @description: 计算摇杆的偏移量
* @return {*}
*/
static void App_DataProcess_JoyStickCaclBias(void)
{
joyStickBias.THR = 0;
joyStickBias.ROL = 0;
joyStickBias.YAW = 0;
joyStickBias.PIT = 0;
for(uint8_t i = 0; i < 100; i++)
{
Inf_JoyStickAndKey_JoyStickScan();
App_DataProcess_JoyStickPolarityAndRange();
joyStickBias.THR += (joyStick.THR - 0); /* 0值校准 */
joyStickBias.PIT += (joyStick.PIT - 500); /* 中值校准 */
joyStickBias.YAW += (joyStick.YAW - 500);
joyStickBias.ROL += (joyStick.ROL - 500);
vTaskDelay(10);
}
joyStickBias.THR /= 100;
joyStickBias.PIT /= 100;
joyStickBias.ROL /= 100;
joyStickBias.YAW /= 100;
// Com_Config_PrintJoyStickBias("bias 2");
}
校准:
/**
* @description: 对摇杆数据做校准
* @return {*}
*/
static void App_DataProcess_JoystickWithBias(void)
{
/* 叠加偏移量 */
joyStick.THR -= joyStickBias.THR;
joyStick.PIT -= joyStickBias.PIT;
joyStick.ROL -= joyStickBias.ROL;
joyStick.YAW -= joyStickBias.YAW;
/* 对校准后的数据做限幅处理 */
joyStick.THR = LIMIT(joyStick.THR, 0, 1000);
joyStick.PIT = LIMIT(joyStick.PIT, 0, 1000);
joyStick.ROL = LIMIT(joyStick.ROL, 0, 1000);
joyStick.YAW = LIMIT(joyStick.YAW, 0, 1000);
}
在打印数据时出现BUG,数值不正确:
原因是扫描摇杆值后未对极性和范围处理,数值错误。
解决:
在执行完扫描后执行极性和范围处理函数,之后再计算偏移量。
在按键处理时,将该函数放在临界区中可以避免在长按时,任务调度到摇杆扫描:
三.微调按键处理
在摇杆结构体中添加isPowerDown和isFixHeight:
在按键处理函数中继续添加关机和定高功能:
继续添加微调按钮:
保持飞行稳定不偏,将需要微调的数据直接加到偏移量中,之后减去偏移量可以达到效果。