1
0
Fork 0
mirror of https://github.com/betaflight/betaflight.git synced 2025-07-12 19:10:32 +03:00

Add 3+ IMU support (Gyro Fusion) (#14383)

* Allow for 3 gyros to be fused at once.

* Handle the case where no GYRO_COUNT is defined

* Fix accel init bug

* Fix bugs found by AI

* Fix compile time assert message

* Move to picking which IMU you want to enable, allow IMU that have the same scale and looprate to run together even if they aren't identical IMU.

* Fully support 8 IMU

* Fix suggestions, except for MSP all suggestions

* Fix bugs found by AI

* Update gyro_init

* Fix unit tests (feels wrong though)

* Allow MSP to update all gyro alignment

* resolve comments

* Only auto set up to 4 gyros in a config.

* Update MSP implementation

* Fix divide by 0 error

* Update src/main/target/common_post.h

Co-authored-by: Mark Haslinghuis <mark@numloq.nl>

* Handle case where gyro 1 does not exist

* Fix 426XX driver

* fix = logic in if statement

* Update src/main/msp/msp.c

Co-authored-by: Petr Ledvina <ledvinap@gmail.com>

* Update src/main/drivers/accgyro/accgyro_spi_icm426xx.c

Co-authored-by: Petr Ledvina <ledvinap@gmail.com>

* Apply ledvinap suggestions

* Fix detectedSensors initialization

* fix getGyroDetectedFlags

* Automatically handle GYRO_COUNT for up to 4 IMU

* better handle unit tests

* Backwards compatible with older config.h files

* Update src/main/sensors/gyro_init.c

Co-authored-by: Mark Haslinghuis <mark@numloq.nl>

* Update src/main/target/common_pre.h

Co-authored-by: nerdCopter <56646290+nerdCopter@users.noreply.github.com>

* Update src/main/sensors/gyro_init.c

Co-authored-by: Petr Ledvina <ledvinap@gmail.com>

* Update src/main/sensors/gyro.c

Co-authored-by: Petr Ledvina <ledvinap@gmail.com>

* This needs to be the case or unit tests fail, without this we cannot choose default gyro either.

* ledvinap suggestions

* whitespace

---------

Co-authored-by: Mark Haslinghuis <mark@numloq.nl>
Co-authored-by: Petr Ledvina <ledvinap@gmail.com>
Co-authored-by: nerdCopter <56646290+nerdCopter@users.noreply.github.com>
This commit is contained in:
Kevin Plaizier 2025-06-23 13:35:11 -06:00 committed by GitHub
parent 3370752442
commit 078ffafec1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 495 additions and 381 deletions

View file

@ -1687,7 +1687,7 @@ static bool blackboxWriteSysinfo(void)
gyroConfig()->gyro_soft_notch_hz_2);
BLACKBOX_PRINT_HEADER_LINE("gyro_notch_cutoff", "%d,%d", gyroConfig()->gyro_soft_notch_cutoff_1,
gyroConfig()->gyro_soft_notch_cutoff_2);
BLACKBOX_PRINT_HEADER_LINE(PARAM_NAME_GYRO_TO_USE, "%d", gyroConfig()->gyro_to_use);
BLACKBOX_PRINT_HEADER_LINE(PARAM_NAME_GYRO_ENABLE_MASK, "%d", gyroConfig()->gyro_enabled_bitmask);
BLACKBOX_PRINT_HEADER_LINE("gyro_debug_axis", "%d", gyroConfig()->gyro_filter_debug_axis);
#ifdef USE_DYN_NOTCH_FILTER
BLACKBOX_PRINT_HEADER_LINE(PARAM_NAME_DYN_NOTCH_MAX_HZ, "%d", dynNotchConfig()->dyn_notch_max_hz);

View file

