Skip to content

Commit

Permalink
Rpm limiter initial throttle cap prediction fix (betaflight#13039)
Browse files Browse the repository at this point in the history
* initial commit

* initial commit

* Update src/main/flight/mixer_init.c

Co-authored-by: Jan Post <[email protected]>

* rpm limiter vbat compensation

* remove forced define

* change to multiply

* rpm limiter vbat compensation method 2

* fixes

* remove def

* test

* test

* test

* cleanup

* fix for maxcheck condition not satisfied if set to 2000

* Refactoring / cleanup

* Rename averageRpmFilter

* missing paren

* Move RPM estimation to motor.h

* Add macro for deadband

---------

Co-authored-by: Jan Post <[email protected]>
  • Loading branch information
Tdogb and KarateBrot authored Dec 6, 2023
1 parent 0b0c63a commit 2733dad
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 10 deletions.
16 changes: 14 additions & 2 deletions src/main/drivers/motor.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,15 @@
#include "config/feature.h"

#include "drivers/dshot.h" // for DSHOT_ constants in initEscEndpoints; may be gone in the future
#include "drivers/pwm_output.h" // for PWM_TYPE_* and others
#include "drivers/time.h"
#include "drivers/dshot_bitbang.h"
#include "drivers/dshot_dpwm.h"
#include "drivers/pwm_output.h" // for PWM_TYPE_* and others
#include "drivers/time.h"

#include "fc/rc_controls.h" // for flight3DConfig_t

#include "sensors/battery.h"

#include "motor.h"

static FAST_DATA_ZERO_INIT motorDevice_t *motorDevice;
Expand Down Expand Up @@ -343,6 +345,16 @@ void motorEnable(void)
}
}

float motorEstimateMaxRpm(void)
{
// Empirical testing found this relationship between estimated max RPM without props attached
// (unloaded) and measured max RPM with props attached (loaded), independent from prop size
float unloadedMaxRpm = 0.01f * getBatteryVoltage() * motorConfig()->kv;
float loadDerating = -5.44e-6f * unloadedMaxRpm + 0.944f;

return unloadedMaxRpm * loadDerating;
}

bool motorIsEnabled(void)
{
return motorDevice->enabled;
Expand Down
1 change: 1 addition & 0 deletions src/main/drivers/motor.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ bool isMotorProtocolEnabled(void);

void motorDisable(void);
void motorEnable(void);
float motorEstimateMaxRpm(void);
bool motorIsEnabled(void);
bool motorIsMotorEnabled(uint8_t index);
timeMs_t motorGetMotorEnableTimeMs(void);
Expand Down
11 changes: 7 additions & 4 deletions src/main/flight/mixer.c
Original file line number Diff line number Diff line change
Expand Up @@ -345,12 +345,13 @@ static void applyFlipOverAfterCrashModeToMotors(void)
}

