mirror of
https://github.com/betaflight/betaflight.git
synced 2025-07-22 07:45:29 +03:00
Only allow arming when valid Rx signals are received (#13033)
* Only allow arming when failsafe criteria are cleared * 500ms RXLOSS period with 100ms minimum
This commit is contained in:
parent
d1025bd1f5
commit
a35a5af16c
9 changed files with 23 additions and 27 deletions
|
@ -880,7 +880,7 @@ const clivalue_t valueTable[] = {
|
|||
{ "failsafe_switch_mode", VAR_UINT8 | MASTER_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_FAILSAFE_SWITCH_MODE }, PG_FAILSAFE_CONFIG, offsetof(failsafeConfig_t, failsafe_switch_mode) },
|
||||
{ "failsafe_throttle_low_delay",VAR_UINT16 | MASTER_VALUE, .config.minmaxUnsigned = { 0, 300 }, PG_FAILSAFE_CONFIG, offsetof(failsafeConfig_t, failsafe_throttle_low_delay) },
|
||||
{ "failsafe_procedure", VAR_UINT8 | MASTER_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_FAILSAFE }, PG_FAILSAFE_CONFIG, offsetof(failsafeConfig_t, failsafe_procedure) },
|
||||
{ "failsafe_recovery_delay", VAR_UINT16 | MASTER_VALUE, .config.minmaxUnsigned = { 0, 200 }, PG_FAILSAFE_CONFIG, offsetof(failsafeConfig_t, failsafe_recovery_delay) },
|
||||
{ "failsafe_recovery_delay", VAR_UINT16 | MASTER_VALUE, .config.minmaxUnsigned = { 1, 200 }, PG_FAILSAFE_CONFIG, offsetof(failsafeConfig_t, failsafe_recovery_delay) },
|
||||
{ "failsafe_stick_threshold", VAR_UINT8 | MASTER_VALUE, .config.minmaxUnsigned = { 0, 50 }, PG_FAILSAFE_CONFIG, offsetof(failsafeConfig_t, failsafe_stick_threshold) },
|
||||
|
||||
// PG_BOARDALIGNMENT_CONFIG
|
||||
|
|
|
@ -297,10 +297,10 @@ void updateArmingStatus(void)
|
|||
|
||||
if (justGotRxBack && IS_RC_MODE_ACTIVE(BOXARM)) {
|
||||
// If the RX has just started to receive a signal again and the arm switch is on, apply arming restriction
|
||||
setArmingDisabled(ARMING_DISABLED_BAD_RX_RECOVERY);
|
||||
setArmingDisabled(ARMING_DISABLED_NOT_DISARMED);
|
||||
} else if (haveRx && !IS_RC_MODE_ACTIVE(BOXARM)) {
|
||||
// If RX signal is OK and the arm switch is off, remove arming restriction
|
||||
unsetArmingDisabled(ARMING_DISABLED_BAD_RX_RECOVERY);
|
||||
unsetArmingDisabled(ARMING_DISABLED_NOT_DISARMED);
|
||||
}
|
||||
|
||||
hadRx = haveRx;
|
||||
|
|
|
@ -37,7 +37,7 @@ const char *armingDisableFlagNames[]= {
|
|||
"NOGYRO",
|
||||
"FAILSAFE",
|
||||
"RXLOSS",
|
||||
"BADRX",
|
||||
"NOT_DISARMED",
|
||||
"BOXFAILSAFE",
|
||||
"RUNAWAY",
|
||||
"CRASH",
|
||||
|
|
|
@ -43,7 +43,7 @@ typedef enum {
|
|||
ARMING_DISABLED_NO_GYRO = (1 << 0),
|
||||
ARMING_DISABLED_FAILSAFE = (1 << 1),
|
||||
ARMING_DISABLED_RX_FAILSAFE = (1 << 2),
|
||||
ARMING_DISABLED_BAD_RX_RECOVERY = (1 << 3),
|
||||
ARMING_DISABLED_NOT_DISARMED = (1 << 3),
|
||||
ARMING_DISABLED_BOXFAILSAFE = (1 << 4),
|
||||
ARMING_DISABLED_RUNAWAY_TAKEOFF = (1 << 5),
|
||||
ARMING_DISABLED_CRASH_DETECTED = (1 << 6),
|
||||
|
|
|
@ -69,7 +69,7 @@ PG_RESET_TEMPLATE(failsafeConfig_t, failsafeConfig,
|
|||
.failsafe_off_delay = 10, // 1 sec in landing phase, if enabled
|
||||
.failsafe_switch_mode = FAILSAFE_SWITCH_MODE_STAGE1, // default failsafe switch action is identical to rc link loss
|
||||
.failsafe_procedure = FAILSAFE_PROCEDURE_DROP_IT, // default full failsafe procedure is 0: auto-landing
|
||||
.failsafe_recovery_delay = 10, // 1 sec of valid rx data needed to allow recovering from failsafe procedure
|
||||
.failsafe_recovery_delay = 5, // 500ms of valid rx data needed to allow recovery from failsafe and arming block
|
||||
.failsafe_stick_threshold = 30 // 30 percent of stick deflection to exit GPS Rescue procedure
|
||||
);
|
||||
|
||||
|
@ -88,12 +88,12 @@ void failsafeReset(void)
|
|||
{
|
||||
failsafeState.rxDataFailurePeriod = failsafeConfig()->failsafe_delay * MILLIS_PER_TENTH_SECOND;
|
||||
if (failsafeState.rxDataFailurePeriod < PERIOD_RXDATA_RECOVERY){
|
||||
// avoid transients and ensure reliable arming for minimum of PERIOD_RXDATA_RECOVERY (200ms)
|
||||
// avoid transients and ensure reliable arming for minimum of PERIOD_RXDATA_RECOVERY (100ms)
|
||||
failsafeState.rxDataFailurePeriod = PERIOD_RXDATA_RECOVERY;
|
||||
}
|
||||
failsafeState.rxDataRecoveryPeriod = failsafeConfig()->failsafe_recovery_delay * MILLIS_PER_TENTH_SECOND;
|
||||
if (failsafeState.rxDataRecoveryPeriod < PERIOD_RXDATA_RECOVERY) {
|
||||
// PERIOD_RXDATA_RECOVERY (200ms) is the minimum allowed RxData recovery time
|
||||
// PERIOD_RXDATA_RECOVERY (100ms) is the minimum allowed RxData recovery time
|
||||
failsafeState.rxDataRecoveryPeriod = PERIOD_RXDATA_RECOVERY;
|
||||
}
|
||||
failsafeState.validRxDataReceivedAt = 0;
|
||||
|
@ -160,25 +160,20 @@ void failsafeOnRxResume(void)
|
|||
}
|
||||
|
||||
void failsafeOnValidDataReceived(void)
|
||||
// enters stage 2
|
||||
// runs, after prior a signal loss, immediately when packets are received or the BOXFAILSAFE switch is reverted
|
||||
// rxLinkState will go RXLINK_UP immediately if BOXFAILSAFE goes back ON since receivingRxDataPeriodPreset is set to zero in that case
|
||||
// otherwise RXLINK_UP is delayed for the recovery period (failsafe_recovery_delay, default 1s, 0-20, min 0.2s)
|
||||
// otherwise RXLINK_UP is delayed for the recovery period (failsafe_recovery_delay, default 500ms, 1-20, min 0.1s)
|
||||
{
|
||||
unsetArmingDisabled(ARMING_DISABLED_RX_FAILSAFE);
|
||||
// clear RXLOSS in OSD immediately we get a good packet, and un-set its arming block
|
||||
|
||||
failsafeState.validRxDataReceivedAt = millis();
|
||||
|
||||
if (failsafeState.validRxDataFailedAt == 0) {
|
||||
// after initialisation, we sometimes only receive valid packets,
|
||||
// then we don't know how long the signal has been valid for
|
||||
// in this setting, the time the signal first valid is also time it was last valid, so
|
||||
// after initialisation, we sometimes only receive valid packets, so validRxDataFailedAt will remain unset (0)
|
||||
// in this setting, the time the signal is first valid is also time it was last valid, so
|
||||
// initialise validRxDataFailedAt to the time of the first valid data
|
||||
failsafeState.validRxDataFailedAt = failsafeState.validRxDataReceivedAt;
|
||||
setArmingDisabled(ARMING_DISABLED_BST);
|
||||
// prevent arming until we have valid data for rxDataRecoveryPeriod after initialisation
|
||||
// using the BST flag since no other suitable name....
|
||||
// show RXLOSS in OSD to indicate reason we cannot arm
|
||||
setArmingDisabled(ARMING_DISABLED_RX_FAILSAFE);
|
||||
}
|
||||
|
||||
if (cmp32(failsafeState.validRxDataReceivedAt, failsafeState.validRxDataFailedAt) > (int32_t)failsafeState.receivingRxDataPeriodPreset) {
|
||||
|
@ -186,7 +181,8 @@ void failsafeOnValidDataReceived(void)
|
|||
// rxDataRecoveryPeriod defaults to 1.0s with minimum of PERIOD_RXDATA_RECOVERY (200ms)
|
||||
// link is not considered 'up', after it has been 'down', until that recovery period has expired
|
||||
failsafeState.rxLinkState = FAILSAFE_RXLINK_UP;
|
||||
unsetArmingDisabled(ARMING_DISABLED_BST);
|
||||
// after the rxDataRecoveryPeriod, typically 1s after receiving valid data, clear RXLOSS in OSD and permit arming
|
||||
unsetArmingDisabled(ARMING_DISABLED_RX_FAILSAFE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -195,12 +191,12 @@ void failsafeOnValidDataFailed(void)
|
|||
// after the stage 1 delay has expired, sets the rxLinkState to RXLINK_DOWN, ie not up, causing failsafeIsReceivingRxData to become false
|
||||
// if failsafe is configured to go direct to stage 2, this is emulated immediately in failsafeUpdateState()
|
||||
{
|
||||
// set RXLOSS in OSD and block arming after 100ms of signal loss
|
||||
setArmingDisabled(ARMING_DISABLED_RX_FAILSAFE);
|
||||
// set RXLOSS in OSD and block arming after 100ms of signal loss (is restored in rx.c immediately signal returns)
|
||||
|
||||
failsafeState.validRxDataFailedAt = millis();
|
||||
if ((cmp32(failsafeState.validRxDataFailedAt, failsafeState.validRxDataReceivedAt) > (int32_t)failsafeState.rxDataFailurePeriod)) {
|
||||
// sets rxLinkState = DOWN to initiate stage 2 failsafe
|
||||
// sets rxLinkState = DOWN to initiate stage 2 failsafe after expiry of the Stage 1 period
|
||||
failsafeState.rxLinkState = FAILSAFE_RXLINK_DOWN;
|
||||
// show RXLOSS and block arming
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
#define PERIOD_OF_3_SECONDS 3 * MILLIS_PER_SECOND
|
||||
#define PERIOD_OF_30_SECONDS 30 * MILLIS_PER_SECOND
|
||||
#define PERIOD_RXDATA_FAILURE 10 // millis
|
||||
#define PERIOD_RXDATA_RECOVERY 200 // millis
|
||||
#define PERIOD_RXDATA_RECOVERY 100 // millis
|
||||
|
||||
typedef struct failsafeConfig_s {
|
||||
uint16_t failsafe_throttle; // Throttle level used for landing - specify value between 1000..2000 (pwm pulse width for slightly below hover). center throttle = 1500.
|
||||
|
@ -38,7 +38,7 @@ typedef struct failsafeConfig_s {
|
|||
uint8_t failsafe_off_delay; // Time for Landing before motors stop in 0.1sec. 1 step = 0.1sec - 20sec in example (200)
|
||||
uint8_t failsafe_switch_mode; // failsafe switch action is 0: Stage 1, 1: Disarms instantly, 2: Stage 2
|
||||
uint8_t failsafe_procedure; // selected full failsafe procedure is 0: auto-landing, 1: Drop it
|
||||
uint16_t failsafe_recovery_delay; // Time (in 0.1sec) of valid rx data (min 200ms PERIOD_RXDATA_RECOVERY) to allow recovering from failsafe procedure
|
||||
uint16_t failsafe_recovery_delay; // Time (in 0.1sec) of valid rx data (min 100ms PERIOD_RXDATA_RECOVERY) to allow recovering from failsafe procedure
|
||||
uint8_t failsafe_stick_threshold; // Stick deflection percentage to exit GPS Rescue procedure
|
||||
} failsafeConfig_t;
|
||||
|
||||
|
|
|
@ -750,7 +750,7 @@ void detectAndApplySignalLossBehaviour(void)
|
|||
// --> start the timer to exit stage 2 failsafe 100ms after losing all packets or the BOXFAILSAFE switch is actioned
|
||||
} else {
|
||||
failsafeOnValidDataFailed();
|
||||
// -> start timer to enter stage2 failsafe the instant we get a good packet or the BOXFAILSAFE switch is reverted
|
||||
// -> start stage 1 timer to enter stage2 failsafe the instant we get a good packet or the BOXFAILSAFE switch is reverted
|
||||
}
|
||||
|
||||
DEBUG_SET(DEBUG_RX_SIGNAL_LOSS, 3, rcData[THROTTLE]);
|
||||
|
|
|
@ -372,7 +372,7 @@ TEST(ArmingPreventionTest, RadioTurnedOnAtAnyTimeArmed)
|
|||
// expect
|
||||
EXPECT_FALSE(isUsingSticksForArming());
|
||||
EXPECT_TRUE(isArmingDisabled());
|
||||
EXPECT_EQ(ARMING_DISABLED_BAD_RX_RECOVERY | ARMING_DISABLED_ARM_SWITCH, getArmingDisableFlags());
|
||||
EXPECT_EQ(ARMING_DISABLED_NOT_DISARMED | ARMING_DISABLED_ARM_SWITCH, getArmingDisableFlags());
|
||||
|
||||
// given
|
||||
// arm switch turned off by user
|
||||
|
@ -1083,7 +1083,7 @@ extern "C" {
|
|||
void failsafeStartMonitoring(void) {}
|
||||
void failsafeUpdateState(void) {}
|
||||
bool failsafeIsActive(void) { return false; }
|
||||
bool failsafeIsReceivingRxData(void) { return false; }
|
||||
bool failsafeIsReceivingRxData(void) { return true; }
|
||||
bool rxAreFlightChannelsValid(void) { return false; }
|
||||
void pidResetIterm(void) {}
|
||||
void updateAdjustmentStates(void) {}
|
||||
|
|
|
@ -86,7 +86,7 @@ void configureFailsafe(void)
|
|||
failsafeConfigMutable()->failsafe_throttle = 1200;
|
||||
failsafeConfigMutable()->failsafe_throttle_low_delay = 100; // 10 seconds
|
||||
failsafeConfigMutable()->failsafe_procedure = FAILSAFE_PROCEDURE_AUTO_LANDING;
|
||||
// NB we don't have failsafe_recovery_delay so use PERIOD_RXDATA_RECOVERY (200ms)
|
||||
// NB we don't have failsafe_recovery_delay so use PERIOD_RXDATA_RECOVERY (100ms)
|
||||
sysTickUptime = 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue