1
0
Fork 0
mirror of https://github.com/betaflight/betaflight.git synced 2025-07-13 11:29:58 +03:00

Merge pull request #2 from StreetLeagueSpec/sl-4.4.0

added adjustable k-factor
This commit is contained in:
Sky FPV 2024-07-27 16:50:46 -06:00 committed by GitHub
commit c6939297ab
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 67 additions and 49 deletions

View file

@ -1,2 +1 @@
HOBBYWING_XROTORF7CONV
BetafpvF411RX

1 HOBBYWING_XROTORF7CONV BetafpvF411RX

View file

@ -28,6 +28,8 @@
#define FC_VERSION_MINOR 4 // increment when a minor release is made (small new feature, change etc)
#define FC_VERSION_PATCH_LEVEL 2 // increment when a bug is fixed
#define SPEC_VERSION "SL-1.3.0"
#define FC_VERSION_STRING STR(FC_VERSION_MAJOR) "." STR(FC_VERSION_MINOR) "." STR(FC_VERSION_PATCH_LEVEL)
extern const char* const targetName;

View file

@ -4951,6 +4951,7 @@ static void printVersion(const char *cmdName, bool printBoardInfo)
cliPrintf("# %s / %s (%s) %s %s / %s (%s) MSP API: %s",
FC_FIRMWARE_NAME,
SPEC_VERSION,
targetName,
systemConfig()->boardIdentifier,
FC_VERSION_STRING,

View file

@ -936,6 +936,26 @@ const clivalue_t valueTable[] = {
{ "mixer_type", VAR_UINT8 | MASTER_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_MIXER_TYPE }, PG_MIXER_CONFIG, offsetof(mixerConfig_t, mixer_type) },
{ "crashflip_motor_percent", VAR_UINT8 | MASTER_VALUE, .config.minmaxUnsigned = { 0, 100 }, PG_MIXER_CONFIG, offsetof(mixerConfig_t, crashflip_motor_percent) },
{ "crashflip_expo", VAR_UINT8 | MASTER_VALUE, .config.minmaxUnsigned = { 0, 100 }, PG_MIXER_CONFIG, offsetof(mixerConfig_t, crashflip_expo) },
//Street League customization
{ "rpm_limiter_idle_rpm", VAR_UINT16 | MASTER_VALUE, .config.minmaxUnsigned = { 0, 999 }, PG_MIXER_CONFIG, offsetof(mixerConfig_t, govenor_idle_rpm) },
//street league locked
// { "rpm_limiter", VAR_INT8 | MASTER_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_OFF_ON }, PG_MIXER_CONFIG, offsetof(mixerConfig_t, govenor) },
// { "rpm_limiter_p", VAR_UINT16 | MASTER_VALUE, .config.minmaxUnsigned = { 20, 20 }, PG_MIXER_CONFIG, offsetof(mixerConfig_t, govenor_p) },
// { "rpm_limiter_i", VAR_UINT16 | MASTER_VALUE, .config.minmaxUnsigned = { 15, 15 }, PG_MIXER_CONFIG, offsetof(mixerConfig_t, govenor_i) },
// { "rpm_limiter_d", VAR_UINT16 | MASTER_VALUE, .config.minmaxUnsigned = { 10, 10 }, PG_MIXER_CONFIG, offsetof(mixerConfig_t, govenor_d) },
// { "rpm_limiter_rpm_limit", VAR_UINT16 | MASTER_VALUE, .config.minmaxUnsigned = { 130, 130 }, PG_MIXER_CONFIG, offsetof(mixerConfig_t, govenor_rpm_limit) },
// { "rpm_limiter_afterburner", VAR_UINT16 | MASTER_VALUE, .config.minmaxUnsigned = { 16, 16 }, PG_MIXER_CONFIG, offsetof(mixerConfig_t, govenor_rpm_afterburner) },
// { "rpm_limiter_afterburner_duration", VAR_UINT8 | MASTER_VALUE, .config.minmaxUnsigned = { 5, 5 }, PG_MIXER_CONFIG, offsetof(mixerConfig_t, govenor_rpm_afterburner_duration) },
// { "rpm_limiter_afterburner_hold_to_use", VAR_INT8 | MASTER_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_OFF_ON }, PG_MIXER_CONFIG, offsetof(mixerConfig_t, govenor_rpm_afterburner_hold_to_use) },
// { "rpm_limiter_afterburner_tank_count", VAR_UINT8 | MASTER_VALUE, .config.minmaxUnsigned = { 3, 3 }, PG_MIXER_CONFIG, offsetof(mixerConfig_t, govenor_rpm_afterburner_tank_count) },
// { "rpm_limiter_afterburner_reset", VAR_INT8 | MASTER_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_OFF_ON }, PG_MIXER_CONFIG, offsetof(mixerConfig_t, govenor_rpm_afterburner_reset) },
// { "rpm_limiter_acceleration_limit", VAR_UINT16 | MASTER_VALUE, .config.minmaxUnsigned = { 60, 60 }, PG_MIXER_CONFIG, offsetof(mixerConfig_t, govenor_acceleration_limit) },
// { "rpm_limiter_deceleration_limit", VAR_UINT16 | MASTER_VALUE, .config.minmaxUnsigned = { 60, 60 }, PG_MIXER_CONFIG, offsetof(mixerConfig_t, govenor_deceleration_limit) },
// { "rpm_limiter_k_factor", VAR_UINT16 | MASTER_VALUE, .config.minmaxUnsigned = { 1000, 1000 }, PG_MIXER_CONFIG, offsetof(mixerConfig_t, govenor_k_factor) },
// { "rpm_limiter_full_linearization", VAR_INT8 | MASTER_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_OFF_ON }, PG_MIXER_CONFIG, offsetof(mixerConfig_t, govenor_rpm_linearization) },
//street league unlocked
{ "rpm_limiter", VAR_INT8 | MASTER_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_OFF_ON }, PG_MIXER_CONFIG, offsetof(mixerConfig_t, govenor) },
{ "rpm_limiter_p", VAR_UINT16 | MASTER_VALUE, .config.minmaxUnsigned = { 0, 10000 }, PG_MIXER_CONFIG, offsetof(mixerConfig_t, govenor_p) },
{ "rpm_limiter_i", VAR_UINT16 | MASTER_VALUE, .config.minmaxUnsigned = { 0, 10000 }, PG_MIXER_CONFIG, offsetof(mixerConfig_t, govenor_i) },
@ -946,9 +966,9 @@ const clivalue_t valueTable[] = {
{ "rpm_limiter_afterburner_hold_to_use", VAR_INT8 | MASTER_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_OFF_ON }, PG_MIXER_CONFIG, offsetof(mixerConfig_t, govenor_rpm_afterburner_hold_to_use) },
{ "rpm_limiter_afterburner_tank_count", VAR_UINT8 | MASTER_VALUE, .config.minmaxUnsigned = { 0, 255 }, PG_MIXER_CONFIG, offsetof(mixerConfig_t, govenor_rpm_afterburner_tank_count) },
{ "rpm_limiter_afterburner_reset", VAR_INT8 | MASTER_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_OFF_ON }, PG_MIXER_CONFIG, offsetof(mixerConfig_t, govenor_rpm_afterburner_reset) },
{ "rpm_limiter_acceleration_limit", VAR_UINT16 | MASTER_VALUE, .config.minmaxUnsigned = { 0, 1000 }, PG_MIXER_CONFIG, offsetof(mixerConfig_t, govenor_acceleration_limit) },
//Street League customization
{ "rpm_limiter_idle_rpm", VAR_UINT16 | MASTER_VALUE, .config.minmaxUnsigned = { 0, 999 }, PG_MIXER_CONFIG, offsetof(mixerConfig_t, govenor_idle_rpm) },
{ "rpm_limiter_acceleration_limit", VAR_UINT16 | MASTER_VALUE, .config.minmaxUnsigned = { 0, 50000 }, PG_MIXER_CONFIG, offsetof(mixerConfig_t, govenor_acceleration_limit) },
{ "rpm_limiter_deceleration_limit", VAR_UINT16 | MASTER_VALUE, .config.minmaxUnsigned = { 0, 50000 }, PG_MIXER_CONFIG, offsetof(mixerConfig_t, govenor_deceleration_limit) },
{ "rpm_limiter_k_factor", VAR_UINT16 | MASTER_VALUE, .config.minmaxUnsigned = { 1, 50000 }, PG_MIXER_CONFIG, offsetof(mixerConfig_t, govenor_k_factor) },
{ "rpm_limiter_full_linearization", VAR_INT8 | MASTER_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_OFF_ON }, PG_MIXER_CONFIG, offsetof(mixerConfig_t, govenor_rpm_linearization) },
{ "3d_deadband_high", VAR_UINT16 | MASTER_VALUE, .config.minmaxUnsigned = { PWM_RANGE_MIDDLE, PWM_PULSE_MAX }, PG_MOTOR_3D_CONFIG, offsetof(flight3DConfig_t, deadband3d_high) },

