2 * This file is part of Cleanflight and Betaflight.
4 * Cleanflight and Betaflight are free software. You can redistribute
5 * this software and/or modify this software under the terms of the
6 * GNU General Public License as published by the Free Software
7 * Foundation, either version 3 of the License, or (at your option)
10 * Cleanflight and Betaflight are distributed in the hope that they
11 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this software.
18 * If not, see <http://www.gnu.org/licenses/>.
29 #include "build/debug.h"
31 #include "common/axis.h"
32 #include "common/maths.h"
33 #include "common/filter.h"
35 #include "config/feature.h"
38 #include "pg/pg_ids.h"
39 #include "pg/gyrodev.h"
41 #include "drivers/accgyro/accgyro.h"
42 #include "drivers/accgyro/accgyro_fake.h"
43 #include "drivers/accgyro/accgyro_mpu.h"
44 #include "drivers/accgyro/accgyro_mpu3050.h"
45 #include "drivers/accgyro/accgyro_mpu6050.h"
46 #include "drivers/accgyro/accgyro_mpu6500.h"
47 #include "drivers/accgyro/accgyro_spi_bmi160.h"
48 #include "drivers/accgyro/accgyro_spi_icm20649.h"
49 #include "drivers/accgyro/accgyro_spi_icm20689.h"
50 #include "drivers/accgyro/accgyro_spi_mpu6000.h"
51 #include "drivers/accgyro/accgyro_spi_mpu6500.h"
52 #include "drivers/accgyro/accgyro_spi_mpu9250.h"
54 #ifdef USE_GYRO_L3GD20
55 #include "drivers/accgyro/accgyro_spi_l3gd20.h"
58 #ifdef USE_GYRO_L3G4200D
59 #include "drivers/accgyro_legacy/accgyro_l3g4200d.h"
62 #include "drivers/accgyro/gyro_sync.h"
63 #include "drivers/bus_spi.h"
64 #include "drivers/io.h"
66 #include "fc/config.h"
67 #include "fc/runtime_config.h"
69 #include "io/beeper.h"
70 #include "io/statusindicator.h"
72 #include "scheduler/scheduler.h"
74 #include "sensors/boardalignment.h"
75 #include "sensors/gyro.h"
76 #ifdef USE_GYRO_DATA_ANALYSE
77 #include "sensors/gyroanalyse.h"
79 #include "sensors/rpm_filter.h"
80 #include "sensors/sensors.h"
82 #if ((FLASH_SIZE > 128) && (defined(USE_GYRO_SPI_ICM20601) || defined(USE_GYRO_SPI_ICM20689) || defined(USE_GYRO_SPI_MPU6500)))
83 #define USE_GYRO_SLEW_LIMITER
86 FAST_RAM_ZERO_INIT gyro_t gyro
;
87 static FAST_RAM_ZERO_INIT
uint8_t gyroDebugMode
;
89 static FAST_RAM_ZERO_INIT
uint8_t gyroToUse
;
90 static FAST_RAM_ZERO_INIT
bool overflowDetected
;
92 #ifdef USE_GYRO_OVERFLOW_CHECK
93 static FAST_RAM_ZERO_INIT
uint8_t overflowAxisMask
;
96 #ifdef USE_YAW_SPIN_RECOVERY
97 static FAST_RAM_ZERO_INIT
bool yawSpinDetected
;
100 static FAST_RAM_ZERO_INIT
float accumulatedMeasurements
[XYZ_AXIS_COUNT
];
101 static FAST_RAM_ZERO_INIT
float gyroPrevious
[XYZ_AXIS_COUNT
];
102 static FAST_RAM_ZERO_INIT timeUs_t accumulatedMeasurementTimeUs
;
103 static FAST_RAM_ZERO_INIT timeUs_t accumulationLastTimeSampledUs
;
105 static FAST_RAM_ZERO_INIT
int16_t gyroSensorTemperature
;
107 static bool gyroHasOverflowProtection
= true;
109 static FAST_RAM_ZERO_INIT
bool useDualGyroDebugging
;
111 typedef struct gyroCalibration_s
{
112 float sum
[XYZ_AXIS_COUNT
];
113 stdev_t var
[XYZ_AXIS_COUNT
];
114 int32_t cyclesRemaining
;
117 bool firstArmingCalibrationWasStarted
= false;
119 typedef union gyroLowpassFilter_u
{
120 pt1Filter_t pt1FilterState
;
121 biquadFilter_t biquadFilterState
;
122 } gyroLowpassFilter_t
;
124 typedef struct gyroSensor_s
{
126 gyroCalibration_t calibration
;
128 // lowpass gyro soft filter
129 filterApplyFnPtr lowpassFilterApplyFn
;
130 gyroLowpassFilter_t lowpassFilter
[XYZ_AXIS_COUNT
];
132 // lowpass2 gyro soft filter
133 filterApplyFnPtr lowpass2FilterApplyFn
;
134 gyroLowpassFilter_t lowpass2Filter
[XYZ_AXIS_COUNT
];
137 filterApplyFnPtr notchFilter1ApplyFn
;
138 biquadFilter_t notchFilter1
[XYZ_AXIS_COUNT
];
140 filterApplyFnPtr notchFilter2ApplyFn
;
141 biquadFilter_t notchFilter2
[XYZ_AXIS_COUNT
];
143 filterApplyFnPtr notchFilterDynApplyFn
;
144 filterApplyFnPtr notchFilterDynApplyFn2
;
145 biquadFilter_t notchFilterDyn
[XYZ_AXIS_COUNT
];
146 biquadFilter_t notchFilterDyn2
[XYZ_AXIS_COUNT
];
148 // overflow and recovery
149 timeUs_t overflowTimeUs
;
150 bool overflowDetected
;
151 #ifdef USE_YAW_SPIN_RECOVERY
152 timeUs_t yawSpinTimeUs
;
153 bool yawSpinDetected
;
154 #endif // USE_YAW_SPIN_RECOVERY
156 #ifdef USE_GYRO_DATA_ANALYSE
157 #define DYNAMIC_NOTCH_DEFAULT_CENTER_HZ 350
158 #define DYNAMIC_NOTCH_DEFAULT_CUTOFF_HZ 300
159 gyroAnalyseState_t gyroAnalyseState
;
162 flight_dynamics_index_t gyroDebugAxis
;
165 STATIC_UNIT_TESTED FAST_RAM_ZERO_INIT gyroSensor_t gyroSensor1
;
166 #ifdef USE_MULTI_GYRO
167 STATIC_UNIT_TESTED FAST_RAM_ZERO_INIT gyroSensor_t gyroSensor2
;
170 static gyroDetectionFlags_t gyroDetectionFlags
= NO_GYROS_DETECTED
;
173 STATIC_UNIT_TESTED gyroSensor_t
* const gyroSensorPtr
= &gyroSensor1
;
174 STATIC_UNIT_TESTED gyroDev_t
* const gyroDevPtr
= &gyroSensor1
.gyroDev
;
177 static void gyroInitSensorFilters(gyroSensor_t
*gyroSensor
);
178 static void gyroInitLowpassFilterLpf(gyroSensor_t
*gyroSensor
, int slot
, int type
, uint16_t lpfHz
);
180 #define DEBUG_GYRO_CALIBRATION 3
183 #define GYRO_SYNC_DENOM_DEFAULT 8
184 #elif defined(USE_GYRO_SPI_MPU6000) || defined(USE_GYRO_SPI_MPU6500) || defined(USE_GYRO_SPI_ICM20601) || defined(USE_GYRO_SPI_ICM20649) \
185 || defined(USE_GYRO_SPI_ICM20689)
186 #define GYRO_SYNC_DENOM_DEFAULT 1
188 #define GYRO_SYNC_DENOM_DEFAULT 3
191 #define GYRO_OVERFLOW_TRIGGER_THRESHOLD 31980 // 97.5% full scale (1950dps for 2000dps gyro)
192 #define GYRO_OVERFLOW_RESET_THRESHOLD 30340 // 92.5% full scale (1850dps for 2000dps gyro)
194 PG_REGISTER_WITH_RESET_FN(gyroConfig_t
, gyroConfig
, PG_GYRO_CONFIG
, 7);
196 #ifndef GYRO_CONFIG_USE_GYRO_DEFAULT
197 #define GYRO_CONFIG_USE_GYRO_DEFAULT GYRO_CONFIG_USE_GYRO_1
200 void pgResetFn_gyroConfig(gyroConfig_t
*gyroConfig
)
202 gyroConfig
->gyroCalibrationDuration
= 125; // 1.25 seconds
203 gyroConfig
->gyroMovementCalibrationThreshold
= 48;
204 gyroConfig
->gyro_sync_denom
= GYRO_SYNC_DENOM_DEFAULT
;
205 gyroConfig
->gyro_hardware_lpf
= GYRO_HARDWARE_LPF_NORMAL
;
206 gyroConfig
->gyro_lowpass_type
= FILTER_BIQUAD
;
207 gyroConfig
->gyro_lowpass_hz
= 150; // NOTE: dynamic lpf is enabled by default so this setting is actually
208 // overridden and the static lowpass 1 is disabled. We can't set this
209 // value to 0 otherwise Configurator versions 10.4 and earlier will also
210 // reset the lowpass filter type to PT1 overriding the desired BIQUAD setting.
211 gyroConfig
->gyro_lowpass2_type
= FILTER_PT1
;
212 gyroConfig
->gyro_lowpass2_hz
= 150;
213 gyroConfig
->gyro_high_fsr
= false;
214 gyroConfig
->gyro_to_use
= GYRO_CONFIG_USE_GYRO_DEFAULT
;
215 gyroConfig
->gyro_soft_notch_hz_1
= 0;
216 gyroConfig
->gyro_soft_notch_cutoff_1
= 0;
217 gyroConfig
->gyro_soft_notch_hz_2
= 0;
218 gyroConfig
->gyro_soft_notch_cutoff_2
= 0;
219 gyroConfig
->checkOverflow
= GYRO_OVERFLOW_CHECK_ALL_AXES
;
220 gyroConfig
->gyro_offset_yaw
= 0;
221 gyroConfig
->yaw_spin_recovery
= true;
222 gyroConfig
->yaw_spin_threshold
= 1950;
223 gyroConfig
->dyn_lpf_gyro_min_hz
= 150;
224 gyroConfig
->dyn_lpf_gyro_max_hz
= 450;
225 gyroConfig
->dyn_notch_range
= DYN_NOTCH_RANGE_AUTO
;
226 gyroConfig
->dyn_notch_width_percent
= 8;
227 gyroConfig
->dyn_notch_q
= 120;
228 gyroConfig
->dyn_notch_min_hz
= 150;
229 gyroConfig
->gyro_filter_debug_axis
= FD_ROLL
;
232 #ifdef USE_MULTI_GYRO
233 #define ACTIVE_GYRO ((gyroToUse == GYRO_CONFIG_USE_GYRO_2) ? &gyroSensor2 : &gyroSensor1)
235 #define ACTIVE_GYRO (&gyroSensor1)
238 const busDevice_t
*gyroSensorBus(void)
240 return &ACTIVE_GYRO
->gyroDev
.bus
;
243 #ifdef USE_GYRO_REGISTER_DUMP
244 const busDevice_t
*gyroSensorBusByDevice(uint8_t whichSensor
)
246 #ifdef USE_MULTI_GYRO
247 if (whichSensor
== GYRO_CONFIG_USE_GYRO_2
) {
248 return &gyroSensor2
.gyroDev
.bus
;
253 return &gyroSensor1
.gyroDev
.bus
;
255 #endif // USE_GYRO_REGISTER_DUMP
257 const mpuDetectionResult_t
*gyroMpuDetectionResult(void)
259 return &ACTIVE_GYRO
->gyroDev
.mpuDetectionResult
;
262 STATIC_UNIT_TESTED gyroHardware_e
gyroDetect(gyroDev_t
*dev
)
264 gyroHardware_e gyroHardware
= GYRO_DEFAULT
;
266 switch (gyroHardware
) {
270 #ifdef USE_GYRO_MPU6050
272 if (mpu6050GyroDetect(dev
)) {
273 gyroHardware
= GYRO_MPU6050
;
279 #ifdef USE_GYRO_L3G4200D
281 if (l3g4200dDetect(dev
)) {
282 gyroHardware
= GYRO_L3G4200D
;
288 #ifdef USE_GYRO_MPU3050
290 if (mpu3050Detect(dev
)) {
291 gyroHardware
= GYRO_MPU3050
;
297 #ifdef USE_GYRO_L3GD20
299 if (l3gd20GyroDetect(dev
)) {
300 gyroHardware
= GYRO_L3GD20
;
306 #ifdef USE_GYRO_SPI_MPU6000
308 if (mpu6000SpiGyroDetect(dev
)) {
309 gyroHardware
= GYRO_MPU6000
;
315 #if defined(USE_GYRO_MPU6500) || defined(USE_GYRO_SPI_MPU6500)
320 #ifdef USE_GYRO_SPI_MPU6500
321 if (mpu6500GyroDetect(dev
) || mpu6500SpiGyroDetect(dev
)) {
323 if (mpu6500GyroDetect(dev
)) {
325 switch (dev
->mpuDetectionResult
.sensor
) {
327 gyroHardware
= GYRO_MPU9250
;
330 gyroHardware
= GYRO_ICM20601
;
333 gyroHardware
= GYRO_ICM20602
;
336 gyroHardware
= GYRO_ICM20608G
;
339 gyroHardware
= GYRO_MPU6500
;
346 #ifdef USE_GYRO_SPI_MPU9250
348 if (mpu9250SpiGyroDetect(dev
)) {
349 gyroHardware
= GYRO_MPU9250
;
355 #ifdef USE_GYRO_SPI_ICM20649
357 if (icm20649SpiGyroDetect(dev
)) {
358 gyroHardware
= GYRO_ICM20649
;
364 #ifdef USE_GYRO_SPI_ICM20689
366 if (icm20689SpiGyroDetect(dev
)) {
367 gyroHardware
= GYRO_ICM20689
;
373 #ifdef USE_ACCGYRO_BMI160
375 if (bmi160SpiGyroDetect(dev
)) {
376 gyroHardware
= GYRO_BMI160
;
384 if (fakeGyroDetect(dev
)) {
385 gyroHardware
= GYRO_FAKE
;
392 gyroHardware
= GYRO_NONE
;
395 if (gyroHardware
!= GYRO_NONE
) {
396 sensorsSet(SENSOR_GYRO
);
403 static void gyroPreInitSensor(const gyroDeviceConfig_t
*config
)
405 #if defined(USE_GYRO_MPU6050) || defined(USE_GYRO_MPU3050) || defined(USE_GYRO_MPU6500) || defined(USE_GYRO_SPI_MPU6500) || defined(USE_GYRO_SPI_MPU6000) \
406 || defined(USE_ACC_MPU6050) || defined(USE_GYRO_SPI_MPU9250) || defined(USE_GYRO_SPI_ICM20601) || defined(USE_GYRO_SPI_ICM20649) || defined(USE_GYRO_SPI_ICM20689)
413 static bool gyroDetectSensor(gyroSensor_t
*gyroSensor
, const gyroDeviceConfig_t
*config
)
415 #if defined(USE_GYRO_MPU6050) || defined(USE_GYRO_MPU3050) || defined(USE_GYRO_MPU6500) || defined(USE_GYRO_SPI_MPU6500) || defined(USE_GYRO_SPI_MPU6000) \
416 || defined(USE_ACC_MPU6050) || defined(USE_GYRO_SPI_MPU9250) || defined(USE_GYRO_SPI_ICM20601) || defined(USE_GYRO_SPI_ICM20649) || defined(USE_GYRO_SPI_ICM20689) || defined(USE_GYRO_L3GD20)
418 if (!mpuDetect(&gyroSensor
->gyroDev
, config
)) {
425 const gyroHardware_e gyroHardware
= gyroDetect(&gyroSensor
->gyroDev
);
426 gyroSensor
->gyroDev
.gyroHardware
= gyroHardware
;
428 return gyroHardware
!= GYRO_NONE
;
431 static void gyroInitSensor(gyroSensor_t
*gyroSensor
, const gyroDeviceConfig_t
*config
)
433 gyroSensor
->gyroDebugAxis
= gyroConfig()->gyro_filter_debug_axis
;
434 gyroSensor
->gyroDev
.gyro_high_fsr
= gyroConfig()->gyro_high_fsr
;
435 gyroSensor
->gyroDev
.gyroAlign
= config
->align
;
436 gyroSensor
->gyroDev
.mpuIntExtiTag
= config
->extiTag
;
438 // Must set gyro targetLooptime before gyroDev.init and initialisation of filters
439 gyro
.targetLooptime
= gyroSetSampleRate(&gyroSensor
->gyroDev
, gyroConfig()->gyro_hardware_lpf
, gyroConfig()->gyro_sync_denom
);
440 gyroSensor
->gyroDev
.hardware_lpf
= gyroConfig()->gyro_hardware_lpf
;
441 gyroSensor
->gyroDev
.initFn(&gyroSensor
->gyroDev
);
443 // As new gyros are supported, be sure to add them below based on whether they are subject to the overflow/inversion bug
444 // Any gyro not explicitly defined will default to not having built-in overflow protection as a safe alternative.
445 switch (gyroSensor
->gyroDev
.gyroHardware
) {
446 case GYRO_NONE
: // Won't ever actually get here, but included to account for all gyro types
457 gyroSensor
->gyroDev
.gyroHasOverflowProtection
= true;
463 case GYRO_ICM20649
: // we don't actually know if this is affected, but as there are currently no flight controllers using it we err on the side of caution
465 gyroSensor
->gyroDev
.gyroHasOverflowProtection
= false;
469 gyroSensor
->gyroDev
.gyroHasOverflowProtection
= false; // default catch for newly added gyros until proven to be unaffected
473 gyroInitSensorFilters(gyroSensor
);
475 #ifdef USE_GYRO_DATA_ANALYSE
476 gyroDataAnalyseStateInit(&gyroSensor
->gyroAnalyseState
, gyro
.targetLooptime
);
481 void gyroPreInit(void)
483 gyroPreInitSensor(gyroDeviceConfig(0));
484 #ifdef USE_MULTI_GYRO
485 gyroPreInitSensor(gyroDeviceConfig(1));
491 #ifdef USE_GYRO_OVERFLOW_CHECK
492 if (gyroConfig()->checkOverflow
== GYRO_OVERFLOW_CHECK_YAW
) {
493 overflowAxisMask
= GYRO_OVERFLOW_Z
;
494 } else if (gyroConfig()->checkOverflow
== GYRO_OVERFLOW_CHECK_ALL_AXES
) {
495 overflowAxisMask
= GYRO_OVERFLOW_X
| GYRO_OVERFLOW_Y
| GYRO_OVERFLOW_Z
;
497 overflowAxisMask
= 0;
501 gyroDebugMode
= DEBUG_NONE
;
502 useDualGyroDebugging
= false;
508 case DEBUG_GYRO_SCALED
:
509 case DEBUG_GYRO_FILTERED
:
511 gyroDebugMode
= debugMode
;
513 case DEBUG_DUAL_GYRO
:
514 case DEBUG_DUAL_GYRO_COMBINE
:
515 case DEBUG_DUAL_GYRO_DIFF
:
516 case DEBUG_DUAL_GYRO_RAW
:
517 case DEBUG_DUAL_GYRO_SCALED
:
518 useDualGyroDebugging
= true;
521 firstArmingCalibrationWasStarted
= false;
523 gyroDetectionFlags
= NO_GYROS_DETECTED
;
525 gyroToUse
= gyroConfig()->gyro_to_use
;
527 if (gyroDetectSensor(&gyroSensor1
, gyroDeviceConfig(0))) {
528 gyroDetectionFlags
|= DETECTED_GYRO_1
;
531 #if defined(USE_MULTI_GYRO)
532 if (gyroDetectSensor(&gyroSensor2
, gyroDeviceConfig(1))) {
533 gyroDetectionFlags
|= DETECTED_GYRO_2
;
537 if (gyroDetectionFlags
== NO_GYROS_DETECTED
) {
541 #if defined(USE_MULTI_GYRO)
542 if ((gyroToUse
== GYRO_CONFIG_USE_GYRO_BOTH
&& !(gyroDetectionFlags
& DETECTED_BOTH_GYROS
))
543 || (gyroToUse
== GYRO_CONFIG_USE_GYRO_1
&& !(gyroDetectionFlags
& DETECTED_GYRO_1
))
544 || (gyroToUse
== GYRO_CONFIG_USE_GYRO_2
&& !(gyroDetectionFlags
& DETECTED_GYRO_2
))) {
545 if (gyroDetectionFlags
& DETECTED_GYRO_1
) {
546 gyroToUse
= GYRO_CONFIG_USE_GYRO_1
;
548 gyroToUse
= GYRO_CONFIG_USE_GYRO_2
;
551 gyroConfigMutable()->gyro_to_use
= gyroToUse
;
554 // Only allow using both gyros simultaneously if they are the same hardware type.
555 if ((gyroDetectionFlags
& DETECTED_BOTH_GYROS
) && gyroSensor1
.gyroDev
.gyroHardware
== gyroSensor2
.gyroDev
.gyroHardware
) {
556 gyroDetectionFlags
|= DETECTED_DUAL_GYROS
;
557 } else if (gyroToUse
== GYRO_CONFIG_USE_GYRO_BOTH
) {
558 // If the user selected "BOTH" and they are not the same type, then reset to using only the first gyro.
559 gyroToUse
= GYRO_CONFIG_USE_GYRO_1
;
560 gyroConfigMutable()->gyro_to_use
= gyroToUse
;
563 if (gyroToUse
== GYRO_CONFIG_USE_GYRO_2
|| gyroToUse
== GYRO_CONFIG_USE_GYRO_BOTH
) {
564 gyroInitSensor(&gyroSensor2
, gyroDeviceConfig(1));
565 gyroHasOverflowProtection
= gyroHasOverflowProtection
&& gyroSensor2
.gyroDev
.gyroHasOverflowProtection
;
566 detectedSensors
[SENSOR_INDEX_GYRO
] = gyroSensor2
.gyroDev
.gyroHardware
;
570 if (gyroToUse
== GYRO_CONFIG_USE_GYRO_1
|| gyroToUse
== GYRO_CONFIG_USE_GYRO_BOTH
) {
571 gyroInitSensor(&gyroSensor1
, gyroDeviceConfig(0));
572 gyroHasOverflowProtection
= gyroHasOverflowProtection
&& gyroSensor1
.gyroDev
.gyroHasOverflowProtection
;
573 detectedSensors
[SENSOR_INDEX_GYRO
] = gyroSensor1
.gyroDev
.gyroHardware
;
579 gyroDetectionFlags_t
getGyroDetectionFlags(void)
581 return gyroDetectionFlags
;
585 static FAST_RAM
uint8_t dynLpfFilter
= DYN_LPF_NONE
;
586 static FAST_RAM_ZERO_INIT
uint16_t dynLpfMin
;
587 static FAST_RAM_ZERO_INIT
uint16_t dynLpfMax
;
589 static void dynLpfFilterInit()
591 if (gyroConfig()->dyn_lpf_gyro_min_hz
> 0) {
592 switch (gyroConfig()->gyro_lowpass_type
) {
594 dynLpfFilter
= DYN_LPF_PT1
;
597 dynLpfFilter
= DYN_LPF_BIQUAD
;
600 dynLpfFilter
= DYN_LPF_NONE
;
604 dynLpfFilter
= DYN_LPF_NONE
;
606 dynLpfMin
= gyroConfig()->dyn_lpf_gyro_min_hz
;
607 dynLpfMax
= gyroConfig()->dyn_lpf_gyro_max_hz
;
611 void gyroInitLowpassFilterLpf(gyroSensor_t
*gyroSensor
, int slot
, int type
, uint16_t lpfHz
)
613 filterApplyFnPtr
*lowpassFilterApplyFn
;
614 gyroLowpassFilter_t
*lowpassFilter
= NULL
;
618 lowpassFilterApplyFn
= &gyroSensor
->lowpassFilterApplyFn
;
619 lowpassFilter
= gyroSensor
->lowpassFilter
;
622 case FILTER_LOWPASS2
:
623 lowpassFilterApplyFn
= &gyroSensor
->lowpass2FilterApplyFn
;
624 lowpassFilter
= gyroSensor
->lowpass2Filter
;
631 // Establish some common constants
632 const uint32_t gyroFrequencyNyquist
= 1000000 / 2 / gyro
.targetLooptime
;
633 const float gyroDt
= gyro
.targetLooptime
* 1e-6f
;
635 // Gain could be calculated a little later as it is specific to the pt1/bqrcf2/fkf branches
636 const float gain
= pt1FilterGain(lpfHz
, gyroDt
);
638 // Dereference the pointer to null before checking valid cutoff and filter
639 // type. It will be overridden for positive cases.
640 *lowpassFilterApplyFn
= nullFilterApply
;
642 // If lowpass cutoff has been specified and is less than the Nyquist frequency
643 if (lpfHz
&& lpfHz
<= gyroFrequencyNyquist
) {
646 *lowpassFilterApplyFn
= (filterApplyFnPtr
) pt1FilterApply
;
647 for (int axis
= 0; axis
< XYZ_AXIS_COUNT
; axis
++) {
648 pt1FilterInit(&lowpassFilter
[axis
].pt1FilterState
, gain
);
653 *lowpassFilterApplyFn
= (filterApplyFnPtr
) biquadFilterApplyDF1
;
655 *lowpassFilterApplyFn
= (filterApplyFnPtr
) biquadFilterApply
;
657 for (int axis
= 0; axis
< XYZ_AXIS_COUNT
; axis
++) {
658 biquadFilterInitLPF(&lowpassFilter
[axis
].biquadFilterState
, lpfHz
, gyro
.targetLooptime
);
665 static uint16_t calculateNyquistAdjustedNotchHz(uint16_t notchHz
, uint16_t notchCutoffHz
)
667 const uint32_t gyroFrequencyNyquist
= 1000000 / 2 / gyro
.targetLooptime
;
668 if (notchHz
> gyroFrequencyNyquist
) {
669 if (notchCutoffHz
< gyroFrequencyNyquist
) {
670 notchHz
= gyroFrequencyNyquist
;
679 #if defined(USE_GYRO_SLEW_LIMITER)
680 void gyroInitSlewLimiter(gyroSensor_t
*gyroSensor
) {
682 for (int axis
= 0; axis
< XYZ_AXIS_COUNT
; axis
++) {
683 gyroSensor
->gyroDev
.gyroADCRawPrevious
[axis
] = 0;
688 static void gyroInitFilterNotch1(gyroSensor_t
*gyroSensor
, uint16_t notchHz
, uint16_t notchCutoffHz
)
690 gyroSensor
->notchFilter1ApplyFn
= nullFilterApply
;
692 notchHz
= calculateNyquistAdjustedNotchHz(notchHz
, notchCutoffHz
);
694 if (notchHz
!= 0 && notchCutoffHz
!= 0) {
695 gyroSensor
->notchFilter1ApplyFn
= (filterApplyFnPtr
)biquadFilterApply
;
696 const float notchQ
= filterGetNotchQ(notchHz
, notchCutoffHz
);
697 for (int axis
= 0; axis
< XYZ_AXIS_COUNT
; axis
++) {
698 biquadFilterInit(&gyroSensor
->notchFilter1
[axis
], notchHz
, gyro
.targetLooptime
, notchQ
, FILTER_NOTCH
);
703 static void gyroInitFilterNotch2(gyroSensor_t
*gyroSensor
, uint16_t notchHz
, uint16_t notchCutoffHz
)
705 gyroSensor
->notchFilter2ApplyFn
= nullFilterApply
;
707 notchHz
= calculateNyquistAdjustedNotchHz(notchHz
, notchCutoffHz
);
709 if (notchHz
!= 0 && notchCutoffHz
!= 0) {
710 gyroSensor
->notchFilter2ApplyFn
= (filterApplyFnPtr
)biquadFilterApply
;
711 const float notchQ
= filterGetNotchQ(notchHz
, notchCutoffHz
);
712 for (int axis
= 0; axis
< XYZ_AXIS_COUNT
; axis
++) {
713 biquadFilterInit(&gyroSensor
->notchFilter2
[axis
], notchHz
, gyro
.targetLooptime
, notchQ
, FILTER_NOTCH
);
718 #ifdef USE_GYRO_DATA_ANALYSE
719 static bool isDynamicFilterActive(void)
721 return featureIsEnabled(FEATURE_DYNAMIC_FILTER
);
724 static void gyroInitFilterDynamicNotch(gyroSensor_t
*gyroSensor
)
726 gyroSensor
->notchFilterDynApplyFn
= nullFilterApply
;
727 gyroSensor
->notchFilterDynApplyFn2
= nullFilterApply
;
729 if (isDynamicFilterActive()) {
730 gyroSensor
->notchFilterDynApplyFn
= (filterApplyFnPtr
)biquadFilterApplyDF1
; // must be this function, not DF2
731 if(gyroConfig()->dyn_notch_width_percent
!= 0) {
732 gyroSensor
->notchFilterDynApplyFn2
= (filterApplyFnPtr
)biquadFilterApplyDF1
; // must be this function, not DF2
734 const float notchQ
= filterGetNotchQ(DYNAMIC_NOTCH_DEFAULT_CENTER_HZ
, DYNAMIC_NOTCH_DEFAULT_CUTOFF_HZ
); // any defaults OK here
735 for (int axis
= 0; axis
< XYZ_AXIS_COUNT
; axis
++) {
736 biquadFilterInit(&gyroSensor
->notchFilterDyn
[axis
], DYNAMIC_NOTCH_DEFAULT_CENTER_HZ
, gyro
.targetLooptime
, notchQ
, FILTER_NOTCH
);
737 biquadFilterInit(&gyroSensor
->notchFilterDyn2
[axis
], DYNAMIC_NOTCH_DEFAULT_CENTER_HZ
, gyro
.targetLooptime
, notchQ
, FILTER_NOTCH
);
743 static void gyroInitSensorFilters(gyroSensor_t
*gyroSensor
)
745 #if defined(USE_GYRO_SLEW_LIMITER)
746 gyroInitSlewLimiter(gyroSensor
);
749 uint16_t gyro_lowpass_hz
= gyroConfig()->gyro_lowpass_hz
;
752 if (gyroConfig()->dyn_lpf_gyro_min_hz
> 0) {
753 gyro_lowpass_hz
= gyroConfig()->dyn_lpf_gyro_min_hz
;
757 gyroInitLowpassFilterLpf(
760 gyroConfig()->gyro_lowpass_type
,
764 gyroInitLowpassFilterLpf(
767 gyroConfig()->gyro_lowpass2_type
,
768 gyroConfig()->gyro_lowpass2_hz
771 gyroInitFilterNotch1(gyroSensor
, gyroConfig()->gyro_soft_notch_hz_1
, gyroConfig()->gyro_soft_notch_cutoff_1
);
772 gyroInitFilterNotch2(gyroSensor
, gyroConfig()->gyro_soft_notch_hz_2
, gyroConfig()->gyro_soft_notch_cutoff_2
);
773 #ifdef USE_GYRO_DATA_ANALYSE
774 gyroInitFilterDynamicNotch(gyroSensor
);
781 void gyroInitFilters(void)
783 gyroInitSensorFilters(&gyroSensor1
);
784 #ifdef USE_MULTI_GYRO
785 gyroInitSensorFilters(&gyroSensor2
);
789 FAST_CODE
bool isGyroSensorCalibrationComplete(const gyroSensor_t
*gyroSensor
)
791 return gyroSensor
->calibration
.cyclesRemaining
== 0;
794 FAST_CODE
bool isGyroCalibrationComplete(void)
798 case GYRO_CONFIG_USE_GYRO_1
: {
799 return isGyroSensorCalibrationComplete(&gyroSensor1
);
801 #ifdef USE_MULTI_GYRO
802 case GYRO_CONFIG_USE_GYRO_2
: {
803 return isGyroSensorCalibrationComplete(&gyroSensor2
);
805 case GYRO_CONFIG_USE_GYRO_BOTH
: {
806 return isGyroSensorCalibrationComplete(&gyroSensor1
) && isGyroSensorCalibrationComplete(&gyroSensor2
);
812 static bool isOnFinalGyroCalibrationCycle(const gyroCalibration_t
*gyroCalibration
)
814 return gyroCalibration
->cyclesRemaining
== 1;
817 static int32_t gyroCalculateCalibratingCycles(void)
819 return (gyroConfig()->gyroCalibrationDuration
* 10000) / gyro
.targetLooptime
;
822 static bool isOnFirstGyroCalibrationCycle(const gyroCalibration_t
*gyroCalibration
)
824 return gyroCalibration
->cyclesRemaining
== gyroCalculateCalibratingCycles();
827 static void gyroSetCalibrationCycles(gyroSensor_t
*gyroSensor
)
829 gyroSensor
->calibration
.cyclesRemaining
= gyroCalculateCalibratingCycles();
832 void gyroStartCalibration(bool isFirstArmingCalibration
)
834 if (!(isFirstArmingCalibration
&& firstArmingCalibrationWasStarted
)) {
835 gyroSetCalibrationCycles(&gyroSensor1
);
836 #ifdef USE_MULTI_GYRO
837 gyroSetCalibrationCycles(&gyroSensor2
);
840 if (isFirstArmingCalibration
) {
841 firstArmingCalibrationWasStarted
= true;
846 bool isFirstArmingGyroCalibrationRunning(void)
848 return firstArmingCalibrationWasStarted
&& !isGyroCalibrationComplete();
851 STATIC_UNIT_TESTED
void performGyroCalibration(gyroSensor_t
*gyroSensor
, uint8_t gyroMovementCalibrationThreshold
)
853 for (int axis
= 0; axis
< XYZ_AXIS_COUNT
; axis
++) {
854 // Reset g[axis] at start of calibration
855 if (isOnFirstGyroCalibrationCycle(&gyroSensor
->calibration
)) {
856 gyroSensor
->calibration
.sum
[axis
] = 0.0f
;
857 devClear(&gyroSensor
->calibration
.var
[axis
]);
858 // gyroZero is set to zero until calibration complete
859 gyroSensor
->gyroDev
.gyroZero
[axis
] = 0.0f
;
862 // Sum up CALIBRATING_GYRO_TIME_US readings
863 gyroSensor
->calibration
.sum
[axis
] += gyroSensor
->gyroDev
.gyroADCRaw
[axis
];
864 devPush(&gyroSensor
->calibration
.var
[axis
], gyroSensor
->gyroDev
.gyroADCRaw
[axis
]);
866 if (isOnFinalGyroCalibrationCycle(&gyroSensor
->calibration
)) {
867 const float stddev
= devStandardDeviation(&gyroSensor
->calibration
.var
[axis
]);
868 // DEBUG_GYRO_CALIBRATION records the standard deviation of roll
869 // into the spare field - debug[3], in DEBUG_GYRO_RAW
871 DEBUG_SET(DEBUG_GYRO_RAW
, DEBUG_GYRO_CALIBRATION
, lrintf(stddev
));
874 // check deviation and startover in case the model was moved
875 if (gyroMovementCalibrationThreshold
&& stddev
> gyroMovementCalibrationThreshold
) {
876 gyroSetCalibrationCycles(gyroSensor
);
880 // please take care with exotic boardalignment !!
881 gyroSensor
->gyroDev
.gyroZero
[axis
] = gyroSensor
->calibration
.sum
[axis
] / gyroCalculateCalibratingCycles();
883 gyroSensor
->gyroDev
.gyroZero
[axis
] -= ((float)gyroConfig()->gyro_offset_yaw
/ 100);
888 if (isOnFinalGyroCalibrationCycle(&gyroSensor
->calibration
)) {
889 schedulerResetTaskStatistics(TASK_SELF
); // so calibration cycles do not pollute tasks statistics
890 if (!firstArmingCalibrationWasStarted
|| (getArmingDisableFlags() & ~ARMING_DISABLED_CALIBRATING
) == 0) {
891 beeper(BEEPER_GYRO_CALIBRATED
);
894 --gyroSensor
->calibration
.cyclesRemaining
;
898 #if defined(USE_GYRO_SLEW_LIMITER)
899 FAST_CODE
int32_t gyroSlewLimiter(gyroSensor_t
*gyroSensor
, int axis
)
901 int32_t ret
= (int32_t)gyroSensor
->gyroDev
.gyroADCRaw
[axis
];
902 if (gyroConfig()->checkOverflow
|| gyroHasOverflowProtection
) {
903 // don't use the slew limiter if overflow checking is on or gyro is not subject to overflow bug
906 if (abs(ret
- gyroSensor
->gyroDev
.gyroADCRawPrevious
[axis
]) > (1<<14)) {
907 // there has been a large change in value, so assume overflow has occurred and return the previous value
908 ret
= gyroSensor
->gyroDev
.gyroADCRawPrevious
[axis
];
910 gyroSensor
->gyroDev
.gyroADCRawPrevious
[axis
] = ret
;
916 #ifdef USE_GYRO_OVERFLOW_CHECK
917 static FAST_CODE_NOINLINE
void handleOverflow(gyroSensor_t
*gyroSensor
, timeUs_t currentTimeUs
)
919 const float gyroOverflowResetRate
= GYRO_OVERFLOW_RESET_THRESHOLD
* gyroSensor
->gyroDev
.scale
;
920 if ((abs(gyroSensor
->gyroDev
.gyroADCf
[X
]) < gyroOverflowResetRate
)
921 && (abs(gyroSensor
->gyroDev
.gyroADCf
[Y
]) < gyroOverflowResetRate
)
922 && (abs(gyroSensor
->gyroDev
.gyroADCf
[Z
]) < gyroOverflowResetRate
)) {
923 // if we have 50ms of consecutive OK gyro vales, then assume yaw readings are OK again and reset overflowDetected
924 // reset requires good OK values on all axes
925 if (cmpTimeUs(currentTimeUs
, gyroSensor
->overflowTimeUs
) > 50000) {
926 gyroSensor
->overflowDetected
= false;
929 // not a consecutive OK value, so reset the overflow time
930 gyroSensor
->overflowTimeUs
= currentTimeUs
;
934 static FAST_CODE
void checkForOverflow(gyroSensor_t
*gyroSensor
, timeUs_t currentTimeUs
)
936 // check for overflow to handle Yaw Spin To The Moon (YSTTM)
937 // ICM gyros are specified to +/- 2000 deg/sec, in a crash they can go out of spec.
938 // This can cause an overflow and sign reversal in the output.
939 // Overflow and sign reversal seems to result in a gyro value of +1996 or -1996.
940 if (gyroSensor
->overflowDetected
) {
941 handleOverflow(gyroSensor
, currentTimeUs
);
943 #ifndef SIMULATOR_BUILD
944 // check for overflow in the axes set in overflowAxisMask
945 gyroOverflow_e overflowCheck
= GYRO_OVERFLOW_NONE
;
946 const float gyroOverflowTriggerRate
= GYRO_OVERFLOW_TRIGGER_THRESHOLD
* gyroSensor
->gyroDev
.scale
;
947 if (abs(gyroSensor
->gyroDev
.gyroADCf
[X
]) > gyroOverflowTriggerRate
) {
948 overflowCheck
|= GYRO_OVERFLOW_X
;
950 if (abs(gyroSensor
->gyroDev
.gyroADCf
[Y
]) > gyroOverflowTriggerRate
) {
951 overflowCheck
|= GYRO_OVERFLOW_Y
;
953 if (abs(gyroSensor
->gyroDev
.gyroADCf
[Z
]) > gyroOverflowTriggerRate
) {
954 overflowCheck
|= GYRO_OVERFLOW_Z
;
956 if (overflowCheck
& overflowAxisMask
) {
957 gyroSensor
->overflowDetected
= true;
958 gyroSensor
->overflowTimeUs
= currentTimeUs
;
959 #ifdef USE_YAW_SPIN_RECOVERY
960 gyroSensor
->yawSpinDetected
= false;
961 #endif // USE_YAW_SPIN_RECOVERY
963 #endif // SIMULATOR_BUILD
966 #endif // USE_GYRO_OVERFLOW_CHECK
968 #ifdef USE_YAW_SPIN_RECOVERY
969 static FAST_CODE_NOINLINE
void handleYawSpin(gyroSensor_t
*gyroSensor
, timeUs_t currentTimeUs
)
971 const float yawSpinResetRate
= gyroConfig()->yaw_spin_threshold
- 100.0f
;
972 if (abs(gyroSensor
->gyroDev
.gyroADCf
[Z
]) < yawSpinResetRate
) {
973 // testing whether 20ms of consecutive OK gyro yaw values is enough
974 if (cmpTimeUs(currentTimeUs
, gyroSensor
->yawSpinTimeUs
) > 20000) {
975 gyroSensor
->yawSpinDetected
= false;
978 // reset the yaw spin time
979 gyroSensor
->yawSpinTimeUs
= currentTimeUs
;
983 static FAST_CODE
void checkForYawSpin(gyroSensor_t
*gyroSensor
, timeUs_t currentTimeUs
)
985 // if not in overflow mode, handle yaw spins above threshold
986 #ifdef USE_GYRO_OVERFLOW_CHECK
987 if (gyroSensor
->overflowDetected
) {
988 gyroSensor
->yawSpinDetected
= false;
991 #endif // USE_GYRO_OVERFLOW_CHECK
993 if (gyroSensor
->yawSpinDetected
) {
994 handleYawSpin(gyroSensor
, currentTimeUs
);
996 #ifndef SIMULATOR_BUILD
997 // check for spin on yaw axis only
998 if (abs(gyroSensor
->gyroDev
.gyroADCf
[Z
]) > gyroConfig()->yaw_spin_threshold
) {
999 gyroSensor
->yawSpinDetected
= true;
1000 gyroSensor
->yawSpinTimeUs
= currentTimeUs
;
1002 #endif // SIMULATOR_BUILD
1005 #endif // USE_YAW_SPIN_RECOVERY
1007 #define GYRO_FILTER_FUNCTION_NAME filterGyro
1008 #define GYRO_FILTER_DEBUG_SET(mode, index, value) { UNUSED(mode); UNUSED(index); UNUSED(value); }
1009 #include "gyro_filter_impl.h"
1010 #undef GYRO_FILTER_FUNCTION_NAME
1011 #undef GYRO_FILTER_DEBUG_SET
1013 #define GYRO_FILTER_FUNCTION_NAME filterGyroDebug
1014 #define GYRO_FILTER_DEBUG_SET DEBUG_SET
1015 #include "gyro_filter_impl.h"
1016 #undef GYRO_FILTER_FUNCTION_NAME
1017 #undef GYRO_FILTER_DEBUG_SET
1019 static FAST_CODE FAST_CODE_NOINLINE
void gyroUpdateSensor(gyroSensor_t
*gyroSensor
, timeUs_t currentTimeUs
)
1021 if (!gyroSensor
->gyroDev
.readFn(&gyroSensor
->gyroDev
)) {
1024 gyroSensor
->gyroDev
.dataReady
= false;
1026 if (isGyroSensorCalibrationComplete(gyroSensor
)) {
1027 // move 16-bit gyro data into 32-bit variables to avoid overflows in calculations
1029 #if defined(USE_GYRO_SLEW_LIMITER)
1030 gyroSensor
->gyroDev
.gyroADC
[X
] = gyroSlewLimiter(gyroSensor
, X
) - gyroSensor
->gyroDev
.gyroZero
[X
];
1031 gyroSensor
->gyroDev
.gyroADC
[Y
] = gyroSlewLimiter(gyroSensor
, Y
) - gyroSensor
->gyroDev
.gyroZero
[Y
];
1032 gyroSensor
->gyroDev
.gyroADC
[Z
] = gyroSlewLimiter(gyroSensor
, Z
) - gyroSensor
->gyroDev
.gyroZero
[Z
];
1034 gyroSensor
->gyroDev
.gyroADC
[X
] = gyroSensor
->gyroDev
.gyroADCRaw
[X
] - gyroSensor
->gyroDev
.gyroZero
[X
];
1035 gyroSensor
->gyroDev
.gyroADC
[Y
] = gyroSensor
->gyroDev
.gyroADCRaw
[Y
] - gyroSensor
->gyroDev
.gyroZero
[Y
];
1036 gyroSensor
->gyroDev
.gyroADC
[Z
] = gyroSensor
->gyroDev
.gyroADCRaw
[Z
] - gyroSensor
->gyroDev
.gyroZero
[Z
];
1039 alignSensors(gyroSensor
->gyroDev
.gyroADC
, gyroSensor
->gyroDev
.gyroAlign
);
1041 performGyroCalibration(gyroSensor
, gyroConfig()->gyroMovementCalibrationThreshold
);
1042 // still calibrating, so no need to further process gyro data
1046 if (gyroDebugMode
== DEBUG_NONE
) {
1047 filterGyro(gyroSensor
);
1049 filterGyroDebug(gyroSensor
);
1052 #ifdef USE_GYRO_OVERFLOW_CHECK
1053 if (gyroConfig()->checkOverflow
&& !gyroHasOverflowProtection
) {
1054 checkForOverflow(gyroSensor
, currentTimeUs
);
1058 #ifdef USE_YAW_SPIN_RECOVERY
1059 if (gyroConfig()->yaw_spin_recovery
) {
1060 checkForYawSpin(gyroSensor
, currentTimeUs
);
1064 #ifdef USE_GYRO_DATA_ANALYSE
1065 if (isDynamicFilterActive()) {
1066 gyroDataAnalyse(&gyroSensor
->gyroAnalyseState
, gyroSensor
->notchFilterDyn
, gyroSensor
->notchFilterDyn2
);
1070 #if (!defined(USE_GYRO_OVERFLOW_CHECK) && !defined(USE_YAW_SPIN_RECOVERY))
1071 UNUSED(currentTimeUs
);
1075 FAST_CODE
void gyroUpdate(timeUs_t currentTimeUs
)
1077 const timeDelta_t sampleDeltaUs
= currentTimeUs
- accumulationLastTimeSampledUs
;
1078 accumulationLastTimeSampledUs
= currentTimeUs
;
1079 accumulatedMeasurementTimeUs
+= sampleDeltaUs
;
1081 switch (gyroToUse
) {
1082 case GYRO_CONFIG_USE_GYRO_1
:
1083 gyroUpdateSensor(&gyroSensor1
, currentTimeUs
);
1084 if (isGyroSensorCalibrationComplete(&gyroSensor1
)) {
1085 gyro
.gyroADCf
[X
] = gyroSensor1
.gyroDev
.gyroADCf
[X
];
1086 gyro
.gyroADCf
[Y
] = gyroSensor1
.gyroDev
.gyroADCf
[Y
];
1087 gyro
.gyroADCf
[Z
] = gyroSensor1
.gyroDev
.gyroADCf
[Z
];
1088 #ifdef USE_GYRO_OVERFLOW_CHECK
1089 overflowDetected
= gyroSensor1
.overflowDetected
;
1091 #ifdef USE_YAW_SPIN_RECOVERY
1092 yawSpinDetected
= gyroSensor1
.yawSpinDetected
;
1095 if (useDualGyroDebugging
) {
1096 DEBUG_SET(DEBUG_DUAL_GYRO_RAW
, 0, gyroSensor1
.gyroDev
.gyroADCRaw
[X
]);
1097 DEBUG_SET(DEBUG_DUAL_GYRO_RAW
, 1, gyroSensor1
.gyroDev
.gyroADCRaw
[Y
]);
1098 DEBUG_SET(DEBUG_DUAL_GYRO
, 0, lrintf(gyroSensor1
.gyroDev
.gyroADCf
[X
]));
1099 DEBUG_SET(DEBUG_DUAL_GYRO
, 1, lrintf(gyroSensor1
.gyroDev
.gyroADCf
[Y
]));
1100 DEBUG_SET(DEBUG_DUAL_GYRO_COMBINE
, 0, lrintf(gyro
.gyroADCf
[X
]));
1101 DEBUG_SET(DEBUG_DUAL_GYRO_COMBINE
, 1, lrintf(gyro
.gyroADCf
[Y
]));
1102 DEBUG_SET(DEBUG_DUAL_GYRO_SCALED
, 0, lrintf(gyroSensor1
.gyroDev
.gyroADC
[X
] * gyroSensor1
.gyroDev
.scale
));
1103 DEBUG_SET(DEBUG_DUAL_GYRO_SCALED
, 1, lrintf(gyroSensor1
.gyroDev
.gyroADC
[Y
] * gyroSensor1
.gyroDev
.scale
));
1106 #ifdef USE_MULTI_GYRO
1107 case GYRO_CONFIG_USE_GYRO_2
:
1108 gyroUpdateSensor(&gyroSensor2
, currentTimeUs
);
1109 if (isGyroSensorCalibrationComplete(&gyroSensor2
)) {
1110 gyro
.gyroADCf
[X
] = gyroSensor2
.gyroDev
.gyroADCf
[X
];
1111 gyro
.gyroADCf
[Y
] = gyroSensor2
.gyroDev
.gyroADCf
[Y
];
1112 gyro
.gyroADCf
[Z
] = gyroSensor2
.gyroDev
.gyroADCf
[Z
];
1113 #ifdef USE_GYRO_OVERFLOW_CHECK
1114 overflowDetected
= gyroSensor2
.overflowDetected
;
1116 #ifdef USE_YAW_SPIN_RECOVERY
1117 yawSpinDetected
= gyroSensor2
.yawSpinDetected
;
1120 if (useDualGyroDebugging
) {
1121 DEBUG_SET(DEBUG_DUAL_GYRO_RAW
, 2, gyroSensor2
.gyroDev
.gyroADCRaw
[X
]);
1122 DEBUG_SET(DEBUG_DUAL_GYRO_RAW
, 3, gyroSensor2
.gyroDev
.gyroADCRaw
[Y
]);
1123 DEBUG_SET(DEBUG_DUAL_GYRO
, 2, lrintf(gyroSensor2
.gyroDev
.gyroADCf
[X
]));
1124 DEBUG_SET(DEBUG_DUAL_GYRO
, 3, lrintf(gyroSensor2
.gyroDev
.gyroADCf
[Y
]));
1125 DEBUG_SET(DEBUG_DUAL_GYRO_COMBINE
, 2, lrintf(gyro
.gyroADCf
[X
]));
1126 DEBUG_SET(DEBUG_DUAL_GYRO_COMBINE
, 3, lrintf(gyro
.gyroADCf
[Y
]));
1127 DEBUG_SET(DEBUG_DUAL_GYRO_SCALED
, 2, lrintf(gyroSensor2
.gyroDev
.gyroADC
[X
] * gyroSensor2
.gyroDev
.scale
));
1128 DEBUG_SET(DEBUG_DUAL_GYRO_SCALED
, 3, lrintf(gyroSensor2
.gyroDev
.gyroADC
[Y
] * gyroSensor2
.gyroDev
.scale
));
1131 case GYRO_CONFIG_USE_GYRO_BOTH
:
1132 gyroUpdateSensor(&gyroSensor1
, currentTimeUs
);
1133 gyroUpdateSensor(&gyroSensor2
, currentTimeUs
);
1134 if (isGyroSensorCalibrationComplete(&gyroSensor1
) && isGyroSensorCalibrationComplete(&gyroSensor2
)) {
1135 gyro
.gyroADCf
[X
] = (gyroSensor1
.gyroDev
.gyroADCf
[X
] + gyroSensor2
.gyroDev
.gyroADCf
[X
]) / 2.0f
;
1136 gyro
.gyroADCf
[Y
] = (gyroSensor1
.gyroDev
.gyroADCf
[Y
] + gyroSensor2
.gyroDev
.gyroADCf
[Y
]) / 2.0f
;
1137 gyro
.gyroADCf
[Z
] = (gyroSensor1
.gyroDev
.gyroADCf
[Z
] + gyroSensor2
.gyroDev
.gyroADCf
[Z
]) / 2.0f
;
1138 #ifdef USE_GYRO_OVERFLOW_CHECK
1139 overflowDetected
= gyroSensor1
.overflowDetected
|| gyroSensor2
.overflowDetected
;
1141 #ifdef USE_YAW_SPIN_RECOVERY
1142 yawSpinDetected
= gyroSensor1
.yawSpinDetected
|| gyroSensor2
.yawSpinDetected
;
1146 if (useDualGyroDebugging
) {
1147 DEBUG_SET(DEBUG_DUAL_GYRO_RAW
, 0, gyroSensor1
.gyroDev
.gyroADCRaw
[X
]);
1148 DEBUG_SET(DEBUG_DUAL_GYRO_RAW
, 1, gyroSensor1
.gyroDev
.gyroADCRaw
[Y
]);
1149 DEBUG_SET(DEBUG_DUAL_GYRO
, 0, lrintf(gyroSensor1
.gyroDev
.gyroADCf
[X
]));
1150 DEBUG_SET(DEBUG_DUAL_GYRO
, 1, lrintf(gyroSensor1
.gyroDev
.gyroADCf
[Y
]));
1151 DEBUG_SET(DEBUG_DUAL_GYRO_RAW
, 2, gyroSensor2
.gyroDev
.gyroADCRaw
[X
]);
1152 DEBUG_SET(DEBUG_DUAL_GYRO_RAW
, 3, gyroSensor2
.gyroDev
.gyroADCRaw
[Y
]);
1153 DEBUG_SET(DEBUG_DUAL_GYRO
, 2, lrintf(gyroSensor2
.gyroDev
.gyroADCf
[X
]));
1154 DEBUG_SET(DEBUG_DUAL_GYRO
, 3, lrintf(gyroSensor2
.gyroDev
.gyroADCf
[Y
]));
1155 DEBUG_SET(DEBUG_DUAL_GYRO_COMBINE
, 1, lrintf(gyro
.gyroADCf
[X
]));
1156 DEBUG_SET(DEBUG_DUAL_GYRO_COMBINE
, 2, lrintf(gyro
.gyroADCf
[Y
]));
1157 DEBUG_SET(DEBUG_DUAL_GYRO_DIFF
, 0, lrintf(gyroSensor1
.gyroDev
.gyroADCf
[X
] - gyroSensor2
.gyroDev
.gyroADCf
[X
]));
1158 DEBUG_SET(DEBUG_DUAL_GYRO_DIFF
, 1, lrintf(gyroSensor1
.gyroDev
.gyroADCf
[Y
] - gyroSensor2
.gyroDev
.gyroADCf
[Y
]));
1159 DEBUG_SET(DEBUG_DUAL_GYRO_DIFF
, 2, lrintf(gyroSensor1
.gyroDev
.gyroADCf
[Z
] - gyroSensor2
.gyroDev
.gyroADCf
[Z
]));
1160 DEBUG_SET(DEBUG_DUAL_GYRO_SCALED
, 0, lrintf(gyroSensor1
.gyroDev
.gyroADC
[X
] * gyroSensor1
.gyroDev
.scale
));
1161 DEBUG_SET(DEBUG_DUAL_GYRO_SCALED
, 1, lrintf(gyroSensor1
.gyroDev
.gyroADC
[Y
] * gyroSensor1
.gyroDev
.scale
));
1162 DEBUG_SET(DEBUG_DUAL_GYRO_SCALED
, 2, lrintf(gyroSensor2
.gyroDev
.gyroADC
[X
] * gyroSensor2
.gyroDev
.scale
));
1163 DEBUG_SET(DEBUG_DUAL_GYRO_SCALED
, 3, lrintf(gyroSensor2
.gyroDev
.gyroADC
[Y
] * gyroSensor2
.gyroDev
.scale
));
1169 if (!overflowDetected
) {
1170 for (int axis
= 0; axis
< XYZ_AXIS_COUNT
; axis
++) {
1171 // integrate using trapezium rule to avoid bias
1172 accumulatedMeasurements
[axis
] += 0.5f
* (gyroPrevious
[axis
] + gyro
.gyroADCf
[axis
]) * sampleDeltaUs
;
1173 gyroPrevious
[axis
] = gyro
.gyroADCf
[axis
];
1179 bool gyroGetAccumulationAverage(float *accumulationAverage
)
1181 if (accumulatedMeasurementTimeUs
> 0) {
1182 // If we have gyro data accumulated, calculate average rate that will yield the same rotation
1183 for (int axis
= 0; axis
< XYZ_AXIS_COUNT
; axis
++) {
1184 accumulationAverage
[axis
] = accumulatedMeasurements
[axis
] / accumulatedMeasurementTimeUs
;
1185 accumulatedMeasurements
[axis
] = 0.0f
;
1187 accumulatedMeasurementTimeUs
= 0;
1190 for (int axis
= 0; axis
< XYZ_AXIS_COUNT
; axis
++) {
1191 accumulationAverage
[axis
] = 0.0f
;
1197 int16_t gyroReadSensorTemperature(gyroSensor_t gyroSensor
)
1199 if (gyroSensor
.gyroDev
.temperatureFn
) {
1200 gyroSensor
.gyroDev
.temperatureFn(&gyroSensor
.gyroDev
, &gyroSensor
.gyroDev
.temperature
);
1202 return gyroSensor
.gyroDev
.temperature
;
1205 void gyroReadTemperature(void)
1207 switch (gyroToUse
) {
1208 case GYRO_CONFIG_USE_GYRO_1
:
1209 gyroSensorTemperature
= gyroReadSensorTemperature(gyroSensor1
);
1212 #ifdef USE_MULTI_GYRO
1213 case GYRO_CONFIG_USE_GYRO_2
:
1214 gyroSensorTemperature
= gyroReadSensorTemperature(gyroSensor2
);
1217 case GYRO_CONFIG_USE_GYRO_BOTH
:
1218 gyroSensorTemperature
= MAX(gyroReadSensorTemperature(gyroSensor1
), gyroReadSensorTemperature(gyroSensor2
));
1220 #endif // USE_MULTI_GYRO
1224 int16_t gyroGetTemperature(void)
1226 return gyroSensorTemperature
;
1229 int16_t gyroRateDps(int axis
)
1231 return lrintf(gyro
.gyroADCf
[axis
] / ACTIVE_GYRO
->gyroDev
.scale
);
1234 bool gyroOverflowDetected(void)
1236 #ifdef USE_GYRO_OVERFLOW_CHECK
1237 return overflowDetected
;
1240 #endif // USE_GYRO_OVERFLOW_CHECK
1243 #ifdef USE_YAW_SPIN_RECOVERY
1244 bool gyroYawSpinDetected(void)
1246 return yawSpinDetected
;
1248 #endif // USE_YAW_SPIN_RECOVERY
1250 uint16_t gyroAbsRateDps(int axis
)
1252 return fabsf(gyro
.gyroADCf
[axis
]);
1255 #ifdef USE_GYRO_REGISTER_DUMP
1256 uint8_t gyroReadRegister(uint8_t whichSensor
, uint8_t reg
)
1258 return mpuGyroReadRegister(gyroSensorBusByDevice(whichSensor
), reg
);
1260 #endif // USE_GYRO_REGISTER_DUMP
1264 float dynThrottle(float throttle
) {
1265 return throttle
* (1 - (throttle
* throttle
) / 3.0f
) * 1.5f
;
1268 void dynLpfGyroUpdate(float throttle
)
1270 if (dynLpfFilter
!= DYN_LPF_NONE
) {
1271 const unsigned int cutoffFreq
= fmax(dynThrottle(throttle
) * dynLpfMax
, dynLpfMin
);
1273 if (dynLpfFilter
== DYN_LPF_PT1
) {
1274 DEBUG_SET(DEBUG_DYN_LPF
, 2, cutoffFreq
);
1275 const float gyroDt
= gyro
.targetLooptime
* 1e-6f
;
1276 for (int axis
= 0; axis
< XYZ_AXIS_COUNT
; axis
++) {
1277 #ifdef USE_MULTI_GYRO
1278 if (gyroConfig()->gyro_to_use
== GYRO_CONFIG_USE_GYRO_1
|| gyroConfig()->gyro_to_use
== GYRO_CONFIG_USE_GYRO_BOTH
) {
1279 pt1FilterUpdateCutoff(&gyroSensor1
.lowpassFilter
[axis
].pt1FilterState
, pt1FilterGain(cutoffFreq
, gyroDt
));
1281 if (gyroConfig()->gyro_to_use
== GYRO_CONFIG_USE_GYRO_2
|| gyroConfig()->gyro_to_use
== GYRO_CONFIG_USE_GYRO_BOTH
) {
1282 pt1FilterUpdateCutoff(&gyroSensor2
.lowpassFilter
[axis
].pt1FilterState
, pt1FilterGain(cutoffFreq
, gyroDt
));
1285 pt1FilterUpdateCutoff(&gyroSensor1
.lowpassFilter
[axis
].pt1FilterState
, pt1FilterGain(cutoffFreq
, gyroDt
));
1288 } else if (dynLpfFilter
== DYN_LPF_BIQUAD
) {
1289 DEBUG_SET(DEBUG_DYN_LPF
, 2, cutoffFreq
);
1290 for (int axis
= 0; axis
< XYZ_AXIS_COUNT
; axis
++) {
1291 #ifdef USE_MULTI_GYRO
1292 if (gyroConfig()->gyro_to_use
== GYRO_CONFIG_USE_GYRO_1
|| gyroConfig()->gyro_to_use
== GYRO_CONFIG_USE_GYRO_BOTH
) {
1293 biquadFilterUpdateLPF(&gyroSensor1
.lowpassFilter
[axis
].biquadFilterState
, cutoffFreq
, gyro
.targetLooptime
);
1295 if (gyroConfig()->gyro_to_use
== GYRO_CONFIG_USE_GYRO_2
|| gyroConfig()->gyro_to_use
== GYRO_CONFIG_USE_GYRO_BOTH
) {
1296 biquadFilterUpdateLPF(&gyroSensor2
.lowpassFilter
[axis
].biquadFilterState
, cutoffFreq
, gyro
.targetLooptime
);
1299 biquadFilterUpdateLPF(&gyroSensor1
.lowpassFilter
[axis
].biquadFilterState
, cutoffFreq
, gyro
.targetLooptime
);