#ifdef USE_RPM_LIMIT
#define STICK_HIGH_DEADBAND 5 // deadband to make sure throttle cap can raise, even with maxcheck set around 2000
static void applyRpmLimiter(mixerRuntime_t *mixer)
{
static float prevError = 0.0f;
static float i = 0.0f;
const float unsmoothedAverageRpm = getDshotRpmAverage();
const float averageRpm = pt1FilterApply(&mixer->averageRpmFilter, unsmoothedAverageRpm);
const float averageRpm = pt1FilterApply(&mixer->rpmLimiterAverageRpmFilter, unsmoothedAverageRpm);
const float error = averageRpm - mixer->rpmLimiterRpmLimit;

// PID
Expand All @@ -363,19 +364,21 @@ static void applyRpmLimiter(mixerRuntime_t *mixer)
// Throttle limit learning
if (error > 0.0f && rcCommand[THROTTLE] < rxConfig()->maxcheck) {
mixer->rpmLimiterThrottleScale *= 1.0f - 4.8f * pidGetDT();
} else if (pidOutput < -400 * pidGetDT() && rcCommand[THROTTLE] >= rxConfig()->maxcheck && !areMotorsSaturated()) { // Throttle accel corresponds with motor accel
} else if (pidOutput < -400.0f * pidGetDT() && lrintf(rcCommand[THROTTLE]) >= rxConfig()->maxcheck - STICK_HIGH_DEADBAND && !areMotorsSaturated()) { // Throttle accel corresponds with motor accel
mixer->rpmLimiterThrottleScale *= 1.0f + 3.2f * pidGetDT();
}
mixer->rpmLimiterThrottleScale = constrainf(mixer->rpmLimiterThrottleScale, 0.01f, 1.0f);
throttle *= mixer->rpmLimiterThrottleScale;

float rpmLimiterThrottleScaleOffset = pt1FilterApply(&mixer->rpmLimiterThrottleScaleOffsetFilter, constrainf(mixer->rpmLimiterRpmLimit / motorEstimateMaxRpm(), 0.0f, 1.0f) - mixer->rpmLimiterInitialThrottleScale);
throttle *= constrainf(mixer->rpmLimiterThrottleScale + rpmLimiterThrottleScaleOffset, 0.0f, 1.0f);

// Output
pidOutput = MAX(0.0f, pidOutput);
throttle = constrainf(throttle - pidOutput, 0.0f, 1.0f);
prevError = error;

DEBUG_SET(DEBUG_RPM_LIMIT, 0, lrintf(averageRpm));
DEBUG_SET(DEBUG_RPM_LIMIT, 1, lrintf(unsmoothedAverageRpm));
DEBUG_SET(DEBUG_RPM_LIMIT, 1, lrintf(rpmLimiterThrottleScaleOffset * 100.0f));
DEBUG_SET(DEBUG_RPM_LIMIT, 2, lrintf(mixer->rpmLimiterThrottleScale * 100.0f));
DEBUG_SET(DEBUG_RPM_LIMIT, 3, lrintf(throttle * 100.0f));
DEBUG_SET(DEBUG_RPM_LIMIT, 4, lrintf(error));
Expand Down
8 changes: 5 additions & 3 deletions src/main/flight/mixer_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -361,17 +361,19 @@ void mixerInitProfile(void)
mixerRuntime.rpmLimiterPGain = mixerConfig()->rpm_limit_p * 15e-6f;
mixerRuntime.rpmLimiterIGain = mixerConfig()->rpm_limit_i * 1e-3f * pidGetDT();
mixerRuntime.rpmLimiterDGain = mixerConfig()->rpm_limit_d * 3e-7f * pidGetPidFrequency();
pt1FilterInit(&mixerRuntime.averageRpmFilter, pt1FilterGain(6.0f, pidGetDT()));
pt1FilterInit(&mixerRuntime.rpmLimiterAverageRpmFilter, pt1FilterGain(6.0f, pidGetDT()));
pt1FilterInit(&mixerRuntime.rpmLimiterThrottleScaleOffsetFilter, pt1FilterGain(2.0f, pidGetDT()));
mixerResetRpmLimiter();
#endif
}

#ifdef USE_RPM_LIMIT
void mixerResetRpmLimiter(void)
{
const float maxExpectedRpm = MAX(1.0f, motorConfig()->kv * getBatteryVoltage() * 0.01f);
mixerRuntime.rpmLimiterThrottleScale = constrainf(mixerRuntime.rpmLimiterRpmLimit / maxExpectedRpm, 0.0f, 1.0f);
mixerRuntime.rpmLimiterThrottleScale = constrainf(mixerRuntime.rpmLimiterRpmLimit / motorEstimateMaxRpm(), 0.0f, 1.0f);
mixerRuntime.rpmLimiterInitialThrottleScale = mixerRuntime.rpmLimiterThrottleScale;
}

#endif // USE_RPM_LIMIT

#ifdef USE_LAUNCH_CONTROL
Expand Down
4 changes: 3 additions & 1 deletion src/main/flight/mixer_init.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,12 @@ typedef struct mixerRuntime_s {
#if defined(USE_RPM_LIMIT)
float rpmLimiterRpmLimit;
float rpmLimiterThrottleScale;
float rpmLimiterInitialThrottleScale;
float rpmLimiterPGain;
float rpmLimiterIGain;
float rpmLimiterDGain;
pt1Filter_t averageRpmFilter;
pt1Filter_t rpmLimiterAverageRpmFilter;
pt1Filter_t rpmLimiterThrottleScaleOffsetFilter;
#endif
} mixerRuntime_t;

Expand Down

0 comments on commit 2733dad

Please sign in to comment.