View file

@ -357,12 +357,12 @@ float getAfterburnerTankPercent(void)
static void applyRPMLimiter(void)
{
if (mixerRuntime.govenorEnabled) {
float RPM_GOVENOR_LIMIT = 0;
float averageRPM = 0;
float averageRPM_smoothed = 0;
float PIDOutput = 0;
float RPM_GOVENOR_LIMIT = 0.0f;
float averageRPM = 0.0f;
float averageRPM_smoothed = 0.0f;
float PIDOutput = 0.0f;
float rcCommandThrottle = (rcCommand[THROTTLE]-1000)/1000.0f;
float maxRPMLimit = 0;
float maxRPMLimit = 0.0f;
maxRPMLimit = mixerRuntime.RPMLimit;
@ -444,7 +444,7 @@ static void applyRPMLimiter(void)
bool motorsSaturated = false;
bool motorsDesaturated = false;
for (int i = 0; i < getMotorCount(); i++) {
averageRPM += getDshotTelemetry(i);
averageRPM += (float)getDshotTelemetry(i);
if (motor[i] >= motorConfig()->maxthrottle) {
motorsSaturated = true;
}
@ -452,10 +452,10 @@ static void applyRPMLimiter(void)
motorsDesaturated = false;
}
}
averageRPM = 100 * averageRPM / (getMotorCount()*mixerRuntime.motorPoleCount/2.0f);
averageRPM = 100.0f * averageRPM / (float)(getMotorCount()*mixerRuntime.motorPoleCount/2.0f);
//get the smoothed rpm to avoid d term noise
averageRPM_smoothed = mixerRuntime.govenorPreviousSmoothedRPM + mixerRuntime.govenorDelayK * (averageRPM - mixerRuntime.govenorPreviousSmoothedRPM); //kinda braindead to convert to rps then back
averageRPM_smoothed = mixerRuntime.govenorPreviousSmoothedRPM + (float)mixerRuntime.govenorDelayK * (averageRPM - mixerRuntime.govenorPreviousSmoothedRPM); //kinda braindead to convert to rps then back
float smoothedRPMError = averageRPM_smoothed - RPM_GOVENOR_LIMIT;
float govenorP = smoothedRPMError * mixerRuntime.govenorPGain; //+ when overspped
@ -527,10 +527,11 @@ static void applyRPMLimiter(void)
mixerRuntime.govenorPreviousSmoothedRPMError = smoothedRPMError;
mixerRuntime.govenorPreviousRPMLimit = RPM_GOVENOR_LIMIT;
DEBUG_SET(DEBUG_RPM_LIMITER, 0, averageRPM);
DEBUG_SET(DEBUG_RPM_LIMITER, 1, smoothedRPMError);
DEBUG_SET(DEBUG_RPM_LIMITER, 2, mixerRuntime.govenorI*100.0f);
DEBUG_SET(DEBUG_RPM_LIMITER, 3, govenorD*10000.0f);
DEBUG_SET(DEBUG_RPM_LIMITER, 0, averageRPM);//unfiltered average rpm
DEBUG_SET(DEBUG_RPM_LIMITER, 1, averageRPM_smoothed); //filtered average rpm
DEBUG_SET(DEBUG_RPM_LIMITER, 2, smoothedRPMError); //P term
DEBUG_SET(DEBUG_RPM_LIMITER, 3, mixerRuntime.govenorI*100.0f); // I term
DEBUG_SET(DEBUG_RPM_LIMITER, 4, govenorD*10000.0f); // D term
/*DEBUG_SET(DEBUG_RPM_LIMITER, 0, mixerRuntime.afterburnerInitiated);
DEBUG_SET(DEBUG_RPM_LIMITER, 1, mixerRuntime.afterburnerTankPercent);

View file

@ -101,6 +101,7 @@ typedef struct mixerConfig_s {
uint8_t govenor_rpm_afterburner_tank_count;
uint16_t govenor_acceleration_limit;
uint16_t govenor_deceleration_limit;
uint16_t govenor_k_factor;
bool govenor_rpm_linearization;
uint16_t govenorThrottleLimitLearningTimeMS;
uint16_t govenor_idle_rpm;

View file

@ -59,6 +59,7 @@ PG_RESET_TEMPLATE(mixerConfig_t, mixerConfig,
.govenor_idle_rpm = 17,
.govenor_acceleration_limit = 60,
.govenor_deceleration_limit = 60,
.govenor_k_factor = 1000,
.govenor_rpm_limit = 130.0f,
.govenor_rpm_afterburner = 16,
.govenor_rpm_afterburner_duration = 5,
@ -327,48 +328,38 @@ void mixerInitProfile(void)
mixerRuntime.govenorExpectedThrottleLimit = 1.0f;
//Street League spec settings
mixerRuntime.govenorPGain = 20.0f * 0.0000015f;
mixerRuntime.govenorIGain = 15.0f * 0.0001f * pidGetDT();
mixerRuntime.govenorDGain = 10.0f * 0.00000003f * pidGetPidFrequency();
mixerRuntime.govenorAccelerationLimit = 60.0f * 1000.0f * pidGetDT();
mixerRuntime.govenorDecelerationLimit = 60.0f * 1000.0f * pidGetDT();
mixerRuntime.afterburnerRPM = 16;
mixerRuntime.afterburnerReset = false;
mixerRuntime.afterburnerDuration = 5;
mixerRuntime.afterburnerTanksRemaining = 3;
mixerRuntime.afterburnerHoldToBoost = false;
mixerRuntime.rpmLinearization = true;
mixerRuntime.RPMLimit = 130.0f;
mixerRuntime.motorPoleCount = 14;
mixerRuntime.govenorEnabled = true;
//Locked rpm settings
// mixerRuntime.govenorEnabled = true;
// mixerRuntime.rpmLinearization = true;
// mixerRuntime.motorPoleCount = 14;
// mixerRuntime.afterburnerReset = false;
// mixerRuntime.afterburnerHoldToBoost = false;
//Unlocked rpm settings
mixerRuntime.govenorEnabled = mixerConfig()->govenor;
mixerRuntime.rpmLinearization = mixerConfig()->govenor_rpm_linearization;
mixerRuntime.motorPoleCount = motorConfig()->motorPoleCount;
mixerRuntime.afterburnerReset = mixerConfig()->govenor_rpm_afterburner_reset;
mixerRuntime.afterburnerHoldToBoost = mixerConfig()->govenor_rpm_afterburner_hold_to_use;
mixerRuntime.govenorPGain = mixerConfig()->govenor_p * 0.0000015f;
mixerRuntime.govenorIGain = mixerConfig()->govenor_i * 0.0001f * pidGetDT();
mixerRuntime.govenorDGain = mixerConfig()->govenor_d * 0.00000003f * pidGetPidFrequency();
mixerRuntime.govenorAccelerationLimit = mixerConfig()->govenor_acceleration_limit * 1000.0f * pidGetDT();
mixerRuntime.govenorDecelerationLimit = mixerConfig()->govenor_deceleration_limit * 1000.0f * pidGetDT();
mixerRuntime.govenorKFactor = mixerConfig()->govenor_k_factor;
mixerRuntime.afterburnerRPM = mixerConfig()->govenor_rpm_afterburner;
mixerRuntime.afterburnerReset = mixerConfig()->govenor_rpm_afterburner_reset;
mixerRuntime.afterburnerDuration = mixerConfig()->govenor_rpm_afterburner_duration;
mixerRuntime.afterburnerTanksRemaining = mixerConfig()->govenor_rpm_afterburner_tank_count;
mixerRuntime.afterburnerHoldToBoost = mixerConfig()->govenor_rpm_afterburner_hold_to_use;
mixerRuntime.rpmLinearization = mixerConfig()->govenor_rpm_linearization;
mixerRuntime.RPMLimit = mixerConfig()->govenor_rpm_limit;
mixerRuntime.motorPoleCount = motorConfig()->motorPoleCount;
mixerRuntime.govenorEnabled = mixerConfig()->govenor;
mixerRuntime.govenorI = 0;
mixerRuntime.afterburnerTankPercent = 100.0f;
mixerRuntime.afterburnerInitiated = false;
// mixerRuntime.govenorPrevThrottle = 0;
// mixerRuntime.govenorFFGain = 0.05f * (float)(mixerConfig()->govenor_ff) * 0.001f;
// mixerRuntime.govenorAverageAverageRPM = 0;
// mixerRuntime.govenorAverageStickThrottle = 0;
mixerRuntime.govenorPreviousSmoothedRPMError = 0;
// mixerRuntime.govenorIterationStep = 1.0f/(pidGetPidFrequency() * mixerConfig()->govenor_learning_threshold_window); // 3 is the averaging
mixerRuntime.govenorDelayK = 800 * pidGetDT() / 20.0f;
mixerRuntime.govenorDelayK = mixerRuntime.govenorKFactor * pidGetDT() / 20.0f;
mixerRuntime.govenorLearningThrottleK = 0.5 / (pidGetPidFrequency() * mixerConfig()->govenorThrottleLimitLearningTimeMS / 1000); // 0.5 = value ^ (4000 * time) 0.99^(4000*(20/1000))
mixerRuntime.govenor_init = false;

View file

@ -56,6 +56,7 @@ typedef struct mixerRuntime_s {
float govenorExpectedThrottleLimit;
float govenorAccelerationLimit;
float govenorDecelerationLimit;
float govenorKFactor;
float prevAverageRPM;
float govenorPreviousSmoothedRPMError;
float minRPMDelayK;

View file

@ -370,17 +370,19 @@ void renderOsdWarning(char *warningText, bool *blinking, uint8_t *displayAttr)
}
}
#endif
if (mixerRuntime.afterburnerInitiated) {
tfp_sprintf(warningText, "BOOST ENGAGED");
*displayAttr = DISPLAYPORT_SEVERITY_WARNING;
*blinking = true;
return;
}
if (osdWarnGetState(OSD_WARNING_BATTERY_WARNING) && batteryState == BATTERY_WARNING) {
tfp_sprintf(warningText, "LOW BATTERY");
*displayAttr = DISPLAYPORT_SEVERITY_WARNING;
*blinking = true;
return;
}/*else if (mixerRuntime.afterburnerInitiated) {
tfp_sprintf(warningText, "BOOST ENGAGED");
*displayAttr = DISPLAYPORT_ATTR_CRITICAL;
return;
}*/
}
#ifdef USE_RC_SMOOTHING_FILTER
// Show warning if rc smoothing hasn't initialized the filters