mirror of
https://github.com/betaflight/betaflight.git
synced 2025-07-15 04:15:44 +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:
parent
e5c53597a3
commit
4454286165
7 changed files with 30 additions and 30 deletions
|
@ -107,4 +107,5 @@ const char * const debugModeNames[DEBUG_COUNT] = {
|
||||||
"ATTITUDE",
|
"ATTITUDE",
|
||||||
"VTX_MSP",
|
"VTX_MSP",
|
||||||
"GPS_DOP",
|
"GPS_DOP",
|
||||||
|
"FAILSAFE",
|
||||||
};
|
};
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1150,5 +1150,5 @@ extern "C" {
|
||||||
UNUSED(pitchLpf);
|
UNUSED(pitchLpf);
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
}
|
}
|
||||||
|
void getRcDeflectionAbs(void) {}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue