1
0
Fork 0
mirror of https://github.com/iNavFlight/inav.git synced 2025-07-13 11:29:56 +03:00

Merge branch 'master' into change-profiles-with-programming

This commit is contained in:
Darren Lines 2021-10-28 18:37:24 +01:00
commit 787e9a76b2
22 changed files with 325 additions and 82 deletions

View file

@ -74,9 +74,9 @@ IPF can be edited using INAV Configurator user interface, of via CLI
| 38 | RC_CHANNEL_OVERRIDE | Overrides channel set by `Operand A` to value of `Operand B` | | 38 | RC_CHANNEL_OVERRIDE | Overrides channel set by `Operand A` to value of `Operand B` |
| 39 | SET_HEADING_TARGET | Sets heading-hold target to `Operand A`, in degrees. Value wraps-around. | | 39 | SET_HEADING_TARGET | Sets heading-hold target to `Operand A`, in degrees. Value wraps-around. |
| 40 | MOD | Divide `Operand A` by `Operand B` and returns the remainder | | 40 | MOD | Divide `Operand A` by `Operand B` and returns the remainder |
| 41 | LOITER_RADIUS_OVERRIDE | Sets the loiter radius to `Operand A` [`0` : `100000`] in cm. If the value is lower than the loiter radius set in the **Advanced Tuning**, that will be used. |
| 42 | SET_PROFILE | Sets the active config profile (PIDFF/Rates/Filters/etc) to `Operand A`. `Operand A` must be a valid profile number, currently from 1 to 3. If not, the profile will not change | | 42 | SET_PROFILE | Sets the active config profile (PIDFF/Rates/Filters/etc) to `Operand A`. `Operand A` must be a valid profile number, currently from 1 to 3. If not, the profile will not change |
### Operands ### Operands
| Operand Type | Name | Notes | | Operand Type | Name | Notes |
@ -126,9 +126,10 @@ IPF can be edited using INAV Configurator user interface, of via CLI
| 30 | ACTIVE_WAYPOINT_ACTION | See ACTIVE_WAYPOINT_ACTION paragraph | | 30 | ACTIVE_WAYPOINT_ACTION | See ACTIVE_WAYPOINT_ACTION paragraph |
| 31 | 3D HOME_DISTANCE | in `meters`, calculated from HOME_DISTANCE and ALTITUDE using Pythagorean theorem | | 31 | 3D HOME_DISTANCE | in `meters`, calculated from HOME_DISTANCE and ALTITUDE using Pythagorean theorem |
| 32 | CROSSFIRE LQ | Crossfire Link quality as returned by the CRSF protocol | | 32 | CROSSFIRE LQ | Crossfire Link quality as returned by the CRSF protocol |
| 33 | CROSSFIRE SNR | Crossfire SNR as returned by the CRSF protocol | | 33 | CROSSFIRE SNR | Crossfire SNR as returned by the CRSF protocol |
| 34 | GPS_VALID | boolean `0`/`1`. True when the GPS has a valid 3D Fix | | 34 | GPS_VALID | boolean `0`/`1`. True when the GPS has a valid 3D Fix |
| 35 | ACTIVE_PROFILE | integer for the active config profile `[1..MAX_PROFILE_COUNT]` | | 35 | LOITER_RADIUS | The current loiter radius in cm. |
| 36 | ACTIVE_PROFILE | integer for the active config profile `[1..MAX_PROFILE_COUNT]` |
#### ACTIVE_WAYPOINT_ACTION #### ACTIVE_WAYPOINT_ACTION

View file

@ -788,17 +788,17 @@ Enable/disable dynamic gyro notch also known as Matrix Filter
| Default | Min | Max | | Default | Min | Max |
| --- | --- | --- | | --- | --- | --- |
| OFF | | | | ON | | |
--- ---
### dynamic_gyro_notch_min_hz ### dynamic_gyro_notch_min_hz
Minimum frequency for dynamic notches. Default value of `150` works best with 5" multirors. Should be lowered with increased size of propellers. Values around `100` work fine on 7" drones. 10" can go down to `60` - `70` Minimum frequency for dynamic notches. Default value of `150` works best with 5" multirotors. Should be lowered with increased size of propellers. Values around `100` work fine on 7" drones. 10" can go down to `60` - `70`
| Default | Min | Max | | Default | Min | Max |
| --- | --- | --- | | --- | --- | --- |
| 150 | 30 | 1000 | | 50 | 30 | 1000 |
--- ---
@ -812,16 +812,6 @@ Q factor for dynamic notches
--- ---
### dynamic_gyro_notch_range
Range for dynamic gyro notches. `MEDIUM` for 5", `HIGH` for 3" and `MEDIUM`/`LOW` for 7" and bigger propellers
| Default | Min | Max |
| --- | --- | --- |
| MEDIUM | | |
---
### eleres_freq ### eleres_freq
_// TODO_ _// TODO_
@ -4092,6 +4082,16 @@ Value above which to make the OSD distance from home indicator blink (meters)
--- ---
### osd_esc_rpm_precision
Number of characters used to display the RPM value.
| Default | Min | Max |
| --- | --- | --- |
| 3 | 3 | 6 |
---
### osd_esc_temp_alarm_max ### osd_esc_temp_alarm_max
Temperature above which the IMU temperature OSD element will start blinking (decidegrees centigrade) Temperature above which the IMU temperature OSD element will start blinking (decidegrees centigrade)

View file

