Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
3895d95
Added ICM20984
atinm Jun 29, 2025
e896acf
Added Sparkfun ICM20948 breakout board (SPI only, I2C TBD)
atinm Jun 29, 2025
527d8b1
Merge branch 'main-upstream' into atinm/icm20948-imu
atinm Jul 2, 2025
8bd66ff
Copied files to top level from Sparkfun's subdirectory and updated RE…
atinm Jul 2, 2025
1ded436
Added back the config for imu_int_mode for ICM20948
atinm Jul 2, 2025
c258480
Use uint8_t for interrupt_mode
atinm Jul 2, 2025
42736b0
Handle when we aren't using MBED or RP2040
atinm Jul 2, 2025
176314e
Moved interrupt_mode from config to gizmo
atinm Jul 2, 2025
9fa51c6
Use bool to pass interrupt mode to _imu_ll_interrupt_setup
atinm Jul 2, 2025
af6d8bf
Added some comments about the quaternion math and fixed yaw radian ca…
atinm Jul 3, 2025
b04db65
Make the IMU interrupt check a loop rather than a die for IMUs that t…
atinm Jul 3, 2025
860abb5
Added mf_IMU for AHR and fixed sign
atinm Jul 4, 2025
86d07e9
Removed extra comment
atinm Jul 4, 2025
21d4588
Moved ImuGizmoICM20948.cpp to src/imu
atinm Jul 4, 2025
726d540
Add src/imu/ImuGizmoICM20948.cpp since move
atinm Jul 4, 2025
c6ed36a
Allow imu_has_mag config option
atinm Jul 4, 2025
0088470
Fix config->has_mag - it is a bool
atinm Jul 4, 2025
7b99f7e
Move AHR setup after IMU setup, and separate interrupt setup
atinm Jul 4, 2025
af09253
Die if using mf_IMU on AHR with an IMU that does not have sensor fusion
atinm Jul 4, 2025
fa4f032
Moved imu_use_mag to bottom and pass it along to the IMUs
atinm Jul 4, 2025
73232a7
Set sample rate to 225 Hz which is the best ICM20948 can do
atinm Jul 5, 2025
bec9795
Do bias correction on the quaternions as well
atinm Jul 5, 2025
f77ef9a
Fix more Quaternion calculations and calibration
atinm Jul 5, 2025
1a3495d
Fix quaternion align and remove hack for flipYaw()
atinm Jul 6, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 5 additions & 12 deletions src/ahr/ahr.cpp
Comment thread
atinm marked this conversation as resolved.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's put this in a new PR - I think this will need some additional considerations...

Some (random) thoughts:

Rather add a new imu_gizmo mf_ICM20948_6DOF than a new parameter. (I try to keep number of parameters as low as possible)

If adding a parameter:

New config params should be added at the end of the array - this allows users to upgrade without eeprom corruption.

I would use value 0 or 1 (not <=0 or 1)

Default value 1 makes more sense to me - use mag if we have it.

Rather name the param and related vars imu_use_mag, and reserve the "has" properties for driver capabilities.

Not consistent with current 9dof drivers...

@atinm atinm Jul 4, 2025

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, not consistent with existing drivers - made it use_mag and moved to bottom. Only really used by ICM20948 for now, could be used by MPU9250 if it supports 6DOF. But left others alone to have minimal code changes.

@atinm atinm Jul 4, 2025

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the meantime, my quadcopter crashed and burned badly - need to debug it, it stopped listening to IBUS and didn't automatically disarm itself when it lost contact!

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

my quadcopter crashed and burned badly

ouch!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I seemed to have lost some code when I split Icm20948 and ibus code so putting it back - related to calibration and quaternions

