1
0
Fork 0
mirror of https://github.com/betaflight/betaflight.git synced 2025-07-19 14:25:20 +03:00

Filter Cleanup CF coding style// Remove Old pt1 for acc etc // F1 slower acc update

This commit is contained in:
borisbstyle 2016-01-17 22:33:30 +01:00
parent e15ee54513
commit a105af1225
11 changed files with 52 additions and 64 deletions

View file

@ -30,37 +30,22 @@
#define M_LN2_FLOAT 0.69314718055994530942f #define M_LN2_FLOAT 0.69314718055994530942f
#define M_PI_FLOAT 3.14159265358979323846f #define M_PI_FLOAT 3.14159265358979323846f
#define BIQUAD_GAIN 6.0f /* gain in db */
#define BIQUAD_BANDWIDTH 1.9f /* bandwidth in octaves */ #define BIQUAD_BANDWIDTH 1.9f /* bandwidth in octaves */
// PT1 Low Pass filter (when no dT specified it will be calculated from the cycleTime)
float filterApplyPt1(float input, filterStatePt1_t *filter, uint8_t f_cut, float dT) {
// Pre calculate and store RC
if (!filter->RC) {
filter->RC = 1.0f / ( 2.0f * (float)M_PI * f_cut );
}
filter->state = filter->state + dT / (filter->RC + dT) * (input - filter->state);
return filter->state;
}
/* sets up a biquad Filter */ /* sets up a biquad Filter */
biquad_t *BiQuadNewLpf(uint8_t filterCutFreq) void BiQuadNewLpf(uint8_t filterCutFreq, biquad_t *newState, float refreshRate)
{ {
float samplingRate; float samplingRate;
samplingRate = 1 / (targetLooptime * 0.000001f);
biquad_t *newState; if (!refreshRate) {
samplingRate = 1 / (targetLooptime * 0.000001f);
} else {
samplingRate = refreshRate;
}
float omega, sn, cs, alpha; float omega, sn, cs, alpha;
float a0, a1, a2, b0, b1, b2; float a0, a1, a2, b0, b1, b2;
newState = malloc(sizeof(biquad_t));
if (newState == NULL)
return NULL;
/* setup variables */ /* setup variables */
omega = 2 * M_PI_FLOAT * (float) filterCutFreq / samplingRate; omega = 2 * M_PI_FLOAT * (float) filterCutFreq / samplingRate;
sn = sinf(omega); sn = sinf(omega);
@ -84,8 +69,6 @@ biquad_t *BiQuadNewLpf(uint8_t filterCutFreq)
/* zero initial samples */ /* zero initial samples */
newState->x1 = newState->x2 = 0; newState->x1 = newState->x2 = 0;
newState->y1 = newState->y2 = 0; newState->y1 = newState->y2 = 0;
return newState;
} }
/* Computes a biquad_t filter on a sample */ /* Computes a biquad_t filter on a sample */

View file

@ -15,20 +15,11 @@
* along with Cleanflight. If not, see <http://www.gnu.org/licenses/>. * along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
*/ */
#define FILTER_TAPS 14
typedef struct filterStatePt1_s {
float state;
float RC;
float constdT;
} filterStatePt1_t;
/* this holds the data required to update samples thru a filter */ /* this holds the data required to update samples thru a filter */
typedef struct biquad_s { typedef struct biquad_s {
float a0, a1, a2, a3, a4; float a0, a1, a2, a3, a4;
float x1, x2, y1, y2; float x1, x2, y1, y2;
} biquad_t; } biquad_t;
float filterApplyPt1(float input, filterStatePt1_t *filter, uint8_t f_cut, float dt);
float applyBiQuadFilter(float sample, biquad_t *state); float applyBiQuadFilter(float sample, biquad_t *state);
biquad_t *BiQuadNewLpf(uint8_t filterCutFreq); void BiQuadNewLpf(uint8_t filterCutFreq, biquad_t *newState, float refreshRate);

View file

