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

Failsafe - Add rxfail auto mode. Allow rxfail to be used for all

channels, not just aux channel.
This commit is contained in:
Dominic Clifton 2015-08-20 01:25:32 +01:00
parent 5142ff032a
commit a030d4dd9e
6 changed files with 105 additions and 61 deletions

View file

@ -133,7 +133,7 @@ The software has signal loss detection which is always enabled. Signal loss det
The `rx_min_usec` and `rx_max_usec` settings helps detect when your RX stops sending any data, enters failsafe mode or when the RX looses signal.
By default, when the signal loss is detected the FC will set pitch/roll/yaw to the value configured for `mid_rc`. The throttle will be set to the value configured for `rx_min_usec`.
By default, when the signal loss is detected the FC will set pitch/roll/yaw to the value configured for `mid_rc`. The throttle will be set to the value configured for `rx_min_usec` or `mid_rc` if using 3D feature.
Signal loss can be detected when:
@ -141,29 +141,47 @@ Signal loss can be detected when:
2. using Serial RX and receiver indicates failsafe condition.
3. using any of the first 4 stick channels do not have a value in the range specified by `rx_min_usec` and `rx_max_usec`.
#### `rxfail`
### RX loss configuration
The `rxfail` command is used to configure per-aux-channel rx-loss behaviour. Unless otherwise configured all AUX channels will HOLD the last value received. You can use the `rxfail` cli command to change this behaviour, a channel can either HOLD it's last value or be SET to a specific value.
The `rxfail` cli command is used to configure per-channel rx-loss behaviour.
You can use the `rxfail` command to change this behaviour, a channel can either be AUTOMATIC, HOLD or SET.
* AUTOMATIC - Flight channels are set to safe values (low throttle, mid position for yaw/pitch/roll), all AUX channels HOLD last value.
* HOLD - Channel holds the last value.
* SET - Channel is set to a specific configured value.
The default mode for all channels is AUTOMATIC.
The rxfail command can be used in conjunction with mode ranges to trigger various actions.
The `rxfail` command takes 3 arguments.
The `rxfail` command takes 2 or 3 arguments.
* Index of aux channel (AUX1 = 0, AUX2 = 1,...)
* A mode ('h' = HOLD, 's' = SET)
* A value to use when in SET mode. (always required, even if using HOLD mode).
* Mode ('a' = AUTOMATIC, 'h' = HOLD, 's' = SET)
* A value to use when in SET mode.
Channels are always specified in the same order, regardless of your channel mapping.
* Roll is 0
* Pitch is 1
* Yaw is 2
* Throttle is 3.
* Aux channels are 4 onwards.
Examples:
To make Throttle channel have an automatic value when RX loss is detected:
`rxfail 3 a`
To make AUX4 have a value of 2000 when RX loss is detected:
`rxfail 3 s 2000`
`rxfail 7 s 2000`
To make AUX8 hold it's value when RX loss is detected:
`rxfail 7 h 1500`
In the above example the '1500' will be ignored.
`rxfail 11 h`
WARNING: Always make sure you test the behavior is as expected after configuring rxfail settings!
#### `rx_min_usec`

View file