@ -161,6 +161,8 @@ main_sources(COMMON_SRC
drivers/compass/compass_rm3100.h drivers/compass/compass_rm3100.h
drivers/compass/compass_vcm5883.c drivers/compass/compass_vcm5883.c
drivers/compass/compass_vcm5883.h drivers/compass/compass_vcm5883.h
drivers/compass/compass_mlx90393.c
drivers/compass/compass_mlx90393.h
drivers/compass/compass_msp.c drivers/compass/compass_msp.c
drivers/compass/compass_msp.h drivers/compass/compass_msp.h

View file

@ -1809,7 +1809,6 @@ static bool blackboxWriteSysinfo(void)
BLACKBOX_PRINT_HEADER_LINE("gyro_lpf_hz", "%d", gyroConfig()->gyro_main_lpf_hz); BLACKBOX_PRINT_HEADER_LINE("gyro_lpf_hz", "%d", gyroConfig()->gyro_main_lpf_hz);
BLACKBOX_PRINT_HEADER_LINE("gyro_lpf_type", "%d", gyroConfig()->gyro_main_lpf_type); BLACKBOX_PRINT_HEADER_LINE("gyro_lpf_type", "%d", gyroConfig()->gyro_main_lpf_type);
#ifdef USE_DYNAMIC_FILTERS #ifdef USE_DYNAMIC_FILTERS
BLACKBOX_PRINT_HEADER_LINE("dynamicGyroNotchRange", "%d", gyroConfig()->dynamicGyroNotchRange);
BLACKBOX_PRINT_HEADER_LINE("dynamicGyroNotchQ", "%d", gyroConfig()->dynamicGyroNotchQ); BLACKBOX_PRINT_HEADER_LINE("dynamicGyroNotchQ", "%d", gyroConfig()->dynamicGyroNotchQ);
BLACKBOX_PRINT_HEADER_LINE("dynamicGyroNotchMinHz", "%d", gyroConfig()->dynamicGyroNotchMinHz); BLACKBOX_PRINT_HEADER_LINE("dynamicGyroNotchMinHz", "%d", gyroConfig()->dynamicGyroNotchMinHz);
#endif #endif

View file

@ -118,6 +118,7 @@ typedef enum {
DEVHW_LIS3MDL, DEVHW_LIS3MDL,
DEVHW_RM3100, DEVHW_RM3100,
DEVHW_VCM5883, DEVHW_VCM5883,
DEVHW_MLX90393,
/* Temp sensor chips */ /* Temp sensor chips */
DEVHW_LM75_0, DEVHW_LM75_0,

View file

@ -0,0 +1,176 @@
/*
* This file is part of iNav.
*
* iNav is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* iNav is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with iNav. If not, see <http://www.gnu.org/licenses/>.
*/
#include "platform.h"
#ifdef USE_MAG_MLX90393
#include <stdbool.h>
#include <stdint.h>
#include <math.h>
#include "build/debug.h"
#include "common/axis.h"
#include "common/maths.h"
#include "common/utils.h"
#include "drivers/time.h"
#include "drivers/io.h"
#include "drivers/bus.h"
#include "drivers/sensor.h"
#include "drivers/compass/compass.h"
#define MLX90393_MEASURE_3D 0b00001110
#define MLX90393_NOP 0b00000000
#define MLX90393_START_BURST_MODE 0b00010000 //uses with zyxt flags
#define MLX90393_START_WAKE_UP_ON_CHANGE_MODE 0b00100000 //uses with zyxt flags
#define MLX90393_START_SINGLE_MEASUREMENT_MODE 0b00110000 //uses with zyxt flags
#define MLX90393_READ_MEASUREMENT 0b01000000 //uses with zyxt flags
#define MLX90393_READ_REGISTER 0b01010000
#define MLX90393_WRITE_REGISTER 0b01100000
#define MLX90393_EXIT_MODE 0b10000000
#define MLX90393_MEMORY_RECALL 0b11010000
#define MLX90393_MEMORY_STORE 0b11100000
#define MLX90393_RESET 0b11110000
#define MLX90393_BURST_MODE_FLAG 0b10000000
#define MLX90393_WAKE_UP_ON_CHANGE_MODE_FLAG 0b01000000
#define MLX90393_SINGLE_MEASUREMENT_MODE_FLAG 0b00100000
#define MLX90393_ERROR_FLAG 0b00010000
#define MLX90393_SINGLE_ERROR_DETECTION_FLAG 0b00001000
#define MLX90393_RESET_FLAG 0b00000100
#define MLX90393_D1_FLAG 0b00000010
#define MLX90393_D0_FLAG 0b00000001
#define DETECTION_MAX_RETRY_COUNT 5
#define REG_BUF_LEN 3
// Register 1
#define GAIN_SEL_HALLCONF_REG 0x0 //from datasheet 0x0 << 2 = 0x0
// GAIN - 0b111
// Hall_conf - 0xC
#define GAIN_SEL_HALLCONF_REG_VALUE 0x007C
// Register 2
#define TCMP_EN_REG 0x4 //from datasheet 0x1 << 2 = 0x4
// Burst Data Rate 0b000100
#define TCMP_EN_REG_VALUE 0x62C4
// Register 3
#define RES_XYZ_OSR_FLT_REG 0x8 //from datasheet 0x2 << 2 = 0x8
// Oversampling 0b01
// Filtering 0b111
#define RES_XYZ_OSR_FLT_REG_VALUE 0x001D
static void mlx90393WriteRegister(magDev_t * mag, uint8_t reg_val, uint16_t value) {
uint8_t buf[REG_BUF_LEN] = {0};
buf[0] = (value >> 8) & 0xFF;
buf[1] = (value >> 0) & 0xFF;
buf[2] = reg_val;
busWriteBuf(mag->busDev, MLX90393_WRITE_REGISTER, buf, REG_BUF_LEN);
// PAUSE
delay(20);
// To skip ACK FLAG of Write
uint8_t sig = 0;
busRead(mag->busDev, MLX90393_NOP, &sig);
return;
}
// =======================================================================================
static bool mlx90393Read(magDev_t * mag)
{
uint8_t buf[7] = {0};
busReadBuf(mag->busDev, MLX90393_READ_MEASUREMENT | MLX90393_MEASURE_3D, buf, 7);
mag->magADCRaw[X] = ((short)(buf[1] << 8 | buf[2]));
mag->magADCRaw[Y] = ((short)(buf[3] << 8 | buf[4]));
mag->magADCRaw[Z] = ((short)(buf[5] << 8 | buf[6]));
return true;
}
static bool deviceDetect(magDev_t * mag)
{
for (int retryCount = 0; retryCount < DETECTION_MAX_RETRY_COUNT; retryCount++) {
uint8_t sig = 0;
bool ack = busRead(mag->busDev, MLX90393_RESET, &sig);
delay(20);
if (ack && ((sig & MLX90393_RESET_FLAG) == MLX90393_RESET_FLAG)) { // Check Reset Flag -> MLX90393
return true;
}
}
return false;
}
//--------------------------------------------------
static bool mlx90393Init(magDev_t * mag)
{
uint8_t sig = 0;
delay(20);
// Remove reset flag
busRead(mag->busDev, MLX90393_NOP, &sig);
// Exit if already in burst mode. (For example when external i2c source power the bus.)
busRead(mag->busDev, MLX90393_EXIT_MODE, &sig);
// Writing Registers
mlx90393WriteRegister(mag, GAIN_SEL_HALLCONF_REG, GAIN_SEL_HALLCONF_REG_VALUE);
mlx90393WriteRegister(mag, TCMP_EN_REG, TCMP_EN_REG_VALUE);
mlx90393WriteRegister(mag, RES_XYZ_OSR_FLT_REG, RES_XYZ_OSR_FLT_REG_VALUE);
// Start burst mode
busRead(mag->busDev, MLX90393_START_BURST_MODE | MLX90393_MEASURE_3D, &sig);
return true;
}
// ==========================================================================
bool mlx90393Detect(magDev_t * mag)
{
mag->busDev = busDeviceInit(BUSTYPE_ANY, DEVHW_MLX90393, mag->magSensorToUse, OWNER_COMPASS);
if (mag->busDev == NULL) {
return false;
}
if (!deviceDetect(mag)) {
busDeviceDeInit(mag->busDev);
return false;
}
mag->init = mlx90393Init;
mag->read = mlx90393Read;
return true;
}
#endif

View file

@ -0,0 +1,20 @@
/*
* This file is part of iNav.
*
* iNav is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* iNav is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with iNav. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
bool mlx90393Detect(magDev_t* mag);

View file

@ -13,7 +13,7 @@ tables:
values: ["NONE", "BNO055", "BNO055_SERIAL"] values: ["NONE", "BNO055", "BNO055_SERIAL"]
enum: secondaryImuType_e enum: secondaryImuType_e
- name: mag_hardware - name: mag_hardware
values: ["NONE", "AUTO", "HMC5883", "AK8975", "GPSMAG", "MAG3110", "AK8963", "IST8310", "QMC5883", "MPU9250", "IST8308", "LIS3MDL", "MSP", "RM3100", "VCM5883", "FAKE"] values: ["NONE", "AUTO", "HMC5883", "AK8975", "GPSMAG", "MAG3110", "AK8963", "IST8310", "QMC5883", "MPU9250", "IST8308", "LIS3MDL", "MSP", "RM3100", "VCM5883", "MLX90393", "FAKE"]
enum: magSensor_e enum: magSensor_e
- name: opflow_hardware - name: opflow_hardware
values: ["NONE", "CXOF", "MSP", "FAKE"] values: ["NONE", "CXOF", "MSP", "FAKE"]
@ -144,9 +144,6 @@ tables:
- name: rssi_source - name: rssi_source
values: ["NONE", "AUTO", "ADC", "CHANNEL", "PROTOCOL", "MSP"] values: ["NONE", "AUTO", "ADC", "CHANNEL", "PROTOCOL", "MSP"]
enum: rssiSource_e enum: rssiSource_e
- name: dynamicFilterRangeTable
values: ["HIGH", "MEDIUM", "LOW"]
enum: dynamicFilterRange_e
- name: pidTypeTable - name: pidTypeTable
values: ["NONE", "PID", "PIFF", "AUTO"] values: ["NONE", "PID", "PIFF", "AUTO"]
enum: pidType_e enum: pidType_e
@ -280,16 +277,10 @@ groups:
max: 10 max: 10
- name: dynamic_gyro_notch_enabled - name: dynamic_gyro_notch_enabled
description: "Enable/disable dynamic gyro notch also known as Matrix Filter" description: "Enable/disable dynamic gyro notch also known as Matrix Filter"
default_value: OFF default_value: ON
field: dynamicGyroNotchEnabled field: dynamicGyroNotchEnabled
condition: USE_DYNAMIC_FILTERS condition: USE_DYNAMIC_FILTERS
type: bool type: bool
- name: dynamic_gyro_notch_range
description: "Range for dynamic gyro notches. `MEDIUM` for 5\", `HIGH` for 3\" and `MEDIUM`/`LOW` for 7\" and bigger propellers"
default_value: "MEDIUM"
field: dynamicGyroNotchRange
condition: USE_DYNAMIC_FILTERS
table: dynamicFilterRangeTable
- name: dynamic_gyro_notch_q - name: dynamic_gyro_notch_q
description: "Q factor for dynamic notches" description: "Q factor for dynamic notches"
default_value: 120 default_value: 120
@ -298,8 +289,8 @@ groups:
min: 1 min: 1
max: 1000 max: 1000
- name: dynamic_gyro_notch_min_hz - name: dynamic_gyro_notch_min_hz
description: "Minimum frequency for dynamic notches. Default value of `150` works best with 5\" multirors. Should be lowered with increased size of propellers. Values around `100` work fine on 7\" drones. 10\" can go down to `60` - `70`" description: "Minimum frequency for dynamic notches. Default value of `150` works best with 5\" multirotors. Should be lowered with increased size of propellers. Values around `100` work fine on 7\" drones. 10\" can go down to `60` - `70`"
default_value: 150 default_value: 50
field: dynamicGyroNotchMinHz field: dynamicGyroNotchMinHz
condition: USE_DYNAMIC_FILTERS condition: USE_DYNAMIC_FILTERS
min: 30 min: 30
@ -3319,7 +3310,6 @@ groups:
description: "How many navigation waypoints are displayed, set to 0 (zero) to disable. As sample, if set to 2, and you just passed the 3rd waypoint of the mission, you'll see markers for the 4th waypoint (marked 1) and the 5th waypoint (marked 2)" description: "How many navigation waypoints are displayed, set to 0 (zero) to disable. As sample, if set to 2, and you just passed the 3rd waypoint of the mission, you'll see markers for the 4th waypoint (marked 1) and the 5th waypoint (marked 2)"
default_value: 0 default_value: 0
field: hud_wp_disp field: hud_wp_disp
min: 0 min: 0
max: 3 max: 3
- name: osd_left_sidebar_scroll - name: osd_left_sidebar_scroll
@ -3455,6 +3445,13 @@ groups:
min: -36 min: -36
max: 36 max: 36
- name: osd_esc_rpm_precision
description: Number of characters used to display the RPM value.
field: esc_rpm_precision
min: 3
max: 6
default_value: 3
- name: PG_OSD_COMMON_CONFIG - name: PG_OSD_COMMON_CONFIG
type: osdCommonConfig_t type: osdCommonConfig_t
headers: ["io/osd_common.h"] headers: ["io/osd_common.h"]

View file

@ -60,25 +60,11 @@ FILE_COMPILE_FOR_SPEED
void gyroDataAnalyseStateInit( void gyroDataAnalyseStateInit(
gyroAnalyseState_t *state, gyroAnalyseState_t *state,
uint16_t minFrequency, uint16_t minFrequency,
uint8_t range,
uint32_t targetLooptimeUs uint32_t targetLooptimeUs
) { ) {
state->fftSamplingRateHz = DYN_NOTCH_RANGE_HZ_LOW;
state->minFrequency = minFrequency; state->minFrequency = minFrequency;
if (range == DYN_NOTCH_RANGE_HIGH) { state->fftSamplingRateHz = lrintf(1e6f / targetLooptimeUs / 3); // Looptime divided by 3
state->fftSamplingRateHz = DYN_NOTCH_RANGE_HZ_HIGH;
}
else if (range == DYN_NOTCH_RANGE_MEDIUM) {
state->fftSamplingRateHz = DYN_NOTCH_RANGE_HZ_MEDIUM;
}
// If we get at least 3 samples then use the default FFT sample frequency
// otherwise we need to calculate a FFT sample frequency to ensure we get 3 samples (gyro loops < 4K)
const int gyroLoopRateHz = lrintf((1.0f / targetLooptimeUs) * 1e6f);
state->fftSamplingRateHz = MIN((gyroLoopRateHz / 3), state->fftSamplingRateHz);
state->fftResolution = (float)state->fftSamplingRateHz / FFT_WINDOW_SIZE; state->fftResolution = (float)state->fftSamplingRateHz / FFT_WINDOW_SIZE;
state->fftStartBin = state->minFrequency / lrintf(state->fftResolution); state->fftStartBin = state->minFrequency / lrintf(state->fftResolution);

View file

@ -68,7 +68,6 @@ STATIC_ASSERT(FFT_WINDOW_SIZE <= (uint8_t) -1, window_size_greater_than_underlyi
void gyroDataAnalyseStateInit( void gyroDataAnalyseStateInit(
gyroAnalyseState_t *state, gyroAnalyseState_t *state,
uint16_t minFrequency, uint16_t minFrequency,
uint8_t range,
uint32_t targetLooptimeUs uint32_t targetLooptimeUs
); );
void gyroDataAnalysePush(gyroAnalyseState_t *gyroAnalyse, int axis, float sample); void gyroDataAnalysePush(gyroAnalyseState_t *gyroAnalyse, int axis, float sample);

View file

@ -1037,17 +1037,37 @@ static void osdFormatRpm(char *buff, uint32_t rpm)
{ {
buff[0] = SYM_RPM; buff[0] = SYM_RPM;
if (rpm) { if (rpm) {
if (rpm >= 1000) { if ( digitCount(rpm) > osdConfig()->esc_rpm_precision) {
osdFormatCentiNumber(buff + 1, rpm / 10, 0, 1, 1, 2); uint8_t rpmMaxDecimals = (osdConfig()->esc_rpm_precision - 3);
buff[3] = 'K'; osdFormatCentiNumber(buff + 1, rpm / 10, 0, rpmMaxDecimals, rpmMaxDecimals, osdConfig()->esc_rpm_precision-1);
buff[4] = '\0'; buff[osdConfig()->esc_rpm_precision] = 'K';
buff[osdConfig()->esc_rpm_precision+1] = '\0';
} }
else { else {
tfp_sprintf(buff + 1, "%3lu", rpm); switch(osdConfig()->esc_rpm_precision) {
case 6:
tfp_sprintf(buff + 1, "%6lu", rpm);
break;
case 5:
tfp_sprintf(buff + 1, "%5lu", rpm);
break;
case 4:
tfp_sprintf(buff + 1, "%4lu", rpm);
break;
case 3:
default:
tfp_sprintf(buff + 1, "%3lu", rpm);
break;
}
} }
} }
else { else {
strcpy(buff + 1, "---"); uint8_t buffPos = 1;
while (buffPos <=( osdConfig()->esc_rpm_precision)) {
strcpy(buff + buffPos++, "-");
}
} }
} }
#endif #endif
@ -3153,6 +3173,7 @@ PG_RESET_TEMPLATE(osdConfig_t, osdConfig,
.osd_home_position_arm_screen = SETTING_OSD_HOME_POSITION_ARM_SCREEN_DEFAULT, .osd_home_position_arm_screen = SETTING_OSD_HOME_POSITION_ARM_SCREEN_DEFAULT,
.pan_servo_index = SETTING_OSD_PAN_SERVO_INDEX_DEFAULT, .pan_servo_index = SETTING_OSD_PAN_SERVO_INDEX_DEFAULT,
.pan_servo_pwm2centideg = SETTING_OSD_PAN_SERVO_PWM2CENTIDEG_DEFAULT, .pan_servo_pwm2centideg = SETTING_OSD_PAN_SERVO_PWM2CENTIDEG_DEFAULT,
.esc_rpm_precision = SETTING_OSD_ESC_RPM_PRECISION_DEFAULT,
.units = SETTING_OSD_UNITS_DEFAULT, .units = SETTING_OSD_UNITS_DEFAULT,
.main_voltage_decimals = SETTING_OSD_MAIN_VOLTAGE_DECIMALS_DEFAULT, .main_voltage_decimals = SETTING_OSD_MAIN_VOLTAGE_DECIMALS_DEFAULT,

View file

@ -385,6 +385,7 @@ typedef struct osdConfig_s {
uint8_t crsf_lq_format; uint8_t crsf_lq_format;
uint8_t sidebar_height; // sidebar height in rows, 0 turns off sidebars leaving only level indicator arrows uint8_t sidebar_height; // sidebar height in rows, 0 turns off sidebars leaving only level indicator arrows
uint8_t telemetry; // use telemetry on displayed pixel line 0 uint8_t telemetry; // use telemetry on displayed pixel line 0
uint8_t esc_rpm_precision; // Number of characters used for the RPM numbers.
} osdConfig_t; } osdConfig_t;

View file

@ -49,6 +49,8 @@
#include "navigation/navigation.h" #include "navigation/navigation.h"
#include "navigation/navigation_private.h" #include "navigation/navigation_private.h"
#include "programming/logic_condition.h"
#include "rx/rx.h" #include "rx/rx.h"
#include "sensors/battery.h" #include "sensors/battery.h"
@ -271,10 +273,12 @@ static void calculateVirtualPositionTarget_FW(float trackingPeriod)
// Limit minimum forward velocity to 1 m/s // Limit minimum forward velocity to 1 m/s
float trackingDistance = trackingPeriod * MAX(posControl.actualState.velXY, 100.0f); float trackingDistance = trackingPeriod * MAX(posControl.actualState.velXY, 100.0f);
uint32_t navLoiterRadius = getLoiterRadius(navConfig()->fw.loiter_radius);
// If angular visibility of a waypoint is less than 30deg, don't calculate circular loiter, go straight to the target // If angular visibility of a waypoint is less than 30deg, don't calculate circular loiter, go straight to the target
#define TAN_15DEG 0.26795f #define TAN_15DEG 0.26795f
bool needToCalculateCircularLoiter = (isApproachingLastWaypoint() || isWaypointWait()) bool needToCalculateCircularLoiter = (isApproachingLastWaypoint() || isWaypointWait())
&& (distanceToActualTarget <= (navConfig()->fw.loiter_radius / TAN_15DEG)) && (distanceToActualTarget <= (navLoiterRadius / TAN_15DEG))
&& (distanceToActualTarget > 50.0f) && (distanceToActualTarget > 50.0f)
&& !FLIGHT_MODE(NAV_COURSE_HOLD_MODE); && !FLIGHT_MODE(NAV_COURSE_HOLD_MODE);
@ -283,8 +287,8 @@ static void calculateVirtualPositionTarget_FW(float trackingPeriod)
// We are closing in on a waypoint, calculate circular loiter // We are closing in on a waypoint, calculate circular loiter
float loiterAngle = atan2_approx(-posErrorY, -posErrorX) + DEGREES_TO_RADIANS(loiterDirection() * 45.0f); float loiterAngle = atan2_approx(-posErrorY, -posErrorX) + DEGREES_TO_RADIANS(loiterDirection() * 45.0f);
float loiterTargetX = posControl.desiredState.pos.x + navConfig()->fw.loiter_radius * cos_approx(loiterAngle); float loiterTargetX = posControl.desiredState.pos.x + navLoiterRadius * cos_approx(loiterAngle);
float loiterTargetY = posControl.desiredState.pos.y + navConfig()->fw.loiter_radius * sin_approx(loiterAngle); float loiterTargetY = posControl.desiredState.pos.y + navLoiterRadius * sin_approx(loiterAngle);
// We have temporary loiter target. Recalculate distance and position error // We have temporary loiter target. Recalculate distance and position error
posErrorX = loiterTargetX - navGetCurrentActualPositionAndVelocity()->pos.x; posErrorX = loiterTargetX - navGetCurrentActualPositionAndVelocity()->pos.x;

View file

@ -83,10 +83,10 @@ void pgResetFn_logicConditions(logicCondition_t *instance)
logicConditionState_t logicConditionStates[MAX_LOGIC_CONDITIONS]; logicConditionState_t logicConditionStates[MAX_LOGIC_CONDITIONS];
static int logicConditionCompute( static int logicConditionCompute(
int currentVaue, int32_t currentVaue,
logicOperation_e operation, logicOperation_e operation,
int operandA, int32_t operandA,
int operandB int32_t operandB
) { ) {
int temporaryValue; int temporaryValue;
vtxDeviceCapability_t vtxDeviceCapability; vtxDeviceCapability_t vtxDeviceCapability;
@ -177,20 +177,20 @@ static int logicConditionCompute(
break; break;
case LOGIC_CONDITION_ADD: case LOGIC_CONDITION_ADD:
return constrain(operandA + operandB, INT16_MIN, INT16_MAX); return constrain(operandA + operandB, INT32_MIN, INT32_MAX);
break; break;
case LOGIC_CONDITION_SUB: case LOGIC_CONDITION_SUB:
return constrain(operandA - operandB, INT16_MIN, INT16_MAX); return constrain(operandA - operandB, INT32_MIN, INT32_MAX);
break; break;
case LOGIC_CONDITION_MUL: case LOGIC_CONDITION_MUL:
return constrain(operandA * operandB, INT16_MIN, INT16_MAX); return constrain(operandA * operandB, INT32_MIN, INT32_MAX);
break; break;
case LOGIC_CONDITION_DIV: case LOGIC_CONDITION_DIV:
if (operandB != 0) { if (operandB != 0) {
return constrain(operandA / operandB, INT16_MIN, INT16_MAX); return constrain(operandA / operandB, INT32_MIN, INT32_MAX);
} else { } else {
return operandA; return operandA;
} }
@ -328,7 +328,7 @@ static int logicConditionCompute(
case LOGIC_CONDITION_MODULUS: case LOGIC_CONDITION_MODULUS:
if (operandB != 0) { if (operandB != 0) {
return constrain(operandA % operandB, INT16_MIN, INT16_MAX); return constrain(operandA % operandB, INT32_MIN, INT32_MAX);
} else { } else {
return operandA; return operandA;
} }
@ -350,6 +350,12 @@ static int logicConditionCompute(
} }
break; break;
case LOGIC_CONDITION_LOITER_OVERRIDE:
logicConditionValuesByType[LOGIC_CONDITION_LOITER_OVERRIDE] = constrain(operandA, 0, 100000);
LOGIC_CONDITION_GLOBAL_FLAG_ENABLE(LOGIC_CONDITION_GLOBAL_FLAG_OVERRIDE_LOITER_RADIUS);
return true;
break;
default: default:
return false; return false;
break; break;
@ -554,6 +560,9 @@ static int logicConditionGetFlightOperandValue(int operand) {
return getConfigProfile() + 1; return getConfigProfile() + 1;
break; break;
case LOGIC_CONDITION_OPERAND_FLIGHT_LOITER_RADIUS:
return getLoiterRadius(navConfig()->fw.loiter_radius);
default: default:
return 0; return 0;
break; break;
@ -741,3 +750,16 @@ int16_t getRcChannelOverride(uint8_t channel, int16_t originalValue) {
return originalValue; return originalValue;
} }
} }
uint32_t getLoiterRadius(uint32_t loiterRadius) {
#ifdef USE_PROGRAMMING_FRAMEWORK
if (LOGIC_CONDITION_GLOBAL_FLAG(LOGIC_CONDITION_GLOBAL_FLAG_OVERRIDE_LOITER_RADIUS) &&
!(FLIGHT_MODE(FAILSAFE_MODE) || FLIGHT_MODE(NAV_RTH_MODE) || FLIGHT_MODE(NAV_WP_MODE) || navigationIsExecutingAnEmergencyLanding())) {
return constrain(logicConditionValuesByType[LOGIC_CONDITION_LOITER_OVERRIDE], loiterRadius, 100000);
} else {
return loiterRadius;
}
#else
return loiterRadius;
#endif
}

View file

@ -70,6 +70,7 @@ typedef enum {
LOGIC_CONDITION_RC_CHANNEL_OVERRIDE = 38, LOGIC_CONDITION_RC_CHANNEL_OVERRIDE = 38,
LOGIC_CONDITION_SET_HEADING_TARGET = 39, LOGIC_CONDITION_SET_HEADING_TARGET = 39,
LOGIC_CONDITION_MODULUS = 40, LOGIC_CONDITION_MODULUS = 40,
LOGIC_CONDITION_LOITER_OVERRIDE = 41,
LOGIC_CONDITION_SET_PROFILE = 42, LOGIC_CONDITION_SET_PROFILE = 42,
LOGIC_CONDITION_LAST = 43, LOGIC_CONDITION_LAST = 43,
} logicOperation_e; } logicOperation_e;
@ -121,7 +122,8 @@ typedef enum {
LOGIC_CONDITION_OPERAND_FLIGHT_CRSF_LQ, // 32 LOGIC_CONDITION_OPERAND_FLIGHT_CRSF_LQ, // 32
LOGIC_CONDITION_OPERAND_FLIGHT_CRSF_SNR, // 33 LOGIC_CONDITION_OPERAND_FLIGHT_CRSF_SNR, // 33
LOGIC_CONDITION_OPERAND_FLIGHT_GPS_VALID, // 0/1 // 34 LOGIC_CONDITION_OPERAND_FLIGHT_GPS_VALID, // 0/1 // 34
LOGIC_CONDITION_OPERAND_FLIGHT_ACTIVE_PROFILE, //int // 35 LOGIC_CONDITION_OPERAND_FLIGHT_LOITER_RADIUS // 35
LOGIC_CONDITION_OPERAND_FLIGHT_ACTIVE_PROFILE, //int // 36
} logicFlightOperands_e; } logicFlightOperands_e;
@ -150,6 +152,7 @@ typedef enum {
LOGIC_CONDITION_GLOBAL_FLAG_OVERRIDE_THROTTLE = (1 << 6), LOGIC_CONDITION_GLOBAL_FLAG_OVERRIDE_THROTTLE = (1 << 6),
LOGIC_CONDITION_GLOBAL_FLAG_OVERRIDE_OSD_LAYOUT = (1 << 7), LOGIC_CONDITION_GLOBAL_FLAG_OVERRIDE_OSD_LAYOUT = (1 << 7),
LOGIC_CONDITION_GLOBAL_FLAG_OVERRIDE_RC_CHANNEL = (1 << 8), LOGIC_CONDITION_GLOBAL_FLAG_OVERRIDE_RC_CHANNEL = (1 << 8),
LOGIC_CONDITION_GLOBAL_FLAG_OVERRIDE_LOITER_RADIUS = (1 << 9),
} logicConditionsGlobalFlags_t; } logicConditionsGlobalFlags_t;
typedef enum { typedef enum {
@ -200,3 +203,4 @@ void logicConditionReset(void);
float getThrottleScale(float globalThrottleScale); float getThrottleScale(float globalThrottleScale);
int16_t getRcCommandOverride(int16_t command[], uint8_t axis); int16_t getRcCommandOverride(int16_t command[], uint8_t axis);
int16_t getRcChannelOverride(uint8_t channel, int16_t originalValue); int16_t getRcChannelOverride(uint8_t channel, int16_t originalValue);
uint32_t getLoiterRadius(uint32_t loiterRadius);

View file

@ -42,6 +42,7 @@
#include "drivers/compass/compass_lis3mdl.h" #include "drivers/compass/compass_lis3mdl.h"
#include "drivers/compass/compass_rm3100.h" #include "drivers/compass/compass_rm3100.h"
#include "drivers/compass/compass_vcm5883.h" #include "drivers/compass/compass_vcm5883.h"
#include "drivers/compass/compass_mlx90393.h"
#include "drivers/compass/compass_msp.h" #include "drivers/compass/compass_msp.h"
#include "drivers/io.h" #include "drivers/io.h"
#include "drivers/light_led.h" #include "drivers/light_led.h"
@ -260,6 +261,19 @@ bool compassDetect(magDev_t *dev, magSensor_e magHardwareToUse)
} }
FALLTHROUGH; FALLTHROUGH;
case MAG_MLX90393:
#ifdef USE_MAG_MLX90393
if (mlx90393Detect(dev)) {
magHardware = MAG_MLX90393;
break;
}
#endif
/* If we are asked for a specific sensor - break out, otherwise - fall through and continue */
if (magHardwareToUse != MAG_AUTODETECT) {
break;
}
FALLTHROUGH;
case MAG_FAKE: case MAG_FAKE:
#ifdef USE_FAKE_MAG #ifdef USE_FAKE_MAG
if (fakeMagDetect(dev)) { if (fakeMagDetect(dev)) {

View file

@ -43,7 +43,8 @@ typedef enum {
MAG_MSP = 12, MAG_MSP = 12,
MAG_RM3100 = 13, MAG_RM3100 = 13,
MAG_VCM5883 = 14, MAG_VCM5883 = 14,
MAG_FAKE = 15, MAG_MLX90393 = 15,
MAG_FAKE = 16,
MAG_MAX = MAG_FAKE MAG_MAX = MAG_FAKE
} magSensor_e; } magSensor_e;

View file

@ -124,7 +124,6 @@ PG_RESET_TEMPLATE(gyroConfig_t, gyroConfig,
.gyroDynamicLpfMaxHz = SETTING_GYRO_DYN_LPF_MAX_HZ_DEFAULT, .gyroDynamicLpfMaxHz = SETTING_GYRO_DYN_LPF_MAX_HZ_DEFAULT,
.gyroDynamicLpfCurveExpo = SETTING_GYRO_DYN_LPF_CURVE_EXPO_DEFAULT, .gyroDynamicLpfCurveExpo = SETTING_GYRO_DYN_LPF_CURVE_EXPO_DEFAULT,
#ifdef USE_DYNAMIC_FILTERS #ifdef USE_DYNAMIC_FILTERS
.dynamicGyroNotchRange = SETTING_DYNAMIC_GYRO_NOTCH_RANGE_DEFAULT,
.dynamicGyroNotchQ = SETTING_DYNAMIC_GYRO_NOTCH_Q_DEFAULT, .dynamicGyroNotchQ = SETTING_DYNAMIC_GYRO_NOTCH_Q_DEFAULT,
.dynamicGyroNotchMinHz = SETTING_DYNAMIC_GYRO_NOTCH_MIN_HZ_DEFAULT, .dynamicGyroNotchMinHz = SETTING_DYNAMIC_GYRO_NOTCH_MIN_HZ_DEFAULT,
.dynamicGyroNotchEnabled = SETTING_DYNAMIC_GYRO_NOTCH_ENABLED_DEFAULT, .dynamicGyroNotchEnabled = SETTING_DYNAMIC_GYRO_NOTCH_ENABLED_DEFAULT,
@ -355,7 +354,6 @@ bool gyroInit(void)
gyroDataAnalyseStateInit( gyroDataAnalyseStateInit(
&gyroAnalyseState, &gyroAnalyseState,
gyroConfig()->dynamicGyroNotchMinHz, gyroConfig()->dynamicGyroNotchMinHz,
gyroConfig()->dynamicGyroNotchRange,
getLooptime() getLooptime()
); );
#endif #endif

View file

@ -41,16 +41,6 @@ typedef enum {
GYRO_FAKE GYRO_FAKE
} gyroSensor_e; } gyroSensor_e;
typedef enum {
DYN_NOTCH_RANGE_HIGH = 0,
DYN_NOTCH_RANGE_MEDIUM,
DYN_NOTCH_RANGE_LOW
} dynamicFilterRange_e;
#define DYN_NOTCH_RANGE_HZ_HIGH 2000
#define DYN_NOTCH_RANGE_HZ_MEDIUM 1333
#define DYN_NOTCH_RANGE_HZ_LOW 1000
typedef struct gyro_s { typedef struct gyro_s {
bool initialized; bool initialized;
uint32_t targetLooptime; uint32_t targetLooptime;
@ -78,7 +68,6 @@ typedef struct gyroConfig_s {
uint16_t gyroDynamicLpfMaxHz; uint16_t gyroDynamicLpfMaxHz;
uint8_t gyroDynamicLpfCurveExpo; uint8_t gyroDynamicLpfCurveExpo;
#ifdef USE_DYNAMIC_FILTERS #ifdef USE_DYNAMIC_FILTERS
uint8_t dynamicGyroNotchRange;
uint16_t dynamicGyroNotchQ; uint16_t dynamicGyroNotchQ;
uint16_t dynamicGyroNotchMinHz; uint16_t dynamicGyroNotchMinHz;
uint8_t dynamicGyroNotchEnabled; uint8_t dynamicGyroNotchEnabled;

View file

@ -144,6 +144,7 @@
#define USE_MAG_IST8310 #define USE_MAG_IST8310
#define USE_MAG_IST8308 #define USE_MAG_IST8308
#define USE_MAG_LIS3MDL #define USE_MAG_LIS3MDL
#define USE_MAG_MLX90393
#define TEMPERATURE_I2C_BUS BUS_I2C1 #define TEMPERATURE_I2C_BUS BUS_I2C1

View file

@ -260,6 +260,13 @@
BUSDEV_REGISTER_I2C(busdev_vcm5883, DEVHW_VCM5883, VCM5883_I2C_BUS, 0x0C, NONE, DEVFLAGS_NONE, 0); BUSDEV_REGISTER_I2C(busdev_vcm5883, DEVHW_VCM5883, VCM5883_I2C_BUS, 0x0C, NONE, DEVFLAGS_NONE, 0);
#endif #endif
#if defined(USE_MAG_MLX90393)
#if !defined(MLX90393_I2C_BUS)
#define MLX90393_I2C_BUS MAG_I2C_BUS
#endif
BUSDEV_REGISTER_I2C(busdev_mlx90393, DEVHW_MLX90393, MLX90393_I2C_BUS, 0x0C, NONE, DEVFLAGS_NONE, 0);
#endif
#endif #endif

View file

@ -332,9 +332,9 @@ static void crsfFrameFlightMode(sbuf_t *dst)
} else if (FLIGHT_MODE(NAV_POSHOLD_MODE)) { } else if (FLIGHT_MODE(NAV_POSHOLD_MODE)) {
flightMode = "HOLD"; flightMode = "HOLD";
} else if (FLIGHT_MODE(NAV_COURSE_HOLD_MODE) && FLIGHT_MODE(NAV_ALTHOLD_MODE)) { } else if (FLIGHT_MODE(NAV_COURSE_HOLD_MODE) && FLIGHT_MODE(NAV_ALTHOLD_MODE)) {
flightMode = "3CRS"; flightMode = "CRUZ";
} else if (FLIGHT_MODE(NAV_COURSE_HOLD_MODE)) { } else if (FLIGHT_MODE(NAV_COURSE_HOLD_MODE)) {
flightMode = "CRS"; flightMode = "CRSH";
} else if (FLIGHT_MODE(NAV_ALTHOLD_MODE)) { } else if (FLIGHT_MODE(NAV_ALTHOLD_MODE)) {
flightMode = "AH"; flightMode = "AH";
} else if (FLIGHT_MODE(NAV_WP_MODE)) { } else if (FLIGHT_MODE(NAV_WP_MODE)) {