@ -493,7 +493,7 @@ static void resetConf(void)
resetRollAndPitchTrims(&currentProfile->accelerometerTrims); resetRollAndPitchTrims(&currentProfile->accelerometerTrims);
currentProfile->mag_declination = 0; currentProfile->mag_declination = 0;
currentProfile->acc_cut_hz = 15; currentProfile->acc_lpf_hz = 20;
currentProfile->accz_lpf_cutoff = 5.0f; currentProfile->accz_lpf_cutoff = 5.0f;
currentProfile->accDeadband.xy = 40; currentProfile->accDeadband.xy = 40;
currentProfile->accDeadband.z = 40; currentProfile->accDeadband.z = 40;
@ -748,7 +748,7 @@ void activateConfig(void)
&currentProfile->pidProfile &currentProfile->pidProfile
); );
useGyroConfig(&masterConfig.gyroConfig, &currentProfile->pidProfile.gyro_lpf_hz); useGyroConfig(&masterConfig.gyroConfig, currentProfile->pidProfile.gyro_lpf_hz);
#ifdef TELEMETRY #ifdef TELEMETRY
telemetryUseConfig(&masterConfig.telemetryConfig); telemetryUseConfig(&masterConfig.telemetryConfig);
@ -778,7 +778,7 @@ void activateConfig(void)
imuRuntimeConfig.dcm_kp = masterConfig.dcm_kp / 10000.0f; imuRuntimeConfig.dcm_kp = masterConfig.dcm_kp / 10000.0f;
imuRuntimeConfig.dcm_ki = masterConfig.dcm_ki / 10000.0f; imuRuntimeConfig.dcm_ki = masterConfig.dcm_ki / 10000.0f;
imuRuntimeConfig.acc_cut_hz = currentProfile->acc_cut_hz; imuRuntimeConfig.acc_cut_hz = currentProfile->acc_lpf_hz;
imuRuntimeConfig.acc_unarmedcal = currentProfile->acc_unarmedcal; imuRuntimeConfig.acc_unarmedcal = currentProfile->acc_unarmedcal;
imuRuntimeConfig.small_angle = masterConfig.small_angle; imuRuntimeConfig.small_angle = masterConfig.small_angle;

View file

