1
0
Fork 0
mirror of https://github.com/iNavFlight/inav.git synced 2025-07-20 23:05:17 +03:00

Merge remote-tracking branch 'origin/development' into dzikuvx-mr-cruise-experiments

This commit is contained in:
Pawel Spychalski (DzikuVx) 2018-06-13 11:56:51 +02:00
commit 8132e59b7e
44 changed files with 458 additions and 361 deletions

2
.gitignore vendored
View file

@ -20,6 +20,4 @@ docs/Manual.pdf
README.pdf
# build generated files
/src/main/fc/settings_generated.h
/src/main/fc/settings_generated.c
/settings.json

View file

@ -274,9 +274,10 @@ TARGET_BIN = $(BIN_DIR)/$(FORKNAME)_$(FC_VER)_$(TARGET)_$(BUILD_SUFFIX).bin
TARGET_HEX = $(BIN_DIR)/$(FORKNAME)_$(FC_VER)_$(TARGET)_$(BUILD_SUFFIX).hex
endif
TARGET_OBJ_DIR = $(OBJECT_DIR)/$(TARGET)
TARGET_ELF = $(OBJECT_DIR)/$(FORKNAME)_$(TARGET).elf
TARGET_OBJS = $(addsuffix .o,$(addprefix $(OBJECT_DIR)/$(TARGET)/,$(basename $(TARGET_SRC))))
TARGET_DEPS = $(addsuffix .d,$(addprefix $(OBJECT_DIR)/$(TARGET)/,$(basename $(TARGET_SRC))))
TARGET_OBJS = $(addsuffix .o,$(addprefix $(TARGET_OBJ_DIR)/,$(basename $(TARGET_SRC))))
TARGET_DEPS = $(addsuffix .d,$(addprefix $(TARGET_OBJ_DIR)/,$(basename $(TARGET_SRC))))
TARGET_MAP = $(OBJECT_DIR)/$(FORKNAME)_$(TARGET).map
@ -285,20 +286,23 @@ CLEAN_ARTIFACTS += $(TARGET_HEX)
CLEAN_ARTIFACTS += $(TARGET_ELF) $(TARGET_OBJS) $(TARGET_MAP)
# Make sure build date and revision is updated on every incremental build
$(OBJECT_DIR)/$(TARGET)/build/version.o : $(TARGET_SRC)
$(TARGET_OBJ_DIR)/build/version.o : $(TARGET_SRC)
# Settings generator
.PHONY: .FORCE settings clean-settings
UTILS_DIR = $(ROOT)/src/utils
SETTINGS_GENERATOR = $(UTILS_DIR)/settings.rb
BUILD_STAMP = $(UTILS_DIR)/build_stamp.rb
STAMP = $(BIN_DIR)/build.stamp
UTILS_DIR = $(ROOT)/src/utils
SETTINGS_GENERATOR = $(UTILS_DIR)/settings.rb
BUILD_STAMP = $(UTILS_DIR)/build_stamp.rb
STAMP = $(TARGET_OBJ_DIR)/build.stamp
GENERATED_SETTINGS = $(SRC_DIR)/fc/settings_generated.h $(SRC_DIR)/fc/settings_generated.c
SETTINGS_FILE = $(SRC_DIR)/fc/settings.yaml
GENERATED_FILES = $(GENERATED_SETTINGS)
GENERATED_SETTINGS = $(TARGET_OBJ_DIR)/settings_generated.h $(TARGET_OBJ_DIR)/settings_generated.c
SETTINGS_FILE = $(SRC_DIR)/fc/settings.yaml
GENERATED_FILES = $(GENERATED_SETTINGS)
$(GENERATED_SETTINGS): $(SETTINGS_GENERATOR) $(SETTINGS_FILE) $(STAMP)
# Make sure the generated files are in the include path
CFLAGS += -I$(TARGET_OBJ_DIR)
$(STAMP): .FORCE
$(V1) CFLAGS="$(CFLAGS)" TARGET=$(TARGET) ruby $(BUILD_STAMP) $(SETTINGS_FILE) $(STAMP)
@ -306,7 +310,7 @@ $(STAMP): .FORCE
# See https://www.gnu.org/software/make/manual/make.html#Pattern-Examples
%generated.h %generated.c:
$(V1) echo "settings.yaml -> settings_generated.h, settings_generated.c" "$(STDOUT)"
$(V1) CFLAGS="$(CFLAGS)" TARGET=$(TARGET) ruby $(SETTINGS_GENERATOR) . $(SETTINGS_FILE)
$(V1) CFLAGS="$(CFLAGS)" TARGET=$(TARGET) ruby $(SETTINGS_GENERATOR) . $(SETTINGS_FILE) -o $(TARGET_OBJ_DIR)
settings-json:
$(V0) CFLAGS="$(CFLAGS)" TARGET=$(TARGET) ruby $(SETTINGS_GENERATOR) . $(SETTINGS_FILE) --json settings.json
@ -329,18 +333,18 @@ $(TARGET_ELF): $(TARGET_OBJS)
$(V0) $(SIZE) $(TARGET_ELF)
# Compile
$(OBJECT_DIR)/$(TARGET)/%.o: %.c
$(TARGET_OBJ_DIR)/%.o: %.c
$(V1) mkdir -p $(dir $@)
$(V1) echo %% $(notdir $<) "$(STDOUT)"
$(V1) $(CROSS_CC) -c -o $@ $(CFLAGS) $<
# Assemble
$(OBJECT_DIR)/$(TARGET)/%.o: %.s
$(TARGET_OBJ_DIR)/%.o: %.s
$(V1) mkdir -p $(dir $@)
$(V1) echo %% $(notdir $<) "$(STDOUT)"
$(V1) $(CROSS_CC) -c -o $@ $(ASFLAGS) $<
$(OBJECT_DIR)/$(TARGET)/%.o: %.S
$(TARGET_OBJ_DIR)/%.o: %.S
$(V1) mkdir -p $(dir $@)
$(V1) echo %% $(notdir $<) "$(STDOUT)"
$(V1) $(CROSS_CC) -c -o $@ $(ASFLAGS) $<
@ -377,8 +381,7 @@ $(VALID_TARGETS):
clean:
$(V0) echo "Cleaning $(TARGET)"
$(V0) rm -f $(CLEAN_ARTIFACTS)
$(V0) rm -rf $(OBJECT_DIR)/$(TARGET)
$(V0) rm -f $(GENERATED_SETTINGS)
$(V0) rm -rf $(TARGET_OBJ_DIR)
$(V0) echo "Cleaning $(TARGET) succeeded."
## clean_test : clean up all temporary / machine-generated files (tests)

View file

