diff --git a/src/main/common/filter.c b/src/main/common/filter.c index 852215853..cb91b4740 100644 --- a/src/main/common/filter.c +++ b/src/main/common/filter.c @@ -1,8 +1,18 @@ /* - * filter.c + * This file is part of Cleanflight. * - * Created on: 24 jun. 2015 - * Author: borisb + * Cleanflight is free software: you can redistribute it 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. + * + * Cleanflight 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 Cleanflight. If not, see . */ #include @@ -10,8 +20,9 @@ #include #include -#include "common/filter.h" #include "common/axis.h" +#include "common/filter.h" +#include "common/maths.h" // PT1 Low Pass filter (when no dT specified it will be calculated from the cycleTime) @@ -27,23 +38,37 @@ float filterApplyPt1(float input, filterStatePt1_t *filter, uint8_t f_cut, float return filter->state; } -// 7 Tap FIR filter as described here: -// Thanks to Qcopter -void filterApplyFIR(int16_t data[]) { - int16_t FIRcoeff[7] = { 12, 23, 40, 51, 52, 40, 38 }; // TODO - More coefficients needed. Now fixed to 1khz - static int16_t gyro_delay[3][7] = { {0}, {0}, {0} }; +static int8_t gyroFIRCoeff_500[FILTER_TAPS] = { 18, 14, 16, 20, 22, 24, 25, 25, 24, 20, 18, 12, 18 }; // looptime=500; +static int8_t gyroFIRCoeff_1000[FILTER_TAPS] = { 0, 0, 0, 0, 0, 0, 12, 23, 40, 51, 52, 40, 38 }; // looptime=1000; group delay 2.5ms; -0.5db = 32Hz ; -1db = 45Hz; -5db = 97Hz; -10db = 132Hz + +int8_t * filterGetFIRCoefficientsTable(uint8_t filter_level, uint32_t targetLooptime) +{ + if (filter_level == 0) { + return NULL; + } + + // filter for 2kHz looptime + if (targetLooptime == 500) { + return gyroFIRCoeff_500; + } else { // filter for 1kHz looptime + return gyroFIRCoeff_1000; + } +} + +// Thanks to Qcopter & BorisB & DigitalEntity +void filterApplyFIR(int16_t data[3], int16_t state[3][FILTER_TAPS], int8_t coeff[FILTER_TAPS]) +{ int32_t FIRsum; int axis, i; - // 7 tap FIR, <-20dB at >170Hz with looptime 1ms, groupdelay = 2.5ms for (axis = 0; axis < XYZ_AXIS_COUNT; axis++) { FIRsum = 0; - for (i = 0; i <= 5; i++) { - gyro_delay[axis][i] = gyro_delay[axis][i + 1]; - FIRsum += gyro_delay[axis][i] * FIRcoeff[i]; + for (i = 0; i <= 7; i++) { + state[axis][i] = state[axis][i + 1]; + FIRsum += state[axis][i] * (int16_t)coeff[i]; } - gyro_delay[axis][6] = data[axis]; - FIRsum += gyro_delay[axis][6] * FIRcoeff[6]; + state[axis][FILTER_TAPS-1] = data[axis]; + FIRsum += state[axis][FILTER_TAPS-1] * coeff[FILTER_TAPS-1]; data[axis] = FIRsum / 256; } } diff --git a/src/main/common/filter.h b/src/main/common/filter.h index 39afd96ee..278fbbacc 100644 --- a/src/main/common/filter.h +++ b/src/main/common/filter.h @@ -1,16 +1,28 @@ /* - * filter.h + * This file is part of Cleanflight. * - * Created on: 24 jun. 2015 - * Author: borisb + * Cleanflight is free software: you can redistribute it 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. + * + * Cleanflight 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 Cleanflight. If not, see . */ - +#define FILTER_TAPS 13 typedef struct filterStatePt1_s { float state; float RC; + float constdT; } filterStatePt1_t; float filterApplyPt1(float input, filterStatePt1_t *filter, uint8_t f_cut, float dt); -void filterApplyFIR(int16_t data[3]); +int8_t * filterGetFIRCoefficientsTable(uint8_t filter_level, uint32_t targetLooptime); +void filterApplyFIR(int16_t data[3], int16_t state[3][FILTER_TAPS], int8_t coeff[FILTER_TAPS]); diff --git a/src/main/config/config.c b/src/main/config/config.c index 648fc101e..0b377775e 100755 --- a/src/main/config/config.c +++ b/src/main/config/config.c @@ -36,6 +36,7 @@ #include "drivers/timer.h" #include "drivers/pwm_rx.h" #include "drivers/serial.h" +#include "drivers/gyro_sync.h" #include "sensors/sensors.h" #include "sensors/gyro.h" @@ -751,7 +752,7 @@ void activateConfig(void) ); - useGyroConfig(&masterConfig.gyroConfig, currentProfile->pidProfile.gyro_soft_lpf); // Leave this for more coefficients in the future + useGyroConfig(&masterConfig.gyroConfig, filterGetFIRCoefficientsTable(currentProfile->pidProfile.gyro_soft_lpf, targetLooptime)); #ifdef TELEMETRY telemetryUseConfig(&masterConfig.telemetryConfig); diff --git a/src/main/drivers/gyro_sync.c b/src/main/drivers/gyro_sync.c index b6fdb4225..4b1536d3f 100644 --- a/src/main/drivers/gyro_sync.c +++ b/src/main/drivers/gyro_sync.c @@ -46,10 +46,18 @@ void gyroUpdateSampleRate(uint8_t lpf) { if (!lpf) { gyroSamplePeriod = 125; - gyroSyncDenominator = 8; // Sample every 8th gyro measurement +#ifdef STM32F303xC + gyroSyncDenominator = 4; // Sample every 4th gyro measurement 2khz +#else + if (!sensors(SENSOR_ACC) && !sensors(SENSOR_BARO) && !sensors(SENSOR_MAG)) { + gyroSyncDenominator = 4; // Sample every 4th gyro measurement 2khz + } else { + gyroSyncDenominator = 8; // Sample every 8th gyro measurement 1khz + } +#endif } else { gyroSamplePeriod = 1000; - gyroSyncDenominator = 1; // Full Sampling + gyroSyncDenominator = 1; // Full Sampling 1khz } // calculate gyro divider and targetLooptime (expected cycleTime) diff --git a/src/main/mw.c b/src/main/mw.c index d2640c923..18cdf7004 100644 --- a/src/main/mw.c +++ b/src/main/mw.c @@ -91,7 +91,7 @@ enum { ALIGN_MAG = 2 }; -//#define JITTER_DEBUG 0 // Specify debug value for jitter debug +#define JITTER_DEBUG 0 // Specify debug value for jitter debug /* VBAT monitoring interval (in microseconds) - 1s*/ #define VBATINTERVAL (6 * 3500) diff --git a/src/main/scheduler.c b/src/main/scheduler.c index ea2ab1414..b62cacbb5 100755 --- a/src/main/scheduler.c +++ b/src/main/scheduler.c @@ -27,7 +27,7 @@ #include "drivers/system.h" -//#define SCHEDULER_DEBUG +#define SCHEDULER_DEBUG cfTaskId_e currentTaskId = TASK_NONE; diff --git a/src/main/sensors/gyro.c b/src/main/sensors/gyro.c index 22a5efc94..852f6e9e4 100644 --- a/src/main/sensors/gyro.c +++ b/src/main/sensors/gyro.c @@ -38,15 +38,17 @@ int16_t gyroADC[XYZ_AXIS_COUNT]; int16_t gyroZero[FLIGHT_DYNAMICS_INDEX_COUNT] = { 0, 0, 0 }; static gyroConfig_t *gyroConfig; -static uint8_t gyroFIRFilter; +static int8_t * gyroFIRTable = 0L; +static int16_t gyroFIRState[3][FILTER_TAPS]; + gyro_t gyro; // gyro access functions sensor_align_e gyroAlign = 0; -void useGyroConfig(gyroConfig_t *gyroConfigToUse, int8_t filter) +void useGyroConfig(gyroConfig_t *gyroConfigToUse, int8_t * filterTableToUse) { gyroConfig = gyroConfigToUse; - gyroFIRFilter = filter; + gyroFIRTable = filterTableToUse; } void gyroSetCalibrationCycles(uint16_t calibrationCyclesRequired) @@ -124,8 +126,8 @@ void gyroUpdate(void) return; } - if (gyroFIRFilter) { - filterApplyFIR(gyroADC); + if (gyroFIRTable) { + filterApplyFIR(gyroADC, gyroFIRState, gyroFIRTable); } alignSensors(gyroADC, gyroADC, gyroAlign); diff --git a/src/main/sensors/gyro.h b/src/main/sensors/gyro.h index 6d0b6e7e8..6fa5f5e40 100644 --- a/src/main/sensors/gyro.h +++ b/src/main/sensors/gyro.h @@ -39,7 +39,7 @@ typedef struct gyroConfig_s { uint8_t gyroMovementCalibrationThreshold; // people keep forgetting that moving model while init results in wrong gyro offsets. and then they never reset gyro. so this is now on by default. } gyroConfig_t; -void useGyroConfig(gyroConfig_t *gyroConfigToUse, int8_t filter); +void useGyroConfig(gyroConfig_t *gyroConfigToUse, int8_t * filterTableToUse); void gyroSetCalibrationCycles(uint16_t calibrationCyclesRequired); void gyroUpdate(void); bool isGyroCalibrationComplete(void);