@ -28,7 +28,7 @@ typedef struct profile_s {
rollAndPitchTrims_t accelerometerTrims; // accelerometer trim rollAndPitchTrims_t accelerometerTrims; // accelerometer trim
// sensor-related stuff // sensor-related stuff
uint8_t acc_cut_hz; // Set the Low Pass Filter factor for ACC. Reducing this value would reduce ACC noise (visible in GUI), but would increase ACC lag time. Zero = no filter uint8_t acc_lpf_hz; // Set the Low Pass Filter factor for ACC. Reducing this value would reduce ACC noise (visible in GUI), but would increase ACC lag time. Zero = no filter
float accz_lpf_cutoff; // cutoff frequency for the low pass filter used on the acc z-axis for althold in Hz float accz_lpf_cutoff; // cutoff frequency for the low pass filter used on the acc z-axis for althold in Hz
accDeadband_t accDeadband; accDeadband_t accDeadband;

View file

@ -377,7 +377,8 @@ static bool isMagnetometerHealthy(void)
static void imuCalculateEstimatedAttitude(void) static void imuCalculateEstimatedAttitude(void)
{ {
static filterStatePt1_t accLPFState[3]; static biquad_t accLPFState[3];
static bool accStateIsSet;
static uint32_t previousIMUUpdateTime; static uint32_t previousIMUUpdateTime;
float rawYawError = 0; float rawYawError = 0;
int32_t axis; int32_t axis;
@ -391,8 +392,13 @@ static void imuCalculateEstimatedAttitude(void)
// Smooth and use only valid accelerometer readings // Smooth and use only valid accelerometer readings
for (axis = 0; axis < 3; axis++) { for (axis = 0; axis < 3; axis++) {
if (imuRuntimeConfig->acc_cut_hz > 0) { if (imuRuntimeConfig->acc_cut_hz) {
accSmooth[axis] = filterApplyPt1(accADC[axis], &accLPFState[axis], imuRuntimeConfig->acc_cut_hz, deltaT * 1e-6f); if (accStateIsSet) {
accSmooth[axis] = lrintf(applyBiQuadFilter((float) accADC[axis], &accLPFState[axis]));
} else {
for (axis = 0; axis < 3; axis++) BiQuadNewLpf(imuRuntimeConfig->acc_cut_hz, &accLPFState[axis], 1000);
accStateIsSet = true;
}
} else { } else {
accSmooth[axis] = accADC[axis]; accSmooth[axis] = accADC[axis];
} }

View file

@ -113,7 +113,7 @@ void airModePlus(airModePlus_t *axisState, int axis, pidProfile_t *pidProfile) {
const angle_index_t rcAliasToAngleIndexMap[] = { AI_ROLL, AI_PITCH }; const angle_index_t rcAliasToAngleIndexMap[] = { AI_ROLL, AI_PITCH };
static airModePlus_t airModePlusAxisState[3]; static airModePlus_t airModePlusAxisState[3];
static biquad_t *deltaBiQuadState[3]; static biquad_t deltaBiQuadState[3];
static bool deltaStateIsSet; static bool deltaStateIsSet;
static void pidLuxFloat(pidProfile_t *pidProfile, controlRateConfig_t *controlRateConfig, static void pidLuxFloat(pidProfile_t *pidProfile, controlRateConfig_t *controlRateConfig,
@ -128,7 +128,7 @@ static void pidLuxFloat(pidProfile_t *pidProfile, controlRateConfig_t *controlRa
static float previousErrorGyroIf[3] = { 0.0f, 0.0f, 0.0f }; static float previousErrorGyroIf[3] = { 0.0f, 0.0f, 0.0f };
if (!deltaStateIsSet && pidProfile->dterm_lpf_hz) { if (!deltaStateIsSet && pidProfile->dterm_lpf_hz) {
for (axis = 0; axis < 3; axis++) deltaBiQuadState[axis] = (biquad_t *)BiQuadNewLpf(pidProfile->dterm_lpf_hz); for (axis = 0; axis < 3; axis++) BiQuadNewLpf(pidProfile->dterm_lpf_hz, &deltaBiQuadState[axis], 0);
deltaStateIsSet = true; deltaStateIsSet = true;
} }
@ -215,7 +215,7 @@ static void pidLuxFloat(pidProfile_t *pidProfile, controlRateConfig_t *controlRa
lastError[axis] = RateError; lastError[axis] = RateError;
if (deltaStateIsSet) { if (deltaStateIsSet) {
delta = applyBiQuadFilter(delta, deltaBiQuadState[axis]); delta = applyBiQuadFilter(delta, &deltaBiQuadState[axis]);
} }
// Correct difference by cycle time. Cycle time is jittery (can be different 2 times), so calculated difference // Correct difference by cycle time. Cycle time is jittery (can be different 2 times), so calculated difference
@ -259,7 +259,7 @@ static void pidRewrite(pidProfile_t *pidProfile, controlRateConfig_t *controlRat
int8_t horizonLevelStrength = 100; int8_t horizonLevelStrength = 100;
if (!deltaStateIsSet && pidProfile->dterm_lpf_hz) { if (!deltaStateIsSet && pidProfile->dterm_lpf_hz) {
for (axis = 0; axis < 3; axis++) deltaBiQuadState[axis] = (biquad_t *)BiQuadNewLpf(pidProfile->dterm_lpf_hz); for (axis = 0; axis < 3; axis++) BiQuadNewLpf(pidProfile->dterm_lpf_hz, &deltaBiQuadState[axis], 0);
deltaStateIsSet = true; deltaStateIsSet = true;
} }
@ -348,7 +348,7 @@ static void pidRewrite(pidProfile_t *pidProfile, controlRateConfig_t *controlRat
lastError[axis] = RateError; lastError[axis] = RateError;
if (deltaStateIsSet) { if (deltaStateIsSet) {
delta = lrintf(applyBiQuadFilter((float) delta, deltaBiQuadState[axis])); delta = lrintf(applyBiQuadFilter((float) delta, &deltaBiQuadState[axis]));
} }
// Correct difference by cycle time. Cycle time is jittery (can be different 2 times), so calculated difference // Correct difference by cycle time. Cycle time is jittery (can be different 2 times), so calculated difference

View file

@ -602,7 +602,7 @@ const clivalue_t valueTable[] = {
#endif #endif
{ "acc_hardware", VAR_UINT8 | MASTER_VALUE, &masterConfig.acc_hardware, .config.minmax = { 0, ACC_MAX } }, { "acc_hardware", VAR_UINT8 | MASTER_VALUE, &masterConfig.acc_hardware, .config.minmax = { 0, ACC_MAX } },
{ "acc_cut_hz", VAR_UINT8 | PROFILE_VALUE, &masterConfig.profile[0].acc_cut_hz, .config.minmax = { 0, 200 } }, { "acc_lpf_hz", VAR_UINT8 | PROFILE_VALUE, &masterConfig.profile[0].acc_lpf_hz, .config.minmax = { 0, 200 } },
{ "accxy_deadband", VAR_UINT8 | PROFILE_VALUE, &masterConfig.profile[0].accDeadband.xy, .config.minmax = { 0, 100 } }, { "accxy_deadband", VAR_UINT8 | PROFILE_VALUE, &masterConfig.profile[0].accDeadband.xy, .config.minmax = { 0, 100 } },
{ "accz_deadband", VAR_UINT8 | PROFILE_VALUE, &masterConfig.profile[0].accDeadband.z, .config.minmax = { 0, 100 } }, { "accz_deadband", VAR_UINT8 | PROFILE_VALUE, &masterConfig.profile[0].accDeadband.z, .config.minmax = { 0, 100 } },
{ "accz_lpf_cutoff", VAR_FLOAT | PROFILE_VALUE, &masterConfig.profile[0].accz_lpf_cutoff, .config.minmax = { 1, 20 } }, { "accz_lpf_cutoff", VAR_FLOAT | PROFILE_VALUE, &masterConfig.profile[0].accz_lpf_cutoff, .config.minmax = { 1, 20 } },

View file

@ -549,15 +549,21 @@ int main(void) {
setTaskEnabled(TASK_GYROPID, true); setTaskEnabled(TASK_GYROPID, true);
if(sensors(SENSOR_ACC)) { if(sensors(SENSOR_ACC)) {
uint32_t accTargetLooptime = 0;
setTaskEnabled(TASK_ACCEL, true); setTaskEnabled(TASK_ACCEL, true);
switch(targetLooptime) { switch(targetLooptime) {
case(500): case(500):
rescheduleTask(TASK_ACCEL, 10000); accTargetLooptime = 10000;
break; break;
default: default:
case(1000): case(1000):
rescheduleTask(TASK_ACCEL, 1000); #ifdef STM32F10X
accTargetLooptime = 3000;
#else
accTargetLooptime = 1000;
#endif
} }
rescheduleTask(TASK_ACCEL, accTargetLooptime);
} }
setTaskEnabled(TASK_SERIAL, true); setTaskEnabled(TASK_SERIAL, true);
setTaskEnabled(TASK_BEEPER, true); setTaskEnabled(TASK_BEEPER, true);

View file

@ -121,8 +121,6 @@ extern uint32_t currentTime;
extern uint8_t PIDweight[3]; extern uint8_t PIDweight[3];
static bool isRXDataNew; static bool isRXDataNew;
static filterStatePt1_t filteredCycleTimeState;
uint16_t filteredCycleTime;
typedef void (*pidControllerFuncPtr)(pidProfile_t *pidProfile, controlRateConfig_t *controlRateConfig, typedef void (*pidControllerFuncPtr)(pidProfile_t *pidProfile, controlRateConfig_t *controlRateConfig,
uint16_t max_angle_inclination, rollAndPitchTrims_t *angleTrim, rxConfig_t *rxConfig); // pid controller function prototype uint16_t max_angle_inclination, rollAndPitchTrims_t *angleTrim, rxConfig_t *rxConfig); // pid controller function prototype
@ -179,10 +177,21 @@ void filterRc(void){
static int16_t deltaRC[4] = { 0, 0, 0, 0 }; static int16_t deltaRC[4] = { 0, 0, 0, 0 };
static int16_t factor, rcInterpolationFactor; static int16_t factor, rcInterpolationFactor;
uint16_t rxRefreshRate; uint16_t rxRefreshRate;
static biquad_t filteredCycleTimeState;
static bool filterIsSet;
uint16_t filteredCycleTime;
// Set RC refresh rate for sampling and channels to filter // Set RC refresh rate for sampling and channels to filter
initRxRefreshRate(&rxRefreshRate); initRxRefreshRate(&rxRefreshRate);
/* Initialize cycletime filter */
if (!filterIsSet) {
BiQuadNewLpf(1, &filteredCycleTimeState, 0);
filterIsSet = true;
}
filteredCycleTime = applyBiQuadFilter((float) cycleTime, &filteredCycleTimeState);
rcInterpolationFactor = rxRefreshRate / filteredCycleTime + 1; rcInterpolationFactor = rxRefreshRate / filteredCycleTime + 1;
if (isRXDataNew) { if (isRXDataNew) {
@ -657,13 +666,6 @@ void taskMainPidLoop(void)
cycleTime = getTaskDeltaTime(TASK_SELF); cycleTime = getTaskDeltaTime(TASK_SELF);
dT = (float)targetLooptime * 0.000001f; dT = (float)targetLooptime * 0.000001f;
// Calculate average cycle time and average jitter
filteredCycleTime = filterApplyPt1(cycleTime, &filteredCycleTimeState, 1, dT);
#if defined JITTER_DEBUG
debug[JITTER_DEBUG] = cycleTime - filteredCycleTime;
#endif
imuUpdateGyroAndAttitude(); imuUpdateGyroAndAttitude();
annexCode(); annexCode();

View file

@ -41,7 +41,7 @@ int16_t gyroADC[XYZ_AXIS_COUNT];
int16_t gyroZero[FLIGHT_DYNAMICS_INDEX_COUNT] = { 0, 0, 0 }; int16_t gyroZero[FLIGHT_DYNAMICS_INDEX_COUNT] = { 0, 0, 0 };
static gyroConfig_t *gyroConfig; static gyroConfig_t *gyroConfig;
static biquad_t *gyroBiQuadState[3]; static biquad_t gyroBiQuadState[3];
static bool gyroFilterStateIsSet; static bool gyroFilterStateIsSet;
static uint8_t gyroLpfCutFreq; static uint8_t gyroLpfCutFreq;
int axis; int axis;
@ -49,15 +49,15 @@ int axis;
gyro_t gyro; // gyro access functions gyro_t gyro; // gyro access functions
sensor_align_e gyroAlign = 0; sensor_align_e gyroAlign = 0;
void useGyroConfig(gyroConfig_t *gyroConfigToUse, uint8_t *gyro_lpf_hz) void useGyroConfig(gyroConfig_t *gyroConfigToUse, uint8_t gyro_lpf_hz)
{ {
gyroConfig = gyroConfigToUse; gyroConfig = gyroConfigToUse;
gyroLpfCutFreq = *gyro_lpf_hz; gyroLpfCutFreq = gyro_lpf_hz;
} }
void initGyroFilterCoefficients(void) { void initGyroFilterCoefficients(void) {
if (gyroLpfCutFreq && targetLooptime) { /* Initialisation needs to happen once samplingrate is known */ if (gyroLpfCutFreq && targetLooptime) { /* Initialisation needs to happen once samplingrate is known */
for (axis = 0; axis < 3; axis++) gyroBiQuadState[axis] = (biquad_t *)BiQuadNewLpf(gyroLpfCutFreq); for (axis = 0; axis < 3; axis++) BiQuadNewLpf(gyroLpfCutFreq, &gyroBiQuadState[axis], 0);
gyroFilterStateIsSet = true; gyroFilterStateIsSet = true;
} }
} }
@ -143,7 +143,7 @@ void gyroUpdate(void)
if (!gyroFilterStateIsSet) { if (!gyroFilterStateIsSet) {
initGyroFilterCoefficients(); initGyroFilterCoefficients();
} else { } else {
for (axis = 0; axis < XYZ_AXIS_COUNT; axis++) gyroADC[axis] = lrintf(applyBiQuadFilter((float) gyroADC[axis], gyroBiQuadState[axis])); for (axis = 0; axis < XYZ_AXIS_COUNT; axis++) gyroADC[axis] = lrintf(applyBiQuadFilter((float) gyroADC[axis], &gyroBiQuadState[axis]));
} }
} }

View file

@ -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. 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; } gyroConfig_t;
void useGyroConfig(gyroConfig_t *gyroConfigToUse, uint8_t *gyro_lpf_hz); void useGyroConfig(gyroConfig_t *gyroConfigToUse, uint8_t gyro_lpf_hz);
void gyroSetCalibrationCycles(uint16_t calibrationCyclesRequired); void gyroSetCalibrationCycles(uint16_t calibrationCyclesRequired);
void gyroUpdate(void); void gyroUpdate(void);
bool isGyroCalibrationComplete(void); bool isGyroCalibrationComplete(void);