diff --git a/device.csv b/device.csv index e404f24ade..6f452b8dde 100644 --- a/device.csv +++ b/device.csv @@ -1,2 +1 @@ -HOBBYWING_XROTORF7CONV - +BetafpvF411RX diff --git a/src/main/build/version.h b/src/main/build/version.h index 4f45c31020..950e20371d 100644 --- a/src/main/build/version.h +++ b/src/main/build/version.h @@ -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; diff --git a/src/main/cli/cli.c b/src/main/cli/cli.c index 6031adb437..01f5b14515 100644 --- a/src/main/cli/cli.c +++ b/src/main/cli/cli.c @@ -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, diff --git a/src/main/cli/settings.c b/src/main/cli/settings.c index b7749f74ee..7d47da1325 100644 --- a/src/main/cli/settings.c +++ b/src/main/cli/settings.c @@ -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) }, diff --git a/src/main/flight/mixer.c b/src/main/flight/mixer.c index f8ef4f4b4d..2fe49745a5 100644 --- a/src/main/flight/mixer.c +++ b/src/main/flight/mixer.c @@ -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); diff --git a/src/main/flight/mixer.h b/src/main/flight/mixer.h index a4424536ab..a4d431c966 100644 --- a/src/main/flight/mixer.h +++ b/src/main/flight/mixer.h @@ -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; diff --git a/src/main/flight/mixer_init.c b/src/main/flight/mixer_init.c index 1fb55131e0..aa06f385b7 100644 --- a/src/main/flight/mixer_init.c +++ b/src/main/flight/mixer_init.c @@ -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; diff --git a/src/main/flight/mixer_init.h b/src/main/flight/mixer_init.h index dd88519036..2122c915ef 100644 --- a/src/main/flight/mixer_init.h +++ b/src/main/flight/mixer_init.h @@ -56,6 +56,7 @@ typedef struct mixerRuntime_s { float govenorExpectedThrottleLimit; float govenorAccelerationLimit; float govenorDecelerationLimit; + float govenorKFactor; float prevAverageRPM; float govenorPreviousSmoothedRPMError; float minRPMDelayK; diff --git a/src/main/osd/osd_warnings.c b/src/main/osd/osd_warnings.c index f8f44d0392..381ef9ae92 100644 --- a/src/main/osd/osd_warnings.c +++ b/src/main/osd/osd_warnings.c @@ -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