Browse Source
RPM filters (#5188)
RPM filters (#5188)
* Empty framework to apply RPM filter * Init gyro RPM filter * Entry point for Dterm filter * RPM filter implementation * Bugfixes * Fix Dterm fileter bank * Save RPM filter configuration in blackbox header * Debug RPM frequency * Disable PWM servo driver on all F3 boards * Move RPM filter to ITCM_RAM * Disable target COLIBRI_RACE as it's out of RAM * Drop FEATURE in favor of just settingsmaster
Paweł Spychalski
5 years ago
committed by
GitHub
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 400 additions and 12 deletions
-
2Makefile
-
1fake_travis_build.sh
-
2make/release.mk
-
1make/source.mk
-
11src/main/blackbox/blackbox.c
-
2src/main/build/debug.h
-
3src/main/config/parameter_group_ids.h
-
2src/main/fc/cli.c
-
2src/main/fc/config.h
-
9src/main/fc/fc_init.c
-
9src/main/fc/fc_tasks.c
-
1src/main/fc/settings.c
-
42src/main/fc/settings.yaml
-
5src/main/flight/pid.c
-
232src/main/flight/rpm_filter.c
-
53src/main/flight/rpm_filter.h
-
3src/main/scheduler/scheduler.h
-
11src/main/sensors/esc_sensor.c
-
3src/main/sensors/esc_sensor.h
-
8src/main/sensors/gyro.c
-
0src/main/target/COLIBRI_RACE/target.mk_
-
2src/main/target/MATEKF722SE/target.h
-
2src/main/target/OMNIBUS/target.h
-
1src/main/target/SPRACINGF3NEO/target.h
-
5src/main/target/common_post.h
@ -0,0 +1,232 @@ |
|||||
|
/* |
||||
|
* This file is part of INAV Project. |
||||
|
* |
||||
|
* This Source Code Form is subject to the terms of the Mozilla Public |
||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file, |
||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/. |
||||
|
* |
||||
|
* Alternatively, the contents of this file may be used under the terms |
||||
|
* of the GNU General Public License Version 3, as described below: |
||||
|
* |
||||
|
* This file is free software: you may copy, redistribute and/or modify |
||||
|
* it under the terms of the GNU General Public License as published by the |
||||
|
* Free Software Foundation, either version 3 of the License, or (at your |
||||
|
* option) any later version. |
||||
|
* |
||||
|
* This file is distributed in the hope that it will be useful, but |
||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General |
||||
|
* Public License for more details. |
||||
|
* |
||||
|
* You should have received a copy of the GNU General Public License |
||||
|
* along with this program. If not, see http://www.gnu.org/licenses/. |
||||
|
*/ |
||||
|
|
||||
|
#include "flight/rpm_filter.h" |
||||
|
|
||||
|
#include "config/parameter_group.h" |
||||
|
#include "config/parameter_group_ids.h" |
||||
|
|
||||
|
#include "build/debug.h" |
||||
|
|
||||
|
#include "common/axis.h" |
||||
|
#include "common/utils.h" |
||||
|
#include "common/maths.h" |
||||
|
#include "common/filter.h" |
||||
|
#include "flight/mixer.h" |
||||
|
#include "sensors/esc_sensor.h" |
||||
|
#include "fc/config.h" |
||||
|
|
||||
|
#ifdef USE_RPM_FILTER |
||||
|
|
||||
|
#define RPM_TO_HZ 60.0f |
||||
|
#define RPM_FILTER_RPM_LPF_HZ 150 |
||||
|
#define RPM_FILTER_HARMONICS 3 |
||||
|
|
||||
|
PG_REGISTER_WITH_RESET_TEMPLATE(rpmFilterConfig_t, rpmFilterConfig, PG_RPM_FILTER_CONFIG, 0); |
||||
|
|
||||
|
PG_RESET_TEMPLATE(rpmFilterConfig_t, rpmFilterConfig, |
||||
|
.gyro_filter_enabled = 0, |
||||
|
.dterm_filter_enabled = 0, |
||||
|
.gyro_harmonics = 1, |
||||
|
.gyro_min_hz = 100, |
||||
|
.gyro_q = 500, |
||||
|
.dterm_harmonics = 1, |
||||
|
.dterm_min_hz = 100, |
||||
|
.dterm_q = 500, ); |
||||
|
|
||||
|
typedef struct |
||||
|
{ |
||||
|
float q; |
||||
|
float minHz; |
||||
|
float maxHz; |
||||
|
uint8_t harmonics; |
||||
|
biquadFilter_t filters[XYZ_AXIS_COUNT][MAX_SUPPORTED_MOTORS][RPM_FILTER_HARMONICS]; |
||||
|
} rpmFilterBank_t; |
||||
|
|
||||
|
typedef float (*rpmFilterApplyFnPtr)(rpmFilterBank_t *filter, uint8_t axis, float input); |
||||
|
typedef void (*rpmFilterUpdateFnPtr)(rpmFilterBank_t *filterBank, uint8_t motor, float baseFrequency); |
||||
|
|
||||
|
static EXTENDED_FASTRAM pt1Filter_t motorFrequencyFilter[MAX_SUPPORTED_MOTORS]; |
||||
|
static EXTENDED_FASTRAM float erpmToHz; |
||||
|
static EXTENDED_FASTRAM rpmFilterBank_t gyroRpmFilters; |
||||
|
static EXTENDED_FASTRAM rpmFilterBank_t dtermRpmFilters; |
||||
|
static EXTENDED_FASTRAM rpmFilterApplyFnPtr rpmGyroApplyFn; |
||||
|
static EXTENDED_FASTRAM rpmFilterApplyFnPtr rpmDtermApplyFn; |
||||
|
static EXTENDED_FASTRAM rpmFilterUpdateFnPtr rpmGyroUpdateFn; |
||||
|
static EXTENDED_FASTRAM rpmFilterUpdateFnPtr rpmDtermUpdateFn; |
||||
|
|
||||
|
float nullRpmFilterApply(rpmFilterBank_t *filter, uint8_t axis, float input) |
||||
|
{ |
||||
|
UNUSED(filter); |
||||
|
UNUSED(axis); |
||||
|
return input; |
||||
|
} |
||||
|
|
||||
|
void nullRpmFilterUpdate(rpmFilterBank_t *filterBank, uint8_t motor, float baseFrequency) { |
||||
|
UNUSED(filterBank); |
||||
|
UNUSED(motor); |
||||
|
UNUSED(baseFrequency); |
||||
|
} |
||||
|
|
||||
|
float FAST_CODE rpmFilterApply(rpmFilterBank_t *filterBank, uint8_t axis, float input) |
||||
|
{ |
||||
|
float output = input; |
||||
|
|
||||
|
for (uint8_t motor = 0; motor < getMotorCount(); motor++) |
||||
|
{ |
||||
|
for (int harmonicIndex = 0; harmonicIndex < filterBank->harmonics; harmonicIndex++) |
||||
|
{ |
||||
|
output = biquadFilterApplyDF1( |
||||
|
&filterBank->filters[axis][motor][harmonicIndex], |
||||
|
output |
||||
|
); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return output; |
||||
|
} |
||||
|
|
||||
|
static void rpmFilterInit(rpmFilterBank_t *filter, uint16_t q, uint8_t minHz, uint8_t harmonics) |
||||
|
{ |
||||
|
filter->q = q / 100.0f; |
||||
|
filter->minHz = minHz; |
||||
|
filter->harmonics = harmonics; |
||||
|
/* |
||||
|
* Max frequency has to be lower than Nyquist frequency for looptime |
||||
|
*/ |
||||
|
filter->maxHz = 0.48f * 1000000.0f / getLooptime(); |
||||
|
|
||||
|
for (int axis = 0; axis < XYZ_AXIS_COUNT; axis++) |
||||
|
{ |
||||
|
for (int motor = 0; motor < getMotorCount(); motor++) |
||||
|
{ |
||||
|
|
||||
|
/* |
||||
|
* Harmonics are indexed from 1 where 1 means base frequency |
||||
|
* C indexes arrays from 0, so we need to shift |
||||
|
*/ |
||||
|
for (int harmonicIndex = 0; harmonicIndex < harmonics; harmonicIndex++) |
||||
|
{ |
||||
|
biquadFilterInit( |
||||
|
&filter->filters[axis][motor][harmonicIndex], |
||||
|
filter->minHz * (harmonicIndex + 1), |
||||
|
getLooptime(), |
||||
|
filter->q, |
||||
|
FILTER_NOTCH); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void disableRpmFilters(void) { |
||||
|
rpmGyroApplyFn = (rpmFilterApplyFnPtr)nullRpmFilterApply; |
||||
|
rpmDtermApplyFn = (rpmFilterApplyFnPtr)nullRpmFilterApply; |
||||
|
} |
||||
|
|
||||
|
void FAST_CODE NOINLINE rpmFilterUpdate(rpmFilterBank_t *filterBank, uint8_t motor, float baseFrequency) |
||||
|
{ |
||||
|
for (int axis = 0; axis < XYZ_AXIS_COUNT; axis++) |
||||
|
{ |
||||
|
for (int harmonicIndex = 0; harmonicIndex < filterBank->harmonics; harmonicIndex++) |
||||
|
{ |
||||
|
float harmonicFrequency = baseFrequency * (harmonicIndex + 1); |
||||
|
harmonicFrequency = constrainf(harmonicFrequency, filterBank->minHz, filterBank->maxHz); |
||||
|
|
||||
|
biquadFilterUpdate( |
||||
|
&filterBank->filters[axis][motor][harmonicIndex], |
||||
|
harmonicFrequency, |
||||
|
getLooptime(), |
||||
|
filterBank->q, |
||||
|
FILTER_NOTCH); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void rpmFiltersInit(void) |
||||
|
{ |
||||
|
for (uint8_t i = 0; i < MAX_SUPPORTED_MOTORS; i++) |
||||
|
{ |
||||
|
pt1FilterInit(&motorFrequencyFilter[i], RPM_FILTER_RPM_LPF_HZ, RPM_FILTER_UPDATE_RATE_US * 1e-6f); |
||||
|
} |
||||
|
erpmToHz = ERPM_PER_LSB / (motorConfig()->motorPoleCount / 2) / RPM_TO_HZ; |
||||
|
|
||||
|
rpmGyroUpdateFn = (rpmFilterUpdateFnPtr)nullRpmFilterUpdate; |
||||
|
rpmDtermUpdateFn = (rpmFilterUpdateFnPtr)nullRpmFilterUpdate; |
||||
|
|
||||
|
if (rpmFilterConfig()->gyro_filter_enabled) |
||||
|
{ |
||||
|
rpmFilterInit( |
||||
|
&gyroRpmFilters, |
||||
|
rpmFilterConfig()->gyro_q, |
||||
|
rpmFilterConfig()->gyro_min_hz, |
||||
|
rpmFilterConfig()->gyro_harmonics); |
||||
|
rpmGyroApplyFn = (rpmFilterApplyFnPtr)rpmFilterApply; |
||||
|
rpmGyroUpdateFn = (rpmFilterUpdateFnPtr)rpmFilterUpdate; |
||||
|
} |
||||
|
|
||||
|
if (rpmFilterConfig()->dterm_filter_enabled) |
||||
|
{ |
||||
|
rpmFilterInit( |
||||
|
&dtermRpmFilters, |
||||
|
rpmFilterConfig()->dterm_q, |
||||
|
rpmFilterConfig()->dterm_min_hz, |
||||
|
rpmFilterConfig()->dterm_harmonics); |
||||
|
rpmDtermApplyFn = (rpmFilterApplyFnPtr)rpmFilterApply; |
||||
|
rpmDtermUpdateFn = (rpmFilterUpdateFnPtr)rpmFilterUpdate; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void FAST_CODE NOINLINE rpmFilterUpdateTask(timeUs_t currentTimeUs) |
||||
|
{ |
||||
|
UNUSED(currentTimeUs); |
||||
|
|
||||
|
uint8_t motorCount = getMotorCount(); |
||||
|
/* |
||||
|
* For each motor, read ERPM, filter it and update motor frequency |
||||
|
*/ |
||||
|
for (uint8_t i = 0; i < motorCount; i++) |
||||
|
{ |
||||
|
const escSensorData_t *escState = getEscTelemetry(i); //Get ESC telemetry |
||||
|
const float baseFrequency = pt1FilterApply(&motorFrequencyFilter[i], escState->rpm * erpmToHz); //Filter motor frequency |
||||
|
|
||||
|
if (i < 4) { |
||||
|
DEBUG_SET(DEBUG_RPM_FREQ, i, (int)baseFrequency); |
||||
|
} |
||||
|
|
||||
|
rpmGyroUpdateFn(&gyroRpmFilters, i, baseFrequency); |
||||
|
rpmDtermUpdateFn(&dtermRpmFilters, i, baseFrequency); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
float FAST_CODE rpmFilterGyroApply(uint8_t axis, float input) |
||||
|
{ |
||||
|
return rpmGyroApplyFn(&gyroRpmFilters, axis, input); |
||||
|
} |
||||
|
|
||||
|
float FAST_CODE rpmFilterDtermApply(uint8_t axis, float input) |
||||
|
{ |
||||
|
return rpmDtermApplyFn(&dtermRpmFilters, axis, input); |
||||
|
} |
||||
|
|
||||
|
#endif |
@ -0,0 +1,53 @@ |
|||||
|
/* |
||||
|
* This file is part of INAV Project. |
||||
|
* |
||||
|
* This Source Code Form is subject to the terms of the Mozilla Public |
||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file, |
||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/. |
||||
|
* |
||||
|
* Alternatively, the contents of this file may be used under the terms |
||||
|
* of the GNU General Public License Version 3, as described below: |
||||
|
* |
||||
|
* This file is free software: you may copy, redistribute and/or modify |
||||
|
* it under the terms of the GNU General Public License as published by the |
||||
|
* Free Software Foundation, either version 3 of the License, or (at your |
||||
|
* option) any later version. |
||||
|
* |
||||
|
* This file is distributed in the hope that it will be useful, but |
||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General |
||||
|
* Public License for more details. |
||||
|
* |
||||
|
* You should have received a copy of the GNU General Public License |
||||
|
* along with this program. If not, see http://www.gnu.org/licenses/. |
||||
|
*/ |
||||
|
|
||||
|
#pragma once |
||||
|
|
||||
|
#include "config/parameter_group.h" |
||||
|
#include "common/time.h" |
||||
|
|
||||
|
typedef struct rpmFilterConfig_s { |
||||
|
uint8_t gyro_filter_enabled; |
||||
|
uint8_t dterm_filter_enabled; |
||||
|
|
||||
|
uint8_t gyro_harmonics; |
||||
|
uint8_t gyro_min_hz; |
||||
|
uint16_t gyro_q; |
||||
|
|
||||
|
uint8_t dterm_harmonics; |
||||
|
uint8_t dterm_min_hz; |
||||
|
uint16_t dterm_q; |
||||
|
|
||||
|
} rpmFilterConfig_t; |
||||
|
|
||||
|
PG_DECLARE(rpmFilterConfig_t, rpmFilterConfig); |
||||
|
|
||||
|
#define RPM_FILTER_UPDATE_RATE_HZ 500 |
||||
|
#define RPM_FILTER_UPDATE_RATE_US (1000000.0f / RPM_FILTER_UPDATE_RATE_HZ) |
||||
|
|
||||
|
void disableRpmFilters(void); |
||||
|
void rpmFiltersInit(void); |
||||
|
void rpmFilterUpdateTask(timeUs_t currentTimeUs); |
||||
|
float rpmFilterGyroApply(uint8_t axis, float input); |
||||
|
float rpmFilterDtermApply(uint8_t axis, float input); |
Write
Preview
Loading…
Cancel
Save
Reference in new issue