@ -8,8 +8,7 @@ Current support of rangefinders in INAV is very limited. They are used only to:
* landing detection for multirotors
* automated landing support for fixed wings
INAV currently does not support _terrain following_ or _rangefinder supported altitude hold_ flight modes.
* _Experimental_ terrain following (Surface) flight mode activated with _SURFACE_ and _ALTHOLD_ flight mode
## Hardware
@ -18,15 +17,16 @@ Following rangefinders are supported:
* HC-SR04 - ***DO NOT USE*** HC-SR04 while most popular is not suited to use in noise reach environments (like multirotors). It is proven that this sonar rangefinder start to report random values already at 1.5m above solid concrete surface. Reported altitude is valid up to only 75cm above concrete. ***DO NOT USE***
* US-100 in trigger-echo mode - Can be used as direct replacement of _HC-SR04_ when `rangefinder_hardware` is set to _HCSR04_. Useful up to 2m over concrete and correctly reporting _out of range_ when out of range
* SRF10 - experimental
* HCSR04I2C - is a simple [DIY rangefinder interface](https://github.com/iNavFlight/INAV-Rangefinder-I2C-interface). Can be used to connect when flight controller has no Trigger-Echo ports.
* INAV_I2C - is a simple [DIY rangefinder interface with Arduino Pro Mini 3.3V](https://github.com/iNavFlight/inav-rangefinder). Can be used to connect when flight controller has no Trigger-Echo ports.
* VL53L0X - simple laser rangefinder usable up to 75cm
* UIB - experimental
* MSP - experimental
## Connections
Target dependent in case of Trigger/Echo solutions like HC-SR04 and US-100.
I2C solutions like VL53L0X or HCSR04I2C can be connected to I2C port and used as any other I2C device.
Target dependent in case of Trigger/Echo solutions like `HC-SR04` and `US-100`.
I2C solutions like `VL53L0X` or `INAV_I2C` can be connected to I2C port and used as any other I2C device.
#### Constraints
Target dependent in case of Trigger/Echo solutions like HC-SR04 and US-100. No constrains for I2C like VL53L0X or HCSR04I2C.
Target dependent in case of Trigger/Echo solutions like `HC-SR04` and `US-100`. No constrains for I2C like `VL53L0X` or `INAV_I2C`.

View file

@ -59,6 +59,7 @@ typedef enum {
DEBUG_ALWAYS,
DEBUG_STAGE2,
DEBUG_WIND_ESTIMATOR,
DEBUG_SAG_COMP_VOLTAGE,
DEBUG_COUNT
} debugType_e;
@ -75,4 +76,4 @@ void debugTracePrintBufferHex(bool synchronous, const void *buffer, size_t size)
#define DEBUG_TRACE_SYNC(fmt, ...)
#define DEBUG_TRACE_BUFFER_HEX(buf, size)
#define DEBUG_TRACE_BUFFER_HEX_SYNC(buf, size)
#endif
#endif

View file

@ -775,8 +775,13 @@ long cmsMenuExit(displayPort_t *pDisplay, const void *ptr)
void cmsYieldDisplay(displayPort_t *pPort, timeMs_t duration)
{
// Check if we're already yielding, in that case just extend
// the yield time without releasing the display again, otherwise
// the yield/grab become unbalanced.
if (cmsYieldUntil == 0) {
displayRelease(pPort);
}
cmsYieldUntil = millis() + duration;
displayRelease(pPort);
}
// Stick/key detection and key codes
@ -1209,6 +1214,8 @@ void cmsUpdate(uint32_t currentTimeUs)
// Only scan keys and draw if we're not yielding
if (cmsYieldUntil == 0) {
// XXX: Note that one call to cmsScanKeys() might generate multiple keypresses
// when repeating, that's why cmsYieldDisplay() has to check for multiple calls.
rcDelayMs = cmsScanKeys(currentTimeMs, lastCalledMs, rcDelayMs);
// Check again, the keypress might have produced a yield
if (cmsYieldUntil == 0) {

View file

@ -148,6 +148,7 @@ static const OSD_Entry menuOsdElemsEntries[] =
OSD_ELEMENT_ENTRY("RSSI", OSD_RSSI_VALUE),
OSD_ELEMENT_ENTRY("MAIN BATTERY", OSD_MAIN_BATT_VOLTAGE),
OSD_ELEMENT_ENTRY("MAIN BATT SC", OSD_SAG_COMPENSATED_MAIN_BATT_VOLTAGE),
OSD_ELEMENT_ENTRY("CELL VOLTAGE", OSD_MAIN_BATT_CELL_VOLTAGE),
OSD_ELEMENT_ENTRY("CROSSHAIRS", OSD_CROSSHAIRS),
OSD_ELEMENT_ENTRY("HORIZON", OSD_ARTIFICIAL_HORIZON),

View file

@ -141,7 +141,7 @@ int16_t getAxisRcCommand(int16_t rawData, int16_t rate, int16_t deadband)
{
int16_t stickDeflection;
stickDeflection = constrain(rawData - rxConfig()->midrc, -500, 500);
stickDeflection = constrain(rawData - PWM_RANGE_MIDDLE, -500, 500);
stickDeflection = applyDeadband(stickDeflection, deadband);
return rcLookup(stickDeflection, rate);
@ -401,14 +401,6 @@ void tryArm(void)
#endif
statsOnArm();
#ifdef USE_RANGEFINDER
/*
* Since each arm can happen over different surface type, we have to reset
* previously computed max. dynamic range threshold
*/
rangefinderResetDynamicThreshold();
#endif
return;
}
@ -488,7 +480,7 @@ void processRx(timeUs_t currentTimeUs)
updateActivatedModes();
if (!cliMode) {
if ((!cliMode) && (!FLIGHT_MODE(FAILSAFE_MODE))) {
updateAdjustmentStates();
processRcAdjustments(CONST_CAST(controlRateConfig_t*, currentControlRateProfile));
}

View file

@ -647,7 +647,7 @@ static bool mspFcProcessOutCommand(uint16_t cmdMSP, sbuf_t *dst, mspPostProcessF
break;
case MSP_MISC:
sbufWriteU16(dst, rxConfig()->midrc);
sbufWriteU16(dst, PWM_RANGE_MIDDLE);
sbufWriteU16(dst, motorConfig()->minthrottle);
sbufWriteU16(dst, motorConfig()->maxthrottle);
@ -677,7 +677,7 @@ static bool mspFcProcessOutCommand(uint16_t cmdMSP, sbuf_t *dst, mspPostProcessF
break;
case MSP2_INAV_MISC:
sbufWriteU16(dst, rxConfig()->midrc);
sbufWriteU16(dst, PWM_RANGE_MIDDLE);
sbufWriteU16(dst, motorConfig()->minthrottle);
sbufWriteU16(dst, motorConfig()->maxthrottle);
@ -829,7 +829,7 @@ static bool mspFcProcessOutCommand(uint16_t cmdMSP, sbuf_t *dst, mspPostProcessF
case MSP_RX_CONFIG:
sbufWriteU8(dst, rxConfig()->serialrx_provider);
sbufWriteU16(dst, rxConfig()->maxcheck);
sbufWriteU16(dst, rxConfig()->midrc);
sbufWriteU16(dst, PWM_RANGE_MIDDLE);
sbufWriteU16(dst, rxConfig()->mincheck);
sbufWriteU8(dst, rxConfig()->spektrum_sat_bind);
sbufWriteU16(dst, rxConfig()->rx_min_usec);
@ -1595,7 +1595,7 @@ static mspResult_e mspFcProcessInCommand(uint16_t cmdMSP, sbuf_t *src)
case MSP_SET_MISC:
if (dataSize >= 22) {
rxConfigMutable()->midrc = constrain(sbufReadU16(src), MIDRC_MIN, MIDRC_MAX);
sbufReadU16(src); // midrc
motorConfigMutable()->minthrottle = constrain(sbufReadU16(src), PWM_RANGE_MIN, PWM_RANGE_MAX);
motorConfigMutable()->maxthrottle = constrain(sbufReadU16(src), PWM_RANGE_MIN, PWM_RANGE_MAX);
@ -1635,7 +1635,7 @@ static mspResult_e mspFcProcessInCommand(uint16_t cmdMSP, sbuf_t *src)
case MSP2_INAV_SET_MISC:
if (dataSize == 39) {
rxConfigMutable()->midrc = constrain(sbufReadU16(src), MIDRC_MIN, MIDRC_MAX);
sbufReadU16(src); // midrc
motorConfigMutable()->minthrottle = constrain(sbufReadU16(src), PWM_RANGE_MIN, PWM_RANGE_MAX);
motorConfigMutable()->maxthrottle = constrain(sbufReadU16(src), PWM_RANGE_MIN, PWM_RANGE_MAX);
@ -2264,7 +2264,7 @@ static mspResult_e mspFcProcessInCommand(uint16_t cmdMSP, sbuf_t *src)
if (dataSize >= 24) {
rxConfigMutable()->serialrx_provider = sbufReadU8(src);
rxConfigMutable()->maxcheck = sbufReadU16(src);
rxConfigMutable()->midrc = sbufReadU16(src);
sbufReadU16(src); // midrc
rxConfigMutable()->mincheck = sbufReadU16(src);
rxConfigMutable()->spektrum_sat_bind = sbufReadU8(src);
rxConfigMutable()->rx_min_usec = sbufReadU16(src);

View file

@ -58,6 +58,7 @@ static const box_t boxes[CHECKBOX_ITEM_COUNT + 1] = {
{ BOXBEEPERON, "BEEPER", 13 },
{ BOXLEDLOW, "LEDLOW", 15 },
{ BOXLIGHTS, "LIGHTS", 16 },
{ BOXOSD, "OSD SW", 19 },
{ BOXTELEMETRY, "TELEMETRY", 20 },
{ BOXAUTOTUNE, "AUTO TUNE", 21 },
{ BOXBLACKBOX, "BLACKBOX", 26 },
@ -228,6 +229,8 @@ void initActiveBoxIds(void)
}
#endif
activeBoxIds[activeBoxIdCount++] = BOXOSD;
#ifdef USE_TELEMETRY
if (feature(FEATURE_TELEMETRY) && telemetryConfig()->telemetry_switch)
activeBoxIds[activeBoxIdCount++] = BOXTELEMETRY;
@ -282,6 +285,7 @@ void packBoxModeFlags(boxBitmask_t * mspBoxModeFlags)
CHECK_ACTIVE_BOX(IS_ENABLED(IS_RC_MODE_ACTIVE(BOXBEEPERON)), BOXBEEPERON);
CHECK_ACTIVE_BOX(IS_ENABLED(IS_RC_MODE_ACTIVE(BOXLEDLOW)), BOXLEDLOW);
CHECK_ACTIVE_BOX(IS_ENABLED(IS_RC_MODE_ACTIVE(BOXLIGHTS)), BOXLIGHTS);
CHECK_ACTIVE_BOX(IS_ENABLED(IS_RC_MODE_ACTIVE(BOXOSD)), BOXOSD);
CHECK_ACTIVE_BOX(IS_ENABLED(IS_RC_MODE_ACTIVE(BOXTELEMETRY)), BOXTELEMETRY);
CHECK_ACTIVE_BOX(IS_ENABLED(ARMING_FLAG(ARMED)), BOXARM);
CHECK_ACTIVE_BOX(IS_ENABLED(IS_RC_MODE_ACTIVE(BOXBLACKBOX)), BOXBLACKBOX);

View file

@ -106,8 +106,10 @@ void taskUpdateBattery(timeUs_t currentTimeUs)
#ifdef USE_ADC
if (feature(FEATURE_VBAT))
batteryUpdate(BatMonitoringTimeSinceLastServiced);
if (feature(FEATURE_VBAT) && feature(FEATURE_CURRENT_METER))
if (feature(FEATURE_VBAT) && feature(FEATURE_CURRENT_METER)) {
powerMeterUpdate(BatMonitoringTimeSinceLastServiced);
sagCompensatedVBatUpdate(currentTimeUs);
}
#endif
batMonitoringLastServiced = currentTimeUs;
}

View file

@ -475,9 +475,9 @@ void processRcAdjustments(controlRateConfig_t *controlRateConfig)
if (adjustmentState->config->mode == ADJUSTMENT_MODE_STEP) {
int delta;
if (rcData[channelIndex] > rxConfig()->midrc + 200) {
if (rcData[channelIndex] > PWM_RANGE_MIDDLE + 200) {
delta = adjustmentState->config->data.stepConfig.step;
} else if (rcData[channelIndex] < rxConfig()->midrc - 200) {
} else if (rcData[channelIndex] < PWM_RANGE_MIDDLE - 200) {
delta = 0 - adjustmentState->config->data.stepConfig.step;
} else {
// returning the switch to the middle immediately resets the ready state

View file

@ -101,7 +101,7 @@ bool areSticksDeflectedMoreThanPosHoldDeadband(void)
throttleStatus_e calculateThrottleStatus(void)
{
const uint16_t deadband3d_throttle = rcControlsConfig()->deadband3d_throttle;
if (feature(FEATURE_3D) && (rcData[THROTTLE] > (rxConfig()->midrc - deadband3d_throttle) && rcData[THROTTLE] < (rxConfig()->midrc + deadband3d_throttle)))
if (feature(FEATURE_3D) && (rcData[THROTTLE] > (PWM_RANGE_MIDDLE - deadband3d_throttle) && rcData[THROTTLE] < (PWM_RANGE_MIDDLE + deadband3d_throttle)))
return THROTTLE_LOW;
else if (!feature(FEATURE_3D) && (rcData[THROTTLE] < rxConfig()->mincheck))
return THROTTLE_LOW;
@ -111,8 +111,8 @@ throttleStatus_e calculateThrottleStatus(void)
rollPitchStatus_e calculateRollPitchCenterStatus(void)
{
if (((rcData[PITCH] < (rxConfig()->midrc + AIRMODE_DEADBAND)) && (rcData[PITCH] > (rxConfig()->midrc -AIRMODE_DEADBAND)))
&& ((rcData[ROLL] < (rxConfig()->midrc + AIRMODE_DEADBAND)) && (rcData[ROLL] > (rxConfig()->midrc -AIRMODE_DEADBAND))))
if (((rcData[PITCH] < (PWM_RANGE_MIDDLE + AIRMODE_DEADBAND)) && (rcData[PITCH] > (PWM_RANGE_MIDDLE -AIRMODE_DEADBAND)))
&& ((rcData[ROLL] < (PWM_RANGE_MIDDLE + AIRMODE_DEADBAND)) && (rcData[ROLL] > (PWM_RANGE_MIDDLE -AIRMODE_DEADBAND))))
return CENTERED;
return NOT_CENTERED;
@ -328,7 +328,7 @@ void processRcStickPositions(throttleStatus_e throttleStatus)
}
}
int32_t getRcStickDeflection(int32_t axis, uint16_t midrc) {
return MIN(ABS(rcData[axis] - midrc), 500);
int32_t getRcStickDeflection(int32_t axis) {
return MIN(ABS(rcData[axis] - PWM_RANGE_MIDDLE), 500);
}

View file

@ -99,4 +99,4 @@ throttleStatus_e calculateThrottleStatus(void);
rollPitchStatus_e calculateRollPitchCenterStatus(void);
void processRcStickPositions(throttleStatus_e throttleStatus);
int32_t getRcStickDeflection(int32_t axis, uint16_t midrc);
int32_t getRcStickDeflection(int32_t axis);

View file

@ -39,7 +39,7 @@ typedef enum {
BOXLEDLOW = 12,
BOXLIGHTS = 13,
BOXNAVLAUNCH = 14,
// BOXOSD = 15,
BOXOSD = 15,
BOXTELEMETRY = 16,
BOXBLACKBOX = 17,
BOXFAILSAFE = 18,

View file

@ -4,10 +4,11 @@
#include "common/string_light.h"
#include "common/utils.h"
#include "fc/settings_generated.h"
#include "settings_generated.h"
#include "fc/settings.h"
#include "fc/settings_generated.c"
#include "settings_generated.c"
void setting_get_name(const setting_t *val, char *buf)
{

View file

@ -6,7 +6,7 @@
#include "config/parameter_group.h"
#include "fc/settings_generated.h"
#include "settings_generated.h"
typedef struct lookupTableEntry_s {
const char * const *values;

View file

@ -7,7 +7,7 @@ tables:
values: ["NONE", "AUTO", "ADXL345", "MPU6050", "MMA845x", "BMA280", "LSM303DLHC", "MPU6000", "MPU6500", "MPU9250", "BMI160", "FAKE"]
enum: accelerationSensor_e
- name: rangefinder_hardware
values: ["NONE", "HCSR04", "SRF10", "HCSR04I2C", "VL53L0X", "MSP", "UIB"]
values: ["NONE", "HCSR04", "SRF10", "INAV_I2C", "VL53L0X", "MSP", "UIB"]
enum: rangefinderType_e
- name: mag_hardware
values: ["NONE", "AUTO", "HMC5883", "AK8975", "GPSMAG", "MAG3110", "AK8963", "IST8310", "QMC5883", "MPU9250", "IST8308", "FAKE"]
@ -67,7 +67,7 @@ tables:
- name: i2c_speed
values: ["400KHZ", "800KHZ", "100KHZ", "200KHZ"]
- name: debug_modes
values: ["NONE", "GYRO", "NOTCH", "NAV_LANDING", "FW_ALTITUDE", "AGL", "FLOW_RAW", "SBUS", "FPORT", "ALWAYS", "STAGE2", "WIND_ESTIMATOR"]
values: ["NONE", "GYRO", "NOTCH", "NAV_LANDING", "FW_ALTITUDE", "AGL", "FLOW_RAW", "SBUS", "FPORT", "ALWAYS", "STAGE2", "WIND_ESTIMATOR", "SAG_COMP_VOLTAGE"]
- name: async_mode
values: ["NONE", "GYRO", "ALL"]
- name: aux_operator
@ -321,10 +321,6 @@ groups:
- name: receiver_type
field: receiverType
table: receiver_type
- name: mid_rc
field: midrc
min: MIDRC_MIN
max: MIDRC_MAX
- name: min_check
field: mincheck
min: PWM_RANGE_MIN
@ -427,6 +423,9 @@ groups:
- name: motor_pwm_protocol
field: motorPwmProtocol
table: motor_pwm_protocol
- name: throttle_vbat_compensation
field: throttleVBatCompensation
type: bool
- name: PG_FAILSAFE_CONFIG
type: failsafeConfig_t

View file

@ -275,7 +275,7 @@ void failsafeApplyControlInput(void)
break;
case THROTTLE:
rcCommand[idx] = feature(FEATURE_3D) ? rxConfig()->midrc : motorConfig()->minthrottle;
rcCommand[idx] = feature(FEATURE_3D) ? PWM_RANGE_MIDDLE : motorConfig()->minthrottle;
break;
}
break;
@ -330,9 +330,9 @@ static bool failsafeCheckStickMotion(void)
if (failsafeConfig()->failsafe_stick_motion_threshold > 0) {
uint32_t totalRcDelta = 0;
totalRcDelta += ABS(rcData[ROLL] - rxConfig()->midrc);
totalRcDelta += ABS(rcData[PITCH] - rxConfig()->midrc);
totalRcDelta += ABS(rcData[YAW] - rxConfig()->midrc);
totalRcDelta += ABS(rcData[ROLL] - PWM_RANGE_MIDDLE);
totalRcDelta += ABS(rcData[PITCH] - PWM_RANGE_MIDDLE);
totalRcDelta += ABS(rcData[YAW] - PWM_RANGE_MIDDLE);
return totalRcDelta >= failsafeConfig()->failsafe_stick_motion_threshold;
}

View file

@ -50,6 +50,8 @@
#include "rx/rx.h"
#include "sensors/battery.h"
//#define MIXER_DEBUG
@ -87,7 +89,7 @@ PG_RESET_TEMPLATE(mixerConfig_t, mixerConfig,
#define DEFAULT_MIN_THROTTLE 1150
#endif
PG_REGISTER_WITH_RESET_TEMPLATE(motorConfig_t, motorConfig, PG_MOTOR_CONFIG, 1);
PG_REGISTER_WITH_RESET_TEMPLATE(motorConfig_t, motorConfig, PG_MOTOR_CONFIG, 2);
PG_RESET_TEMPLATE(motorConfig_t, motorConfig,
.minthrottle = DEFAULT_MIN_THROTTLE,
@ -96,7 +98,8 @@ PG_RESET_TEMPLATE(motorConfig_t, motorConfig,
.maxthrottle = 1850,
.mincommand = 1000,
.motorAccelTimeMs = 0,
.motorDecelTimeMs = 0
.motorDecelTimeMs = 0,
.throttleVBatCompensation = false
);
static motorMixer_t currentMixer[MAX_SUPPORTED_MOTORS];
@ -284,17 +287,17 @@ void mixTable(const float dT)
// Find min and max throttle based on condition.
if (feature(FEATURE_3D)) {
if (!ARMING_FLAG(ARMED)) throttlePrevious = rxConfig()->midrc; // When disarmed set to mid_rc. It always results in positive direction after arming.
if (!ARMING_FLAG(ARMED)) throttlePrevious = PWM_RANGE_MIDDLE; // When disarmed set to mid_rc. It always results in positive direction after arming.
if ((rcCommand[THROTTLE] <= (rxConfig()->midrc - rcControlsConfig()->deadband3d_throttle))) { // Out of band handling
if ((rcCommand[THROTTLE] <= (PWM_RANGE_MIDDLE - rcControlsConfig()->deadband3d_throttle))) { // Out of band handling
throttleMax = flight3DConfig()->deadband3d_low;
throttleMin = motorConfig()->minthrottle;
throttlePrevious = throttleCommand = rcCommand[THROTTLE];
} else if (rcCommand[THROTTLE] >= (rxConfig()->midrc + rcControlsConfig()->deadband3d_throttle)) { // Positive handling
} else if (rcCommand[THROTTLE] >= (PWM_RANGE_MIDDLE + rcControlsConfig()->deadband3d_throttle)) { // Positive handling
throttleMax = motorConfig()->maxthrottle;
throttleMin = flight3DConfig()->deadband3d_high;
throttlePrevious = throttleCommand = rcCommand[THROTTLE];
} else if ((throttlePrevious <= (rxConfig()->midrc - rcControlsConfig()->deadband3d_throttle))) { // Deadband handling from negative to positive
} else if ((throttlePrevious <= (PWM_RANGE_MIDDLE - rcControlsConfig()->deadband3d_throttle))) { // Deadband handling from negative to positive
throttleCommand = throttleMax = flight3DConfig()->deadband3d_low;
throttleMin = motorConfig()->minthrottle;
} else { // Deadband handling from positive to negative
@ -305,6 +308,10 @@ void mixTable(const float dT)
throttleCommand = rcCommand[THROTTLE];
throttleMin = motorConfig()->minthrottle;
throttleMax = motorConfig()->maxthrottle;
// Throttle compensation based on battery voltage
if (motorConfig()->throttleVBatCompensation && STATE(FIXED_WING) && isAmperageConfigured() && feature(FEATURE_VBAT))
throttleCommand = MIN(throttleCommand * calculateThrottleCompensationFactor(), throttleMax);
}
throttleRange = throttleMax - throttleMin;
@ -333,7 +340,7 @@ void mixTable(const float dT)
if (failsafeIsActive()) {
motor[i] = constrain(motor[i], motorConfig()->mincommand, motorConfig()->maxthrottle);
} else if (feature(FEATURE_3D)) {
if (throttlePrevious <= (rxConfig()->midrc - rcControlsConfig()->deadband3d_throttle)) {
if (throttlePrevious <= (PWM_RANGE_MIDDLE - rcControlsConfig()->deadband3d_throttle)) {
motor[i] = constrain(motor[i], motorConfig()->minthrottle, flight3DConfig()->deadband3d_low);
} else {
motor[i] = constrain(motor[i], flight3DConfig()->deadband3d_high, motorConfig()->maxthrottle);
@ -349,7 +356,7 @@ void mixTable(const float dT)
bool userMotorStop = !navigationIsFlyingAutonomousMode() && !failsafeIsActive() && (rcData[THROTTLE] < rxConfig()->mincheck);
if (failsafeMotorStop || navMotorStop || userMotorStop) {
if (feature(FEATURE_3D)) {
motor[i] = rxConfig()->midrc;
motor[i] = PWM_RANGE_MIDDLE;
}
else {
motor[i] = motorConfig()->mincommand;

View file

@ -80,6 +80,7 @@ typedef struct motorConfig_s {
uint8_t motorPwmProtocol;
uint16_t motorAccelTimeMs; // Time limit for motor to accelerate from 0 to 100% throttle [ms]
uint16_t motorDecelTimeMs; // Time limit for motor to decelerate from 0 to 100% throttle [ms]
bool throttleVBatCompensation;
} motorConfig_t;
PG_DECLARE(motorConfig_t, motorConfig);

View file

@ -392,8 +392,8 @@ void updatePIDCoefficients(void)
static float calcHorizonRateMagnitude(void)
{
// Figure out the raw stick positions
const int32_t stickPosAil = ABS(getRcStickDeflection(FD_ROLL, rxConfig()->midrc));
const int32_t stickPosEle = ABS(getRcStickDeflection(FD_PITCH, rxConfig()->midrc));
const int32_t stickPosAil = ABS(getRcStickDeflection(FD_ROLL));
const int32_t stickPosEle = ABS(getRcStickDeflection(FD_PITCH));
const float mostDeflectedStickPos = constrain(MAX(stickPosAil, stickPosEle), 0, 500) / 500.0f;
const float modeTransitionStickPos = constrain(pidBank()->pid[PID_LEVEL].D, 0, 100) / 100.0f;

View file

@ -230,7 +230,7 @@ void servoMixer(float dT)
input[INPUT_STABILIZED_YAW] = axisPID[YAW];
// Reverse yaw servo when inverted in 3D mode only for multirotor and tricopter
if (feature(FEATURE_3D) && (rcData[THROTTLE] < rxConfig()->midrc) &&
if (feature(FEATURE_3D) && (rcData[THROTTLE] < PWM_RANGE_MIDDLE) &&
(mixerConfig()->platformType == PLATFORM_MULTIROTOR || mixerConfig()->platformType == PLATFORM_TRICOPTER)) {
input[INPUT_STABILIZED_YAW] *= -1;
}
@ -254,22 +254,22 @@ void servoMixer(float dT)
// 2000 - 1500 = +500
// 1500 - 1500 = 0
// 1000 - 1500 = -500
input[INPUT_RC_ROLL] = rcData[ROLL] - rxConfig()->midrc;
input[INPUT_RC_PITCH] = rcData[PITCH] - rxConfig()->midrc;
input[INPUT_RC_YAW] = rcData[YAW] - rxConfig()->midrc;
input[INPUT_RC_THROTTLE] = rcData[THROTTLE] - rxConfig()->midrc;
input[INPUT_RC_CH5] = rcData[AUX1] - rxConfig()->midrc;
input[INPUT_RC_CH6] = rcData[AUX2] - rxConfig()->midrc;
input[INPUT_RC_CH7] = rcData[AUX3] - rxConfig()->midrc;
input[INPUT_RC_CH8] = rcData[AUX4] - rxConfig()->midrc;
input[INPUT_RC_CH9] = rcData[AUX5] - rxConfig()->midrc;
input[INPUT_RC_CH10] = rcData[AUX6] - rxConfig()->midrc;
input[INPUT_RC_CH11] = rcData[AUX7] - rxConfig()->midrc;
input[INPUT_RC_CH12] = rcData[AUX8] - rxConfig()->midrc;
input[INPUT_RC_CH13] = rcData[AUX9] - rxConfig()->midrc;
input[INPUT_RC_CH14] = rcData[AUX10] - rxConfig()->midrc;
input[INPUT_RC_CH15] = rcData[AUX11] - rxConfig()->midrc;
input[INPUT_RC_CH16] = rcData[AUX12] - rxConfig()->midrc;
input[INPUT_RC_ROLL] = rcData[ROLL] - PWM_RANGE_MIDDLE;
input[INPUT_RC_PITCH] = rcData[PITCH] - PWM_RANGE_MIDDLE;
input[INPUT_RC_YAW] = rcData[YAW] - PWM_RANGE_MIDDLE;
input[INPUT_RC_THROTTLE] = rcData[THROTTLE] - PWM_RANGE_MIDDLE;
input[INPUT_RC_CH5] = rcData[AUX1] - PWM_RANGE_MIDDLE;
input[INPUT_RC_CH6] = rcData[AUX2] - PWM_RANGE_MIDDLE;
input[INPUT_RC_CH7] = rcData[AUX3] - PWM_RANGE_MIDDLE;
input[INPUT_RC_CH8] = rcData[AUX4] - PWM_RANGE_MIDDLE;
input[INPUT_RC_CH9] = rcData[AUX5] - PWM_RANGE_MIDDLE;
input[INPUT_RC_CH10] = rcData[AUX6] - PWM_RANGE_MIDDLE;
input[INPUT_RC_CH11] = rcData[AUX7] - PWM_RANGE_MIDDLE;
input[INPUT_RC_CH12] = rcData[AUX8] - PWM_RANGE_MIDDLE;
input[INPUT_RC_CH13] = rcData[AUX9] - PWM_RANGE_MIDDLE;
input[INPUT_RC_CH14] = rcData[AUX10] - PWM_RANGE_MIDDLE;
input[INPUT_RC_CH15] = rcData[AUX11] - PWM_RANGE_MIDDLE;
input[INPUT_RC_CH16] = rcData[AUX12] - PWM_RANGE_MIDDLE;
for (int i = 0; i < MAX_SUPPORTED_SERVOS; i++) {
servo[i] = 0;

View file

@ -107,7 +107,7 @@
// Adjust OSD_MESSAGE's default position when
// changing OSD_MESSAGE_LENGTH
#define OSD_MESSAGE_LENGTH 28
#define OSD_ALTERNATING_TEXT(ms, num_choices) ((millis() / ms) % num_choices)
#define OSD_ALTERNATING_CHOICES(ms, num_choices) ((millis() / ms) % num_choices)
#define _CONST_STR_SIZE(s) ((sizeof(s)/sizeof(s[0]))-1) // -1 to avoid counting final '\0'
// Wrap all string constants intenteded for display as messages with
// this macro to ensure compile time length validation.
@ -678,13 +678,12 @@ static const char * navigationStateMessage(void)
case MW_NAV_STATE_LAND_START:
return OSD_MESSAGE_STR("STARTING EMERGENCY LANDING");
case MW_NAV_STATE_LAND_IN_PROGRESS:
if (!navigationRTHAllowsLanding()) {
if (STATE(FIXED_WING)) {
return OSD_MESSAGE_STR("LOITERING AROUND HOME");
}
return OSD_MESSAGE_STR("HOVERING");
}
return OSD_MESSAGE_STR("LANDING");
case MW_NAV_STATE_HOVER_ABOVE_HOME:
if (STATE(FIXED_WING)) {
return OSD_MESSAGE_STR("LOITERING AROUND HOME");
}
return OSD_MESSAGE_STR("HOVERING");
case MW_NAV_STATE_LANDED:
return OSD_MESSAGE_STR("LANDED");
case MW_NAV_STATE_LAND_SETTLE:
@ -934,9 +933,9 @@ static void osdDrawMap(int referenceHeading, uint8_t referenceSym, uint8_t cente
break;
}
if (STATE(GPS_FIX) && poiDistance > scale) {
if (STATE(GPS_FIX)) {
int directionToPoi = osdGetHeadingAngle(poiDirection + referenceHeading);
int directionToPoi = osdGetHeadingAngle(poiDirection - referenceHeading);
float poiAngle = DEGREES_TO_RADIANS(directionToPoi);
float poiSin = sin_approx(poiAngle);
float poiCos = cos_approx(poiAngle);
@ -947,7 +946,7 @@ static void osdDrawMap(int referenceHeading, uint8_t referenceSym, uint8_t cente
int points = poiDistance / (float)(scale / charHeight);
float pointsX = points * poiSin;
int poiX = midX + roundf(pointsX / charWidth);
int poiX = midX - roundf(pointsX / charWidth);
if (poiX < minX || poiX > maxX) {
continue;
}
@ -958,18 +957,21 @@ static void osdDrawMap(int referenceHeading, uint8_t referenceSym, uint8_t cente
continue;
}
if (poiX == midX && poiY == midY && centerSym != SYM_BLANK) {
if (poiX == midX && poiY == midY) {
// We're over the map center symbol, so we would be drawing
// over it even if we increased the scale. No reason to run
// this loop 50 times.
break;
}
// over it even if we increased the scale. Alternate between
// drawing the center symbol or drawing the POI.
if (centerSym != SYM_BLANK && OSD_ALTERNATING_CHOICES(1000, 2) == 0) {
break;
}
} else {
uint8_t c;
if (displayReadCharWithAttr(osdDisplayPort, poiY, poiY, &c, NULL) && c != SYM_BLANK) {
// Something else written here, increase scale. If the display doesn't support reading
// back characters, we assume there's nothing.
continue;
uint8_t c;
if (displayReadCharWithAttr(osdDisplayPort, poiY, poiY, &c, NULL) && c != SYM_BLANK) {
// Something else written here, increase scale. If the display doesn't support reading
// back characters, we assume there's nothing.
continue;
}
}
// Draw the point on the map
@ -1050,6 +1052,19 @@ static bool osdDrawSingleElement(uint8_t item)
displayWriteWithAttr(osdDisplayPort, elemPosX + 1, elemPosY, buff, elemAttr);
return true;
case OSD_SAG_COMPENSATED_MAIN_BATT_VOLTAGE:
osdFormatBatteryChargeSymbol(buff);
buff[1] = '\0';
osdUpdateBatteryCapacityOrVoltageTextAttributes(&elemAttr);
displayWriteWithAttr(osdDisplayPort, elemPosX, elemPosY, buff, elemAttr);
elemAttr = TEXT_ATTRIBUTES_NONE;
osdFormatCentiNumber(buff, getSagCompensatedBatteryVoltage(), 0, osdConfig()->main_voltage_decimals, 0, osdConfig()->main_voltage_decimals + 2);
strcat(buff, "V");
if ((getBatteryState() != BATTERY_NOT_PRESENT) && (getSagCompensatedBatteryVoltage() <= getBatteryWarningVoltage()))
TEXT_ATTRIBUTES_ADD_BLINK(elemAttr);
displayWriteWithAttr(osdDisplayPort, elemPosX + 1, elemPosY, buff, elemAttr);
return true;
case OSD_CURRENT_DRAW:
buff[0] = SYM_AMP;
osdFormatCentiNumber(buff + 1, getAmperage(), 0, 2, 0, 3);
@ -1590,7 +1605,7 @@ static bool osdDrawSingleElement(uint8_t item)
messages[messageCount++] = navStateFSMessage;
}
if (messageCount > 0) {
message = messages[OSD_ALTERNATING_TEXT(1000, messageCount)];
message = messages[OSD_ALTERNATING_CHOICES(1000, messageCount)];
if (message == failsafeInfoMessage) {
// failsafeInfoMessage is not useful for recovering
// a lost model, but might help avoiding a crash.
@ -1630,12 +1645,12 @@ static bool osdDrawSingleElement(uint8_t item)
// Pick one of the available messages. Each message lasts
// a second.
if (messageCount > 0) {
message = messages[OSD_ALTERNATING_TEXT(1000, messageCount)];
message = messages[OSD_ALTERNATING_CHOICES(1000, messageCount)];
}
}
} else if (ARMING_FLAG(ARMING_DISABLED_ALL_FLAGS)) {
// Check if we're unable to arm for some reason
if (OSD_ALTERNATING_TEXT(1000, 2) == 0) {
if (OSD_ALTERNATING_CHOICES(1000, 2) == 0) {
message = "UNABLE TO ARM";
TEXT_ATTRIBUTES_ADD_INVERTED(elemAttr);
} else {
@ -1895,6 +1910,8 @@ void pgResetFn_osdConfig(osdConfig_t *osdConfig)
{
osdConfig->item_pos[0][OSD_ALTITUDE] = OSD_POS(1, 0) | OSD_VISIBLE_FLAG;
osdConfig->item_pos[0][OSD_MAIN_BATT_VOLTAGE] = OSD_POS(12, 0) | OSD_VISIBLE_FLAG;
osdConfig->item_pos[0][OSD_SAG_COMPENSATED_MAIN_BATT_VOLTAGE] = OSD_POS(12, 1);
osdConfig->item_pos[0][OSD_RSSI_VALUE] = OSD_POS(23, 0) | OSD_VISIBLE_FLAG;
//line 2
osdConfig->item_pos[0][OSD_HOME_DIST] = OSD_POS(1, 1);
@ -2224,6 +2241,12 @@ static void osdRefresh(timeUs_t currentTimeUs)
{
static timeUs_t lastTimeUs = 0;
if (IS_RC_MODE_ACTIVE(BOXOSD) && (!cmsInMenu)) {
displayClearScreen(osdDisplayPort);
armState = ARMING_FLAG(ARMED);
return;
}
// detect arm/disarm
if (armState != ARMING_FLAG(ARMED)) {
if (ARMING_FLAG(ARMED)) {

View file

@ -83,6 +83,7 @@ typedef enum {
OSD_DEBUG, // Number 46. Intentionally absent from configurator and CMS. Set it from CLI.
OSD_WIND_SPEED_HORIZONTAL,
OSD_WIND_SPEED_VERTICAL,
OSD_SAG_COMPENSATED_MAIN_BATT_VOLTAGE,
OSD_ITEM_COUNT // MUST BE LAST
} osd_items_e;

View file

@ -199,6 +199,7 @@ static navigationFSMEvent_t navOnEnteringState_NAV_STATE_RTH_INITIALIZE(navigati
static navigationFSMEvent_t navOnEnteringState_NAV_STATE_RTH_CLIMB_TO_SAFE_ALT(navigationFSMState_t previousState);
static navigationFSMEvent_t navOnEnteringState_NAV_STATE_RTH_HEAD_HOME(navigationFSMState_t previousState);
static navigationFSMEvent_t navOnEnteringState_NAV_STATE_RTH_HOVER_PRIOR_TO_LANDING(navigationFSMState_t previousState);
static navigationFSMEvent_t navOnEnteringState_NAV_STATE_RTH_HOVER_ABOVE_HOME(navigationFSMState_t previousState);
static navigationFSMEvent_t navOnEnteringState_NAV_STATE_RTH_LANDING(navigationFSMState_t previousState);
static navigationFSMEvent_t navOnEnteringState_NAV_STATE_RTH_FINISHING(navigationFSMState_t previousState);
static navigationFSMEvent_t navOnEnteringState_NAV_STATE_RTH_FINISHED(navigationFSMState_t previousState);
@ -368,6 +369,24 @@ static const navigationFSMStateDescriptor_t navFSM[NAV_STATE_COUNT] = {
.onEvent = {
[NAV_FSM_EVENT_TIMEOUT] = NAV_STATE_RTH_HOVER_PRIOR_TO_LANDING,
[NAV_FSM_EVENT_SUCCESS] = NAV_STATE_RTH_LANDING,
[NAV_FSM_EVENT_SWITCH_TO_RTH_HOVER_ABOVE_HOME] = NAV_STATE_RTH_HOVER_ABOVE_HOME,
[NAV_FSM_EVENT_SWITCH_TO_IDLE] = NAV_STATE_IDLE,
[NAV_FSM_EVENT_SWITCH_TO_ALTHOLD] = NAV_STATE_ALTHOLD_INITIALIZE,
[NAV_FSM_EVENT_SWITCH_TO_POSHOLD_3D] = NAV_STATE_POSHOLD_3D_INITIALIZE,
[NAV_FSM_EVENT_SWITCH_TO_EMERGENCY_LANDING] = NAV_STATE_EMERGENCY_LANDING_INITIALIZE,
}
},
[NAV_STATE_RTH_HOVER_ABOVE_HOME] = {
.persistentId = NAV_PERSISTENT_ID_RTH_HOVER_ABOVE_HOME,
.onEntry = navOnEnteringState_NAV_STATE_RTH_HOVER_ABOVE_HOME,
.timeoutMs = 500,
.stateFlags = NAV_CTL_ALT | NAV_CTL_POS | NAV_CTL_YAW | NAV_REQUIRE_ANGLE | NAV_REQUIRE_MAGHOLD | NAV_REQUIRE_THRTILT | NAV_AUTO_RTH | NAV_RC_POS | NAV_RC_YAW | NAV_RC_ALT,
.mapToFlightModes = NAV_RTH_MODE | NAV_ALTHOLD_MODE,
.mwState = MW_NAV_STATE_HOVER_ABOVE_HOME,
.mwError = MW_NAV_ERROR_NONE,
.onEvent = {
[NAV_FSM_EVENT_TIMEOUT] = NAV_STATE_RTH_HOVER_ABOVE_HOME,
[NAV_FSM_EVENT_SWITCH_TO_IDLE] = NAV_STATE_IDLE,
[NAV_FSM_EVENT_SWITCH_TO_ALTHOLD] = NAV_STATE_ALTHOLD_INITIALIZE,
[NAV_FSM_EVENT_SWITCH_TO_POSHOLD_3D] = NAV_STATE_POSHOLD_3D_INITIALIZE,
@ -784,7 +803,7 @@ static navigationFSMEvent_t navOnEnteringState_NAV_STATE_RTH_INITIALIZE(navigati
// If close to home - reset home position and land
if (posControl.homeDistance < navConfig()->general.min_rth_distance) {
setHomePosition(&navGetCurrentActualPositionAndVelocity()->pos, posControl.actualState.yaw, NAV_POS_UPDATE_XY | NAV_POS_UPDATE_HEADING);
setHomePosition(&navGetCurrentActualPositionAndVelocity()->pos, posControl.actualState.yaw, NAV_POS_UPDATE_XY | NAV_POS_UPDATE_HEADING, NAV_HOME_VALID_ALL);
setDesiredPosition(&navGetCurrentActualPositionAndVelocity()->pos, posControl.actualState.yaw, NAV_POS_UPDATE_XY | NAV_POS_UPDATE_Z | NAV_POS_UPDATE_HEADING);
return NAV_FSM_EVENT_SWITCH_TO_RTH_LANDING; // NAV_STATE_RTH_HOVER_PRIOR_TO_LANDING
@ -932,12 +951,12 @@ static navigationFSMEvent_t navOnEnteringState_NAV_STATE_RTH_HOVER_PRIOR_TO_LAND
// Wait until target heading is reached (with 15 deg margin for error)
if (STATE(FIXED_WING)) {
resetLandingDetector();
return NAV_FSM_EVENT_SUCCESS;
return navigationRTHAllowsLanding() ? NAV_FSM_EVENT_SUCCESS : NAV_FSM_EVENT_SWITCH_TO_RTH_HOVER_ABOVE_HOME;
}
else {
if (ABS(wrap_18000(posControl.homeWaypointAbove.yaw - posControl.actualState.yaw)) < DEGREES_TO_CENTIDEGREES(15)) {
resetLandingDetector();
return NAV_FSM_EVENT_SUCCESS;
return navigationRTHAllowsLanding() ? NAV_FSM_EVENT_SUCCESS : NAV_FSM_EVENT_SWITCH_TO_RTH_HOVER_ABOVE_HOME;
}
else if (!validateRTHSanityChecker()) {
// Continue to check for RTH sanity during pre-landing hover
@ -954,6 +973,16 @@ static navigationFSMEvent_t navOnEnteringState_NAV_STATE_RTH_HOVER_PRIOR_TO_LAND
}
}
static navigationFSMEvent_t navOnEnteringState_NAV_STATE_RTH_HOVER_ABOVE_HOME(navigationFSMState_t previousState)
{
UNUSED(previousState);
if (!(validateRTHSanityChecker() || (posControl.flags.estPosStatus >= EST_USABLE) || !checkForPositionSensorTimeout()))
return NAV_FSM_EVENT_SWITCH_TO_EMERGENCY_LANDING;
return NAV_FSM_EVENT_NONE;
}
static navigationFSMEvent_t navOnEnteringState_NAV_STATE_RTH_LANDING(navigationFSMState_t previousState)
{
UNUSED(previousState);
@ -970,28 +999,26 @@ static navigationFSMEvent_t navOnEnteringState_NAV_STATE_RTH_LANDING(navigationF
return NAV_FSM_EVENT_SWITCH_TO_EMERGENCY_LANDING;
}
if (navigationRTHAllowsLanding()) {
float descentVelLimited = 0;
float descentVelLimited = 0;
// A safeguard - if surface altitude sensors is available and it is reading < 50cm altitude - drop to low descend speed
if ((posControl.flags.estAglStatus == EST_TRUSTED) && posControl.actualState.agl.pos.z < 50.0f) {
// land_descent_rate == 200 : descend speed = 30 cm/s, gentle touchdown
// Do not allow descent velocity slower than -30cm/s so the landing detector works.
descentVelLimited = MIN(-0.15f * navConfig()->general.land_descent_rate, -30.0f);
}
else {
// Ramp down descent velocity from 100% at maxAlt altitude to 25% from minAlt to 0cm.
float descentVelScaling = (navGetCurrentActualPositionAndVelocity()->pos.z - posControl.homePosition.pos.z - navConfig()->general.land_slowdown_minalt)
/ (navConfig()->general.land_slowdown_maxalt - navConfig()->general.land_slowdown_minalt) * 0.75f + 0.25f; // Yield 1.0 at 2000 alt and 0.25 at 500 alt
descentVelScaling = constrainf(descentVelScaling, 0.25f, 1.0f);
// Do not allow descent velocity slower than -50cm/s so the landing detector works.
descentVelLimited = MIN(-descentVelScaling * navConfig()->general.land_descent_rate, -50.0f);
}
updateClimbRateToAltitudeController(descentVelLimited, ROC_TO_ALT_NORMAL);
// A safeguard - if surface altitude sensors is available and it is reading < 50cm altitude - drop to low descend speed
if ((posControl.flags.estAglStatus == EST_TRUSTED) && posControl.actualState.agl.pos.z < 50.0f) {
// land_descent_rate == 200 : descend speed = 30 cm/s, gentle touchdown
// Do not allow descent velocity slower than -30cm/s so the landing detector works.
descentVelLimited = MIN(-0.15f * navConfig()->general.land_descent_rate, -30.0f);
}
else {
// Ramp down descent velocity from 100% at maxAlt altitude to 25% from minAlt to 0cm.
float descentVelScaling = (navGetCurrentActualPositionAndVelocity()->pos.z - posControl.homePosition.pos.z - navConfig()->general.land_slowdown_minalt)
/ (navConfig()->general.land_slowdown_maxalt - navConfig()->general.land_slowdown_minalt) * 0.75f + 0.25f; // Yield 1.0 at 2000 alt and 0.25 at 500 alt
descentVelScaling = constrainf(descentVelScaling, 0.25f, 1.0f);
// Do not allow descent velocity slower than -50cm/s so the landing detector works.
descentVelLimited = MIN(-descentVelScaling * navConfig()->general.land_descent_rate, -50.0f);
}
updateClimbRateToAltitudeController(descentVelLimited, ROC_TO_ALT_NORMAL);
return NAV_FSM_EVENT_NONE;
}
@ -1331,12 +1358,16 @@ float navPidApply3(pidController_t *pid, const float setpoint, const float measu
newProportional = error * pid->param.kP * gainScaler;
/* D-term */
if (pid->reset) {
pid->last_input = (pidFlags & PID_DTERM_FROM_ERROR) ? error : measurement;
pid->reset = false;
}
if (pidFlags & PID_DTERM_FROM_ERROR) {
/* Error-tracking D-term */
newDerivative = (error - pid->last_input) / dt;
pid->last_input = error;
}
else {
} else {
/* Measurement tracking D-term */
newDerivative = -(measurement - pid->last_input) / dt;
pid->last_input = measurement;
@ -1378,6 +1409,7 @@ float navPidApply2(pidController_t *pid, const float setpoint, const float measu
void navPidReset(pidController_t *pid)
{
pid->reset = true;
pid->integrator = 0.0f;
pid->last_input = 0.0f;
pid->dterm_filter_state.state = 0.0f;
@ -1532,9 +1564,30 @@ void updateActualAltitudeAndClimbRate(bool estimateValid, float newAltitude, flo
*-----------------------------------------------------------*/
void updateActualHeading(bool headingValid, int32_t newHeading)
{
/* Update heading */
/* Update heading. Check if we're acquiring a valid heading for the
* first time and update home heading accordingly.
*/
navigationEstimateStatus_e newEstHeading = headingValid ? EST_TRUSTED : EST_NONE;
if (newEstHeading >= EST_USABLE && posControl.flags.estHeadingStatus < EST_USABLE &&
(posControl.homeFlags & (NAV_HOME_VALID_XY | NAV_HOME_VALID_Z)) &&
(posControl.homeFlags & NAV_HOME_VALID_HEADING) == 0) {
// Home was stored using the fake heading (assuming boot as 0deg). Calculate
// the offset from the fake to the actual yaw and apply the same rotation
// to the home point.
int32_t fakeToRealYawOffset = newHeading - posControl.actualState.yaw;
posControl.homePosition.yaw += fakeToRealYawOffset;
if (posControl.homePosition.yaw < 0) {
posControl.homePosition.yaw += DEGREES_TO_CENTIDEGREES(360);
}
if (posControl.homePosition.yaw >= DEGREES_TO_CENTIDEGREES(360)) {
posControl.homePosition.yaw -= DEGREES_TO_CENTIDEGREES(360);
}
posControl.homeFlags |= NAV_HOME_VALID_HEADING;
}
posControl.actualState.yaw = newHeading;
posControl.flags.estHeadingStatus = headingValid ? EST_TRUSTED : EST_NONE;
posControl.flags.estHeadingStatus = newEstHeading;
/* Precompute sin/cos of yaw angle */
posControl.actualState.sinYaw = sin_approx(CENTIDEGREES_TO_RADIANS(newHeading));
@ -1678,30 +1731,43 @@ bool validateRTHSanityChecker(void)
/*-----------------------------------------------------------
* Reset home position to current position
*-----------------------------------------------------------*/
void setHomePosition(const fpVector3_t * pos, int32_t yaw, navSetWaypointFlags_t useMask)
void setHomePosition(const fpVector3_t * pos, int32_t yaw, navSetWaypointFlags_t useMask, navigationHomeFlags_t homeFlags)
{
// XY-position
if ((useMask & NAV_POS_UPDATE_XY) != 0) {
posControl.homePosition.pos.x = pos->x;
posControl.homePosition.pos.y = pos->y;
if (homeFlags & NAV_HOME_VALID_XY) {
posControl.homeFlags |= NAV_HOME_VALID_XY;
} else {
posControl.homeFlags &= ~NAV_HOME_VALID_XY;
}
}
// Z-position
if ((useMask & NAV_POS_UPDATE_Z) != 0) {
posControl.homePosition.pos.z = pos->z;
if (homeFlags & NAV_HOME_VALID_Z) {
posControl.homeFlags |= NAV_HOME_VALID_Z;
} else {
posControl.homeFlags &= ~NAV_HOME_VALID_Z;
}
}
// Heading
if ((useMask & NAV_POS_UPDATE_HEADING) != 0) {
// Heading
posControl.homePosition.yaw = yaw;
if (homeFlags & NAV_HOME_VALID_HEADING) {
posControl.homeFlags |= NAV_HOME_VALID_HEADING;
} else {
posControl.homeFlags &= ~NAV_HOME_VALID_HEADING;
}
}
posControl.homeDistance = 0;
posControl.homeDirection = 0;
posControl.flags.isHomeValid = true;
// Update target RTH altitude as a waypoint above home
posControl.homeWaypointAbove = posControl.homePosition;
updateDesiredRTHAltitude();
@ -1710,6 +1776,21 @@ void setHomePosition(const fpVector3_t * pos, int32_t yaw, navSetWaypointFlags_t
ENABLE_STATE(GPS_FIX_HOME);
}
static navigationHomeFlags_t navigationActualStateHomeValidity(void)
{
navigationHomeFlags_t flags = 0;
if (posControl.flags.estPosStatus >= EST_USABLE) {
flags |= NAV_HOME_VALID_XY | NAV_HOME_VALID_Z;
}
if (posControl.flags.estHeadingStatus >= EST_USABLE) {
flags |= NAV_HOME_VALID_HEADING;
}
return flags;
}
/*-----------------------------------------------------------
* Update home position, calculate distance and bearing to home
*-----------------------------------------------------------*/
@ -1718,7 +1799,8 @@ void updateHomePosition(void)
// Disarmed and have a valid position, constantly update home
if (!ARMING_FLAG(ARMED)) {
if (posControl.flags.estPosStatus >= EST_USABLE) {
bool setHome = !posControl.flags.isHomeValid;
const navigationHomeFlags_t validHomeFlags = NAV_HOME_VALID_XY | NAV_HOME_VALID_Z;
bool setHome = (posControl.homeFlags & validHomeFlags) != validHomeFlags;
switch ((nav_reset_type_e)positionEstimationConfig()->reset_home_type) {
case NAV_RESET_NEVER:
break;
@ -1730,7 +1812,7 @@ void updateHomePosition(void)
break;
}
if (setHome) {
setHomePosition(&posControl.actualState.abs.pos, posControl.actualState.yaw, NAV_POS_UPDATE_XY | NAV_POS_UPDATE_Z | NAV_POS_UPDATE_HEADING );
setHomePosition(&posControl.actualState.abs.pos, posControl.actualState.yaw, NAV_POS_UPDATE_XY | NAV_POS_UPDATE_Z | NAV_POS_UPDATE_HEADING, navigationActualStateHomeValidity());
}
}
}
@ -1741,7 +1823,7 @@ void updateHomePosition(void)
if (IS_RC_MODE_ACTIVE(BOXHOMERESET)) {
if (isHomeResetAllowed && !FLIGHT_MODE(FAILSAFE_MODE) && !FLIGHT_MODE(NAV_RTH_MODE) && !FLIGHT_MODE(NAV_WP_MODE) && (posControl.flags.estPosStatus >= EST_USABLE)) {
const navSetWaypointFlags_t homeUpdateFlags = STATE(GPS_FIX_HOME) ? (NAV_POS_UPDATE_XY | NAV_POS_UPDATE_HEADING) : (NAV_POS_UPDATE_XY | NAV_POS_UPDATE_Z | NAV_POS_UPDATE_HEADING);
setHomePosition(&posControl.actualState.abs.pos, posControl.actualState.yaw, homeUpdateFlags);
setHomePosition(&posControl.actualState.abs.pos, posControl.actualState.yaw, homeUpdateFlags, navigationActualStateHomeValidity());
isHomeResetAllowed = false;
}
}
@ -2120,7 +2202,7 @@ void setWaypoint(uint8_t wpNumber, const navWaypoint_t * wpData)
if ((wpNumber == 0) && ARMING_FLAG(ARMED) && (posControl.flags.estPosStatus >= EST_USABLE) && posControl.gpsOrigin.valid && posControl.flags.isGCSAssistedNavigationEnabled) {
// Forcibly set home position. Note that this is only valid if already armed, otherwise home will be reset instantly
geoConvertGeodeticToLocal(&posControl.gpsOrigin, &wpLLH, &wpPos.pos, GEO_ALT_RELATIVE);
setHomePosition(&wpPos.pos, 0, NAV_POS_UPDATE_XY | NAV_POS_UPDATE_Z | NAV_POS_UPDATE_HEADING);
setHomePosition(&wpPos.pos, 0, NAV_POS_UPDATE_XY | NAV_POS_UPDATE_Z | NAV_POS_UPDATE_HEADING, NAV_HOME_VALID_ALL);
}
// WP #255 - special waypoint - directly set desiredPosition
// Only valid when armed and in poshold mode
@ -2441,9 +2523,13 @@ static navigationFSMEvent_t selectNavEventFromBoxModeInput(void)
}
}
else {
// If we were in LAUNCH mode - force switch to IDLE
// If we were in LAUNCH mode - force switch to IDLE only if the throttle is low
if (FLIGHT_MODE(NAV_LAUNCH_MODE)) {
return NAV_FSM_EVENT_SWITCH_TO_IDLE;
throttleStatus_e throttleStatus = calculateThrottleStatus();
if (throttleStatus != THROTTLE_LOW)
return NAV_FSM_EVENT_NONE;
else
return NAV_FSM_EVENT_SWITCH_TO_IDLE;
}
}
}
@ -2554,8 +2640,8 @@ bool navigationTerrainFollowingEnabled(void)
bool navigationBlockArming(void)
{
const bool navBoxModesEnabled = IS_RC_MODE_ACTIVE(BOXNAVRTH) || IS_RC_MODE_ACTIVE(BOXNAVWP) || IS_RC_MODE_ACTIVE(BOXNAVPOSHOLD);
const bool navLaunchComboModesEnabled = isNavLaunchEnabled() && (IS_RC_MODE_ACTIVE(BOXNAVRTH) || IS_RC_MODE_ACTIVE(BOXNAVWP));
const bool navBoxModesEnabled = IS_RC_MODE_ACTIVE(BOXNAVRTH) || IS_RC_MODE_ACTIVE(BOXNAVWP) || IS_RC_MODE_ACTIVE(BOXNAVPOSHOLD) || (STATE(FIXED_WING) && IS_RC_MODE_ACTIVE(BOXNAVALTHOLD));
const bool navLaunchComboModesEnabled = isNavLaunchEnabled() && (IS_RC_MODE_ACTIVE(BOXNAVRTH) || IS_RC_MODE_ACTIVE(BOXNAVWP) || IS_RC_MODE_ACTIVE(BOXNAVALTHOLD));
bool shouldBlockArming = false;
if (!navConfig()->general.flags.extra_arming_safety)
@ -2767,7 +2853,7 @@ rthState_e getStateOfForcedRTH(void)
bool navigationIsControllingThrottle(void)
{
navigationFSMStateFlags_t stateFlags = navGetCurrentStateFlags();
return (stateFlags & (NAV_CTL_ALT | NAV_CTL_EMERG | NAV_CTL_LAUNCH | NAV_CTL_LAND)) || (STATE(FIXED_WING) && (stateFlags & (NAV_CTL_POS)));
return (stateFlags & (NAV_CTL_ALT | NAV_CTL_EMERG | NAV_CTL_LAUNCH | NAV_CTL_LAND));
}
bool navigationIsFlyingAutonomousMode(void)

View file

@ -230,7 +230,8 @@ typedef enum {
MW_NAV_STATE_LAND_IN_PROGRESS, // Land in Progress
MW_NAV_STATE_LANDED, // Landed
MW_NAV_STATE_LAND_SETTLE, // Settling before land
MW_NAV_STATE_LAND_START_DESCENT // Start descent
MW_NAV_STATE_LAND_START_DESCENT, // Start descent
MW_NAV_STATE_HOVER_ABOVE_HOME // Hover/Loitering above home
} navSystemStatus_State_e;
typedef enum {

View file

@ -412,28 +412,24 @@ int16_t applyFixedWingMinSpeedController(timeUs_t currentTimeUs)
void applyFixedWingPitchRollThrottleController(navigationFSMStateFlags_t navStateFlags, timeUs_t currentTimeUs)
{
int16_t pitchCorrection = 0; // >0 climb, <0 dive
int16_t rollCorrection = 0; // >0 right, <0 left
int16_t throttleCorrection = 0; // raw throttle
int16_t minThrottleCorrection = navConfig()->fw.min_throttle - navConfig()->fw.cruise_throttle;
int16_t maxThrottleCorrection = navConfig()->fw.max_throttle - navConfig()->fw.cruise_throttle;
// Mix Pitch/Roll/Throttle
if (isRollAdjustmentValid && (navStateFlags & NAV_CTL_POS)) {
rollCorrection += posControl.rcAdjustment[ROLL];
// ROLL >0 right, <0 left
int16_t rollCorrection = constrain(posControl.rcAdjustment[ROLL], -DEGREES_TO_DECIDEGREES(navConfig()->fw.max_bank_angle), DEGREES_TO_DECIDEGREES(navConfig()->fw.max_bank_angle));
rcCommand[ROLL] = pidAngleToRcCommand(rollCorrection, pidProfile()->max_angle_inclination[FD_ROLL]);
}
if (isPitchAdjustmentValid && (navStateFlags & NAV_CTL_ALT)) {
pitchCorrection += posControl.rcAdjustment[PITCH];
throttleCorrection += DECIDEGREES_TO_DEGREES(pitchCorrection) * navConfig()->fw.pitch_to_throttle;
// PITCH >0 dive, <0 climb
int16_t pitchCorrection = constrain(posControl.rcAdjustment[PITCH], -DEGREES_TO_DECIDEGREES(navConfig()->fw.max_dive_angle), DEGREES_TO_DECIDEGREES(navConfig()->fw.max_climb_angle));
rcCommand[PITCH] = -pidAngleToRcCommand(pitchCorrection, pidProfile()->max_angle_inclination[FD_PITCH]);
int16_t throttleCorrection = DECIDEGREES_TO_DEGREES(pitchCorrection) * navConfig()->fw.pitch_to_throttle;
#ifdef NAV_FIXED_WING_LANDING
if (navStateFlags & NAV_CTL_LAND) {
/*
* During LAND we do not allow to raise THROTTLE when nose is up
* to reduce speed
*/
// During LAND we do not allow to raise THROTTLE when nose is up to reduce speed
throttleCorrection = constrain(throttleCorrection, minThrottleCorrection, 0);
} else {
#endif
@ -441,28 +437,13 @@ void applyFixedWingPitchRollThrottleController(navigationFSMStateFlags_t navStat
#ifdef NAV_FIXED_WING_LANDING
}
#endif
}
// Speed controller - only apply in POS mode when NOT NAV_CTL_LAND
if ((navStateFlags & NAV_CTL_POS) && !(navStateFlags & NAV_CTL_LAND)) {
throttleCorrection += applyFixedWingMinSpeedController(currentTimeUs);
throttleCorrection = constrain(throttleCorrection, minThrottleCorrection, maxThrottleCorrection);
}
// Speed controller - only apply in POS mode when NOT NAV_CTL_LAND
if ((navStateFlags & NAV_CTL_POS) && !(navStateFlags & NAV_CTL_LAND)) {
throttleCorrection += applyFixedWingMinSpeedController(currentTimeUs);
throttleCorrection = constrain(throttleCorrection, minThrottleCorrection, maxThrottleCorrection);
}
// Limit and apply
if (isPitchAdjustmentValid && (navStateFlags & NAV_CTL_ALT)) {
// PITCH correction is measured according to altitude: <0 - dive/lose altitude, >0 - climb/gain altitude
// PITCH angle is measured in opposite direction ( >0 - dive, <0 - climb)
pitchCorrection = constrain(pitchCorrection, -DEGREES_TO_DECIDEGREES(navConfig()->fw.max_dive_angle), DEGREES_TO_DECIDEGREES(navConfig()->fw.max_climb_angle));
rcCommand[PITCH] = -pidAngleToRcCommand(pitchCorrection, pidProfile()->max_angle_inclination[FD_PITCH]);
}
if (isRollAdjustmentValid && (navStateFlags & NAV_CTL_POS)) {
rollCorrection = constrain(rollCorrection, -DEGREES_TO_DECIDEGREES(navConfig()->fw.max_bank_angle), DEGREES_TO_DECIDEGREES(navConfig()->fw.max_bank_angle));
rcCommand[ROLL] = pidAngleToRcCommand(rollCorrection, pidProfile()->max_angle_inclination[FD_ROLL]);
}
if ((navStateFlags & NAV_CTL_ALT) || (navStateFlags & NAV_CTL_POS)) {
uint16_t correctedThrottleValue = constrain(navConfig()->fw.cruise_throttle + throttleCorrection, navConfig()->fw.min_throttle, navConfig()->fw.max_throttle);
rcCommand[THROTTLE] = constrain(correctedThrottleValue, motorConfig()->minthrottle, motorConfig()->maxthrottle);
}
@ -475,23 +456,15 @@ void applyFixedWingPitchRollThrottleController(navigationFSMStateFlags_t navStat
if (navStateFlags & NAV_CTL_LAND) {
if ( ((posControl.flags.estAltStatus >= EST_USABLE) && (navGetCurrentActualPositionAndVelocity()->pos.z <= navConfig()->general.land_slowdown_minalt)) ||
((posControl.flags.estAglStatus == EST_TRUSTED) && (posControl.actualState.agl.pos.z <= navConfig()->general.land_slowdown_minalt)) ) {
/*
* Set motor to min. throttle and stop it when MOTOR_STOP feature is enabled
*/
// Set motor to min. throttle and stop it when MOTOR_STOP feature is enabled
rcCommand[THROTTLE] = motorConfig()->minthrottle;
ENABLE_STATE(NAV_MOTOR_STOP_OR_IDLE);
/*
* Stabilize ROLL axis on 0 degrees banking regardless of loiter radius and position
*/
// Stabilize ROLL axis on 0 degrees banking regardless of loiter radius and position
rcCommand[ROLL] = 0;
/*
* Stabilize PITCH angle into shallow dive as specified by the
* nav_fw_land_dive_angle setting (default value is 2 - defined
* in navigation.c).
* PITCH angle is measured: >0 - dive, <0 - climb)
*/
// Stabilize PITCH angle into shallow dive as specified by the nav_fw_land_dive_angle setting (default value is 2 - defined in navigation.c).
rcCommand[PITCH] = pidAngleToRcCommand(DEGREES_TO_DECIDEGREES(navConfig()->fw.land_dive_angle), pidProfile()->max_angle_inclination[FD_PITCH]);
}
}

View file

@ -62,6 +62,14 @@ typedef enum {
EST_TRUSTED = 2 // Estimate is usable and based on actual sensor data
} navigationEstimateStatus_e;
typedef enum {
NAV_HOME_INVALID = 0,
NAV_HOME_VALID_XY = 1 << 0,
NAV_HOME_VALID_Z = 1 << 1,
NAV_HOME_VALID_HEADING = 1 << 2,
NAV_HOME_VALID_ALL = NAV_HOME_VALID_XY | NAV_HOME_VALID_Z | NAV_HOME_VALID_HEADING,
} navigationHomeFlags_t;
typedef struct navigationFlags_s {
bool horizontalPositionDataNew;
bool verticalPositionDataNew;
@ -85,8 +93,6 @@ typedef struct navigationFlags_s {
bool isTerrainFollowEnabled; // Does iNav use rangefinder for terrain following (adjusting baro altitude target according to rangefinders readings)
bool forcedRTHActivated;
bool isHomeValid;
} navigationFlags_t;
typedef struct {
@ -107,6 +113,7 @@ typedef enum {
} pidControllerFlags_e;
typedef struct {
bool reset;
pidControllerParam_t param;
pt1Filter_t dterm_filter_state; // last derivative for low-pass filter
float integrator; // integrator value
@ -163,6 +170,7 @@ typedef enum {
NAV_FSM_EVENT_SWITCH_TO_ALTHOLD,
NAV_FSM_EVENT_SWITCH_TO_POSHOLD_3D,
NAV_FSM_EVENT_SWITCH_TO_RTH,
NAV_FSM_EVENT_SWITCH_TO_RTH_HOVER_ABOVE_HOME,
NAV_FSM_EVENT_SWITCH_TO_WAYPOINT,
NAV_FSM_EVENT_SWITCH_TO_EMERGENCY_LANDING,
NAV_FSM_EVENT_SWITCH_TO_LAUNCH,
@ -179,43 +187,44 @@ typedef enum {
// This enum is used to keep values in blackbox logs stable, so we can
// freely change navigationFSMState_t.
typedef enum {
NAV_PERSISTENT_ID_UNDEFINED = 0, // 0
NAV_PERSISTENT_ID_UNDEFINED = 0,
NAV_PERSISTENT_ID_IDLE, // 1
NAV_PERSISTENT_ID_IDLE = 1,
NAV_PERSISTENT_ID_ALTHOLD_INITIALIZE, // 2
NAV_PERSISTENT_ID_ALTHOLD_IN_PROGRESS, // 3
NAV_PERSISTENT_ID_ALTHOLD_INITIALIZE = 2,
NAV_PERSISTENT_ID_ALTHOLD_IN_PROGRESS = 3,
NAV_PERSISTENT_ID_UNUSED_1, // 4, was NAV_STATE_POSHOLD_2D_INITIALIZE
NAV_PERSISTENT_ID_UNUSED_2, // 5, was NAV_STATE_POSHOLD_2D_IN_PROGRESS
NAV_PERSISTENT_ID_UNUSED_1 = 4, // was NAV_STATE_POSHOLD_2D_INITIALIZE
NAV_PERSISTENT_ID_UNUSED_2 = 5, // was NAV_STATE_POSHOLD_2D_IN_PROGRESS
NAV_PERSISTENT_ID_POSHOLD_3D_INITIALIZE, // 6
NAV_PERSISTENT_ID_POSHOLD_3D_IN_PROGRESS, // 7
NAV_PERSISTENT_ID_POSHOLD_3D_INITIALIZE = 6,
NAV_PERSISTENT_ID_POSHOLD_3D_IN_PROGRESS = 7,
NAV_PERSISTENT_ID_RTH_INITIALIZE, // 8
NAV_PERSISTENT_ID_RTH_CLIMB_TO_SAFE_ALT, // 9
NAV_PERSISTENT_ID_RTH_HEAD_HOME, // 10
NAV_PERSISTENT_ID_RTH_HOVER_PRIOR_TO_LANDING, // 11
NAV_PERSISTENT_ID_RTH_LANDING, // 12
NAV_PERSISTENT_ID_RTH_FINISHING, // 13
NAV_PERSISTENT_ID_RTH_FINISHED, // 14
NAV_PERSISTENT_ID_RTH_INITIALIZE = 8,
NAV_PERSISTENT_ID_RTH_CLIMB_TO_SAFE_ALT = 9,
NAV_PERSISTENT_ID_RTH_HEAD_HOME = 10,
NAV_PERSISTENT_ID_RTH_HOVER_PRIOR_TO_LANDING = 11,
NAV_PERSISTENT_ID_RTH_HOVER_ABOVE_HOME = 29,
NAV_PERSISTENT_ID_RTH_LANDING = 12,
NAV_PERSISTENT_ID_RTH_FINISHING = 13,
NAV_PERSISTENT_ID_RTH_FINISHED = 14,
NAV_PERSISTENT_ID_WAYPOINT_INITIALIZE, // 15
NAV_PERSISTENT_ID_WAYPOINT_PRE_ACTION, // 16
NAV_PERSISTENT_ID_WAYPOINT_IN_PROGRESS, // 17
NAV_PERSISTENT_ID_WAYPOINT_REACHED, // 18
NAV_PERSISTENT_ID_WAYPOINT_NEXT, // 19
NAV_PERSISTENT_ID_WAYPOINT_FINISHED, // 20
NAV_PERSISTENT_ID_WAYPOINT_RTH_LAND, // 21
NAV_PERSISTENT_ID_WAYPOINT_INITIALIZE = 15,
NAV_PERSISTENT_ID_WAYPOINT_PRE_ACTION = 16,
NAV_PERSISTENT_ID_WAYPOINT_IN_PROGRESS = 17,
NAV_PERSISTENT_ID_WAYPOINT_REACHED = 18,
NAV_PERSISTENT_ID_WAYPOINT_NEXT = 19,
NAV_PERSISTENT_ID_WAYPOINT_FINISHED = 20,
NAV_PERSISTENT_ID_WAYPOINT_RTH_LAND = 21,
NAV_PERSISTENT_ID_EMERGENCY_LANDING_INITIALIZE, // 22
NAV_PERSISTENT_ID_EMERGENCY_LANDING_IN_PROGRESS, // 23
NAV_PERSISTENT_ID_EMERGENCY_LANDING_FINISHED, // 24
NAV_PERSISTENT_ID_EMERGENCY_LANDING_INITIALIZE = 22,
NAV_PERSISTENT_ID_EMERGENCY_LANDING_IN_PROGRESS = 23,
NAV_PERSISTENT_ID_EMERGENCY_LANDING_FINISHED = 24,
NAV_PERSISTENT_ID_LAUNCH_INITIALIZE, // 25
NAV_PERSISTENT_ID_LAUNCH_WAIT, // 26
NAV_PERSISTENT_ID_UNUSED_3, // 27, was NAV_STATE_LAUNCH_MOTOR_DELAY
NAV_PERSISTENT_ID_LAUNCH_IN_PROGRESS, // 28
NAV_PERSISTENT_ID_LAUNCH_INITIALIZE = 25,
NAV_PERSISTENT_ID_LAUNCH_WAIT = 26,
NAV_PERSISTENT_ID_UNUSED_3 = 27, // was NAV_STATE_LAUNCH_MOTOR_DELAY
NAV_PERSISTENT_ID_LAUNCH_IN_PROGRESS = 28,
} navigationPersistentId_e;
typedef enum {
@ -233,6 +242,7 @@ typedef enum {
NAV_STATE_RTH_CLIMB_TO_SAFE_ALT,
NAV_STATE_RTH_HEAD_HOME,
NAV_STATE_RTH_HOVER_PRIOR_TO_LANDING,
NAV_STATE_RTH_HOVER_ABOVE_HOME,
NAV_STATE_RTH_LANDING,
NAV_STATE_RTH_FINISHING,
NAV_STATE_RTH_FINISHED,
@ -326,6 +336,7 @@ typedef struct {
rthSanityChecker_t rthSanityChecker;
navWaypointPosition_t homePosition; // Special waypoint, stores original yaw (heading when launched)
navWaypointPosition_t homeWaypointAbove; // NEU-coordinates and initial bearing + desired RTH altitude
navigationHomeFlags_t homeFlags;
uint32_t homeDistance; // cm
int32_t homeDirection; // deg*100
@ -362,7 +373,7 @@ bool isLandingDetected(void);
navigationFSMStateFlags_t navGetCurrentStateFlags(void);
void setHomePosition(const fpVector3_t * pos, int32_t yaw, navSetWaypointFlags_t useMask);
void setHomePosition(const fpVector3_t * pos, int32_t yaw, navSetWaypointFlags_t useMask, navigationHomeFlags_t homeFlags);
void setDesiredPosition(const fpVector3_t * pos, int32_t yaw, navSetWaypointFlags_t useMask);
void setDesiredSurfaceOffset(float surfaceOffset);
void setDesiredPositionToFarAwayTarget(int32_t yaw, int32_t distance, navSetWaypointFlags_t useMask);

View file

@ -257,7 +257,7 @@ void crsfRxSendTelemetryData(void)
bool crsfRxInit(const rxConfig_t *rxConfig, rxRuntimeConfig_t *rxRuntimeConfig)
{
for (int ii = 0; ii < CRSF_MAX_CHANNEL; ++ii) {
crsfChannelData[ii] = (16 * rxConfig->midrc) / 10 - 1408;
crsfChannelData[ii] = (16 * PWM_RANGE_MIDDLE) / 10 - 1408;
}
rxRuntimeConfig->channelCount = CRSF_MAX_CHANNEL;

View file

@ -48,6 +48,7 @@
#define FPORT_MIN_TELEMETRY_RESPONSE_DELAY_US 500
#define FPORT_MAX_TELEMETRY_AGE_MS 500
#define FPORT_TELEMETRY_MAX_CONSECUTIVE_SENSORS 2 // Needed to avoid lost sensors on FPort, see #3198
#define FPORT_FRAME_MARKER 0x7E
@ -340,7 +341,17 @@ static bool fportProcessFrame(const rxRuntimeConfig_t *rxRuntimeConfig)
if (clearToSend) {
DEBUG_SET(DEBUG_FPORT, DEBUG_FPORT_TELEMETRY_DELAY, currentTimeUs - lastTelemetryFrameReceivedUs);
processSmartPortTelemetry(mspPayload, &clearToSend, NULL);
uint8_t *consecutiveSensorCount = rxRuntimeConfig->frameData;
if (*consecutiveSensorCount >= FPORT_TELEMETRY_MAX_CONSECUTIVE_SENSORS && !smartPortPayloadContainsMSP(mspPayload)) {
// Stop one cycle to avoid saturating the buffer in the RX, since the
// downstream bandwidth doesn't allow sensor sensors on every cycle.
// We allow MSP frames to run over the resting period, expecting that
// the caller won't flood us with requests.
*consecutiveSensorCount = 0;
} else {
(*consecutiveSensorCount)++;
processSmartPortTelemetry(mspPayload, &clearToSend, NULL);
}
if (clearToSend) {
smartPortWriteFrameFport(&emptySmartPortFrame);
@ -358,8 +369,10 @@ static bool fportProcessFrame(const rxRuntimeConfig_t *rxRuntimeConfig)
bool fportRxInit(const rxConfig_t *rxConfig, rxRuntimeConfig_t *rxRuntimeConfig)
{
static uint16_t sbusChannelData[SBUS_MAX_CHANNEL];
static uint8_t consecutiveSensorCount = 0;
rxRuntimeConfig->channelData = sbusChannelData;
sbusChannelsInit(rxConfig, rxRuntimeConfig);
rxRuntimeConfig->frameData = &consecutiveSensorCount;
sbusChannelsInit(rxRuntimeConfig);
rxRuntimeConfig->channelCount = SBUS_MAX_CHANNEL;
rxRuntimeConfig->rxRefreshRate = 11000;

View file

@ -113,7 +113,6 @@ PG_REGISTER_WITH_RESET_TEMPLATE(rxConfig_t, rxConfig, PG_RX_CONFIG, 4);
#define DEFAULT_RX_TYPE RX_TYPE_NONE
#endif
#define RX_MIDRC 1500
#define RX_MIN_USEX 885
PG_RESET_TEMPLATE(rxConfig_t, rxConfig,
.receiverType = DEFAULT_RX_TYPE,
@ -123,7 +122,6 @@ PG_RESET_TEMPLATE(rxConfig_t, rxConfig,
.rx_spi_protocol = RX_SPI_DEFAULT_PROTOCOL,
.spektrum_sat_bind = 0,
.serialrx_inverted = 0,
.midrc = RX_MIDRC,
.mincheck = 1100,
.maxcheck = 1900,
.rx_min_usec = RX_MIN_USEX, // any of first 4 channels below this value will trigger rx loss detection
@ -244,11 +242,11 @@ void rxInit(void)
rcSampleIndex = 0;
for (int i = 0; i < MAX_SUPPORTED_RC_CHANNEL_COUNT; i++) {
rcData[i] = rxConfig()->midrc;
rcData[i] = PWM_RANGE_MIDDLE;
rcInvalidPulsPeriod[i] = millis() + MAX_INVALID_PULS_TIME;
}
rcData[THROTTLE] = (feature(FEATURE_3D)) ? rxConfig()->midrc : rxConfig()->rx_min_usec;
rcData[THROTTLE] = (feature(FEATURE_3D)) ? PWM_RANGE_MIDDLE : rxConfig()->rx_min_usec;
// Initialize ARM switch to OFF position when arming via switch is defined
for (int i = 0; i < MAX_MODE_ACTIVATION_CONDITION_COUNT; i++) {

View file

@ -121,7 +121,7 @@ typedef struct rxConfig_s {
uint8_t rssi_channel;
uint8_t rssi_scale;
uint8_t rssiInvert;
uint16_t midrc; // Some radios have not a neutral point centered on 1500. can be changed here
uint16_t __reserved; // was micrd
uint16_t mincheck; // minimum rc end
uint16_t maxcheck; // maximum rc end
uint16_t rx_min_usec;

View file

@ -193,7 +193,7 @@ bool sbusInit(const rxConfig_t *rxConfig, rxRuntimeConfig_t *rxRuntimeConfig)
rxRuntimeConfig->channelData = sbusChannelData;
rxRuntimeConfig->frameData = &sbusFrameData;
sbusChannelsInit(rxConfig, rxRuntimeConfig);
sbusChannelsInit(rxRuntimeConfig);
rxRuntimeConfig->channelCount = SBUS_MAX_CHANNEL;
rxRuntimeConfig->rxRefreshRate = 11000;

View file

@ -84,11 +84,11 @@ static uint16_t sbusChannelsReadRawRC(const rxRuntimeConfig_t *rxRuntimeConfig,
return (5 * rxRuntimeConfig->channelData[chan] / 8) + 880;
}
void sbusChannelsInit(const rxConfig_t *rxConfig, rxRuntimeConfig_t *rxRuntimeConfig)
void sbusChannelsInit(rxRuntimeConfig_t *rxRuntimeConfig)
{
rxRuntimeConfig->rcReadRawFn = sbusChannelsReadRawRC;
for (int b = 0; b < SBUS_MAX_CHANNEL; b++) {
rxRuntimeConfig->channelData[b] = (16 * rxConfig->midrc) / 10 - 1408;
rxRuntimeConfig->channelData[b] = (16 * PWM_RANGE_MIDDLE) / 10 - 1408;
}
}
#endif

View file

@ -49,4 +49,4 @@ typedef struct sbusChannels_s {
uint8_t sbusChannelsDecode(rxRuntimeConfig_t *rxRuntimeConfig, const sbusChannels_t *channels);
void sbusChannelsInit(const rxConfig_t *rxConfig, rxRuntimeConfig_t *rxRuntimeConfig);
void sbusChannelsInit(rxRuntimeConfig_t *rxRuntimeConfig);

View file

@ -42,6 +42,7 @@
#include "io/beeper.h"
#include "build/debug.h"
#define ADCVREF 3300 // in mV (3300 = 3.3V)
@ -65,6 +66,8 @@ static bool batteryFullWhenPluggedIn = false;
static uint16_t vbat = 0; // battery voltage in 0.1V steps (filtered)
static uint16_t vbatLatestADC = 0; // most recent unsmoothed raw reading from vbat ADC
static uint16_t amperageLatestADC = 0; // most recent raw reading from current ADC
static uint16_t powerSupplyImpedance = 0; // calculated impedance in milliohm
static uint16_t sagCompensatedVBat = 0; // calculated no load vbat
static int32_t amperage = 0; // amperage read by current sensor in centiampere (1/100th A)
static int32_t power = 0; // power draw in cW (0.01W resolution)
@ -122,20 +125,20 @@ void batteryInit(void)
batteryCriticalVoltage = 0;
}
static void updateBatteryVoltage(uint32_t vbatTimeDelta)
static void updateBatteryVoltage(timeUs_t timeDelta)
{
uint16_t vbatSample;
static pt1Filter_t vbatFilterState;
// store the battery voltage with some other recent battery voltage readings
vbatSample = vbatLatestADC = adcGetChannel(ADC_BATTERY);
vbatSample = pt1FilterApply4(&vbatFilterState, vbatSample, VBATT_LPF_FREQ, vbatTimeDelta * 1e-6f);
vbatSample = pt1FilterApply4(&vbatFilterState, vbatSample, VBATT_LPF_FREQ, timeDelta * 1e-6f);
vbat = batteryAdcToVoltage(vbatSample);
}
void batteryUpdate(uint32_t vbatTimeDelta)
void batteryUpdate(timeUs_t timeDelta)
{
updateBatteryVoltage(vbatTimeDelta);
updateBatteryVoltage(timeDelta);
/* battery has just been connected*/
if (batteryState == BATTERY_NOT_PRESENT && vbat > VBATT_PRESENT_THRESHOLD)
@ -147,7 +150,7 @@ void batteryUpdate(uint32_t vbatTimeDelta)
We only do this on the ground so don't care if we do block, not
worse than original code anyway*/
delay(VBATT_STABLE_DELAY);
updateBatteryVoltage(vbatTimeDelta);
updateBatteryVoltage(timeDelta);
unsigned cells = (batteryAdcToVoltage(vbatLatestADC) / batteryConfig()->voltage.cellDetect) + 1;
if (cells > 8) cells = 8; // something is wrong, we expect 8 cells maximum (and autodetection will be problematic at 6+ cells)
@ -245,6 +248,16 @@ uint16_t getBatteryVoltage(void)
return vbat;
}
uint16_t getSagCompensatedBatteryVoltage(void)
{
return sagCompensatedVBat;
}
float calculateThrottleCompensationFactor(void)
{
return batteryFullVoltage / sagCompensatedVBat;
}
uint16_t getBatteryVoltageLatestADC(void)
{
return vbatLatestADC;
@ -275,7 +288,7 @@ uint32_t getBatteryRemainingCapacity(void)
bool isAmperageConfigured(void)
{
return batteryConfig()->current.type != CURRENT_SENSOR_NONE;
return feature(FEATURE_CURRENT_METER) && batteryConfig()->current.type != CURRENT_SENSOR_NONE;
}
int32_t getAmperage(void)
@ -304,7 +317,7 @@ int32_t getMWhDrawn(void)
}
void currentMeterUpdate(int32_t timeDelta)
void currentMeterUpdate(timeUs_t timeDelta)
{
static pt1Filter_t amperageFilterState;
static int64_t mAhdrawnRaw = 0;
@ -333,15 +346,51 @@ void currentMeterUpdate(int32_t timeDelta)
mAhDrawn = mAhdrawnRaw / (3600 * 100);
}
void powerMeterUpdate(int32_t timeDelta)
void powerMeterUpdate(timeUs_t timeDelta)
{
static int64_t mWhDrawnRaw = 0;
uint32_t power_mW = amperage * vbat / 10;
power = amperage * vbat / 100; // power unit is cW (0.01W resolution)
mWhDrawnRaw += (power_mW * timeDelta) / 10000;
int32_t heatLossesCompensatedPower_mW = amperage * vbat / 10 + sq((int64_t)amperage) * powerSupplyImpedance / 10000;
mWhDrawnRaw += (int64_t)heatLossesCompensatedPower_mW * timeDelta / 10000;
mWhDrawn = mWhDrawnRaw / (3600 * 100);
}
void sagCompensatedVBatUpdate(timeUs_t currentTime)
{
static timeUs_t recordTimestamp = 0;
static int32_t amperageRecord;
static uint16_t vbatRecord;
if (batteryState == BATTERY_NOT_PRESENT) {
recordTimestamp = 0;
powerSupplyImpedance = 0;
sagCompensatedVBat = vbat;
} else {
if (cmpTimeUs(currentTime, recordTimestamp) > 20000000)
recordTimestamp = 0;
if (!recordTimestamp) {
amperageRecord = amperage;
vbatRecord = vbat;
recordTimestamp = currentTime;
} else if ((amperage - amperageRecord >= 400) && ((int16_t)vbatRecord - vbat >= 10)) {
powerSupplyImpedance = (int32_t)(vbatRecord - vbat) * 1000 / (amperage - amperageRecord);
amperageRecord = amperage;
vbatRecord = vbat;
recordTimestamp = currentTime;
}
sagCompensatedVBat = MIN(batteryFullVoltage, vbat + powerSupplyImpedance * amperage / 1000);
}
DEBUG_SET(DEBUG_SAG_COMP_VOLTAGE, 0, powerSupplyImpedance);
DEBUG_SET(DEBUG_SAG_COMP_VOLTAGE, 1, sagCompensatedVBat);
}
uint8_t calculateBatteryPercentage(void)
{
if (batteryState == BATTERY_NOT_PRESENT)

View file

@ -18,6 +18,7 @@
#pragma once
#include "config/parameter_group.h"
#include "drivers/time.h"
#ifndef VBAT_SCALE_DEFAULT
#define VBAT_SCALE_DEFAULT 1100
@ -83,11 +84,11 @@ uint16_t batteryAdcToVoltage(uint16_t src);
batteryState_e getBatteryState(void);
bool batteryWasFullWhenPluggedIn(void);
bool batteryUsesCapacityThresholds(void);
void batteryUpdate(uint32_t vbatTimeDelta);
void batteryInit(void);
bool isBatteryVoltageConfigured(void);
uint16_t getBatteryVoltage(void);
uint16_t getSagCompensatedBatteryVoltage(void);
uint16_t getBatteryVoltageLatestADC(void);
uint16_t getBatteryWarningVoltage(void);
uint8_t getBatteryCellCount(void);
@ -101,8 +102,10 @@ int32_t getPower(void);
int32_t getMAhDrawn(void);
int32_t getMWhDrawn(void);
void currentMeterUpdate(int32_t lastUpdateAt);
void powerMeterUpdate(int32_t lastUpdateAt);
void batteryUpdate(timeUs_t timeDelta);
void currentMeterUpdate(timeUs_t timeDelta);
void sagCompensatedVBatUpdate(timeUs_t currentTime);
void powerMeterUpdate(timeUs_t timeDelta);
uint8_t calculateBatteryPercentage(void);
float calculateThrottleCompensationFactor(void);

View file

@ -169,12 +169,6 @@ static bool rangefinderDetect(rangefinderDev_t * dev, uint8_t rangefinderHardwar
return true;
}
void rangefinderResetDynamicThreshold(void)
{
rangefinder.snrThresholdReached = false;
rangefinder.dynamicDistanceThreshold = 0;
}
bool rangefinderInit(void)
{
if (!rangefinderDetect(&rangefinder.dev, rangefinderConfig()->rangefinder_hardware)) {
@ -186,9 +180,6 @@ bool rangefinderInit(void)
rangefinder.calculatedAltitude = RANGEFINDER_OUT_OF_RANGE;
rangefinder.maxTiltCos = cos_approx(DECIDEGREES_TO_RADIANS(rangefinder.dev.detectionConeExtendedDeciDegrees / 2.0f));
rangefinder.lastValidResponseTimeMs = millis();
rangefinder.snr = 0;
rangefinderResetDynamicThreshold();
return true;
}
@ -211,35 +202,6 @@ static int32_t applyMedianFilter(int32_t newReading)
return medianFilterReady ? quickMedianFilter5(filterSamples) : newReading;
}
static int16_t computePseudoSnr(int32_t newReading) {
#define SNR_SAMPLES 5
static int16_t snrSamples[SNR_SAMPLES];
static uint8_t snrSampleIndex = 0;
static int32_t previousReading = RANGEFINDER_OUT_OF_RANGE;
static bool snrReady = false;
int16_t pseudoSnr = 0;
snrSamples[snrSampleIndex] = constrain((int)(pow(newReading - previousReading, 2) / 10), 0, 6400);
++snrSampleIndex;
if (snrSampleIndex == SNR_SAMPLES) {
snrSampleIndex = 0;
snrReady = true;
}
previousReading = newReading;
if (snrReady) {
for (uint8_t i = 0; i < SNR_SAMPLES; i++) {
pseudoSnr += snrSamples[i];
}
return constrain(pseudoSnr, 0, 32000);
} else {
return RANGEFINDER_OUT_OF_RANGE;
}
}
/*
* This is called periodically by the scheduler
*/
@ -252,34 +214,6 @@ timeDelta_t rangefinderUpdate(void)
return rangefinder.dev.delayMs * 1000; // to microseconds
}
bool isSurfaceAltitudeValid() {
/*
* Preconditions: raw and calculated altidude > 0
* SNR lower than threshold
*/
if (
rangefinder.calculatedAltitude > 0 &&
rangefinder.rawAltitude > 0 &&
rangefinder.snr < RANGEFINDER_DYNAMIC_THRESHOLD
) {
/*
* When critical altitude was determined, distance reported by rangefinder
* has to be lower than it to assume healthy readout
*/
if (rangefinder.snrThresholdReached) {
return (rangefinder.rawAltitude < rangefinder.dynamicDistanceThreshold);
} else {
return true;
}
} else {
return false;
}
}
/**
* Get the last distance measured by the sonar in centimeters. When the ground is too far away, RANGEFINDER_OUT_OF_RANGE is returned.
*/
@ -309,20 +243,6 @@ bool rangefinderProcess(float cosTiltAngle)
// Invalid response / hardware failure
rangefinder.rawAltitude = RANGEFINDER_HARDWARE_FAILURE;
}
rangefinder.snr = computePseudoSnr(distance);
if (rangefinder.snrThresholdReached == false && rangefinder.rawAltitude > 0) {
if (rangefinder.snr < RANGEFINDER_DYNAMIC_THRESHOLD && rangefinder.dynamicDistanceThreshold < rangefinder.rawAltitude) {
rangefinder.dynamicDistanceThreshold = rangefinder.rawAltitude * RANGEFINDER_DYNAMIC_FACTOR / 100;
}
if (rangefinder.snr >= RANGEFINDER_DYNAMIC_THRESHOLD) {
rangefinder.snrThresholdReached = true;
}
}
}
else {
// Bad configuration

View file

@ -44,17 +44,12 @@ typedef struct rangefinder_s {
int32_t rawAltitude;
int32_t calculatedAltitude;
timeMs_t lastValidResponseTimeMs;
bool snrThresholdReached;
int32_t dynamicDistanceThreshold;
int16_t snr;
} rangefinder_t;
extern rangefinder_t rangefinder;
const rangefinderHardwarePins_t * rangefinderGetHardwarePins(void);
void rangefinderResetDynamicThreshold(void);
bool rangefinderInit(void);
int32_t rangefinderGetLatestAltitude(void);

View file

@ -59,7 +59,6 @@
#include "telemetry/msp_shared.h"
#define SMARTPORT_MIN_TELEMETRY_RESPONSE_DELAY_US 500
#define SMARTPORT_REST_PERIOD 3 // Needed to avoid lost sensors on FPort, see #3198
// these data identifiers are obtained from https://github.com/opentx/opentx/blob/master/radio/src/telemetry/frsky_hub.h
enum
@ -138,7 +137,6 @@ enum
static uint8_t telemetryState = TELEMETRY_STATE_UNINITIALIZED;
static uint8_t smartPortIdCnt = 0;
static bool smartPortHasRested = false;
typedef struct smartPortFrame_s {
uint8_t sensorId;
@ -233,6 +231,11 @@ void smartPortSendByte(uint8_t c, uint16_t *checksum, serialPort_t *port)
}
}
bool smartPortPayloadContainsMSP(const smartPortPayload_t *payload)
{
return payload && (payload->frameId == FSSP_MSPC_FRAME_SMARTPORT || payload->frameId == FSSP_MSPC_FRAME_FPORT);
}
void smartPortWriteFrameSerial(const smartPortPayload_t *payload, serialPort_t *port, uint16_t checksum)
{
uint8_t *data = (uint8_t *)payload;
@ -343,7 +346,7 @@ void processSmartPortTelemetry(smartPortPayload_t *payload, volatile bool *clear
// unless we start receiving other sensors' packets
#if defined(USE_MSP_OVER_TELEMETRY)
if (payload->frameId == FSSP_MSPC_FRAME_SMARTPORT || payload->frameId == FSSP_MSPC_FRAME_FPORT) {
if (smartPortPayloadContainsMSP(payload)) {
// Pass only the payload: skip frameId
uint8_t *frameStart = (uint8_t *)&payload->valueId;
smartPortMspReplyPending = handleMspFrame(frameStart, SMARTPORT_MSP_PAYLOAD_SIZE);
@ -380,14 +383,6 @@ void processSmartPortTelemetry(smartPortPayload_t *payload, volatile bool *clear
id = frSkyDataIdTable[smartPortIdCnt];
}
smartPortIdCnt++;
if (smartPortIdCnt % SMARTPORT_REST_PERIOD == 0) {
if (!smartPortHasRested) {
smartPortIdCnt--;
smartPortHasRested = true;
return;
}
smartPortHasRested = false;
}
switch (id) {
case FSSP_DATAID_VFAS :

View file

@ -55,3 +55,4 @@ smartPortPayload_t *smartPortDataReceive(uint16_t c, bool *clearToSend, smartPor
struct serialPort_s;
void smartPortWriteFrameSerial(const smartPortPayload_t *payload, struct serialPort_s *port, uint16_t checksum);
void smartPortSendByte(uint8_t c, uint16_t *checksum, struct serialPort_s *port);
bool smartPortPayloadContainsMSP(const smartPortPayload_t *payload);

View file

@ -65,7 +65,9 @@ class Stamper
output = File.join(@stamp_dir, "stamp")
stdout, stderr = @compiler.run(input, output, ["-dM", "-E"])
File.delete(input)
File.delete(output)
if File.file?(output)
File.delete(output)
end
return Digest::SHA1.hexdigest(stdout)
end
end

View file

@ -80,7 +80,10 @@ class Compiler
if args
all_args.push(*args)
end
all_args << "-o" << output << input
if output
all_args << "-o" << output
end
all_args << input
stdout, stderr, compile_status = Open3.capture3(join_args(all_args))
raise "Compiler error:\n#{all_args.join(' ')}\n#{stderr}" if not options[:noerror] and not compile_status.success?
return stdout, stderr

View file

@ -260,10 +260,10 @@ end
OFF_ON_TABLE = Hash["name" => "off_on", "values" => ["OFF", "ON"]]
class Generator
def initialize(src_root, settings_file)
def initialize(src_root, settings_file, output_dir)
@src_root = src_root
@settings_file = settings_file
@output_dir = File.dirname(settings_file)
@output_dir = output_dir || File.dirname(settings_file)
@compiler = Compiler.new
@ -416,7 +416,7 @@ class Generator
}
add_header.call("platform.h")
add_header.call("config/parameter_group_ids.h")
add_header.call("settings.h")
add_header.call("fc/settings.h")
foreach_enabled_group do |group|
(group["headers"] || []).each do |h|
@ -623,10 +623,12 @@ class Generator
# Use a temporary dir reachable by relative path
# since g++ in cygwin fails to open files
# with absolute paths
tmp = File.join("obj", "tmp")
tmp = File.join(@output_dir, "tmp")
FileUtils.mkdir_p(tmp) unless File.directory?(tmp)
value = yield(tmp)
FileUtils.remove_dir(tmp)
if File.directory?(tmp)
FileUtils.remove_dir(tmp)
end
value
end
@ -882,17 +884,20 @@ if __FILE__ == $0
exit(1)
end
gen = Generator.new(src_root, settings_file)
opts = GetoptLong.new(
[ "--output-dir", "-o", GetoptLong::REQUIRED_ARGUMENT ],
[ "--help", "-h", GetoptLong::NO_ARGUMENT ],
[ "--json", "-j", GetoptLong::REQUIRED_ARGUMENT ],
)
jsonFile = nil
output_dir = nil
opts.each do |opt, arg|
case opt
when "--output-dir"
output_dir = arg
when "--help"
usage()
exit(0)
@ -901,6 +906,8 @@ if __FILE__ == $0
end
end
gen = Generator.new(src_root, settings_file, output_dir)
if jsonFile
gen.write_json(jsonFile)
else