@ -3675,18 +3675,12 @@ static void cliDumpGyroRegisters(const char *cmdName, char *cmdline)
UNUSED(cmdName);
UNUSED(cmdline);
#ifdef USE_MULTI_GYRO
if ((gyroConfig()->gyro_to_use == GYRO_CONFIG_USE_GYRO_1) || (gyroConfig()->gyro_to_use == GYRO_CONFIG_USE_GYRO_BOTH)) {
cliPrintLinef("\r\n# Gyro 1");
cliPrintGyroRegisters(GYRO_CONFIG_USE_GYRO_1);
for (int i = 0; i < GYRO_COUNT; i++) {
if (gyroConfig()->gyro_enabled_bitmask & GYRO_MASK(i)) {
cliPrintLinef("\r\n# Gyro %d", i + 1);
cliPrintGyroRegisters(i); // assuming this takes a 0-based gyro index
}
if ((gyroConfig()->gyro_to_use == GYRO_CONFIG_USE_GYRO_2) || (gyroConfig()->gyro_to_use == GYRO_CONFIG_USE_GYRO_BOTH)) {
cliPrintLinef("\r\n# Gyro 2");
cliPrintGyroRegisters(GYRO_CONFIG_USE_GYRO_2);
}
#else
cliPrintGyroRegisters(GYRO_CONFIG_USE_GYRO_1);
#endif
}
#endif

View file

@ -244,12 +244,6 @@ static const char * const lookupTableAlignment[] = {
"CUSTOM",
};
#ifdef USE_MULTI_GYRO
static const char * const lookupTableGyro[] = {
"FIRST", "SECOND", "BOTH"
};
#endif
#ifdef USE_GPS
static const char * const lookupTableGpsProvider[] = {
"NMEA", "UBLOX", "MSP", "VIRTUAL"
@ -679,9 +673,6 @@ const lookupTableEntry_t lookupTables[] = {
#endif
#ifdef USE_LED_STRIP
LOOKUP_TABLE_ENTRY(lookupLedStripFormatRGB),
#endif
#ifdef USE_MULTI_GYRO
LOOKUP_TABLE_ENTRY(lookupTableGyro),
#endif
LOOKUP_TABLE_ENTRY(lookupTableThrottleLimitType),
#if defined(USE_VIDEO_SYSTEM)
@ -774,9 +765,30 @@ const clivalue_t valueTable[] = {
{ "yaw_spin_threshold", VAR_UINT16 | MASTER_VALUE, .config.minmaxUnsigned = { YAW_SPIN_RECOVERY_THRESHOLD_MIN, YAW_SPIN_RECOVERY_THRESHOLD_MAX }, PG_GYRO_CONFIG, offsetof(gyroConfig_t, yaw_spin_threshold) },
#endif
#ifdef USE_MULTI_GYRO
{ PARAM_NAME_GYRO_TO_USE, VAR_UINT8 | HARDWARE_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_GYRO }, PG_GYRO_CONFIG, offsetof(gyroConfig_t, gyro_to_use) },
#if GYRO_COUNT > 1
{ PARAM_NAME_GYRO_ENABLE_MASK, VAR_UINT8 | HARDWARE_VALUE, .config.minmaxUnsigned = { 0, (1 << GYRO_COUNT) - 1 }, PG_GYRO_CONFIG, offsetof(gyroConfig_t, gyro_enabled_bitmask) },
{ "gyro_1_enabled", VAR_UINT8 | HARDWARE_VALUE | MODE_BITSET, .config.bitpos = 0, PG_GYRO_CONFIG, offsetof(gyroConfig_t, gyro_enabled_bitmask) },
{ "gyro_2_enabled", VAR_UINT8 | HARDWARE_VALUE | MODE_BITSET, .config.bitpos = 1, PG_GYRO_CONFIG, offsetof(gyroConfig_t, gyro_enabled_bitmask) },
#endif
#if GYRO_COUNT > 2
{ "gyro_3_enabled", VAR_UINT8 | HARDWARE_VALUE | MODE_BITSET, .config.bitpos = 2, PG_GYRO_CONFIG, offsetof(gyroConfig_t, gyro_enabled_bitmask) },
#endif
#if GYRO_COUNT > 3
{ "gyro_4_enabled", VAR_UINT8 | HARDWARE_VALUE | MODE_BITSET, .config.bitpos = 3, PG_GYRO_CONFIG, offsetof(gyroConfig_t, gyro_enabled_bitmask) },
#endif
#if GYRO_COUNT > 4
{ "gyro_5_enabled", VAR_UINT8 | HARDWARE_VALUE | MODE_BITSET, .config.bitpos = 4, PG_GYRO_CONFIG, offsetof(gyroConfig_t, gyro_enabled_bitmask) },
#endif
#if GYRO_COUNT > 5
{ "gyro_6_enabled", VAR_UINT8 | HARDWARE_VALUE | MODE_BITSET, .config.bitpos = 5, PG_GYRO_CONFIG, offsetof(gyroConfig_t, gyro_enabled_bitmask) },
#endif
#if GYRO_COUNT > 6
{ "gyro_7_enabled", VAR_UINT8 | HARDWARE_VALUE | MODE_BITSET, .config.bitpos = 6, PG_GYRO_CONFIG, offsetof(gyroConfig_t, gyro_enabled_bitmask) },
#endif
#if GYRO_COUNT > 7
{ "gyro_8_enabled", VAR_UINT8 | HARDWARE_VALUE | MODE_BITSET, .config.bitpos = 7, PG_GYRO_CONFIG, offsetof(gyroConfig_t, gyro_enabled_bitmask) },
#endif // GYRO_COUNT
#if defined(USE_DYN_NOTCH_FILTER)
{ PARAM_NAME_DYN_NOTCH_COUNT, VAR_UINT8 | MASTER_VALUE, .config.minmaxUnsigned = { 0, DYN_NOTCH_COUNT_MAX }, PG_DYN_NOTCH_CONFIG, offsetof(dynNotchConfig_t, dyn_notch_count) },
{ PARAM_NAME_DYN_NOTCH_Q, VAR_UINT16 | MASTER_VALUE, .config.minmaxUnsigned = { 1, 1000 }, PG_DYN_NOTCH_CONFIG, offsetof(dynNotchConfig_t, dyn_notch_q) },
@ -1826,23 +1838,43 @@ const clivalue_t valueTable[] = {
#endif
// PG_GYRO_DEVICE_CONFIG
{ "gyro_1_bustype", VAR_UINT8 | HARDWARE_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_BUS_TYPE }, PG_GYRO_DEVICE_CONFIG, PG_ARRAY_ELEMENT_OFFSET(gyroDeviceConfig_t, 0, busType) },
{ "gyro_1_spibus", VAR_UINT8 | HARDWARE_VALUE, .config.minmaxUnsigned = { 0, SPIDEV_COUNT }, PG_GYRO_DEVICE_CONFIG, PG_ARRAY_ELEMENT_OFFSET(gyroDeviceConfig_t, 0, spiBus) },
{ "gyro_1_i2cBus", VAR_UINT8 | HARDWARE_VALUE, .config.minmaxUnsigned = { 0, I2CDEV_COUNT }, PG_GYRO_DEVICE_CONFIG, PG_ARRAY_ELEMENT_OFFSET(gyroDeviceConfig_t, 0, i2cBus) },
{ "gyro_1_i2c_address", VAR_UINT8 | HARDWARE_VALUE, .config.minmaxUnsigned = { 0, I2C_ADDR7_MAX }, PG_GYRO_DEVICE_CONFIG, PG_ARRAY_ELEMENT_OFFSET(gyroDeviceConfig_t, 0, i2cAddress) },
{ "gyro_1_sensor_align", VAR_UINT8 | HARDWARE_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_ALIGNMENT }, PG_GYRO_DEVICE_CONFIG, PG_ARRAY_ELEMENT_OFFSET(gyroDeviceConfig_t, 0, alignment) },
{ "gyro_1_align_roll", VAR_INT16 | HARDWARE_VALUE, .config.minmax = { -3600, 3600 }, PG_GYRO_DEVICE_CONFIG, PG_ARRAY_ELEMENT_OFFSET(gyroDeviceConfig_t, 0, customAlignment.roll) },
{ "gyro_1_align_pitch", VAR_INT16 | HARDWARE_VALUE, .config.minmax = { -3600, 3600 }, PG_GYRO_DEVICE_CONFIG, PG_ARRAY_ELEMENT_OFFSET(gyroDeviceConfig_t, 0, customAlignment.pitch) },
{ "gyro_1_align_yaw", VAR_INT16 | HARDWARE_VALUE, .config.minmax = { -3600, 3600 }, PG_GYRO_DEVICE_CONFIG, PG_ARRAY_ELEMENT_OFFSET(gyroDeviceConfig_t, 0, customAlignment.yaw) },
#ifdef USE_MULTI_GYRO
{ "gyro_2_bustype", VAR_UINT8 | HARDWARE_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_BUS_TYPE }, PG_GYRO_DEVICE_CONFIG, PG_ARRAY_ELEMENT_OFFSET(gyroDeviceConfig_t, 1, busType) },
{ "gyro_2_spibus", VAR_UINT8 | HARDWARE_VALUE, .config.minmaxUnsigned = { 0, SPIDEV_COUNT }, PG_GYRO_DEVICE_CONFIG, PG_ARRAY_ELEMENT_OFFSET(gyroDeviceConfig_t, 1, spiBus) },
{ "gyro_2_i2cBus", VAR_UINT8 | HARDWARE_VALUE, .config.minmaxUnsigned = { 0, I2CDEV_COUNT }, PG_GYRO_DEVICE_CONFIG, PG_ARRAY_ELEMENT_OFFSET(gyroDeviceConfig_t, 1, i2cBus) },
{ "gyro_2_i2c_address", VAR_UINT8 | HARDWARE_VALUE, .config.minmaxUnsigned = { 0, I2C_ADDR7_MAX }, PG_GYRO_DEVICE_CONFIG, PG_ARRAY_ELEMENT_OFFSET(gyroDeviceConfig_t, 1, i2cAddress) },
{ "gyro_2_sensor_align", VAR_UINT8 | HARDWARE_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_ALIGNMENT }, PG_GYRO_DEVICE_CONFIG, PG_ARRAY_ELEMENT_OFFSET(gyroDeviceConfig_t, 1, alignment) },
{ "gyro_2_align_roll", VAR_INT16 | HARDWARE_VALUE, .config.minmax = { -3600, 3600 }, PG_GYRO_DEVICE_CONFIG, PG_ARRAY_ELEMENT_OFFSET(gyroDeviceConfig_t, 1, customAlignment.roll) },
{ "gyro_2_align_pitch", VAR_INT16 | HARDWARE_VALUE, .config.minmax = { -3600, 3600 }, PG_GYRO_DEVICE_CONFIG, PG_ARRAY_ELEMENT_OFFSET(gyroDeviceConfig_t, 1, customAlignment.pitch) },
{ "gyro_2_align_yaw", VAR_INT16 | HARDWARE_VALUE, .config.minmax = { -3600, 3600 }, PG_GYRO_DEVICE_CONFIG, PG_ARRAY_ELEMENT_OFFSET(gyroDeviceConfig_t, 1, customAlignment.yaw) },
#define GYRO_DEVICE_RECORDS(N, IDX) \
/* bustype */ \
{ "gyro_" STR(N) "_bustype", VAR_UINT8 | HARDWARE_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_BUS_TYPE }, PG_GYRO_DEVICE_CONFIG, PG_ARRAY_ELEMENT_OFFSET(gyroDeviceConfig_t, IDX, busType) },\
/* spibus */ \
{ "gyro_" STR(N) "_spibus", VAR_UINT8 | HARDWARE_VALUE, .config.minmaxUnsigned = { 0, SPIDEV_COUNT }, PG_GYRO_DEVICE_CONFIG, PG_ARRAY_ELEMENT_OFFSET(gyroDeviceConfig_t, IDX, spiBus) },\
/* i2cBus */ \
{ "gyro_" STR(N) "_i2cBus", VAR_UINT8 | HARDWARE_VALUE, .config.minmaxUnsigned = { 0, I2CDEV_COUNT }, PG_GYRO_DEVICE_CONFIG, PG_ARRAY_ELEMENT_OFFSET(gyroDeviceConfig_t, IDX, i2cBus) },\
/* i2c addr */ \
{ "gyro_" STR(N) "_i2c_address", VAR_UINT8 | HARDWARE_VALUE, .config.minmaxUnsigned = { 0, I2C_ADDR7_MAX }, PG_GYRO_DEVICE_CONFIG, PG_ARRAY_ELEMENT_OFFSET(gyroDeviceConfig_t, IDX, i2cAddress) },\
/* align lookup */ \
{ "gyro_" STR(N) "_sensor_align", VAR_UINT8 | HARDWARE_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_ALIGNMENT }, PG_GYRO_DEVICE_CONFIG, PG_ARRAY_ELEMENT_OFFSET(gyroDeviceConfig_t, IDX, alignment) },\
/* custom roll/pitch/yaw */ \
{ "gyro_" STR(N) "_align_roll", VAR_INT16 | HARDWARE_VALUE, .config.minmax = { -3600, 3600 }, PG_GYRO_DEVICE_CONFIG, PG_ARRAY_ELEMENT_OFFSET(gyroDeviceConfig_t, IDX, customAlignment.roll) },\
{ "gyro_" STR(N) "_align_pitch", VAR_INT16 | HARDWARE_VALUE, .config.minmax = { -3600, 3600 }, PG_GYRO_DEVICE_CONFIG, PG_ARRAY_ELEMENT_OFFSET(gyroDeviceConfig_t, IDX, customAlignment.pitch) },\
{ "gyro_" STR(N) "_align_yaw", VAR_INT16 | HARDWARE_VALUE, .config.minmax = { -3600, 3600 }, PG_GYRO_DEVICE_CONFIG, PG_ARRAY_ELEMENT_OFFSET(gyroDeviceConfig_t, IDX, customAlignment.yaw) }\
GYRO_DEVICE_RECORDS(1, 0),
#if GYRO_COUNT > 1
GYRO_DEVICE_RECORDS(2, 1),
#endif
#if GYRO_COUNT > 2
GYRO_DEVICE_RECORDS(3, 2),
#endif
#if GYRO_COUNT > 3
GYRO_DEVICE_RECORDS(4, 3),
#endif
#if GYRO_COUNT > 4
GYRO_DEVICE_RECORDS(5, 4),
#endif
#if GYRO_COUNT > 5
GYRO_DEVICE_RECORDS(6, 5),
#endif
#if GYRO_COUNT > 6
GYRO_DEVICE_RECORDS(7, 6),
#endif
#if GYRO_COUNT > 7
GYRO_DEVICE_RECORDS(8, 7),
#endif
#ifdef I2C_FULL_RECONFIGURABILITY
#ifdef USE_I2C_DEVICE_0

View file