Original file line number Diff line number Diff line change
Expand Up @@ -44,20 +44,9 @@ int Ahr::setup() {
cfg.printModule(MF_MOD);

B_gyr = lowpass_to_beta(config.gyrLpFreq, config.pimu->getSampleRate());
if (isnan(B_gyr)) {
// imu might not be set up yet
B_gyr = 1.0;
}
B_acc = lowpass_to_beta(config.accLpFreq, config.pimu->getSampleRate());
if (isnan(B_acc)) {
// imu might not be set up yet
B_acc = 1.0;
}
B_mag = lowpass_to_beta(config.magLpFreq, config.pimu->getSampleRate());
if (isnan(B_mag)) {
// imu might not be set up yet
B_mag = 1.0;
}

//create gizmo
delete gizmo;
switch(config.gizmo) {
Expand All @@ -75,6 +64,10 @@ int Ahr::setup() {
break;
case Cfg::ahr_gizmo_enum::mf_IMU :
gizmo = new AhrGizmoImu(this);
if (!config.pimu->hasSensorFusion()) {
Serial.printf("Cannot use mf_IMU for AHR with an IMU that does not support sensor fusion!\n");
return -1;
}
break;
default:
gizmo = new AhrGizmoMahony(this, false);
Expand Down
1 change: 1 addition & 0 deletions src/imu/imu.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ class Imu : public ImuState {
ImuGizmo *gizmo = nullptr;

int setup(); // Use config to setup gizmo, returns 0 on success, or error code
int setup_interrupt(); // set up the low level interrupt handler
bool update(); // Returns true if state was updated
bool installed() {return (gizmo != nullptr); } //returns true if a gizmo is installed

Expand Down
16 changes: 10 additions & 6 deletions src/imu/imu_cpp.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,39 +118,39 @@ int Imu::setup() {
auto mpu_iface = new MPU_InterfaceSPI(config.spi_bus, config.spi_cs);
gizmo = new MPUXXXX(MPUXXXX::MPU9250, mpu_iface);
gizmo->uses_i2c = false;
gizmo->has_mag = true || config.has_mag > 0;
gizmo->has_mag = true || config.has_mag;
break;
}
case Cfg::imu_gizmo_enum::mf_MPU6500 : {
auto mpu_iface = new MPU_InterfaceSPI(config.spi_bus, config.spi_cs);
gizmo = new MPUXXXX(MPUXXXX::MPU6500, mpu_iface);
gizmo->uses_i2c = false;
gizmo->has_mag = false || config.has_mag > 0;
gizmo->has_mag = false || config.has_mag;
break;
}
case Cfg::imu_gizmo_enum::mf_MPU6000 : {
auto mpu_iface = new MPU_InterfaceSPI(config.spi_bus, config.spi_cs);
gizmo = new MPUXXXX(MPUXXXX::MPU6000, mpu_iface);
gizmo->uses_i2c = false;
gizmo->has_mag = false || config.has_mag > 0;
gizmo->has_mag = false || config.has_mag;
break;
}
case Cfg::imu_gizmo_enum::mf_BMI270 : {
gizmo = new ImuGizmoBMI270(config.spi_bus, config.spi_cs);
gizmo->uses_i2c = false;
gizmo->has_mag = false || config.has_mag > 0;
gizmo->has_mag = false || config.has_mag;
break;
}
case Cfg::imu_gizmo_enum::mf_ICM45686 : {
auto icm_iface = new Invensensev3_InterfaceSPI(config.spi_bus, config.spi_cs);
gizmo = new ImuGizmoICM45686( (uint8_t)config.pin_int, icm_iface );
gizmo->uses_i2c = false;
gizmo->has_mag = false || config.has_mag > 0;
gizmo->has_mag = false || config.has_mag;
break;
}
case Cfg::imu_gizmo_enum::mf_ICM42688 : {
gizmo = ImuGizmoICM426XX::create(&config, (ImuState*)this);
gizmo->has_mag = gizmo->has_mag || config.has_mag > 0;
gizmo->has_mag = gizmo->has_mag || config.has_mag;
break;
}
case Cfg::imu_gizmo_enum::mf_ICM20948 : {
Expand Down Expand Up @@ -227,6 +227,10 @@ int Imu::setup() {
//exit if no interrupt pin specified
if(config.pin_int < 0) return 0;

return 0;
}

int Imu::setup_interrupt() {
//==============================================================
//setup low-level interrupt stuff
//==============================================================
Expand Down
31 changes: 18 additions & 13 deletions src/madflight.h
Comment thread
atinm marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -206,19 +206,6 @@ void madflight_setup() {
// ALT - Altitude Estimator
alt.setup(bar.alt);

// AHR - setup low pass filters for AHRS filters
ahr.config.gizmo = (Cfg::ahr_gizmo_enum)cfg.ahr_gizmo; //the gizmo to use
ahr.config.gyrLpFreq = cfg.imu_gyr_lp; //gyro low pass filter freq [Hz]
ahr.config.accLpFreq = cfg.imu_acc_lp; //accelerometer low pass filter freq [Hz]
ahr.config.magLpFreq = cfg.mag_lp; //magnetometer low pass filter freq [Hz]
ahr.config.pimu = &imu; //pointer to Imu to use
ahr.config.pmag = &mag; //pointer to Mag to use
ahr.config.gyr_offset = &(cfg.imu_cal_gx); //gyro offset[3] [deg/sec]
ahr.config.acc_offset = &(cfg.imu_cal_ax); //acc offset[3] [G]
ahr.config.mag_offset = &(cfg.mag_cal_x); //mag offset[3] [adc_lsb]
ahr.config.mag_scale = &(cfg.mag_cal_sx); //mag scale[3] [uT/adc_lsb]
ahr.setup();

// IMU - Intertial Measurement Unit (gyro/acc/mag)
imu.config.sampleRate = cfg.imu_rate; //sample rate [Hz]
imu.config.pin_int = cfg.pin_imu_int; //IMU data ready interrupt pin
Expand All @@ -242,6 +229,24 @@ void madflight_setup() {
}
// start IMU update handler
if(imu.installed()) {
// AHR - setup low pass filters for AHRS filters after IMU is set up and installed
ahr.config.gizmo = (Cfg::ahr_gizmo_enum)cfg.ahr_gizmo; //the gizmo to use
ahr.config.gyrLpFreq = cfg.imu_gyr_lp; //gyro low pass filter freq [Hz]
ahr.config.accLpFreq = cfg.imu_acc_lp; //accelerometer low pass filter freq [Hz]
ahr.config.magLpFreq = cfg.mag_lp; //magnetometer low pass filter freq [Hz]
ahr.config.pimu = &imu; //pointer to Imu to use
ahr.config.pmag = &mag; //pointer to Mag to use
ahr.config.gyr_offset = &(cfg.imu_cal_gx); //gyro offset[3] [deg/sec]
ahr.config.acc_offset = &(cfg.imu_cal_ax); //acc offset[3] [G]
ahr.config.mag_offset = &(cfg.mag_cal_x); //mag offset[3] [adc_lsb]
ahr.config.mag_scale = &(cfg.mag_cal_sx); //mag scale[3] [uT/adc_lsb]
if (ahr.setup() < 0) {
madflight_die("AHR setup failed.");
}

// now set up the interrupt handler after IMU and AHR are set up
imu.setup_interrupt();

ahr.setInitalOrientation(); //do this before IMU update handler is started

if(!imu_loop) madflight_warn("'void imu_loop()' not defined.");
Expand Down