diff --git a/src/main/fc/config.c b/src/main/fc/config.c index a16247d1a3..87304fee7c 100755 --- a/src/main/fc/config.c +++ b/src/main/fc/config.c @@ -134,6 +134,7 @@ PG_RESET_TEMPLATE(systemConfig_t, systemConfig, .debug_mode = DEBUG_MODE, .task_statistics = true, .cpu_overclock = false, + .powerOnArmingGraceTime = 5, .boardIdentifier = TARGET_BOARD_IDENTIFIER ); #else diff --git a/src/main/fc/config.h b/src/main/fc/config.h index c9ba28db88..cc40301f04 100644 --- a/src/main/fc/config.h +++ b/src/main/fc/config.h @@ -72,6 +72,7 @@ typedef struct systemConfig_s { #if defined(STM32F4) && !defined(DISABLE_OVERCLOCK) uint8_t cpu_overclock; #endif + uint8_t powerOnArmingGraceTime; // in seconds char boardIdentifier[sizeof(TARGET_BOARD_IDENTIFIER) + 1]; } systemConfig_t; #endif diff --git a/src/main/fc/fc_core.c b/src/main/fc/fc_core.c index f977661d88..05853d1a3f 100644 --- a/src/main/fc/fc_core.c +++ b/src/main/fc/fc_core.c @@ -152,6 +152,12 @@ void updateArmingStatus(void) if (ARMING_FLAG(ARMED)) { LED0_ON; } else { + // Check if the power on arming grace time has elapsed + if ((getArmingDisableFlags() & ARMING_DISABLED_BOOT_GRACE_TIME) && (millis() >= systemConfig()->powerOnArmingGraceTime * 1000)) { + // If so, unset the grace time arming disable flag + unsetArmingDisabled(ARMING_DISABLED_BOOT_GRACE_TIME); + } + if (IS_RC_MODE_ACTIVE(BOXFAILSAFE)) { setArmingDisabled(ARMING_DISABLED_BOXFAILSAFE); } else { diff --git a/src/main/fc/fc_init.c b/src/main/fc/fc_init.c index b886bbc2a4..c9c11bd32c 100644 --- a/src/main/fc/fc_init.c +++ b/src/main/fc/fc_init.c @@ -719,6 +719,8 @@ void init(void) latchActiveFeatures(); pwmEnableMotors(); + setArmingDisabled(ARMING_DISABLED_BOOT_GRACE_TIME); + #ifdef USE_OSD_SLAVE osdSlaveTasksInit(); #else diff --git a/src/main/fc/runtime_config.c b/src/main/fc/runtime_config.c index 5b69b4ef01..dbffafdc27 100644 --- a/src/main/fc/runtime_config.c +++ b/src/main/fc/runtime_config.c @@ -32,8 +32,8 @@ static uint32_t enabledSensors = 0; #if defined(OSD) || !defined(MINIMAL_CLI) const char *armingDisableFlagNames[]= { "NOGYRO", "FAILSAFE", "RX LOSS", "BOXFAILSAFE", "THROTTLE", - "ANGLE", "NO PREARM", "ARM SWITCH", "LOAD", "CALIB", "CLI", - "CMS", "OSD", "BST" + "ANGLE", "BOOT GRACE", "NO PREARM", "ARM SWITCH", "LOAD", + "CALIB", "CLI", "CMS", "OSD", "BST" }; #endif diff --git a/src/main/fc/runtime_config.h b/src/main/fc/runtime_config.h index 664fee4253..109e0442e7 100644 --- a/src/main/fc/runtime_config.h +++ b/src/main/fc/runtime_config.h @@ -35,23 +35,24 @@ extern uint8_t armingFlags; * (Beeper code can notify the most critical reason.) */ typedef enum { - ARMING_DISABLED_NO_GYRO = (1 << 0), - ARMING_DISABLED_FAILSAFE = (1 << 1), - ARMING_DISABLED_RX_FAILSAFE = (1 << 2), - ARMING_DISABLED_BOXFAILSAFE = (1 << 3), - ARMING_DISABLED_THROTTLE = (1 << 4), - ARMING_DISABLED_ANGLE = (1 << 5), - ARMING_DISABLED_NOPREARM = (1 << 6), - ARMING_DISABLED_ARM_SWITCH = (1 << 7), - ARMING_DISABLED_LOAD = (1 << 8), - ARMING_DISABLED_CALIBRATING = (1 << 9), - ARMING_DISABLED_CLI = (1 << 10), - ARMING_DISABLED_CMS_MENU = (1 << 11), - ARMING_DISABLED_OSD_MENU = (1 << 12), - ARMING_DISABLED_BST = (1 << 13) + ARMING_DISABLED_NO_GYRO = (1 << 0), + ARMING_DISABLED_FAILSAFE = (1 << 1), + ARMING_DISABLED_RX_FAILSAFE = (1 << 2), + ARMING_DISABLED_BOXFAILSAFE = (1 << 3), + ARMING_DISABLED_THROTTLE = (1 << 4), + ARMING_DISABLED_ANGLE = (1 << 5), + ARMING_DISABLED_BOOT_GRACE_TIME = (1 << 6), + ARMING_DISABLED_NOPREARM = (1 << 7), + ARMING_DISABLED_ARM_SWITCH = (1 << 8), + ARMING_DISABLED_LOAD = (1 << 9), + ARMING_DISABLED_CALIBRATING = (1 << 10), + ARMING_DISABLED_CLI = (1 << 11), + ARMING_DISABLED_CMS_MENU = (1 << 12), + ARMING_DISABLED_OSD_MENU = (1 << 13), + ARMING_DISABLED_BST = (1 << 14) } armingDisableFlags_e; -#define NUM_ARMING_DISABLE_FLAGS 14 +#define NUM_ARMING_DISABLE_FLAGS 15 #if defined(OSD) || !defined(MINIMAL_CLI) extern const char *armingDisableFlagNames[NUM_ARMING_DISABLE_FLAGS]; diff --git a/src/main/fc/settings.c b/src/main/fc/settings.c index f3431defb8..209f2fa00a 100644 --- a/src/main/fc/settings.c +++ b/src/main/fc/settings.c @@ -704,6 +704,7 @@ const clivalue_t valueTable[] = { #if defined(STM32F4) && !defined(DISABLE_OVERCLOCK) { "cpu_overclock", VAR_UINT8 | MASTER_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_OFF_ON }, PG_SYSTEM_CONFIG, offsetof(systemConfig_t, cpu_overclock) }, #endif + { "pwr_on_arm_grace", VAR_UINT8 | MASTER_VALUE, .config.minmax = { 0, 30 }, PG_SYSTEM_CONFIG, offsetof(systemConfig_t, powerOnArmingGraceTime) }, // PG_VTX_CONFIG #ifdef VTX_RTC6705 diff --git a/src/test/unit/arming_prevention_unittest.cc b/src/test/unit/arming_prevention_unittest.cc index d8edbdf065..893d70cf2e 100644 --- a/src/test/unit/arming_prevention_unittest.cc +++ b/src/test/unit/arming_prevention_unittest.cc @@ -70,7 +70,7 @@ bool gyroCalibDone = false; #include "gtest/gtest.h" -TEST(ArmingPreventionTest, CalibrationAngleThrottleArmSwitch) +TEST(ArmingPreventionTest, CalibrationPowerOnGraceAngleThrottleArmSwitch) { // given simulationTime = 0; @@ -91,13 +91,17 @@ TEST(ArmingPreventionTest, CalibrationAngleThrottleArmSwitch) rcData[THROTTLE] = 1400; rcData[4] = 1800; + // and + systemConfigMutable()->powerOnArmingGraceTime = 5; + setArmingDisabled(ARMING_DISABLED_BOOT_GRACE_TIME); + // when updateActivatedModes(); updateArmingStatus(); // expect EXPECT_TRUE(isArmingDisabled()); - EXPECT_EQ(ARMING_DISABLED_CALIBRATING | ARMING_DISABLED_ANGLE | ARMING_DISABLED_ARM_SWITCH | ARMING_DISABLED_THROTTLE, getArmingDisableFlags()); + EXPECT_EQ(ARMING_DISABLED_BOOT_GRACE_TIME | ARMING_DISABLED_CALIBRATING | ARMING_DISABLED_ANGLE | ARMING_DISABLED_ARM_SWITCH | ARMING_DISABLED_THROTTLE, getArmingDisableFlags()); // given // gyro calibration is done @@ -109,7 +113,7 @@ TEST(ArmingPreventionTest, CalibrationAngleThrottleArmSwitch) // expect EXPECT_TRUE(isArmingDisabled()); - EXPECT_EQ(ARMING_DISABLED_ANGLE | ARMING_DISABLED_ARM_SWITCH | ARMING_DISABLED_THROTTLE, getArmingDisableFlags()); + EXPECT_EQ(ARMING_DISABLED_BOOT_GRACE_TIME | ARMING_DISABLED_ANGLE | ARMING_DISABLED_ARM_SWITCH | ARMING_DISABLED_THROTTLE, getArmingDisableFlags()); // given // quad is level @@ -120,7 +124,7 @@ TEST(ArmingPreventionTest, CalibrationAngleThrottleArmSwitch) // expect EXPECT_TRUE(isArmingDisabled()); - EXPECT_EQ(ARMING_DISABLED_ARM_SWITCH | ARMING_DISABLED_THROTTLE, getArmingDisableFlags()); + EXPECT_EQ(ARMING_DISABLED_BOOT_GRACE_TIME | ARMING_DISABLED_ARM_SWITCH | ARMING_DISABLED_THROTTLE, getArmingDisableFlags()); // given rcData[THROTTLE] = 1000; @@ -128,6 +132,17 @@ TEST(ArmingPreventionTest, CalibrationAngleThrottleArmSwitch) // when updateArmingStatus(); + // expect + EXPECT_TRUE(isArmingDisabled()); + EXPECT_EQ(ARMING_DISABLED_BOOT_GRACE_TIME | ARMING_DISABLED_ARM_SWITCH, getArmingDisableFlags()); + + // given + // arming grace time has elapsed + simulationTime += systemConfig()->powerOnArmingGraceTime * 1e6; + + // when + updateArmingStatus(); + // expect EXPECT_TRUE(isArmingDisabled()); EXPECT_EQ(ARMING_DISABLED_ARM_SWITCH, getArmingDisableFlags()); @@ -220,7 +235,6 @@ TEST(ArmingPreventionTest, ArmingGuardRadioLeftOnAndArmed) EXPECT_FALSE(isArmingDisabled()); } - TEST(ArmingPreventionTest, Prearm) { // given