@ -94,9 +94,6 @@ typedef enum {
#endif
#ifdef USE_LED_STRIP
TABLE_RGB_GRB,
#endif
#ifdef USE_MULTI_GYRO
TABLE_GYRO,
#endif
TABLE_THROTTLE_LIMIT_TYPE,
#if defined(USE_VIDEO_SYSTEM)

View file

@ -76,12 +76,6 @@ static uint8_t rateProfileIndex;
static char rateProfileIndexString[MAX_RATE_PROFILE_NAME_LENGTH + PROFILE_INDEX_STRING_ADDITIONAL_SIZE];
static controlRateConfig_t rateProfile;
#ifdef USE_MULTI_GYRO
static const char * const osdTableGyroToUse[] = {
"FIRST", "SECOND", "BOTH"
};
#endif
static void setProfileIndexString(char *profileString, int profileIndex, const char *profileName)
{
int charIndex = 0;
@ -752,7 +746,6 @@ static uint16_t gyroConfig_gyro_soft_notch_hz_1;
static uint16_t gyroConfig_gyro_soft_notch_cutoff_1;
static uint16_t gyroConfig_gyro_soft_notch_hz_2;
static uint16_t gyroConfig_gyro_soft_notch_cutoff_2;
static uint8_t gyroConfig_gyro_to_use;
static const void *cmsx_menuGyro_onEnter(displayPort_t *pDisp)
{
@ -764,7 +757,6 @@ static const void *cmsx_menuGyro_onEnter(displayPort_t *pDisp)
gyroConfig_gyro_soft_notch_cutoff_1 = gyroConfig()->gyro_soft_notch_cutoff_1;
gyroConfig_gyro_soft_notch_hz_2 = gyroConfig()->gyro_soft_notch_hz_2;
gyroConfig_gyro_soft_notch_cutoff_2 = gyroConfig()->gyro_soft_notch_cutoff_2;
gyroConfig_gyro_to_use = gyroConfig()->gyro_to_use;
return NULL;
}
@ -780,7 +772,6 @@ static const void *cmsx_menuGyro_onExit(displayPort_t *pDisp, const OSD_Entry *s
gyroConfigMutable()->gyro_soft_notch_cutoff_1 = gyroConfig_gyro_soft_notch_cutoff_1;
gyroConfigMutable()->gyro_soft_notch_hz_2 = gyroConfig_gyro_soft_notch_hz_2;
gyroConfigMutable()->gyro_soft_notch_cutoff_2 = gyroConfig_gyro_soft_notch_cutoff_2;
gyroConfigMutable()->gyro_to_use = gyroConfig_gyro_to_use;
return NULL;
}
@ -797,9 +788,6 @@ static const OSD_Entry cmsx_menuFilterGlobalEntries[] =
{ "GYRO NF1C", OME_UINT16, NULL, &(OSD_UINT16_t) { &gyroConfig_gyro_soft_notch_cutoff_1, 0, 500, 1 } },
{ "GYRO NF2", OME_UINT16, NULL, &(OSD_UINT16_t) { &gyroConfig_gyro_soft_notch_hz_2, 0, 500, 1 } },
{ "GYRO NF2C", OME_UINT16, NULL, &(OSD_UINT16_t) { &gyroConfig_gyro_soft_notch_cutoff_2, 0, 500, 1 } },
#ifdef USE_MULTI_GYRO
{ "GYRO TO USE", OME_TAB | REBOOT_REQUIRED, NULL, &(OSD_TAB_t) { &gyroConfig_gyro_to_use, 2, osdTableGyroToUse} },
#endif
{ "BACK", OME_Back, NULL, NULL },
{ NULL, OME_END, NULL, NULL}

View file

@ -293,10 +293,10 @@ static void validateAndFixConfig(void)
#if defined(USE_MAG)
buildAlignmentFromStandardAlignment(&compassConfigMutable()->mag_customAlignment, compassConfig()->mag_alignment);
#endif
buildAlignmentFromStandardAlignment(&gyroDeviceConfigMutable(0)->customAlignment, gyroDeviceConfig(0)->alignment);
#if defined(USE_MULTI_GYRO)
buildAlignmentFromStandardAlignment(&gyroDeviceConfigMutable(1)->customAlignment, gyroDeviceConfig(1)->alignment);
#endif
for (int i = 0; i < GYRO_COUNT; i++) {
buildAlignmentFromStandardAlignment(&gyroDeviceConfigMutable(i)->customAlignment, gyroDeviceConfig(i)->alignment);
}
#ifdef USE_ACC
if (accelerometerConfig()->accZero.values.roll != 0 ||

View file

@ -190,17 +190,25 @@ static void setUserBank(const extDevice_t *dev, const uint8_t user_bank)
#if defined(USE_GYRO_CLKIN)
static pwmOutputPort_t pwmGyroClk = {0};
static int findByExtDevice(const extDevice_t *dev) {
for (int i = 0; i < GYRO_COUNT; i++) {
if (&gyro.gyroSensor[i].gyroDev.dev == dev) {
return i;
}
}
return -1;
}
static bool initExternalClock(const extDevice_t *dev)
{
int cfg;
if (&gyro.gyroSensor1.gyroDev.dev == dev) {
cfg = 0;
} else if (&gyro.gyroSensor2.gyroDev.dev == dev) {
cfg = 1;
} else {
// only gyroSensor<n> device supported
const int cfg = findByExtDevice(dev);
if (cfg < 0) {
// Could not find a valid sensor
return false;
}
const ioTag_t tag = gyroDeviceConfig(cfg)->clkIn;
const IO_t io = IOGetByTag(tag);
if (pwmGyroClk.enabled) {

View file

@ -25,7 +25,7 @@
#define PARAM_NAME_GYRO_LPF1_STATIC_HZ "gyro_lpf1_static_hz"
#define PARAM_NAME_GYRO_LPF2_TYPE "gyro_lpf2_type"
#define PARAM_NAME_GYRO_LPF2_STATIC_HZ "gyro_lpf2_static_hz"
#define PARAM_NAME_GYRO_TO_USE "gyro_to_use"
#define PARAM_NAME_GYRO_ENABLE_MASK "gyro_enable_bitmask"
#define PARAM_NAME_DYN_NOTCH_MAX_HZ "dyn_notch_max_hz"
#define PARAM_NAME_DYN_NOTCH_COUNT "dyn_notch_count"
#define PARAM_NAME_DYN_NOTCH_Q "dyn_notch_q"

View file

@ -1812,21 +1812,7 @@ case MSP_NAME:
break;
case MSP_SENSOR_ALIGNMENT: {
uint8_t gyroAlignment;
#ifdef USE_MULTI_GYRO
switch (gyroConfig()->gyro_to_use) {
case GYRO_CONFIG_USE_GYRO_2:
gyroAlignment = gyroDeviceConfig(1)->alignment;
break;
case GYRO_CONFIG_USE_GYRO_BOTH:
// for dual-gyro in "BOTH" mode we only read/write gyro 0
default:
gyroAlignment = gyroDeviceConfig(0)->alignment;
break;
}
#else
gyroAlignment = gyroDeviceConfig(0)->alignment;
#endif
uint8_t gyroAlignment = gyroDeviceConfig(firstEnabledGyro())->alignment;
sbufWriteU8(dst, gyroAlignment);
sbufWriteU8(dst, gyroAlignment); // Starting with 4.0 gyro and acc alignment are the same
#if defined(USE_MAG)
@ -1836,32 +1822,17 @@ case MSP_NAME:
#endif
// API 1.41 - Add multi-gyro indicator, selected gyro, and support for separate gyro 1 & 2 alignment
sbufWriteU8(dst, getGyroDetectionFlags());
#ifdef USE_MULTI_GYRO
sbufWriteU8(dst, gyroConfig()->gyro_to_use);
sbufWriteU8(dst, gyroDeviceConfig(0)->alignment);
sbufWriteU8(dst, gyroDeviceConfig(1)->alignment);
#else
sbufWriteU8(dst, GYRO_CONFIG_USE_GYRO_1);
sbufWriteU8(dst, gyroDeviceConfig(0)->alignment);
sbufWriteU8(dst, ALIGN_DEFAULT);
#endif
// Added in MSP API 1.47
switch (gyroConfig()->gyro_to_use) {
#ifdef USE_MULTI_GYRO
case GYRO_CONFIG_USE_GYRO_2:
sbufWriteU16(dst, gyroDeviceConfig(1)->customAlignment.roll);
sbufWriteU16(dst, gyroDeviceConfig(1)->customAlignment.pitch);
sbufWriteU16(dst, gyroDeviceConfig(1)->customAlignment.yaw);
break;
#endif
case GYRO_CONFIG_USE_GYRO_BOTH:
// for dual-gyro in "BOTH" mode we only read/write gyro 0
default:
sbufWriteU16(dst, gyroDeviceConfig(0)->customAlignment.roll);
sbufWriteU16(dst, gyroDeviceConfig(0)->customAlignment.pitch);
sbufWriteU16(dst, gyroDeviceConfig(0)->customAlignment.yaw);
break;
sbufWriteU8(dst, getGyroDetectedFlags());
sbufWriteU8(dst, gyroConfig()->gyro_enabled_bitmask); // deprecates gyro_to_use
// Added support for more then two IMUs in MSP API 1.47
for (int i = 0; i < 8; i++) {
sbufWriteU8(dst, i < GYRO_COUNT ? gyroDeviceConfig(i)->alignment : ALIGN_DEFAULT);
}
for (int i = 0; i < 8; i++) {
for (unsigned j; j < ARRAYLEN(gyroDeviceConfig(i)->customAlignment.raw); j++) {
sbufWriteU16(dst, i < GYRO_COUNT ? gyroDeviceConfig(i)->customAlignment.raw[j] : 0);
}
}
#ifdef USE_MAG
@ -1885,7 +1856,7 @@ case MSP_NAME:
sbufWriteU16(dst, motorConfig()->motorIdle);
sbufWriteU8(dst, 0); // DEPRECATED: gyro_use_32kHz
sbufWriteU8(dst, motorConfig()->dev.motorInversion);
sbufWriteU8(dst, gyroConfig()->gyro_to_use);
sbufWriteU8(dst, 0); // deprecated gyro_to_use
sbufWriteU8(dst, gyroConfig()->gyro_high_fsr);
sbufWriteU8(dst, gyroConfig()->gyroMovementCalibrationThreshold);
sbufWriteU16(dst, gyroConfig()->gyroCalibrationDuration);
@ -3014,8 +2985,7 @@ static mspResult_e mspProcessInCommand(mspDescriptor_t srcDesc, int16_t cmdMSP,
break;
case MSP_SET_SENSOR_ALIGNMENT: {
// maintain backwards compatibility for API < 1.41
const uint8_t gyroAlignment = sbufReadU8(src);
sbufReadU8(src);
sbufReadU8(src); // discard deprecated acc_align
#if defined(USE_MAG)
compassConfigMutable()->mag_alignment = sbufReadU8(src);
@ -3023,53 +2993,33 @@ static mspResult_e mspProcessInCommand(mspDescriptor_t srcDesc, int16_t cmdMSP,
sbufReadU8(src);
#endif
if (sbufBytesRemaining(src) >= 3) {
// API >= 1.41 - support the gyro_to_use and alignment for gyros 1 & 2
#ifdef USE_MULTI_GYRO
gyroConfigMutable()->gyro_to_use = sbufReadU8(src);
gyroDeviceConfigMutable(0)->alignment = sbufReadU8(src);
gyroDeviceConfigMutable(1)->alignment = sbufReadU8(src);
#else
sbufReadU8(src); // unused gyro_to_use
gyroDeviceConfigMutable(0)->alignment = sbufReadU8(src);
sbufReadU8(src); // unused gyro_2_sensor_align
#endif
} else {
// maintain backwards compatibility for API < 1.41
#ifdef USE_MULTI_GYRO
switch (gyroConfig()->gyro_to_use) {
case GYRO_CONFIG_USE_GYRO_2:
gyroDeviceConfigMutable(1)->alignment = gyroAlignment;
break;
case GYRO_CONFIG_USE_GYRO_BOTH:
// For dual-gyro in "BOTH" mode we'll only update gyro 0
default:
gyroDeviceConfigMutable(0)->alignment = gyroAlignment;
break;
}
#else
gyroDeviceConfigMutable(0)->alignment = gyroAlignment;
#endif
}
gyroConfigMutable()->gyro_enabled_bitmask = sbufReadU8(src);
// Added in API 1.47
if (sbufBytesRemaining(src) >= 6) {
switch (gyroConfig()->gyro_to_use) {
#ifdef USE_MULTI_GYRO
case GYRO_CONFIG_USE_GYRO_2:
gyroDeviceConfigMutable(1)->customAlignment.roll = sbufReadU16(src);
gyroDeviceConfigMutable(1)->customAlignment.pitch = sbufReadU16(src);
gyroDeviceConfigMutable(1)->customAlignment.yaw = sbufReadU16(src);
break;
#endif
case GYRO_CONFIG_USE_GYRO_BOTH:
// For dual-gyro in "BOTH" mode we'll only update gyro 0
default:
gyroDeviceConfigMutable(0)->customAlignment.roll = sbufReadU16(src);
gyroDeviceConfigMutable(0)->customAlignment.pitch = sbufReadU16(src);
gyroDeviceConfigMutable(0)->customAlignment.yaw = sbufReadU16(src);
break;
if (sbufBytesRemaining(src) >= 8 * 7) {
for (int i = 0; i < 8; i++) {
const uint8_t alignment = sbufReadU8(src);
if (i < GYRO_COUNT) {
gyroDeviceConfigMutable(i)->alignment = alignment;
}
}
for (int i = 0; i < 8; i++) {
if (i < GYRO_COUNT) {
sensorAlignment_t customAlignment;
for (unsigned j = 0; j < ARRAYLEN(customAlignment.raw); j++) {
customAlignment.raw[j] = (int16_t)sbufReadU16(src);
}
if (i < GYRO_COUNT) {
gyroDeviceConfigMutable(i)->customAlignment = customAlignment;
}
} else {
sbufReadU16(src); // skip unused custom alignment roll
sbufReadU16(src); // skip unused custom alignment pitch
sbufReadU16(src); // skip unused custom alignment yaw
}
}
}
if (sbufBytesRemaining(src) >= 6) {
#ifdef USE_MAG
compassConfigMutable()->mag_customAlignment.roll = sbufReadU16(src);
@ -3081,6 +3031,7 @@ static mspResult_e mspProcessInCommand(mspDescriptor_t srcDesc, int16_t cmdMSP,
sbufReadU16(src);
#endif
}
break;
}
@ -3100,7 +3051,7 @@ static mspResult_e mspProcessInCommand(mspDescriptor_t srcDesc, int16_t cmdMSP,
motorConfigMutable()->dev.motorInversion = sbufReadU8(src);
}
if (sbufBytesRemaining(src) >= 8) {
gyroConfigMutable()->gyro_to_use = sbufReadU8(src);
sbufReadU8(src); // deprecated gyro_to_use
gyroConfigMutable()->gyro_high_fsr = sbufReadU8(src);
gyroConfigMutable()->gyroMovementCalibrationThreshold = sbufReadU8(src);
gyroConfigMutable()->gyroCalibrationDuration = sbufReadU16(src);

View file

@ -35,6 +35,10 @@
#include "drivers/sensor.h"
#include "sensors/gyro.h"
#ifdef SIMULATOR_BUILD
#define GYRO_COUNT 1
#endif
#ifndef GYRO_1_CS_PIN
#define GYRO_1_CS_PIN NONE
#endif
@ -43,6 +47,10 @@
#define GYRO_1_EXTI_PIN NONE
#endif
#ifndef GYRO_1_CLKIN_PIN
#define GYRO_1_CLKIN_PIN NONE
#endif
#ifndef GYRO_2_CS_PIN
#define GYRO_2_CS_PIN NONE
#endif
@ -51,14 +59,34 @@
#define GYRO_2_EXTI_PIN NONE
#endif
#ifndef GYRO_1_CLKIN_PIN
#define GYRO_1_CLKIN_PIN NONE
#endif
#ifndef GYRO_2_CLKIN_PIN
#define GYRO_2_CLKIN_PIN NONE
#endif
#ifndef GYRO_3_CS_PIN
#define GYRO_3_CS_PIN NONE
#endif
#ifndef GYRO_3_EXTI_PIN
#define GYRO_3_EXTI_PIN NONE
#endif
#ifndef GYRO_3_CLKIN_PIN
#define GYRO_3_CLKIN_PIN NONE
#endif
#ifndef GYRO_4_CS_PIN
#define GYRO_4_CS_PIN NONE
#endif
#ifndef GYRO_4_EXTI_PIN
#define GYRO_4_EXTI_PIN NONE
#endif
#ifndef GYRO_4_CLKIN_PIN
#define GYRO_4_CLKIN_PIN NONE
#endif
#ifdef MPU_ADDRESS
#define GYRO_I2C_ADDRESS MPU_ADDRESS
#else
@ -102,6 +130,40 @@
#endif
#endif // GYRO_2_ALIGN_ROLL || GYRO_2_ALIGN_PITCH || GYRO_2_ALIGN_YAW
#if defined(GYRO_3_ALIGN_ROLL) || defined(GYRO_3_ALIGN_PITCH) || defined(GYRO_3_ALIGN_YAW)
#ifndef GYRO_3_ALIGN_ROLL
#define GYRO_3_ALIGN_ROLL 0
#endif
#ifndef GYRO_3_ALIGN_PITCH
#define GYRO_3_ALIGN_PITCH 0
#endif
#ifndef GYRO_3_ALIGN_YAW
#define GYRO_3_ALIGN_YAW 0
#endif
#ifndef GYRO_3_CUSTOM_ALIGN
#define GYRO_3_CUSTOM_ALIGN SENSOR_ALIGNMENT( GYRO_3_ALIGN_ROLL / 10, GYRO_3_ALIGN_PITCH / 10, GYRO_3_ALIGN_YAW / 10 )
#else
#error "GYRO_3_ALIGN_x and GYRO_3_CUSTOM_ALIGN are mutually exclusive"
#endif
#endif // GYRO_3_ALIGN_ROLL || GYRO_3_ALIGN_PITCH || GYRO_3_ALIGN_YAW
#if defined(GYRO_4_ALIGN_ROLL) || defined(GYRO_4_ALIGN_PITCH) || defined(GYRO_4_ALIGN_YAW)
#ifndef GYRO_4_ALIGN_ROLL
#define GYRO_4_ALIGN_ROLL 0
#endif
#ifndef GYRO_4_ALIGN_PITCH
#define GYRO_4_ALIGN_PITCH 0
#endif
#ifndef GYRO_4_ALIGN_YAW
#define GYRO_4_ALIGN_YAW 0
#endif
#ifndef GYRO_4_CUSTOM_ALIGN
#define GYRO_4_CUSTOM_ALIGN SENSOR_ALIGNMENT( GYRO_4_ALIGN_ROLL / 10, GYRO_4_ALIGN_PITCH / 10, GYRO_4_ALIGN_YAW / 10 )
#else
#error "GYRO_4_ALIGN_x and GYRO_4_CUSTOM_ALIGN are mutually exclusive"
#endif
#endif // GYRO_4_ALIGN_ROLL || GYRO_4_ALIGN_PITCH || GYRO_4_ALIGN_YAW
#ifndef GYRO_1_ALIGN
#ifdef GYRO_1_CUSTOM_ALIGN
#define GYRO_1_ALIGN ALIGN_CUSTOM
@ -130,6 +192,34 @@ STATIC_ASSERT(GYRO_1_ALIGN == ALIGN_CUSTOM, "GYRO_1_ALIGN and GYRO_1_CUSTOM_ALIG
STATIC_ASSERT(GYRO_2_ALIGN == ALIGN_CUSTOM, "GYRO_2_ALIGN and GYRO_2_CUSTOM_ALIGN mixed");
#endif // GYRO_2_CUSTOM_ALIGN
#ifndef GYRO_3_ALIGN
#ifdef GYRO_3_CUSTOM_ALIGN
#define GYRO_3_ALIGN ALIGN_CUSTOM
#else
#define GYRO_3_ALIGN CW0_DEG
#endif
#endif // GYRO_3_ALIGN
#ifndef GYRO_3_CUSTOM_ALIGN
#define GYRO_3_CUSTOM_ALIGN SENSOR_ALIGNMENT_FROM_STD(GYRO_3_ALIGN)
#else
STATIC_ASSERT(GYRO_3_ALIGN == ALIGN_CUSTOM, "GYRO_3_ALIGN and GYRO_3_CUSTOM_ALIGN mixed");
#endif // GYRO_3_CUSTOM_ALIGN
#ifndef GYRO_4_ALIGN
#ifdef GYRO_4_CUSTOM_ALIGN
#define GYRO_4_ALIGN ALIGN_CUSTOM
#else
#define GYRO_4_ALIGN CW0_DEG
#endif
#endif // GYRO_4_ALIGN
#ifndef GYRO_4_CUSTOM_ALIGN
#define GYRO_4_CUSTOM_ALIGN SENSOR_ALIGNMENT_FROM_STD(GYRO_4_ALIGN)
#else
STATIC_ASSERT(GYRO_4_ALIGN == ALIGN_CUSTOM, "GYRO_4_ALIGN and GYRO_4_CUSTOM_ALIGN mixed");
#endif // GYRO_4_CUSTOM_ALIGN
#if defined(USE_SPI_GYRO) && (defined(GYRO_1_SPI_INSTANCE) || defined(GYRO_2_SPI_INSTANCE))
static void gyroResetSpiDeviceConfig(gyroDeviceConfig_t *devconf, SPI_TypeDef *instance, ioTag_t csnTag, ioTag_t extiTag, ioTag_t clkInTag, uint8_t alignment, sensorAlignment_t customAlignment)
{
@ -143,7 +233,7 @@ static void gyroResetSpiDeviceConfig(gyroDeviceConfig_t *devconf, SPI_TypeDef *i
}
#endif
#if defined(USE_I2C_GYRO) && !defined(USE_MULTI_GYRO)
#if defined(USE_I2C_GYRO) && !(GYRO_COUNT > 1)
static void gyroResetI2cDeviceConfig(gyroDeviceConfig_t *devconf, I2CDevice i2cbus, ioTag_t extiTag, uint8_t alignment, sensorAlignment_t customAlignment)
{
devconf->busType = BUS_TYPE_I2C;
@ -162,25 +252,58 @@ void pgResetFn_gyroDeviceConfig(gyroDeviceConfig_t *devconf)
devconf[0].index = 0;
// All multi-gyro boards use SPI based gyros.
#ifdef USE_SPI_GYRO
#define GYRO_RESET(index, num) \
gyroResetSpiDeviceConfig(&devconf[index], GYRO_##num##_SPI_INSTANCE, \
IO_TAG(GYRO_##num##_CS_PIN), IO_TAG(GYRO_##num##_EXTI_PIN), \
IO_TAG(GYRO_##num##_CLKIN_PIN), GYRO_##num##_ALIGN, GYRO_##num##_CUSTOM_ALIGN)
#ifdef GYRO_1_SPI_INSTANCE
gyroResetSpiDeviceConfig(&devconf[0], GYRO_1_SPI_INSTANCE, IO_TAG(GYRO_1_CS_PIN), IO_TAG(GYRO_1_EXTI_PIN), IO_TAG(GYRO_1_CLKIN_PIN), GYRO_1_ALIGN, GYRO_1_CUSTOM_ALIGN);
GYRO_RESET(0, 1);
#else
devconf[0].busType = BUS_TYPE_NONE;
#endif
#ifdef USE_MULTI_GYRO
#if GYRO_COUNT > 1
devconf[1].index = 1;
#ifdef GYRO_2_SPI_INSTANCE
// TODO: CLKIN gyro 2 on separate pin is not supported yet. need to implement it
gyroResetSpiDeviceConfig(&devconf[1], GYRO_2_SPI_INSTANCE, IO_TAG(GYRO_2_CS_PIN), IO_TAG(GYRO_2_EXTI_PIN), IO_TAG(GYRO_2_CLKIN_PIN), GYRO_2_ALIGN, GYRO_2_CUSTOM_ALIGN);
GYRO_RESET(1, 2);
#else
devconf[1].busType = BUS_TYPE_NONE;
#endif
#endif // GYRO_COUNT 2
#endif // USE_MULTI_GYRO
#if GYRO_COUNT > 2
devconf[2].index = 2;
#ifdef GYRO_3_SPI_INSTANCE
// TODO: CLKIN gyro 3 on separate pin is not supported yet. need to implement it
GYRO_RESET(2, 3);
#else
devconf[2].busType = BUS_TYPE_NONE;
#endif
#endif // GYRO_COUNT 3
#if GYRO_COUNT > 3
devconf[3].index = 3;
#ifdef GYRO_4_SPI_INSTANCE
// TODO: CLKIN gyro 4 on separate pin is not supported yet. need to implement it
GYRO_RESET(3, 4);
#else
devconf[3].busType = BUS_TYPE_NONE;
#endif
#endif // GYRO_COUNT 4
#if GYRO_COUNT > 4
// reset all gyro greater than gyro 5
for (int i = 4; i < 8; i++) {
devconf[i].busType = BUS_TYPE_NONE;
}
#endif
#endif // USE_SPI_GYRO
// I2C gyros appear as a sole gyro in single gyro boards.
#if defined(USE_I2C_GYRO) && !defined(USE_MULTI_GYRO)
#if defined(USE_I2C_GYRO) && !(GYRO_COUNT > 1)
devconf[0].i2cBus = I2C_DEV_TO_CFG(I2CINVALID); // XXX Not required?
gyroResetI2cDeviceConfig(&devconf[0], I2C_DEVICE, IO_TAG(GYRO_1_EXTI_PIN), GYRO_1_ALIGN, customAlignment1);
#endif

View file

@ -26,13 +26,8 @@
#include "common/sensor_alignment.h"
#include "drivers/io_types.h"
#ifdef USE_MULTI_GYRO
#define MAX_GYRODEV_COUNT 2
#define MAX_ACCDEV_COUNT 2
#else
#define MAX_GYRODEV_COUNT 1
#define MAX_ACCDEV_COUNT 1
#endif
#define MAX_GYRODEV_COUNT GYRO_COUNT
#define MAX_ACCDEV_COUNT GYRO_COUNT
typedef struct gyroDeviceConfig_s {
int8_t index;

View file

@ -367,15 +367,9 @@ bool accInit(uint16_t accSampleRateHz)
// Copy alignment from active gyro, as all production boards use acc-gyro-combi chip.
// Exception is STM32F411DISCOVERY, and (may be) handled in future enhancement.
sensor_align_e alignment = gyroDeviceConfig(0)->alignment;
const sensorAlignment_t* customAlignment = &gyroDeviceConfig(0)->customAlignment;
sensor_align_e alignment = gyroDeviceConfig(firstEnabledGyro())->alignment;
const sensorAlignment_t* customAlignment = &gyroDeviceConfig(firstEnabledGyro())->customAlignment;
#ifdef USE_MULTI_GYRO
if (gyroConfig()->gyro_to_use == GYRO_CONFIG_USE_GYRO_2) {
alignment = gyroDeviceConfig(1)->alignment;
customAlignment = &gyroDeviceConfig(1)->customAlignment;
}
#endif
acc.dev.accAlign = alignment;
buildRotationMatrixFromAngles(&acc.dev.rotationMatrix, customAlignment);

View file

@ -86,8 +86,8 @@ FAST_DATA uint8_t activePidLoopDenom = 1;
static bool firstArmingCalibrationWasStarted = false;
#ifdef UNIT_TEST
STATIC_UNIT_TESTED gyroSensor_t * const gyroSensorPtr = &gyro.gyroSensor1;
STATIC_UNIT_TESTED gyroDev_t * const gyroDevPtr = &gyro.gyroSensor1.gyroDev;
STATIC_UNIT_TESTED gyroSensor_t * const gyroSensorPtr = &gyro.gyroSensor[0];
STATIC_UNIT_TESTED gyroDev_t * const gyroDevPtr = &gyro.gyroSensor[0].gyroDev;
#endif
#define DEBUG_GYRO_CALIBRATION_VALUE 3
@ -97,8 +97,9 @@ STATIC_UNIT_TESTED gyroDev_t * const gyroDevPtr = &gyro.gyroSensor1.gyroDev;
PG_REGISTER_WITH_RESET_FN(gyroConfig_t, gyroConfig, PG_GYRO_CONFIG, 9);
#ifndef DEFAULT_GYRO_TO_USE
#define DEFAULT_GYRO_TO_USE GYRO_CONFIG_USE_GYRO_1
#ifndef DEFAULT_GYRO_ENABLED
// enable the first gyro if none are enabled
#define DEFAULT_GYRO_ENABLED GYRO_MASK(0)
#endif
void pgResetFn_gyroConfig(gyroConfig_t *gyroConfig)
@ -115,7 +116,6 @@ void pgResetFn_gyroConfig(gyroConfig_t *gyroConfig)
gyroConfig->gyro_lpf2_type = FILTER_PT1;
gyroConfig->gyro_lpf2_static_hz = GYRO_LPF2_HZ_DEFAULT;
gyroConfig->gyro_high_fsr = false;
gyroConfig->gyro_to_use = DEFAULT_GYRO_TO_USE;
gyroConfig->gyro_soft_notch_hz_1 = 0;
gyroConfig->gyro_soft_notch_cutoff_1 = 0;
gyroConfig->gyro_soft_notch_hz_2 = 0;
@ -130,6 +130,7 @@ void pgResetFn_gyroConfig(gyroConfig_t *gyroConfig)
gyroConfig->gyro_lpf1_dyn_expo = 5;
gyroConfig->simplified_gyro_filter = true;
gyroConfig->simplified_gyro_filter_multiplier = SIMPLIFIED_TUNING_DEFAULT;
gyroConfig->gyro_enabled_bitmask = DEFAULT_GYRO_ENABLED;
}
static bool isGyroSensorCalibrationComplete(const gyroSensor_t *gyroSensor)
@ -139,20 +140,15 @@ static bool isGyroSensorCalibrationComplete(const gyroSensor_t *gyroSensor)
bool gyroIsCalibrationComplete(void)
{
switch (gyro.gyroToUse) {
default:
case GYRO_CONFIG_USE_GYRO_1: {
return isGyroSensorCalibrationComplete(&gyro.gyroSensor1);
for (int i = 0; i < GYRO_COUNT; i++) {
if (gyro.gyroEnabledBitmask & GYRO_MASK(i)) {
if (!isGyroSensorCalibrationComplete(&gyro.gyroSensor[i])) {
return false;
}
#ifdef USE_MULTI_GYRO
case GYRO_CONFIG_USE_GYRO_2: {
return isGyroSensorCalibrationComplete(&gyro.gyroSensor2);
}
case GYRO_CONFIG_USE_GYRO_BOTH: {
return isGyroSensorCalibrationComplete(&gyro.gyroSensor1) && isGyroSensorCalibrationComplete(&gyro.gyroSensor2);
}
#endif
}
return true;
}
static bool isOnFinalGyroCalibrationCycle(const gyroCalibration_t *gyroCalibration)
@ -187,10 +183,11 @@ void gyroStartCalibration(bool isFirstArmingCalibration)
return;
}
gyroSetCalibrationCycles(&gyro.gyroSensor1);
#ifdef USE_MULTI_GYRO
gyroSetCalibrationCycles(&gyro.gyroSensor2);
#endif
for (int i = 0; i < GYRO_COUNT; i++) {
if (gyro.gyroEnabledBitmask & GYRO_MASK(i)) {
gyroSetCalibrationCycles(&gyro.gyroSensor[i]);
}
}
if (isFirstArmingCalibration) {
firstArmingCalibrationWasStarted = true;
@ -410,34 +407,27 @@ static FAST_CODE void gyroUpdateSensor(gyroSensor_t *gyroSensor)
FAST_CODE void gyroUpdate(void)
{
switch (gyro.gyroToUse) {
case GYRO_CONFIG_USE_GYRO_1:
gyroUpdateSensor(&gyro.gyroSensor1);
if (isGyroSensorCalibrationComplete(&gyro.gyroSensor1)) {
gyro.gyroADC[X] = gyro.gyroSensor1.gyroDev.gyroADC.x * gyro.gyroSensor1.gyroDev.scale;
gyro.gyroADC[Y] = gyro.gyroSensor1.gyroDev.gyroADC.y * gyro.gyroSensor1.gyroDev.scale;
gyro.gyroADC[Z] = gyro.gyroSensor1.gyroDev.gyroADC.z * gyro.gyroSensor1.gyroDev.scale;
// ensure that gyroADC don't contain a stale value
float adcSum[XYZ_AXIS_COUNT] = {0};
float active = 0;
for (int i = 0; i < GYRO_COUNT; i++) {
if (gyro.gyroEnabledBitmask & GYRO_MASK(i)) {
gyroUpdateSensor(&gyro.gyroSensor[i]);
if (isGyroSensorCalibrationComplete(&gyro.gyroSensor[i])) {
adcSum[X] += gyro.gyroSensor[i].gyroDev.gyroADC.x * gyro.gyroSensor[i].gyroDev.scale;
adcSum[Y] += gyro.gyroSensor[i].gyroDev.gyroADC.y * gyro.gyroSensor[i].gyroDev.scale;
adcSum[Z] += gyro.gyroSensor[i].gyroDev.gyroADC.z * gyro.gyroSensor[i].gyroDev.scale;
active++;
}
break;
#ifdef USE_MULTI_GYRO
case GYRO_CONFIG_USE_GYRO_2:
gyroUpdateSensor(&gyro.gyroSensor2);
if (isGyroSensorCalibrationComplete(&gyro.gyroSensor2)) {
gyro.gyroADC[X] = gyro.gyroSensor2.gyroDev.gyroADC.x * gyro.gyroSensor2.gyroDev.scale;
gyro.gyroADC[Y] = gyro.gyroSensor2.gyroDev.gyroADC.y * gyro.gyroSensor2.gyroDev.scale;
gyro.gyroADC[Z] = gyro.gyroSensor2.gyroDev.gyroADC.z * gyro.gyroSensor2.gyroDev.scale;
}
break;
case GYRO_CONFIG_USE_GYRO_BOTH:
gyroUpdateSensor(&gyro.gyroSensor1);
gyroUpdateSensor(&gyro.gyroSensor2);
if (isGyroSensorCalibrationComplete(&gyro.gyroSensor1) && isGyroSensorCalibrationComplete(&gyro.gyroSensor2)) {
gyro.gyroADC[X] = ((gyro.gyroSensor1.gyroDev.gyroADC.x * gyro.gyroSensor1.gyroDev.scale) + (gyro.gyroSensor2.gyroDev.gyroADC.x * gyro.gyroSensor2.gyroDev.scale)) / 2.0f;
gyro.gyroADC[Y] = ((gyro.gyroSensor1.gyroDev.gyroADC.y * gyro.gyroSensor1.gyroDev.scale) + (gyro.gyroSensor2.gyroDev.gyroADC.y * gyro.gyroSensor2.gyroDev.scale)) / 2.0f;
gyro.gyroADC[Z] = ((gyro.gyroSensor1.gyroDev.gyroADC.z * gyro.gyroSensor1.gyroDev.scale) + (gyro.gyroSensor2.gyroDev.gyroADC.z * gyro.gyroSensor2.gyroDev.scale)) / 2.0f;
}
break;
#endif
if (active != 0) {
gyro.gyroADC[X] = adcSum[X] / active;
gyro.gyroADC[Y] = adcSum[Y] / active;
gyro.gyroADC[Z] = adcSum[Z] / active;
}
if (gyro.downsampleFilterEnabled) {
@ -485,36 +475,24 @@ FAST_CODE void gyroFiltering(timeUs_t currentTimeUs)
#endif
if (gyro.useDualGyroDebugging) {
switch (gyro.gyroToUse) {
case GYRO_CONFIG_USE_GYRO_1:
DEBUG_SET(DEBUG_DUAL_GYRO_RAW, 0, gyro.gyroSensor1.gyroDev.gyroADCRaw[X]);
DEBUG_SET(DEBUG_DUAL_GYRO_RAW, 1, gyro.gyroSensor1.gyroDev.gyroADCRaw[Y]);
DEBUG_SET(DEBUG_DUAL_GYRO_SCALED, 0, lrintf(gyro.gyroSensor1.gyroDev.gyroADC.x * gyro.gyroSensor1.gyroDev.scale));
DEBUG_SET(DEBUG_DUAL_GYRO_SCALED, 1, lrintf(gyro.gyroSensor1.gyroDev.gyroADC.y * gyro.gyroSensor1.gyroDev.scale));
break;
int debugIndex = 0;
#ifdef USE_MULTI_GYRO
case GYRO_CONFIG_USE_GYRO_2:
DEBUG_SET(DEBUG_DUAL_GYRO_RAW, 2, gyro.gyroSensor2.gyroDev.gyroADCRaw[X]);
DEBUG_SET(DEBUG_DUAL_GYRO_RAW, 3, gyro.gyroSensor2.gyroDev.gyroADCRaw[Y]);
DEBUG_SET(DEBUG_DUAL_GYRO_SCALED, 2, lrintf(gyro.gyroSensor2.gyroDev.gyroADC.x * gyro.gyroSensor2.gyroDev.scale));
DEBUG_SET(DEBUG_DUAL_GYRO_SCALED, 3, lrintf(gyro.gyroSensor2.gyroDev.gyroADC.y * gyro.gyroSensor2.gyroDev.scale));
break;
for (int i = 0; i < GYRO_COUNT; i++) {
if (gyro.gyroEnabledBitmask & GYRO_MASK(i)) {
DEBUG_SET(DEBUG_DUAL_GYRO_RAW, 0 + debugIndex, gyro.gyroSensor[i].gyroDev.gyroADCRaw[X]);
DEBUG_SET(DEBUG_DUAL_GYRO_RAW, 1 + debugIndex, gyro.gyroSensor[i].gyroDev.gyroADCRaw[Y]);
DEBUG_SET(DEBUG_DUAL_GYRO_SCALED, 0 + debugIndex, lrintf(gyro.gyroSensor[i].gyroDev.gyroADC.x * gyro.gyroSensor[i].gyroDev.scale));
DEBUG_SET(DEBUG_DUAL_GYRO_SCALED, 1 + debugIndex, lrintf(gyro.gyroSensor[i].gyroDev.gyroADC.y * gyro.gyroSensor[i].gyroDev.scale));
// grab the difference between each gyro and the fused gyro output, gyro.gyroADCf (it hasn't had filters applied yet)
DEBUG_SET(DEBUG_DUAL_GYRO_DIFF, 0 + debugIndex, lrintf((gyro.gyroSensor[i].gyroDev.gyroADC.x * gyro.gyroSensor[i].gyroDev.scale) - gyro.gyroADCf[0]));
DEBUG_SET(DEBUG_DUAL_GYRO_DIFF, 1 + debugIndex, lrintf((gyro.gyroSensor[i].gyroDev.gyroADC.y * gyro.gyroSensor[i].gyroDev.scale) - gyro.gyroADCf[1]));
case GYRO_CONFIG_USE_GYRO_BOTH:
DEBUG_SET(DEBUG_DUAL_GYRO_RAW, 0, gyro.gyroSensor1.gyroDev.gyroADCRaw[X]);
DEBUG_SET(DEBUG_DUAL_GYRO_RAW, 1, gyro.gyroSensor1.gyroDev.gyroADCRaw[Y]);
DEBUG_SET(DEBUG_DUAL_GYRO_RAW, 2, gyro.gyroSensor2.gyroDev.gyroADCRaw[X]);
DEBUG_SET(DEBUG_DUAL_GYRO_RAW, 3, gyro.gyroSensor2.gyroDev.gyroADCRaw[Y]);
DEBUG_SET(DEBUG_DUAL_GYRO_SCALED, 0, lrintf(gyro.gyroSensor1.gyroDev.gyroADC.x * gyro.gyroSensor1.gyroDev.scale));
DEBUG_SET(DEBUG_DUAL_GYRO_SCALED, 1, lrintf(gyro.gyroSensor1.gyroDev.gyroADC.y * gyro.gyroSensor1.gyroDev.scale));
DEBUG_SET(DEBUG_DUAL_GYRO_SCALED, 2, lrintf(gyro.gyroSensor2.gyroDev.gyroADC.x * gyro.gyroSensor2.gyroDev.scale));
DEBUG_SET(DEBUG_DUAL_GYRO_SCALED, 3, lrintf(gyro.gyroSensor2.gyroDev.gyroADC.y * gyro.gyroSensor2.gyroDev.scale));
DEBUG_SET(DEBUG_DUAL_GYRO_DIFF, 0, lrintf((gyro.gyroSensor1.gyroDev.gyroADC.x * gyro.gyroSensor1.gyroDev.scale) - (gyro.gyroSensor2.gyroDev.gyroADC.x * gyro.gyroSensor2.gyroDev.scale)));
DEBUG_SET(DEBUG_DUAL_GYRO_DIFF, 1, lrintf((gyro.gyroSensor1.gyroDev.gyroADC.y * gyro.gyroSensor1.gyroDev.scale) - (gyro.gyroSensor2.gyroDev.gyroADC.y * gyro.gyroSensor2.gyroDev.scale)));
DEBUG_SET(DEBUG_DUAL_GYRO_DIFF, 2, lrintf((gyro.gyroSensor1.gyroDev.gyroADC.z * gyro.gyroSensor1.gyroDev.scale) - (gyro.gyroSensor2.gyroDev.gyroADC.z * gyro.gyroSensor2.gyroDev.scale)));
debugIndex += 2;
if (debugIndex >= 8) {
break;
#endif
// only iterate over the first 4 enabled gyros, debug can't hold more
}
}
}
}
@ -556,23 +534,17 @@ static int16_t gyroReadSensorTemperature(gyroSensor_t gyroSensor)
void gyroReadTemperature(void)
{
switch (gyro.gyroToUse) {
case GYRO_CONFIG_USE_GYRO_1:
gyroSensorTemperature = gyroReadSensorTemperature(gyro.gyroSensor1);
break;
int16_t max_temp = INT16_MIN;
#ifdef USE_MULTI_GYRO
case GYRO_CONFIG_USE_GYRO_2:
gyroSensorTemperature = gyroReadSensorTemperature(gyro.gyroSensor2);
break;
case GYRO_CONFIG_USE_GYRO_BOTH:
gyroSensorTemperature = MAX(gyroReadSensorTemperature(gyro.gyroSensor1), gyroReadSensorTemperature(gyro.gyroSensor2));
break;
#endif // USE_MULTI_GYRO
for (int i = 0; i < GYRO_COUNT; i++) {
if (gyro.gyroEnabledBitmask & GYRO_MASK(i)) {
max_temp = MAX(max_temp, gyroReadSensorTemperature(gyro.gyroSensor[i]));
}
}
gyroSensorTemperature = max_temp;
}
int16_t gyroGetTemperature(void)
{
return gyroSensorTemperature;

View file

@ -51,6 +51,8 @@
#define GYRO_IMU_DOWNSAMPLE_CUTOFF_HZ 200
#define GYRO_MASK(x) BIT(x)
typedef union gyroLowpassFilter_u {
pt1Filter_t pt1FilterState;
biquadFilter_t biquadFilterState;
@ -58,16 +60,6 @@ typedef union gyroLowpassFilter_u {
pt3Filter_t pt3FilterState;
} gyroLowpassFilter_t;
typedef enum gyroDetectionFlags_e {
GYRO_NONE_MASK = 0,
GYRO_1_MASK = BIT(0),
#if defined(USE_MULTI_GYRO)
GYRO_2_MASK = BIT(1),
GYRO_ALL_MASK = (GYRO_1_MASK | GYRO_2_MASK),
GYRO_IDENTICAL_MASK = BIT(7), // All gyros are of the same hardware type
#endif
} gyroDetectionFlags_t;
typedef struct gyroCalibration_s {
float sum[XYZ_AXIS_COUNT];
stdev_t var[XYZ_AXIS_COUNT];
@ -90,10 +82,7 @@ typedef struct gyro_s {
float sampleSum[XYZ_AXIS_COUNT]; // summed samples used for downsampling
bool downsampleFilterEnabled; // if true then downsample using gyro lowpass 2, otherwise use averaging
gyroSensor_t gyroSensor1;
#ifdef USE_MULTI_GYRO
gyroSensor_t gyroSensor2;
#endif
gyroSensor_t gyroSensor[GYRO_COUNT];
gyroDev_t *rawSensorDev; // pointer to the sensor providing the raw data for DEBUG_GYRO_RAW
@ -113,7 +102,7 @@ typedef struct gyro_s {
biquadFilter_t notchFilter2[XYZ_AXIS_COUNT];
uint16_t accSampleRateHz;
uint8_t gyroToUse;
uint8_t gyroEnabledBitmask;
uint8_t gyroDebugMode;
bool gyroHasOverflowProtection;
bool useDualGyroDebugging;
@ -155,10 +144,6 @@ typedef enum {
YAW_SPIN_RECOVERY_AUTO
} yawSpinRecoveryMode_e;
#define GYRO_CONFIG_USE_GYRO_1 0
#define GYRO_CONFIG_USE_GYRO_2 1
#define GYRO_CONFIG_USE_GYRO_BOTH 2
enum {
FILTER_LPF1 = 0,
FILTER_LPF2
@ -168,7 +153,6 @@ typedef struct gyroConfig_s {
uint8_t gyroMovementCalibrationThreshold; // people keep forgetting that moving model while init results in wrong gyro offsets. and then they never reset gyro. so this is now on by default.
uint8_t gyro_hardware_lpf; // gyro DLPF setting
uint8_t gyro_high_fsr;
uint8_t gyro_to_use;
uint16_t gyro_lpf1_static_hz;
uint16_t gyro_lpf2_static_hz;
@ -194,10 +178,12 @@ typedef struct gyroConfig_s {
uint8_t gyro_filter_debug_axis;
uint8_t gyrosDetected; // What gyros should detection be attempted for on startup. Automatically set on first startup.
uint8_t gyrosDetected; // What gyros should be shown as part of the cli status command.
uint8_t gyro_lpf1_dyn_expo; // set the curve for dynamic gyro lowpass filter
uint8_t simplified_gyro_filter;
uint8_t simplified_gyro_filter_multiplier;
uint8_t gyro_enabled_bitmask;
} gyroConfig_t;
PG_DECLARE(gyroConfig_t, gyroConfig);

View file

@ -73,18 +73,12 @@
#include "gyro_init.h"
#ifdef USE_MULTI_GYRO
#define ACTIVE_GYRO ((gyro.gyroToUse == GYRO_CONFIG_USE_GYRO_2) ? &gyro.gyroSensor2 : &gyro.gyroSensor1)
#else
#define ACTIVE_GYRO (&gyro.gyroSensor1)
#endif
// The gyro buffer is split 50/50, the first half for the transmit buffer, the second half for the receive buffer
// This buffer is large enough for the gyros currently supported in accgyro_mpu.c but should be reviewed id other
// gyro types are supported with SPI DMA.
#define GYRO_BUF_SIZE 32
static gyroDetectionFlags_t gyroDetectionFlags = GYRO_NONE_MASK;
static uint8_t gyroDetectedFlags = 0;
static uint16_t calculateNyquistAdjustedNotchHz(uint16_t notchHz, uint16_t notchCutoffHz)
{
@ -579,10 +573,9 @@ static void gyroPreInitSensor(const gyroDeviceConfig_t *config)
void gyroPreInit(void)
{
gyroPreInitSensor(gyroDeviceConfig(0));
#ifdef USE_MULTI_GYRO
gyroPreInitSensor(gyroDeviceConfig(1));
#endif
for (int i = 0; i < GYRO_COUNT; i++) {
gyroPreInitSensor(gyroDeviceConfig(i));
}
}
bool gyroInit(void)
@ -617,95 +610,104 @@ bool gyroInit(void)
break;
}
gyroDetectionFlags = GYRO_NONE_MASK;
gyroDetectedFlags = 0;
uint8_t gyrosToScan = gyroConfig()->gyrosDetected;
// scan all gyros if gyrosDetected is zero
if (gyrosToScan == 0) {
gyrosToScan = 0xff;
}
// always scan gyro_enabled_bitmask
gyrosToScan |= gyroConfig()->gyro_enabled_bitmask;
gyro.gyroToUse = gyroConfig()->gyro_to_use;
gyro.gyroDebugAxis = gyroConfig()->gyro_filter_debug_axis;
if ((!gyrosToScan || (gyrosToScan & GYRO_1_MASK)) && gyroDetectSensor(&gyro.gyroSensor1, gyroDeviceConfig(0))) {
gyroDetectionFlags |= GYRO_1_MASK;
for (int i = 0; i < GYRO_COUNT; i++) {
// Only attempt to detect a gyro if it's enabled or we're doing an auto-scan
if (gyrosToScan & GYRO_MASK(i)) {
if (gyroDetectSensor(&gyro.gyroSensor[i], gyroDeviceConfig(i))) {
// If we detected a gyro, make sure it's in the enabled bitmask
// This ensures that during first boot, all detected gyros are enabled
gyroDetectedFlags |= GYRO_MASK(i);
}
}
}
#if defined(USE_MULTI_GYRO)
if ((!gyrosToScan || (gyrosToScan & GYRO_2_MASK)) && gyroDetectSensor(&gyro.gyroSensor2, gyroDeviceConfig(1))) {
gyroDetectionFlags |= GYRO_2_MASK;
}
#endif
if (gyroDetectionFlags == GYRO_NONE_MASK) {
if (gyroDetectedFlags == 0) {
return false;
}
bool eepromWriteRequired = false;
if (!gyrosToScan) {
gyroConfigMutable()->gyrosDetected = gyroDetectionFlags;
if (gyrosToScan != gyroConfigMutable()->gyrosDetected) {
gyroConfigMutable()->gyrosDetected = gyroDetectedFlags;
eepromWriteRequired = true;
}
#if defined(USE_MULTI_GYRO)
if ((gyro.gyroToUse == GYRO_CONFIG_USE_GYRO_BOTH && !((gyroDetectionFlags & GYRO_ALL_MASK) == GYRO_ALL_MASK))
|| (gyro.gyroToUse == GYRO_CONFIG_USE_GYRO_1 && !(gyroDetectionFlags & GYRO_1_MASK))
|| (gyro.gyroToUse == GYRO_CONFIG_USE_GYRO_2 && !(gyroDetectionFlags & GYRO_2_MASK))) {
if (gyroDetectionFlags & GYRO_1_MASK) {
gyro.gyroToUse = GYRO_CONFIG_USE_GYRO_1;
} else {
gyro.gyroToUse = GYRO_CONFIG_USE_GYRO_2;
}
// check if all enabled sensors are detected
gyro.gyroEnabledBitmask = gyroDetectedFlags & gyroConfig()->gyro_enabled_bitmask;
gyroConfigMutable()->gyro_to_use = gyro.gyroToUse;
if (gyroConfigMutable()->gyro_enabled_bitmask != gyro.gyroEnabledBitmask) {
gyroConfigMutable()->gyro_enabled_bitmask = gyro.gyroEnabledBitmask;
eepromWriteRequired = true;
}
// Only allow using both gyros simultaneously if they are the same hardware type.
if (((gyroDetectionFlags & GYRO_ALL_MASK) == GYRO_ALL_MASK) && gyro.gyroSensor1.gyroDev.gyroHardware == gyro.gyroSensor2.gyroDev.gyroHardware) {
gyroDetectionFlags |= GYRO_IDENTICAL_MASK;
} else if (gyro.gyroToUse == GYRO_CONFIG_USE_GYRO_BOTH) {
// If the user selected "BOTH" and they are not the same type, then reset to using only the first gyro.
gyro.gyroToUse = GYRO_CONFIG_USE_GYRO_1;
gyroConfigMutable()->gyro_to_use = gyro.gyroToUse;
// Only allow using multiple gyros simultaneously if they are the same hardware type.
// Or allow using if they have the same sample rate and scale.
bool gyro_hardware_compatible = true;
uint16_t gyro_sample_rate = 0;
float gyro_scale = 0.0f;
bool firstFound = false;
for (int i = 0; i < GYRO_COUNT; i++) {
if (gyro.gyroEnabledBitmask & GYRO_MASK(i)) {
if (!firstFound) {
firstFound = true;
gyro_sample_rate = gyro.gyroSensor[i].gyroDev.gyroSampleRateHz;
gyro_scale = gyro.gyroSensor[i].gyroDev.scale;
} else if ((gyro_sample_rate != gyro.gyroSensor[i].gyroDev.gyroSampleRateHz) ||
(gyro_scale != gyro.gyroSensor[i].gyroDev.scale)) {
gyro_hardware_compatible = false;
}
}
}
if (!gyro_hardware_compatible) {
// If the user enabled multiple IMU and they are not compatible types, then reset to using only the first IMU.
gyro.gyroEnabledBitmask = gyro.gyroEnabledBitmask & -gyro.gyroEnabledBitmask;
gyroConfigMutable()->gyro_enabled_bitmask = gyro.gyroEnabledBitmask;
eepromWriteRequired = true;
}
if (gyro.gyroToUse == GYRO_CONFIG_USE_GYRO_2 || gyro.gyroToUse == GYRO_CONFIG_USE_GYRO_BOTH) {
static DMA_DATA uint8_t gyroBuf2[GYRO_BUF_SIZE];
static DMA_DATA uint8_t gyroBuf[GYRO_COUNT][2][GYRO_BUF_SIZE / 2];
for (int i = 0; i < GYRO_COUNT; i++) {
if (gyroDetectedFlags & GYRO_MASK(i)) { // Only initialize detected gyros
// SPI DMA buffer required per device
gyro.gyroSensor2.gyroDev.dev.txBuf = gyroBuf2;
gyro.gyroSensor2.gyroDev.dev.rxBuf = &gyroBuf2[GYRO_BUF_SIZE / 2];
gyro.gyroSensor[i].gyroDev.dev.txBuf = gyroBuf[i][0];
gyro.gyroSensor[i].gyroDev.dev.rxBuf = gyroBuf[i][1];
gyroInitSensor(&gyro.gyroSensor2, gyroDeviceConfig(1));
gyro.gyroHasOverflowProtection = gyro.gyroHasOverflowProtection && gyro.gyroSensor2.gyroDev.gyroHasOverflowProtection;
detectedSensors[SENSOR_INDEX_GYRO] = gyro.gyroSensor2.gyroDev.gyroHardware;
gyroInitSensor(&gyro.gyroSensor[i], gyroDeviceConfig(i));
gyro.gyroHasOverflowProtection = gyro.gyroHasOverflowProtection
&& gyro.gyroSensor[i].gyroDev.gyroHasOverflowProtection;
}
}
#endif
if (eepromWriteRequired) {
writeEEPROM();
}
if (gyro.gyroToUse == GYRO_CONFIG_USE_GYRO_1 || gyro.gyroToUse == GYRO_CONFIG_USE_GYRO_BOTH) {
static DMA_DATA uint8_t gyroBuf1[GYRO_BUF_SIZE];
// SPI DMA buffer required per device
gyro.gyroSensor1.gyroDev.dev.txBuf = gyroBuf1;
gyro.gyroSensor1.gyroDev.dev.rxBuf = &gyroBuf1[GYRO_BUF_SIZE / 2];
gyroInitSensor(&gyro.gyroSensor1, gyroDeviceConfig(0));
gyro.gyroHasOverflowProtection = gyro.gyroHasOverflowProtection && gyro.gyroSensor1.gyroDev.gyroHasOverflowProtection;
detectedSensors[SENSOR_INDEX_GYRO] = gyro.gyroSensor1.gyroDev.gyroHardware;
// Use the first enabled gyro for our scale and raw sensor dev
int firstGyro = firstEnabledGyro();
if (firstGyro >= 0) {
detectedSensors[SENSOR_INDEX_GYRO] = gyro.gyroSensor[firstGyro].gyroDev.gyroHardware;
gyro.scale = gyro.gyroSensor[firstGyro].gyroDev.scale;
gyro.rawSensorDev = &gyro.gyroSensor[firstGyro].gyroDev;
} else {
// no gyros enabled
detectedSensors[SENSOR_INDEX_GYRO] = GYRO_NONE;
gyro.scale = 1.0f;
gyro.rawSensorDev = NULL;
}
// Copy the sensor's scale to the high-level gyro object. If running in "BOTH" mode
// then logic above requires both sensors to be the same so we'll use sensor1's scale.
// This will need to be revised if we ever allow different sensor types to be used simultaneously.
// Likewise determine the appropriate raw data for use in DEBUG_GYRO_RAW
gyro.scale = gyro.gyroSensor1.gyroDev.scale;
gyro.rawSensorDev = &gyro.gyroSensor1.gyroDev;
#if defined(USE_MULTI_GYRO)
if (gyro.gyroToUse == GYRO_CONFIG_USE_GYRO_2) {
gyro.scale = gyro.gyroSensor2.gyroDev.scale;
gyro.rawSensorDev = &gyro.gyroSensor2.gyroDev;
}
#endif
if (gyro.rawSensorDev) {
gyro.sampleRateHz = gyro.rawSensorDev->gyroSampleRateHz;
gyro.accSampleRateHz = gyro.rawSensorDev->accSampleRateHz;
@ -717,9 +719,9 @@ bool gyroInit(void)
return true;
}
gyroDetectionFlags_t getGyroDetectionFlags(void)
uint8_t getGyroDetectedFlags(void)
{
return gyroDetectionFlags;
return gyroDetectedFlags;
}
void gyroSetTargetLooptime(uint8_t pidDenom)
@ -736,34 +738,41 @@ void gyroSetTargetLooptime(uint8_t pidDenom)
gyroDev_t *gyroActiveDev(void)
{
return &ACTIVE_GYRO->gyroDev;
return gyro.rawSensorDev;
}
const mpuDetectionResult_t *gyroMpuDetectionResult(void)
{
return &ACTIVE_GYRO->gyroDev.mpuDetectionResult;
return &gyro.rawSensorDev->mpuDetectionResult;
}
int16_t gyroRateDps(int axis)
{
return lrintf(gyro.gyroADCf[axis] / ACTIVE_GYRO->gyroDev.scale);
return lrintf(gyro.gyroADCf[axis] / gyro.rawSensorDev->scale);
}
#ifdef USE_GYRO_REGISTER_DUMP
static extDevice_t *gyroSensorDevByInstance(uint8_t whichSensor)
static extDevice_t *gyroExtDevice(uint8_t idx)
{
#ifdef USE_MULTI_GYRO
if (whichSensor == GYRO_CONFIG_USE_GYRO_2) {
return &gyro.gyroSensor2.gyroDev.dev;
}
#else
UNUSED(whichSensor);
#endif
return &gyro.gyroSensor1.gyroDev.dev;
return &gyro.gyroSensor[idx].gyroDev.dev;
}
uint8_t gyroReadRegister(uint8_t whichSensor, uint8_t reg)
{
return mpuGyroReadRegister(gyroSensorDevByInstance(whichSensor), reg);
if (whichSensor < GYRO_COUNT) {
return mpuGyroReadRegister(gyroExtDevice(whichSensor), reg);
} else {
return 0;
}
}
#endif // USE_GYRO_REGISTER_DUMP
int firstEnabledGyro(void)
{
if (gyro.gyroEnabledBitmask != 0) {
return llog2(gyro.gyroEnabledBitmask & -gyro.gyroEnabledBitmask);
} else {
// no gyro is enabled
return -1;
}
}

View file

@ -28,9 +28,10 @@ void gyroPreInit(void);
bool gyroInit(void);
void gyroInitFilters(void);
void gyroInitSensor(gyroSensor_t *gyroSensor, const gyroDeviceConfig_t *config);
gyroDetectionFlags_t getGyroDetectionFlags(void);
uint8_t getGyroDetectedFlags(void);
gyroDev_t *gyroActiveDev(void);
struct mpuDetectionResult_s;
const struct mpuDetectionResult_s *gyroMpuDetectionResult(void);
int16_t gyroRateDps(int axis);
uint8_t gyroReadRegister(uint8_t whichSensor, uint8_t reg);
int firstEnabledGyro(void);

View file

@ -703,3 +703,4 @@ extern struct linker_symbol __config_end;
#define USE_PIN_PULL_UP_DOWN
#endif
#endif // USE_PINIO

View file

@ -372,7 +372,6 @@
#define USE_AIRMODE_LPF
#define USE_GYRO_DLPF_EXPERIMENTAL
#define USE_MULTI_GYRO
#define USE_SENSOR_NAMES
#define USE_UNCOMMON_MIXERS
#define USE_SIGNATURE
@ -494,3 +493,66 @@
#if defined(USE_POSITION_HOLD) && !defined(USE_GPS)
#error "USE_POSITION_HOLD requires USE_GPS to be defined"
#endif
// backwards compatibility for older config.h targets
#ifndef GYRO_CONFIG_USE_GYRO_1
#define GYRO_CONFIG_USE_GYRO_1 0
#endif
#ifndef GYRO_CONFIG_USE_GYRO_2
#define GYRO_CONFIG_USE_GYRO_2 1
#endif
#ifndef GYRO_CONFIG_USE_GYRO_BOTH
#define GYRO_CONFIG_USE_GYRO_BOTH 2
#endif
#ifdef DEFAULT_GYRO_TO_USE
#ifndef DEFAULT_GYRO_ENABLED
#if DEFAULT_GYRO_TO_USE == GYRO_CONFIG_USE_GYRO_1
#define DEFAULT_GYRO_ENABLED GYRO_MASK(0)
#elif DEFAULT_GYRO_TO_USE == GYRO_CONFIG_USE_GYRO_2
#define DEFAULT_GYRO_ENABLED GYRO_MASK(1)
#elif DEFAULT_GYRO_TO_USE == GYRO_CONFIG_USE_GYRO_BOTH
#define DEFAULT_GYRO_ENABLED (GYRO_MASK(0) | GYRO_MASK(1))
#endif
#endif
#elif !defined(DEFAULT_GYRO_ENABLED)
// assume one gyro
#define DEFAULT_GYRO_ENABLED GYRO_MASK(0)
#endif
#ifndef GYRO_COUNT
#ifdef GYRO_1_CS_PIN
#define GYRO_1_DEFINED 1
#else
#define GYRO_1_DEFINED 0
#endif
#ifdef GYRO_2_CS_PIN
#define GYRO_2_DEFINED 1
#else
#define GYRO_2_DEFINED 0
#endif
#ifdef GYRO_3_CS_PIN
#define GYRO_3_DEFINED 1
#else
#define GYRO_3_DEFINED 0
#endif
#ifdef GYRO_4_CS_PIN
#define GYRO_4_DEFINED 1
#else
#define GYRO_4_DEFINED 0
#endif
#define GYRO_COUNT_RAW (GYRO_1_DEFINED + GYRO_2_DEFINED + GYRO_3_DEFINED + GYRO_4_DEFINED)
// Ensure GYRO_COUNT is at least 1
#if GYRO_COUNT_RAW > 0
#define GYRO_COUNT GYRO_COUNT_RAW
#else
#define GYRO_COUNT 1
#endif
#endif

View file

@ -125,6 +125,7 @@ typedef struct
#define SPIDEV_COUNT 0
#define I2CDEV_COUNT 0
#define GYRO_COUNT 1
#define WS2811_DMA_TC_FLAG (void *)1
#define WS2811_DMA_HANDLER_IDENTIFER 0