Blackbox device type 'file' (SITL) considered working when file handler is available
[inav.git] / src / main / flight / rpm_filter.c
blobffca6c8ea6845adde82ac245b0ddfa624ed1abe0
1 /*
2 * This file is part of INAV Project.
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
6 * You can obtain one at http://mozilla.org/MPL/2.0/.
8 * Alternatively, the contents of this file may be used under the terms
9 * of the GNU General Public License Version 3, as described below:
11 * This file is free software: you may copy, redistribute and/or modify
12 * it under the terms of the GNU General Public License as published by the
13 * Free Software Foundation, either version 3 of the License, or (at your
14 * option) any later version.
16 * This file is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
19 * Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program. If not, see http://www.gnu.org/licenses/.
25 #include "platform.h"
27 #include "flight/rpm_filter.h"
29 #include "config/parameter_group.h"
30 #include "config/parameter_group_ids.h"
32 #include "build/debug.h"
34 #include "common/axis.h"
35 #include "common/utils.h"
36 #include "common/maths.h"
37 #include "common/filter.h"
38 #include "flight/mixer.h"
39 #include "sensors/esc_sensor.h"
40 #include "fc/config.h"
41 #include "fc/settings.h"
43 #ifdef USE_RPM_FILTER
45 #define HZ_TO_RPM 1/60.0f
46 #define RPM_FILTER_RPM_LPF_HZ 150
47 #define RPM_FILTER_HARMONICS 3
49 PG_REGISTER_WITH_RESET_TEMPLATE(rpmFilterConfig_t, rpmFilterConfig, PG_RPM_FILTER_CONFIG, 1);
51 PG_RESET_TEMPLATE(rpmFilterConfig_t, rpmFilterConfig,
52 .gyro_filter_enabled = SETTING_RPM_GYRO_FILTER_ENABLED_DEFAULT,
53 .gyro_harmonics = SETTING_RPM_GYRO_HARMONICS_DEFAULT,
54 .gyro_min_hz = SETTING_RPM_GYRO_MIN_HZ_DEFAULT,
55 .gyro_q = SETTING_RPM_GYRO_Q_DEFAULT, );
57 typedef struct
59 float q;
60 float minHz;
61 float maxHz;
62 uint8_t harmonics;
63 biquadFilter_t filters[XYZ_AXIS_COUNT][MAX_SUPPORTED_MOTORS][RPM_FILTER_HARMONICS];
64 } rpmFilterBank_t;
66 typedef float (*rpmFilterApplyFnPtr)(rpmFilterBank_t *filter, uint8_t axis, float input);
67 typedef void (*rpmFilterUpdateFnPtr)(rpmFilterBank_t *filterBank, uint8_t motor, float baseFrequency);
69 static EXTENDED_FASTRAM pt1Filter_t motorFrequencyFilter[MAX_SUPPORTED_MOTORS];
70 static EXTENDED_FASTRAM rpmFilterBank_t gyroRpmFilters;
71 static EXTENDED_FASTRAM rpmFilterApplyFnPtr rpmGyroApplyFn;
72 static EXTENDED_FASTRAM rpmFilterUpdateFnPtr rpmGyroUpdateFn;
74 float nullRpmFilterApply(rpmFilterBank_t *filter, uint8_t axis, float input)
76 UNUSED(filter);
77 UNUSED(axis);
78 return input;
81 void nullRpmFilterUpdate(rpmFilterBank_t *filterBank, uint8_t motor, float baseFrequency) {
82 UNUSED(filterBank);
83 UNUSED(motor);
84 UNUSED(baseFrequency);
87 float rpmFilterApply(rpmFilterBank_t *filterBank, uint8_t axis, float input)
89 float output = input;
91 for (uint8_t motor = 0; motor < getMotorCount(); motor++)
93 for (int harmonicIndex = 0; harmonicIndex < filterBank->harmonics; harmonicIndex++)
95 output = biquadFilterApplyDF1(
96 &filterBank->filters[axis][motor][harmonicIndex],
97 output
102 return output;
105 static void rpmFilterInit(rpmFilterBank_t *filter, uint16_t q, uint8_t minHz, uint8_t harmonics)
107 filter->q = q / 100.0f;
108 filter->minHz = minHz;
109 filter->harmonics = harmonics;
111 * Max frequency has to be lower than Nyquist frequency for looptime
113 filter->maxHz = 0.48f * 1000000.0f / getLooptime();
115 for (int axis = 0; axis < XYZ_AXIS_COUNT; axis++)
117 for (int motor = 0; motor < getMotorCount(); motor++)
121 * Harmonics are indexed from 1 where 1 means base frequency
122 * C indexes arrays from 0, so we need to shift
124 for (int harmonicIndex = 0; harmonicIndex < harmonics; harmonicIndex++)
126 biquadFilterInit(
127 &filter->filters[axis][motor][harmonicIndex],
128 filter->minHz * (harmonicIndex + 1),
129 getLooptime(),
130 filter->q,
131 FILTER_NOTCH);
137 void disableRpmFilters(void) {
138 rpmGyroApplyFn = (rpmFilterApplyFnPtr)nullRpmFilterApply;
141 void rpmFilterUpdate(rpmFilterBank_t *filterBank, uint8_t motor, float baseFrequency)
143 for (int axis = 0; axis < XYZ_AXIS_COUNT; axis++)
145 for (int harmonicIndex = 0; harmonicIndex < filterBank->harmonics; harmonicIndex++)
147 float harmonicFrequency = baseFrequency * (harmonicIndex + 1);
148 harmonicFrequency = constrainf(harmonicFrequency, filterBank->minHz, filterBank->maxHz);
150 biquadFilterUpdate(
151 &filterBank->filters[axis][motor][harmonicIndex],
152 harmonicFrequency,
153 getLooptime(),
154 filterBank->q,
155 FILTER_NOTCH);
160 void rpmFiltersInit(void)
162 for (uint8_t i = 0; i < MAX_SUPPORTED_MOTORS; i++)
164 pt1FilterInit(&motorFrequencyFilter[i], RPM_FILTER_RPM_LPF_HZ, US2S(RPM_FILTER_UPDATE_RATE_US));
167 rpmGyroUpdateFn = (rpmFilterUpdateFnPtr)nullRpmFilterUpdate;
169 if (rpmFilterConfig()->gyro_filter_enabled)
171 rpmFilterInit(
172 &gyroRpmFilters,
173 rpmFilterConfig()->gyro_q,
174 rpmFilterConfig()->gyro_min_hz,
175 rpmFilterConfig()->gyro_harmonics);
176 rpmGyroApplyFn = (rpmFilterApplyFnPtr)rpmFilterApply;
177 rpmGyroUpdateFn = (rpmFilterUpdateFnPtr)rpmFilterUpdate;
181 void rpmFilterUpdateTask(timeUs_t currentTimeUs)
183 UNUSED(currentTimeUs);
185 uint8_t motorCount = getMotorCount();
187 * For each motor, read ERPM, filter it and update motor frequency
189 for (uint8_t i = 0; i < motorCount; i++)
191 const escSensorData_t *escState = getEscTelemetry(i); //Get ESC telemetry
192 const float baseFrequency = pt1FilterApply(&motorFrequencyFilter[i], escState->rpm * HZ_TO_RPM); //Filter motor frequency
194 rpmGyroUpdateFn(&gyroRpmFilters, i, baseFrequency);
198 float rpmFilterGyroApply(uint8_t axis, float input)
200 return rpmGyroApplyFn(&gyroRpmFilters, axis, input);
203 #endif