mirror of
https://github.com/iNavFlight/inav.git
synced 2025-07-24 00:35:34 +03:00
Add support for emergency arming
Enabling and disabling the arming switch 10 times during a 10s window will override checks for level, navigation unsafe, compass not calibrated and some hardware failures (it will only enforce gyro and acc to be working). FLASH +224, RAM +24 Fixes #4489 and #4515
This commit is contained in:
parent
5192f3619c
commit
ca3f21e7a1
3 changed files with 92 additions and 2 deletions
|
@ -97,6 +97,21 @@ enum {
|
||||||
|
|
||||||
#define GYRO_WATCHDOG_DELAY 100 // Watchdog for boards without interrupt for gyro
|
#define GYRO_WATCHDOG_DELAY 100 // Watchdog for boards without interrupt for gyro
|
||||||
|
|
||||||
|
#define EMERGENCY_ARMING_TIME_WINDOW_MS 10000
|
||||||
|
#define EMERGENCY_ARMING_COUNTER_STEP_MS 100
|
||||||
|
|
||||||
|
typedef struct emergencyArmingState_s {
|
||||||
|
bool armingSwitchWasOn;
|
||||||
|
// Each entry in the queue is an offset from start,
|
||||||
|
// in 0.1s increments. This lets us represent up to 25.5s
|
||||||
|
// so it will work fine as long as the window for the triggers
|
||||||
|
// is smaller (see EMERGENCY_ARMING_TIME_WINDOW_MS). First
|
||||||
|
// entry of the queue is implicit.
|
||||||
|
timeMs_t start;
|
||||||
|
uint8_t queue[9];
|
||||||
|
uint8_t queueCount;
|
||||||
|
} emergencyArmingState_t;
|
||||||
|
|
||||||
timeDelta_t cycleTime = 0; // this is the number in micro second to achieve a full loop, it can differ a little and is taken into account in the PID loop
|
timeDelta_t cycleTime = 0; // this is the number in micro second to achieve a full loop, it can differ a little and is taken into account in the PID loop
|
||||||
static timeUs_t flightTime = 0;
|
static timeUs_t flightTime = 0;
|
||||||
|
|
||||||
|
@ -108,6 +123,7 @@ uint8_t motorControlEnable = false;
|
||||||
|
|
||||||
static bool isRXDataNew;
|
static bool isRXDataNew;
|
||||||
static disarmReason_t lastDisarmReason = DISARM_NONE;
|
static disarmReason_t lastDisarmReason = DISARM_NONE;
|
||||||
|
static emergencyArmingState_t emergencyArming;
|
||||||
|
|
||||||
bool isCalibrating(void)
|
bool isCalibrating(void)
|
||||||
{
|
{
|
||||||
|
@ -290,6 +306,41 @@ static void updateArmingStatus(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool emergencyArmingIsTriggered(void)
|
||||||
|
{
|
||||||
|
int threshold = (EMERGENCY_ARMING_TIME_WINDOW_MS / EMERGENCY_ARMING_COUNTER_STEP_MS);
|
||||||
|
return emergencyArming.queueCount == ARRAYLEN(emergencyArming.queue) + 1 &&
|
||||||
|
emergencyArming.queue[ARRAYLEN(emergencyArming.queue) - 1] < threshold &&
|
||||||
|
emergencyArming.start >= millis() - EMERGENCY_ARMING_TIME_WINDOW_MS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool emergencyArmingCanOverrideArmingPrevention(void)
|
||||||
|
{
|
||||||
|
uint32_t armingPrevention = armingFlags & ARMING_DISABLED_ALL_FLAGS;
|
||||||
|
|
||||||
|
// This flag is to require a switch flip if it's turned on while arming
|
||||||
|
// is disabled (otherwise craft could arm suddenly if the arming prevention
|
||||||
|
// reasons stop happening - e.g. THR high)
|
||||||
|
armingPrevention &= ~ARMING_DISABLED_ARM_SWITCH;
|
||||||
|
|
||||||
|
// Always override not level, unsafe navigation and compass not calibrated
|
||||||
|
armingPrevention &= ~ARMING_DISABLED_NOT_LEVEL;
|
||||||
|
armingPrevention &= ~ARMING_DISABLED_NAVIGATION_UNSAFE;
|
||||||
|
armingPrevention &= ~ARMING_DISABLED_COMPASS_NOT_CALIBRATED;
|
||||||
|
|
||||||
|
// In the event of a hardware failure, check wether the essential
|
||||||
|
// hardware is working. In that case, go ahead
|
||||||
|
if (getHwGyroStatus() == HW_SENSOR_OK && getHwAccelerometerStatus() == HW_SENSOR_OK) {
|
||||||
|
armingPrevention &= ~ARMING_DISABLED_HARDWARE_FAILURE;
|
||||||
|
}
|
||||||
|
return armingPrevention == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool emergencyArmingIsEnabled(void)
|
||||||
|
{
|
||||||
|
return emergencyArmingIsTriggered() && emergencyArmingCanOverrideArmingPrevention();
|
||||||
|
}
|
||||||
|
|
||||||
void annexCode(void)
|
void annexCode(void)
|
||||||
{
|
{
|
||||||
int32_t throttleValue;
|
int32_t throttleValue;
|
||||||
|
@ -355,6 +406,39 @@ disarmReason_t getDisarmReason(void)
|
||||||
return lastDisarmReason;
|
return lastDisarmReason;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void emergencyArmingUpdate(bool armingSwitchIsOn)
|
||||||
|
{
|
||||||
|
if (armingSwitchIsOn == emergencyArming.armingSwitchWasOn) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (armingSwitchIsOn) {
|
||||||
|
timeMs_t now = millis();
|
||||||
|
if (emergencyArming.queueCount == 0) {
|
||||||
|
emergencyArming.queueCount = 1;
|
||||||
|
emergencyArming.start = now;
|
||||||
|
} else {
|
||||||
|
while (emergencyArming.start < now - EMERGENCY_ARMING_TIME_WINDOW_MS || emergencyArmingIsTriggered()) {
|
||||||
|
if (emergencyArming.queueCount > 1) {
|
||||||
|
uint8_t delta = emergencyArming.queue[0];
|
||||||
|
emergencyArming.start += delta * EMERGENCY_ARMING_COUNTER_STEP_MS;
|
||||||
|
for (int ii = 0; ii < emergencyArming.queueCount - 2; ii++) {
|
||||||
|
emergencyArming.queue[ii] = emergencyArming.queue[ii + 1] - delta;
|
||||||
|
}
|
||||||
|
emergencyArming.queueCount--;
|
||||||
|
} else {
|
||||||
|
emergencyArming.start = now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uint8_t delta = (now - emergencyArming.start) / EMERGENCY_ARMING_COUNTER_STEP_MS;
|
||||||
|
if (delta > 0) {
|
||||||
|
emergencyArming.queue[emergencyArming.queueCount - 1] = delta;
|
||||||
|
emergencyArming.queueCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
emergencyArming.armingSwitchWasOn = !emergencyArming.armingSwitchWasOn;
|
||||||
|
}
|
||||||
|
|
||||||
#define TELEMETRY_FUNCTION_MASK (FUNCTION_TELEMETRY_FRSKY | FUNCTION_TELEMETRY_HOTT | FUNCTION_TELEMETRY_SMARTPORT | FUNCTION_TELEMETRY_LTM | FUNCTION_TELEMETRY_MAVLINK | FUNCTION_TELEMETRY_IBUS)
|
#define TELEMETRY_FUNCTION_MASK (FUNCTION_TELEMETRY_FRSKY | FUNCTION_TELEMETRY_HOTT | FUNCTION_TELEMETRY_SMARTPORT | FUNCTION_TELEMETRY_LTM | FUNCTION_TELEMETRY_MAVLINK | FUNCTION_TELEMETRY_IBUS)
|
||||||
|
|
||||||
void releaseSharedTelemetryPorts(void) {
|
void releaseSharedTelemetryPorts(void) {
|
||||||
|
@ -369,7 +453,7 @@ void tryArm(void)
|
||||||
{
|
{
|
||||||
updateArmingStatus();
|
updateArmingStatus();
|
||||||
|
|
||||||
if (!isArmingDisabled()) {
|
if (!isArmingDisabled() || emergencyArmingIsEnabled()) {
|
||||||
if (ARMING_FLAG(ARMED)) {
|
if (ARMING_FLAG(ARMED)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
#include "common/time.h"
|
#include "common/time.h"
|
||||||
|
|
||||||
typedef enum disarmReason_e {
|
typedef enum disarmReason_e {
|
||||||
|
@ -38,6 +40,8 @@ void disarm(disarmReason_t disarmReason);
|
||||||
void tryArm(void);
|
void tryArm(void);
|
||||||
disarmReason_t getDisarmReason(void);
|
disarmReason_t getDisarmReason(void);
|
||||||
|
|
||||||
|
void emergencyArmingUpdate(bool armingSwitchIsOn);
|
||||||
|
|
||||||
bool isCalibrating(void);
|
bool isCalibrating(void);
|
||||||
float getFlightTime(void);
|
float getFlightTime(void);
|
||||||
|
|
||||||
|
|
|
@ -179,7 +179,9 @@ void processRcStickPositions(throttleStatus_e throttleStatus)
|
||||||
rcSticks = stTmp;
|
rcSticks = stTmp;
|
||||||
|
|
||||||
// perform actions
|
// perform actions
|
||||||
if (IS_RC_MODE_ACTIVE(BOXARM)) {
|
bool armingSwitchIsActive = IS_RC_MODE_ACTIVE(BOXARM);
|
||||||
|
emergencyArmingUpdate(armingSwitchIsActive);
|
||||||
|
if (armingSwitchIsActive) {
|
||||||
rcDisarmTimeMs = currentTimeMs;
|
rcDisarmTimeMs = currentTimeMs;
|
||||||
tryArm();
|
tryArm();
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue