1. 程式人生 >實用技巧 >其它 >BetaFlight模組設計之十三:Gyro過濾任務分析

BetaFlight模組設計之十三:Gyro過濾任務分析


基於BetaFlight開原始碼框架簡介的框架設計,逐步分析內部模組功能設計。

Gyro過濾任務

描述:主要是對Gyro資料的過濾處理。

 ├──> 初始化
 │   ├──> [x]硬體初始化
 │   └──> [v]業務初始化gyroInitFilters
 ├──> 任務
 │   ├──> [v]實時任務[TASK_FILTER] = DEFINE_TASK("FILTER", NULL, NULL, taskFiltering, TASK_GYROPID_DESIRED_PERIOD, TASK_PRIORITY_REALTIME),
 │   ├──> [x]事件任務
 │   └──> [x]時間任務
 ├──> 驅動
 │   ├──> [x]查詢
 │   └──> [x]中斷
 └──> 介面
     └──> TBD

taskFiltering任務分析

沒什麼看頭,外面是一個過濾任務,裡面實質是gyro的過濾函式。
估計最初考慮很多資料平滑或者過濾都在這裡處理。而實際上這個和飛控姿態相關的資料過濾函式呼叫頻率非常高,而其他感測資料並非需要類似高的頻率。

taskFiltering
 └──> gyroFiltering

gyroFiltering函式分析

gyroFiltering
 ├──> GYRO_FILTER_FUNCTION_NAME()
 ├──> <USE_DYN_NOTCH_FILTER><isDynNotchActive()>
 │   └──> dynNotchUpdate
 ├──> <gyro.useDualGyroDebugging>
 │   ├──> <GYRO_CONFIG_USE_GYRO_1>[debug資料更新]
 │   ├──> <GYRO_CONFIG_USE_GYRO_2>[debug資料更新]
 │   └──> <GYRO_CONFIG_USE_GYRO_BOTH>[debug資料更新]
 ├──> <USE_GYRO_OVERFLOW_CHECK><gyroConfig()->checkOverflow && !gyro.gyroHasOverflowProtection>
 │   └──> checkForOverflow
 ├──> <USE_YAW_SPIN_RECOVERY><yawSpinRecoveryEnabled>
 │   └──> checkForYawSpin
 └──> <!overflowDetected> // integrate using trapezium rule to avoid bias
     ├──> accumulatedMeasurements[axis] += 0.5f * (gyroPrevious[axis] + gyro.gyroADCf[axis]) * gyro.targetLooptime;
     ├──> gyroPrevious[axis] = gyro.gyroADCf[axis];
     └──> accumulatedMeasurementCount++;

filterGyro函式分析

這個函式有兩個變種:filterGyro和filterGyroDebug;主要問題是是否需要debug一些資料,filterGyroDebug函式以下巨集定義來資料的記錄。

#define DEBUG_SET(mode, index, value) do { if (debugMode == (mode)) { debug[(index)] = (value); } } while (0)
#define GYRO_FILTER_AXIS_DEBUG_SET(axis, mode, index, value) if (axis == (int)gyro.gyroDebugAxis) DEBUG_SET(mode, index, value)

詳見:\src\main\sensors\gyro.c

#define GYRO_FILTER_FUNCTION_NAME filterGyro
#define GYRO_FILTER_DEBUG_SET(mode, index, value) do { UNUSED(mode); UNUSED(index); UNUSED(value); } while (0)
#define GYRO_FILTER_AXIS_DEBUG_SET(axis, mode, index, value) do { UNUSED(axis); UNUSED(mode); UNUSED(index); UNUSED(value); } while (0)
#include "gyro_filter_impl.c"
#undef GYRO_FILTER_FUNCTION_NAME
#undef GYRO_FILTER_DEBUG_SET
#undef GYRO_FILTER_AXIS_DEBUG_SET

#define GYRO_FILTER_FUNCTION_NAME filterGyroDebug
#define GYRO_FILTER_DEBUG_SET DEBUG_SET
#define GYRO_FILTER_AXIS_DEBUG_SET(axis, mode, index, value) if (axis == (int)gyro.gyroDebugAxis) DEBUG_SET(mode, index, value)
#include "gyro_filter_impl.c"
#undef GYRO_FILTER_FUNCTION_NAME

實際執行或者釋出的程式碼還是使用filterGyro,這裡分析的時候直接使用了GYRO_FILTER_FUNCTION_NAME。

GYRO_FILTER_FUNCTION_NAME
 ├──> <loop axis> // downsample the individual gyro samples
 │   ├──> <gyro.downsampleFilterEnabled> // using gyro lowpass 2 filter for downsampling
 │   │   └──> gyroADCf = gyro.sampleSum[axis];
 │   ├──> <!gyro.downsampleFilterEnabled> // using simple average for downsampling
 │   │   └──> gyroADCf = gyro.sampleSum[axis] / gyro.sampleCount;
 │   ├──> <USE_RPM_FILTER>
 │   │   └──> rpmFilterGyro
 │   ├──> // apply static notch filters and software lowpass filters
 │   │   ├──> gyroADCf = gyro.notchFilter1ApplyFn((filter_t *)&gyro.notchFilter1[axis], gyroADCf);
 │   │   ├──> gyroADCf = gyro.notchFilter2ApplyFn((filter_t *)&gyro.notchFilter2[axis], gyroADCf);
 │   │   └──> gyroADCf = gyro.lowpassFilterApplyFn((filter_t *)&gyro.lowpassFilter[axis], gyroADCf);
 │   ├──> <USE_DYN_NOTCH_FILTER><isDynNotchActive()>
 │   │   ├──> dynNotchPush(axis, gyroADCf);
 │   │   ├──> gyroADCf = dynNotchFilter(axis, gyroADCf);
 │   └──> gyro.gyroADCf[axis] = gyroADCf;
 └──> gyro.sampleCount = 0;

dynamic notch filter

關於dynamic notch filter我們有時間再專門針對濾波這個作為一個模組進行分析,詳見:\src\main\flight\dyn_notch_filter.c。

downsampling概念

這裡是關於資料採集以及downsampling/upsampling資料處理的演算法問題,暫不做展開,有興趣的,這裡有個連結可以簡單瞭解下。