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

GPS Rescue Bugfix, add a failsafe debug, refactor stick deflection (#12195)

* simple failsafe debug

* simplify areSticksActive

use getRcDeflectionAbs and fix unitTest

* bugfix to require stick input to re-take control

* small refactor
This commit is contained in:
ctzsnooze 2023-01-18 13:44:50 +12:00 committed by GitHub
parent e5c53597a3
commit 4454286165
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 30 additions and 30 deletions

View file

@ -107,4 +107,5 @@ const char * const debugModeNames[DEBUG_COUNT] = {
"ATTITUDE", "ATTITUDE",
"VTX_MSP", "VTX_MSP",
"GPS_DOP", "GPS_DOP",
"FAILSAFE",
}; };

View file

@ -105,6 +105,7 @@ typedef enum {
DEBUG_ATTITUDE, DEBUG_ATTITUDE,
DEBUG_VTX_MSP, DEBUG_VTX_MSP,
DEBUG_GPS_DOP, DEBUG_GPS_DOP,
DEBUG_FAILSAFE,
DEBUG_COUNT DEBUG_COUNT
} debugType_e; } debugType_e;

View file

@ -683,18 +683,7 @@ static bool canUpdateVTX(void)
bool areSticksActive(uint8_t stickPercentLimit) bool areSticksActive(uint8_t stickPercentLimit)
{ {
for (int axis = FD_ROLL; axis <= FD_YAW; axis ++) { for (int axis = FD_ROLL; axis <= FD_YAW; axis ++) {
const uint8_t deadband = axis == FD_YAW ? rcControlsConfig()->yaw_deadband : rcControlsConfig()->deadband; if (getRcDeflectionAbs(axis) * 100.f >= stickPercentLimit) {
uint8_t stickPercent = 0;
if ((rcData[axis] >= PWM_RANGE_MAX) || (rcData[axis] <= PWM_RANGE_MIN)) {
stickPercent = 100;
} else {
if (rcData[axis] > (rxConfig()->midrc + deadband)) {
stickPercent = ((rcData[axis] - rxConfig()->midrc - deadband) * 100) / (PWM_RANGE_MAX - rxConfig()->midrc - deadband);
} else if (rcData[axis] < (rxConfig()->midrc - deadband)) {
stickPercent = ((rxConfig()->midrc - deadband - rcData[axis]) * 100) / (rxConfig()->midrc - deadband - PWM_RANGE_MIN);
}
}
if (stickPercent >= stickPercentLimit) {
return true; return true;
} }
} }

View file

@ -104,6 +104,7 @@ void failsafeReset(void)
failsafeState.receivingRxDataPeriodPreset = failsafeState.rxDataRecoveryPeriod; failsafeState.receivingRxDataPeriodPreset = failsafeState.rxDataRecoveryPeriod;
failsafeState.phase = FAILSAFE_IDLE; failsafeState.phase = FAILSAFE_IDLE;
failsafeState.rxLinkState = FAILSAFE_RXLINK_DOWN; failsafeState.rxLinkState = FAILSAFE_RXLINK_DOWN;
failsafeState.failsafeSwitchWasOn = false;
} }
void failsafeInit(void) void failsafeInit(void)
@ -217,17 +218,19 @@ uint32_t failsafeFailurePeriodMs(void)
} }
FAST_CODE_NOINLINE void failsafeUpdateState(void) FAST_CODE_NOINLINE void failsafeUpdateState(void)
// triggered directly, and ONLY, by the cheduler, at 10ms = PERIOD_RXDATA_FAILURE - intervals // triggered directly, and ONLY, by the scheduler, at 10ms = PERIOD_RXDATA_FAILURE - intervals
{ {
if (!failsafeIsMonitoring()) { if (!failsafeIsMonitoring()) {
return; return;
} }
bool receivingRxData = failsafeIsReceivingRxData(); bool receivingRxData = failsafeIsReceivingRxData();
// true when FAILSAFE_RXLINK_UP // returns state of FAILSAFE_RXLINK_UP
// FAILSAFE_RXLINK_UP is set in failsafeOnValidDataReceived // FAILSAFE_RXLINK_UP is set in failsafeOnValidDataReceived, after the various Stage 1 and recovery delays
// failsafeOnValidDataReceived runs from detectAndApplySignalLossBehaviour // failsafeOnValidDataReceived runs from detectAndApplySignalLossBehaviour
DEBUG_SET(DEBUG_FAILSAFE, 2, receivingRxData); // from Rx alone, not considering switch
bool armed = ARMING_FLAG(ARMED); bool armed = ARMING_FLAG(ARMED);
bool failsafeSwitchIsOn = IS_RC_MODE_ACTIVE(BOXFAILSAFE); bool failsafeSwitchIsOn = IS_RC_MODE_ACTIVE(BOXFAILSAFE);
beeperMode_e beeperMode = BEEPER_SILENCE; beeperMode_e beeperMode = BEEPER_SILENCE;
@ -238,7 +241,7 @@ FAST_CODE_NOINLINE void failsafeUpdateState(void)
receivingRxData = false; receivingRxData = false;
} }
// Beep RX lost only if we are not seeing data and we have been armed earlier // Beep RX lost only if we are not seeing data and are armed or have been armed earlier
if (!receivingRxData && (armed || ARMING_FLAG(WAS_EVER_ARMED))) { if (!receivingRxData && (armed || ARMING_FLAG(WAS_EVER_ARMED))) {
beeperMode = BEEPER_RX_LOST; beeperMode = BEEPER_RX_LOST;
} }
@ -250,12 +253,13 @@ FAST_CODE_NOINLINE void failsafeUpdateState(void)
switch (failsafeState.phase) { switch (failsafeState.phase) {
case FAILSAFE_IDLE: case FAILSAFE_IDLE:
failsafeState.failsafeSwitchWasOn = IS_RC_MODE_ACTIVE(BOXFAILSAFE);
if (armed) { if (armed) {
// Track throttle command below minimum time // Track throttle command below minimum time
if (calculateThrottleStatus() != THROTTLE_LOW) { if (calculateThrottleStatus() != THROTTLE_LOW) {
failsafeState.throttleLowPeriod = millis() + failsafeConfig()->failsafe_throttle_low_delay * MILLIS_PER_TENTH_SECOND; failsafeState.throttleLowPeriod = millis() + failsafeConfig()->failsafe_throttle_low_delay * MILLIS_PER_TENTH_SECOND;
} }
if (failsafeSwitchIsOn && (failsafeConfig()->failsafe_switch_mode == FAILSAFE_SWITCH_MODE_KILL)) { if (failsafeState.failsafeSwitchWasOn && (failsafeConfig()->failsafe_switch_mode == FAILSAFE_SWITCH_MODE_KILL)) {
// Failsafe switch is configured as KILL switch and is switched ON // Failsafe switch is configured as KILL switch and is switched ON
failsafeState.active = true; failsafeState.active = true;
failsafeState.events++; failsafeState.events++;
@ -286,8 +290,8 @@ FAST_CODE_NOINLINE void failsafeUpdateState(void)
reprocessState = true; reprocessState = true;
} }
} else { } else {
// When NOT armed, show rxLinkState of failsafe switch in GUI (failsafe mode) // When NOT armed, enable failsafe mode to show warnings in OSD
if (failsafeSwitchIsOn) { if (failsafeState.failsafeSwitchWasOn) {
ENABLE_FLIGHT_MODE(FAILSAFE_MODE); ENABLE_FLIGHT_MODE(FAILSAFE_MODE);
} else { } else {
DISABLE_FLIGHT_MODE(FAILSAFE_MODE); DISABLE_FLIGHT_MODE(FAILSAFE_MODE);
@ -308,8 +312,6 @@ FAST_CODE_NOINLINE void failsafeUpdateState(void)
// Enter Stage 2 with settings for landing mode // Enter Stage 2 with settings for landing mode
ENABLE_FLIGHT_MODE(FAILSAFE_MODE); ENABLE_FLIGHT_MODE(FAILSAFE_MODE);
failsafeState.phase = FAILSAFE_LANDING; failsafeState.phase = FAILSAFE_LANDING;
failsafeState.receivingRxDataPeriodPreset = failsafeState.rxDataRecoveryPeriod;
// allow re-arming 1 second after Rx recovery
failsafeState.landingShouldBeFinishedAt = millis() + failsafeConfig()->failsafe_off_delay * MILLIS_PER_TENTH_SECOND; failsafeState.landingShouldBeFinishedAt = millis() + failsafeConfig()->failsafe_off_delay * MILLIS_PER_TENTH_SECOND;
break; break;
@ -317,21 +319,20 @@ FAST_CODE_NOINLINE void failsafeUpdateState(void)
ENABLE_FLIGHT_MODE(FAILSAFE_MODE); ENABLE_FLIGHT_MODE(FAILSAFE_MODE);
failsafeState.phase = FAILSAFE_LANDED; failsafeState.phase = FAILSAFE_LANDED;
// go directly to FAILSAFE_LANDED // go directly to FAILSAFE_LANDED
failsafeState.receivingRxDataPeriodPreset = failsafeState.rxDataRecoveryPeriod;
// allow re-arming 1 second after Rx recovery
break; break;
#ifdef USE_GPS_RESCUE #ifdef USE_GPS_RESCUE
case FAILSAFE_PROCEDURE_GPS_RESCUE: case FAILSAFE_PROCEDURE_GPS_RESCUE:
ENABLE_FLIGHT_MODE(GPS_RESCUE_MODE); ENABLE_FLIGHT_MODE(GPS_RESCUE_MODE);
failsafeState.phase = FAILSAFE_GPS_RESCUE; failsafeState.phase = FAILSAFE_GPS_RESCUE;
failsafeState.receivingRxDataPeriodPreset = failsafeState.rxDataRecoveryPeriod;
// allow re-arming 1 second after Rx recovery
break; break;
#endif #endif
} }
if (failsafeSwitchIsOn) { if (failsafeState.failsafeSwitchWasOn) {
failsafeState.receivingRxDataPeriodPreset = 0; failsafeState.receivingRxDataPeriodPreset = 0;
// allow immediate recovery if failsafe is triggered by a switch // recover immediately if failsafe was triggered by a switch
} else {
failsafeState.receivingRxDataPeriodPreset = failsafeState.rxDataRecoveryPeriod;
// recover from true link loss failsafe 1 second after RC Link recovers
} }
} }
reprocessState = true; reprocessState = true;
@ -358,8 +359,10 @@ FAST_CODE_NOINLINE void failsafeUpdateState(void)
#ifdef USE_GPS_RESCUE #ifdef USE_GPS_RESCUE
case FAILSAFE_GPS_RESCUE: case FAILSAFE_GPS_RESCUE:
if (receivingRxData) { if (receivingRxData) {
if (areSticksActive(failsafeConfig()->failsafe_stick_threshold) || !failsafeSwitchIsOn) { if (areSticksActive(failsafeConfig()->failsafe_stick_threshold) || failsafeState.failsafeSwitchWasOn) {
// this test requires stick inputs to be received during GPS Rescue see PR #7936 for rationale // exits the rescue immediately if failsafe was initiated by switch, otherwise
// requires stick input to exit the rescue after a true Rx loss failsafe
// NB this test requires stick inputs to be received during GPS Rescue see PR #7936 for rationale
failsafeState.phase = FAILSAFE_RX_LOSS_RECOVERED; failsafeState.phase = FAILSAFE_RX_LOSS_RECOVERED;
reprocessState = true; reprocessState = true;
} }
@ -414,6 +417,10 @@ FAST_CODE_NOINLINE void failsafeUpdateState(void)
default: default:
break; break;
} }
DEBUG_SET(DEBUG_FAILSAFE, 0, failsafeState.failsafeSwitchWasOn);
DEBUG_SET(DEBUG_FAILSAFE, 3, failsafeState.phase);
} while (reprocessState); } while (reprocessState);
if (beeperMode != BEEPER_SILENCE) { if (beeperMode != BEEPER_SILENCE) {

View file

@ -90,6 +90,7 @@ typedef struct failsafeState_s {
uint32_t receivingRxDataPeriodPreset; // preset for the required period of valid rxData uint32_t receivingRxDataPeriodPreset; // preset for the required period of valid rxData
failsafePhase_e phase; failsafePhase_e phase;
failsafeRxLinkState_e rxLinkState; failsafeRxLinkState_e rxLinkState;
bool failsafeSwitchWasOn;
} failsafeState_t; } failsafeState_t;
void failsafeInit(void); void failsafeInit(void);

View file

@ -564,6 +564,7 @@ FAST_CODE_NOINLINE void rxFrameCheck(timeUs_t currentTimeUs, timeDelta_t current
} }
} }
DEBUG_SET(DEBUG_FAILSAFE, 1, rxSignalReceived);
DEBUG_SET(DEBUG_RX_SIGNAL_LOSS, 0, rxSignalReceived); DEBUG_SET(DEBUG_RX_SIGNAL_LOSS, 0, rxSignalReceived);
} }

View file

@ -1150,5 +1150,5 @@ extern "C" {
UNUSED(pitchLpf); UNUSED(pitchLpf);
return 0.0f; return 0.0f;
} }
void getRcDeflectionAbs(void) {}
} }