@ -128,7 +128,7 @@ static uint32_t activeFeaturesLatch = 0;
static uint8_t currentControlRateProfileIndex = 0;
controlRateConfig_t *currentControlRateProfile;
static const uint8_t EEPROM_CONF_VERSION = 103;
static const uint8_t EEPROM_CONF_VERSION = 104;
static void resetAccelerometerTrims(flightDynamicsTrims_t *accelerometerTrims)
{
@ -405,10 +405,9 @@ static void resetConf(void)
masterConfig.rxConfig.rx_min_usec = 885; // any of first 4 channels below this value will trigger rx loss detection
masterConfig.rxConfig.rx_max_usec = 2115; // any of first 4 channels above this value will trigger rx loss detection
for (i = 0; i < MAX_AUX_CHANNEL_COUNT; i++) {
rxFailsafeChannelConfiguration_t *channelFailsafeConfiguration = &masterConfig.rxConfig.failsafe_aux_channel_configurations[i];
channelFailsafeConfiguration->mode = RX_FAILSAFE_MODE_HOLD;
for (i = 0; i < MAX_SUPPORTED_RC_CHANNEL_COUNT; i++) {
rxFailsafeChannelConfiguration_t *channelFailsafeConfiguration = &masterConfig.rxConfig.failsafe_channel_configurations[i];
channelFailsafeConfiguration->mode = RX_FAILSAFE_MODE_AUTO;
channelFailsafeConfiguration->step = CHANNEL_VALUE_TO_RXFAIL_STEP(masterConfig.rxConfig.midrc);
}

View file

@ -169,6 +169,9 @@ static const char * const featureNames[] = {
"BLACKBOX", "CHANNEL_FORWARDING", NULL
};
// sync this with rxFailsafeChannelMode_e
static char rxFailsafeModes[RX_FAILSAFE_MODE_COUNT] = { 'a', 'h', 's'};
#ifndef CJMCU
// sync this with sensors_e
static const char * const sensorTypeNames[] = {
@ -573,23 +576,28 @@ static void cliRxFail(char *cmdline)
if (isEmpty(cmdline)) {
// print out rxConfig failsafe settings
for (channel = 0; channel < MAX_AUX_CHANNEL_COUNT; channel++) {
for (channel = 0; channel < MAX_SUPPORTED_RC_CHANNEL_COUNT; channel++) {
cliRxFail(itoa(channel, buf, 10));
}
} else {
char *ptr = cmdline;
channel = atoi(ptr++);
if ((channel < MAX_AUX_CHANNEL_COUNT)) {
if ((channel < MAX_SUPPORTED_RC_CHANNEL_COUNT)) {
rxFailsafeChannelConfiguration_t *channelFailsafeConfiguration = &masterConfig.rxConfig.failsafe_aux_channel_configurations[channel];
rxFailsafeChannelConfiguration_t *channelFailsafeConfiguration = &masterConfig.rxConfig.failsafe_channel_configurations[channel];
uint16_t value;
rxFailsafeChannelMode_e mode;
rxFailsafeChannelMode_e mode = channelFailsafeConfiguration->mode;
bool requireValue = channelFailsafeConfiguration->mode == RX_FAILSAFE_MODE_SET;
// TODO optimize to use rxFailsafeModes - less logic.
ptr = strchr(ptr, ' ');
if (ptr) {
switch (*(++ptr)) {
case 'a':
mode = RX_FAILSAFE_MODE_AUTO;
break;
case 'h':
mode = RX_FAILSAFE_MODE_HOLD;
break;
@ -601,34 +609,49 @@ static void cliRxFail(char *cmdline)
cliShowParseError();
return;
}
}
ptr = strchr(ptr, ' ');
if (ptr) {
value = atoi(++ptr);
value = CHANNEL_VALUE_TO_RXFAIL_STEP(value);
if (value > MAX_RXFAIL_RANGE_STEP) {
cliPrint("Value out of range\r\n");
return;
requireValue = mode == RX_FAILSAFE_MODE_SET;
ptr = strchr(ptr, ' ');
if (ptr) {
if (!requireValue) {
cliShowParseError();
return;
}
value = atoi(++ptr);
value = CHANNEL_VALUE_TO_RXFAIL_STEP(value);
if (value > MAX_RXFAIL_RANGE_STEP) {
cliPrint("Value out of range\r\n");
return;
}
channelFailsafeConfiguration->step = value;
}
channelFailsafeConfiguration->mode = mode;
channelFailsafeConfiguration->step = value;
}
char modeCharacter = channelFailsafeConfiguration->mode == RX_FAILSAFE_MODE_SET ? 's' : 'h';
char modeCharacter = rxFailsafeModes[channelFailsafeConfiguration->mode];
// triple use of printf below
// 1. acknowledge interpretation on command,
// 2. query current setting on single item,
// 3. recursive use for full list.
printf("rxfail %u %c %d\r\n",
channel,
modeCharacter,
RXFAIL_STEP_TO_CHANNEL_VALUE(channelFailsafeConfiguration->step)
);
if (requireValue) {
printf("rxfail %u %c %d\r\n",
channel,
modeCharacter,
RXFAIL_STEP_TO_CHANNEL_VALUE(channelFailsafeConfiguration->step)
);
} else {
printf("rxfail %u %c\r\n",
channel,
modeCharacter
);
}
} else {
printf("channel must be < %u\r\n", MAX_AUX_CHANNEL_COUNT);
cliShowArgumentRangeError("channel", 0, MAX_SUPPORTED_RC_CHANNEL_COUNT - 1);
}
}
}

View file

@ -1171,10 +1171,10 @@ static bool processOutCommand(uint8_t cmdMSP)
break;
case MSP_RXFAIL_CONFIG:
headSerialReply(3 * (rxRuntimeConfig.channelCount - NON_AUX_CHANNEL_COUNT));
for (i = NON_AUX_CHANNEL_COUNT; i < rxRuntimeConfig.channelCount; i++) {
serialize8(masterConfig.rxConfig.failsafe_aux_channel_configurations[i - NON_AUX_CHANNEL_COUNT].mode);
serialize16(RXFAIL_STEP_TO_CHANNEL_VALUE(masterConfig.rxConfig.failsafe_aux_channel_configurations[i - NON_AUX_CHANNEL_COUNT].step));
headSerialReply(3 * (rxRuntimeConfig.channelCount));
for (i = 0; i < rxRuntimeConfig.channelCount; i++) {
serialize8(masterConfig.rxConfig.failsafe_channel_configurations[i].mode);
serialize16(RXFAIL_STEP_TO_CHANNEL_VALUE(masterConfig.rxConfig.failsafe_channel_configurations[i].step));
}
break;
@ -1606,12 +1606,12 @@ static bool processInCommand(void)
case MSP_SET_RXFAIL_CONFIG:
{
uint8_t channelCount = currentPort->dataSize / 3;
if (channelCount > MAX_AUX_CHANNEL_COUNT) {
if (channelCount > MAX_SUPPORTED_RC_CHANNEL_COUNT) {
headSerialError(0);
} else {
for (i = NON_AUX_CHANNEL_COUNT; i < channelCount; i++) {
masterConfig.rxConfig.failsafe_aux_channel_configurations[i - NON_AUX_CHANNEL_COUNT].mode = read8();
masterConfig.rxConfig.failsafe_aux_channel_configurations[i - NON_AUX_CHANNEL_COUNT].step = CHANNEL_VALUE_TO_RXFAIL_STEP(read16());
for (i = 0; i < channelCount; i++) {
masterConfig.rxConfig.failsafe_channel_configurations[i].mode = read8();
masterConfig.rxConfig.failsafe_channel_configurations[i].step = CHANNEL_VALUE_TO_RXFAIL_STEP(read16());
}
}
}

View file

@ -326,22 +326,23 @@ static uint16_t calculateNonDataDrivenChannel(uint8_t chan, uint16_t sample)
static uint16_t getRxfailValue(uint8_t channel)
{
switch (channel) {
case ROLL:
case PITCH:
case YAW:
return rxConfig->midrc;
case THROTTLE:
if (feature(FEATURE_3D))
return rxConfig->midrc;
else
return rxConfig->rx_min_usec;
}
rxFailsafeChannelConfiguration_t *channelFailsafeConfiguration = &rxConfig->failsafe_aux_channel_configurations[channel - NON_AUX_CHANNEL_COUNT];
rxFailsafeChannelConfiguration_t *channelFailsafeConfiguration = &rxConfig->failsafe_channel_configurations[channel];
switch(channelFailsafeConfiguration->mode) {
default:
case RX_FAILSAFE_MODE_AUTO:
switch (channel) {
case ROLL:
case PITCH:
case YAW:
return rxConfig->midrc;
case THROTTLE:
if (feature(FEATURE_3D))
return rxConfig->midrc;
else
return rxConfig->rx_min_usec;
}
// fall though to HOLD if there's nothing specific to do.
case RX_FAILSAFE_MODE_HOLD:
return rcData[channel];

View file

@ -82,10 +82,13 @@ extern int16_t rcData[MAX_SUPPORTED_RC_CHANNEL_COUNT]; // interval [1000;2
#define RSSI_SCALE_DEFAULT 30
typedef enum {
RX_FAILSAFE_MODE_HOLD = 0,
RX_FAILSAFE_MODE_SET
RX_FAILSAFE_MODE_AUTO = 0,
RX_FAILSAFE_MODE_HOLD,
RX_FAILSAFE_MODE_SET,
} rxFailsafeChannelMode_e;
#define RX_FAILSAFE_MODE_COUNT 3
typedef struct rxFailsafeChannelConfiguration_s {
uint8_t mode; // See rxFailsafeChannelMode_e
uint8_t step;
@ -109,7 +112,7 @@ typedef struct rxConfig_s {
uint16_t rx_min_usec;
uint16_t rx_max_usec;
rxFailsafeChannelConfiguration_t failsafe_aux_channel_configurations[MAX_AUX_CHANNEL_COUNT];
rxFailsafeChannelConfiguration_t failsafe_channel_configurations[MAX_SUPPORTED_RC_CHANNEL_COUNT];
rxChannelRangeConfiguration_t channelRanges[NON_AUX_CHANNEL_COUNT];
} rxConfig_t;