MPU - 9250 - Can't Figure Out How to Read Magnetometer Values

Hello. I'm a little bit of a newbie at this kind of thing, so bear with me.

I'm trying to use an MPU - 9250 for rotational tracking on all 3 axis via I2C. I'm able to successfully read the accelerometer and gyroscope values, but I just can't seem to figure out how to access the magnetometer, which is of course important if I wish to accomplish my goal.

I've looked and looked at all kinds of information across the web and nothing has helped me. From what I understand: the accelerometer and gyroscope are accessible with the I2C address 0x68, and the magnetometer is supposed to be address 0x0C? The problem is, it seems my Arduino Mega-2560 is unable to communicate with 0x0C and doesn't detect it with an I2C Scanner.

So... my question is, how on Earth are you supposed to read from this device's magnetometer?

Here are the data sheets + image for it:

Data Sheet
Register Map

You can communicate to the AK8963 magnetometer through the MPU9250 by configuring the I2C_SLV0_ADDR register with the AK8963 address of 0x0C. I2C_SLV0_REG and I2C_SLV0_CTRL will specify the start register and bytes to read, respectively. Up to you which SLV# you use.

Just a short overview, should look at the datasheet

I struggled with this too. You have to reset one of the registers, then turn back on to begin the compass reading registers. It's not very clear anywhere out there...

The code below is working for me:

//GND - GND
//VCC - VCC
//SDA - Pin A4
//SCL - Pin A5

#include <Wire.h>

#define MPU9250_ADDRESS 0x68
#define MAG_ADDRESS 0x0C

#define GYRO_FULL_SCALE_250_DPS 0x00
#define GYRO_FULL_SCALE_500_DPS 0x08
#define GYRO_FULL_SCALE_1000_DPS 0x10
#define GYRO_FULL_SCALE_2000_DPS 0x18

#define ACC_FULL_SCALE_2_G 0x00
#define ACC_FULL_SCALE_4_G 0x08
#define ACC_FULL_SCALE_8_G 0x10
#define ACC_FULL_SCALE_16_G 0x18

//Funcion auxiliar lectura
void I2Cread(uint8_t Address, uint8_t Register, uint8_t Nbytes, uint8_t* Data)
{
Wire.beginTransmission(Address);
Wire.write(Register);
Wire.endTransmission();

Wire.requestFrom(Address, Nbytes);
uint8_t index = 0;
while (Wire.available())
Data[index++] = Wire.read();
}

// Funcion auxiliar de escritura
void I2CwriteByte(uint8_t Address, uint8_t Register, uint8_t Data)
{
Wire.beginTransmission(Address);
Wire.write(Register);
Wire.write(Data);
Wire.endTransmission();
}

void setup()
{
Wire.begin();
Serial.begin(115200);

// Configurar acelerometro
I2CwriteByte(MPU9250_ADDRESS, 28, ACC_FULL_SCALE_16_G);
// Configurar giroscopio
I2CwriteByte(MPU9250_ADDRESS, 27, GYRO_FULL_SCALE_2000_DPS);
// Configurar magnetometro
I2CwriteByte(MPU9250_ADDRESS, 0x37, 0x02);
I2CwriteByte(MAG_ADDRESS, 0x0A, 0x01);
}

void loop()
{
// --- Lectura acelerometro y giroscopio ---
uint8_t Buf[14];
I2Cread(MPU9250_ADDRESS, 0x3B, 14, Buf);

// Convertir registros acelerometro
int16_t ax = -(Buf[0] << 8 | Buf[1]);
int16_t ay = -(Buf[2] << 8 | Buf[3]);
int16_t az = Buf[4] << 8 | Buf[5];

// Convertir registros giroscopio
int16_t gx = -(Buf[8] << 8 | Buf[9]);
int16_t gy = -(Buf[10] << 8 | Buf[11]);
int16_t gz = Buf[12] << 8 | Buf[13];

// --- Lectura del magnetometro ---
uint8_t ST1;
I2CwriteByte(MAG_ADDRESS,0x0A,0x01);
do
{
I2Cread(MAG_ADDRESS, 0x02, 1, &ST1);
} while (!(ST1 & 0x01));

uint8_t Mag[7];
I2Cread(MAG_ADDRESS, 0x03, 7, Mag);

// Convertir registros magnetometro
int16_t mx = -(Mag[3] << 8 | Mag[2]);
int16_t my = -(Mag[1] << 8 | Mag[0]);
int16_t mz = -(Mag[5] << 8 | Mag[4]);

// --- Mostrar valores ---

// Acelerometro
Serial.print(ax, DEC);
Serial.print("\t");
Serial.print(ay, DEC);
Serial.print("\t");
Serial.print(az, DEC);
Serial.print("\t");

// Giroscopio
Serial.print(gx, DEC);
Serial.print("\t");
Serial.print(gy, DEC);
Serial.print("\t");
Serial.print(gz, DEC);
Serial.print("\t");

// Magnetometro
Serial.print(mx + 200, DEC);
Serial.print("\t");
Serial.print(my - 70, DEC);
Serial.print("\t");
Serial.print(mz - 700, DEC);
Serial.print("\t");

// Fin medicion
Serial.println("");

delay(500);
}

I tried your sample code. I get values, but the magnetometer values stay the same ("static"), even I move the sensor. The other values vary as expected.

Any Idea?

borav:
I tried your sample code. I get values, but the magnetometer values stay the same ("static"), even I move the sensor. The other values vary as expected.

Any Idea?

Yes. Have you tried to use a library written for the MPU9250?

Hi louis002, i have a question about your following code

// Magnetometro
Serial.print(mx + 200, DEC);
Serial.print("\t");
Serial.print(my - 70, DEC);
Serial.print("\t");
Serial.print(mz - 700, DEC);
Serial.print("\t");

Why did you add +200; -70; -700 ?

1 Like

Al_freud:
Hi louis002, i have a question about your following code

  // Magnetometro

Serial.print(mx + 200, DEC);
  Serial.print("\t");
  Serial.print(my - 70, DEC);
  Serial.print("\t");
  Serial.print(mz - 700, DEC);
  Serial.print("\t");




Why did you add +200; -70; -700 ?

That's not my code.

Here is my code to do the mpu9250 thing:
cpp part 1:

#include "ESP32_MPU9250.h"
myMPU9250::myMPU9250( int _queueSize )
{
  ESP32_SPI_API _spi;
  _spi.setQSize( _queueSize );
}
int  myMPU9250::getByte( int _Byte)
{
  return _spi.get_rxData8bit( _Byte );
}
int myMPU9250::fInit_MPU9250( bool resetMPU9250, bool resetAK8962 )
{

  SPI_Err = _spi.fSPIbusConfig( );
  SPI_Err = _spi.fSPIdeviceConfig( );
  // select clock source to gyro
  SPI_Err = _spi.fWriteSPIdata8bits( PWR_MGMNT_1, CLOCK_SEL_PLL );
  vTaskDelay(1);
  // enable I2C master mode
  SPI_Err = _spi.fWriteSPIdata8bits( USER_CTRL, I2C_MST_EN );
  vTaskDelay(1);
  // set the I2C bus speed to 400 kHz
  SPI_Err = _spi.fWriteSPIdata8bits( I2C_MST_CTRL, I2C_MST_CLK );
  vTaskDelay(1);
  // set AK8963 to Power Down
  fWrite_AK8963 (  AK8963_CNTL1, AK8963_PWR_DOWN );
  vTaskDelay(1);
  // reset the MPU9250
  SPI_Err = _spi.fWriteSPIdata8bits( PWR_MGMNT_1, PWR_RESET );
  // wait for MPU-9250 to come back up
  vTaskDelay(1);
  // reset the AK8963 AK8963_CNTL2,AK8963_RESET
  fWrite_AK8963 (  AK8963_CNTL2, AK8963_RESET );
  vTaskDelay(1);
  // select clock source to gyro
  SPI_Err = _spi.fWriteSPIdata8bits( PWR_MGMNT_1, CLOCK_SEL_PLL );
  vTaskDelay(1);
  // enable accelerometer and gyro PWR_MGMNT_2,SEN_ENABLE
  SPI_Err = _spi.fWriteSPIdata8bits( PWR_MGMNT_2, SEN_ENABLE );
  vTaskDelay(1);
  // setting accel range / scale to 16G as default
  setAccelRange( AccellRangeToUse );
  // setting the gyro range / scale to 250DPS as default for calibration
  setGyroRange( GyroRangeToUse );
  // setting bandwidth to 184Hz as default for calibration
  setDlpfBandwidthAccelerometer( DLPF_BANDWIDTH_184HZ );
  // setting bandwidth to 20Hz as default for calibration
  setDlpfBandwidthGyro( DLPF_BANDWIDTH_20HZ );
  // setting the sample rate divider to 19 (0x13) as default
  SPI_Err = _spi.fWriteSPIdata8bits( SMPDIV, 0x13);  // Set sample rate to default of 19
  vTaskDelay(1);
  // enable I2C master mode
  SPI_Err = _spi.fWriteSPIdata8bits( USER_CTRL, I2C_MST_EN );
  vTaskDelay(1);
  // set the I2C bus speed to 400 kHz
  SPI_Err = _spi.fWriteSPIdata8bits( I2C_MST_CTRL, I2C_MST_CLK );
  vTaskDelay(1);
  /* get the magnetometer calibration */
  // set AK8963 to Power Down
  fWrite_AK8963 (  AK8963_CNTL1, AK8963_PWR_DOWN );
  vTaskDelay(100); // long wait between AK8963 mode changes
  // set AK8963 to FUSE ROM access
  fWrite_AK8963 ( AK8963_CNTL1, AK8963_FUSE_ROM );
  vTaskDelay ( 100 ); // delay for mode change
  setMagSensitivityValue( );
  vTaskDelay(1);
  // AK8963_CNTL1,AK8963_CNT_MEAS2
  fWrite_AK8963( AK8963_CNTL1, AK8963_CNT_MEAS2 );
  // delay for mode change
  vTaskDelay ( 100 );
  // AK8963_HXL,7 ;
  fReadAK8963(AK8963_HXL, 7 | SPI_READ );
  vTaskDelay(1);
  fCalculate_GandAbias();
}void myMPU9250::fWrite_AK8963(  int subAddress, int dataAK8963 )
{
  SPI_Err = _spi.fWriteSPIdata8bits( I2C_SLV0_ADDR, AK8963_I2C_ADDR );
  SPI_Err = _spi.fWriteSPIdata8bits( I2C_SLV0_REG, subAddress );
  SPI_Err = _spi.fWriteSPIdata8bits( I2C_SLV0_DO, dataAK8963 );
  SPI_Err = _spi.fWriteSPIdata8bits( I2C_SLV0_CTRL, I2C_SLV0_EN | (uint8_t)1 );
}
int myMPU9250::setDlpfBandwidthAccelerometer( int bandwidth )
{
  SPI_Err = 0;
  if ( bandwidth == DLPF_BANDWIDTH_184HZ)
  {
    SPI_Err = _spi.fWriteSPIdata8bits( (int)ACCEL_CONFIG2, (int)ACCEL_DLPF_184);
    vTaskDelay(1);
    a_bandwidth = bandwidth;
    return SPI_Err;
  }
  if ( bandwidth == DLPF_BANDWIDTH_92HZ)
  {
    SPI_Err = _spi.fWriteSPIdata8bits( (int)ACCEL_CONFIG2, (int)ACCEL_DLPF_92 );
    vTaskDelay(1);
    a_bandwidth = bandwidth;
    return SPI_Err;
  }
  if ( bandwidth == DLPF_BANDWIDTH_41HZ)
  {
    SPI_Err = _spi.fWriteSPIdata8bits( (int)ACCEL_CONFIG2, (int)ACCEL_DLPF_41 );
    vTaskDelay(1);
    a_bandwidth = bandwidth;
    return SPI_Err;
  }
  if ( bandwidth == DLPF_BANDWIDTH_20HZ)
  {
    SPI_Err = _spi.fWriteSPIdata8bits( (int)ACCEL_CONFIG2, (int)ACCEL_DLPF_20 );
    vTaskDelay(1);
    a_bandwidth = bandwidth;
    return SPI_Err;
  }
  if ( bandwidth == DLPF_BANDWIDTH_10HZ )
  {
    SPI_Err = _spi.fWriteSPIdata8bits( (int)ACCEL_CONFIG2, (int)ACCEL_DLPF_10 );
    vTaskDelay(1);
    a_bandwidth = bandwidth;
    return SPI_Err;
  }
  if ( bandwidth == DLPF_BANDWIDTH_5HZ )
  {
    SPI_Err = _spi.fWriteSPIdata8bits( (int)ACCEL_CONFIG2, (int)ACCEL_DLPF_5 );
    vTaskDelay(1);
    a_bandwidth = bandwidth;
    return SPI_Err;
  }
} // int setDlpfBandwidth(DlpfBandwidth bandwidth
int myMPU9250::setDlpfBandwidthGyro( int bandwidth )
{
  SPI_Err = 0;
  if ( bandwidth == DLPF_BANDWIDTH_184HZ)
  {
    SPI_Err = _spi.fWriteSPIdata8bits( (int)CONFIG, (int)GYRO_DLPF_184);
    vTaskDelay(1);
    g_bandwidth = bandwidth;
    return SPI_Err;
  }
  if ( bandwidth == DLPF_BANDWIDTH_92HZ)
  {
    SPI_Err = _spi.fWriteSPIdata8bits( (int)CONFIG, (int)GYRO_DLPF_92 );
    vTaskDelay(1);
    g_bandwidth = bandwidth;
    return SPI_Err;
  }
  if ( bandwidth == DLPF_BANDWIDTH_41HZ)
  {
    SPI_Err = _spi.fWriteSPIdata8bits( (int)CONFIG, (int)GYRO_DLPF_41 );
    vTaskDelay(1);
    g_bandwidth = bandwidth;
    return SPI_Err;
  }
  if ( bandwidth == DLPF_BANDWIDTH_20HZ)
  {
    SPI_Err = _spi.fWriteSPIdata8bits( (int)CONFIG, (int)GYRO_DLPF_20 );
    vTaskDelay(1);
    g_bandwidth = bandwidth;
    return SPI_Err;
  }
  if ( bandwidth == DLPF_BANDWIDTH_10HZ )
  {
    SPI_Err = _spi.fWriteSPIdata8bits( (int)CONFIG, (int)GYRO_DLPF_10 );
    vTaskDelay(1);
    g_bandwidth = bandwidth;
    return SPI_Err;
  }
  if ( bandwidth == DLPF_BANDWIDTH_5HZ )
  {
    SPI_Err = _spi.fWriteSPIdata8bits( (int)CONFIG, (int)GYRO_DLPF_5 );
    vTaskDelay(1);
    g_bandwidth = bandwidth;
    return SPI_Err;
  }
}

cpp part 2

int myMPU9250::useDLPFbandwidth184Hz()
{
  return DLPF_BANDWIDTH_184HZ;
}
int myMPU9250::useDLPFbandwidth92Hz()
{
  return DLPF_BANDWIDTH_92HZ;
}
int myMPU9250::useDLPFbandwidth41Hz()
{
  return DLPF_BANDWIDTH_41HZ;
}
int myMPU9250::useDLPFbandwidth20Hz()
{
  return DLPF_BANDWIDTH_20HZ;
}
int myMPU9250::useDLPFbandwidth10Hz()
{
  return DLPF_BANDWIDTH_10HZ;
}
int myMPU9250::useDLPFbandwidth5Hz()
{
  return DLPF_BANDWIDTH_5HZ;
}
int myMPU9250::SPI_Error()
{
  return SPI_Err;
}
bool myMPU9250::isMPU9250_OK()
{
  return MPU9250_OK;
}
int myMPU9250::fReadAK8963( int subAddress, int count )
{
  // set slave 0 to the AK8963 and set for read
  SPI_Err = _spi.fWriteSPIdata8bits ( I2C_SLV0_ADDR, AK8963_I2C_ADDR | I2C_READ_FLAG );
  // set the register to the desired AK8963 sub address
  // I2C_SLV0_REG, subAddress
  SPI_Err = _spi.fWriteSPIdata8bits ( I2C_SLV0_REG, subAddress );
  // enable I2C and request the bytes
  // I2C_SLV0_CTRL, I2C_SLV0_EN | count
  SPI_Err = _spi.fWriteSPIdata8bits ( I2C_SLV0_CTRL, I2C_SLV0_EN | count );
  vTaskDelay ( 1 );
  return  SPI_Err;
}
bool myMPU9250::isAK8963_OK()
{
  return AK8963_OK;
}
float myMPU9250::getAccelScaleFactor()
{
  return _accelScaleFactor;
}
int myMPU9250::setAccelRange( int range )
{
  SPI_Err = 0;
  if ( ACCEL_RANGE_2G == range )
  {
    // setting the accel range to 2G
    SPI_Err = _spi.fWriteSPIdata8bits( ACCEL_CONFIG, ACCEL_FS_SEL_2G );
    vTaskDelay(1);
    _accelScaleFactor = (G * 2.0f) / AtoDscaleFactor; // setting the accel scale to 2G
    return SPI_Err;
  }
  if ( ACCEL_RANGE_4G == range )
  {
    // setting the accel range to 4G
    SPI_Err = _spi.fWriteSPIdata8bits(ACCEL_CONFIG, ACCEL_FS_SEL_4G);
    vTaskDelay(1);
    _accelScaleFactor = (G * 4.0f) / AtoDscaleFactor; // setting the accel scale to 4G
    return SPI_Err;
  }
  if ( ACCEL_RANGE_8G == range )
  {
    // setting the accel range to 8G
    SPI_Err = _spi.fWriteSPIdata8bits( ACCEL_CONFIG, ACCEL_FS_SEL_8G );
    vTaskDelay(1);
    _accelScaleFactor = (G * 8.0f) / AtoDscaleFactor; // setting the accel scale to 8G
    return SPI_Err;
  }
  if ( ACCEL_RANGE_16G == range )
  {
    // setting the accel range to 16G
    SPI_Err = _spi.fWriteSPIdata8bits( ACCEL_CONFIG, ACCEL_FS_SEL_16G );
    vTaskDelay(1);
    _accelScaleFactor = (G * 16.0f) / AtoDscaleFactor; // setting the accel scale to 16G
    return SPI_Err;
  }
}
int myMPU9250::useAccelerometerRange_2G()
{
  AccellRangeToUse = ACCEL_RANGE_2G;
  return ACCEL_RANGE_2G;
}
int myMPU9250::useAccelerometerRange_4G()
{
  AccellRangeToUse = ACCEL_RANGE_4G;
  return ACCEL_RANGE_4G;
}
int myMPU9250::useAccelerometerRange_8G()
{
  AccellRangeToUse = ACCEL_RANGE_8G;
  return ACCEL_RANGE_8G;
}
int myMPU9250::useAccelerometerRange_16G()
{
  AccellRangeToUse = ACCEL_RANGE_16G;
  return ACCEL_RANGE_16G;
}
void myMPU9250::setACCEL_RANGE_2G()
{
  AccellRangeToUse = ACCEL_RANGE_2G;
}
void myMPU9250::setACCEL_RANGE_4G()
{
  AccellRangeToUse = ACCEL_RANGE_4G;
}
void myMPU9250::setACCEL_RANGE_8G()
{
  AccellRangeToUse = ACCEL_RANGE_8G;
}
void myMPU9250::setACCEL_RANGE_16G()
{
  AccellRangeToUse = ACCEL_RANGE_16G;
}
int myMPU9250::setGyroRange( int range )
{
  SPI_Err = 0;
  if ( GYRO_RANGE_250DPS == range )
  {
    // setting the gyro range to 250DPS
    SPI_Err = _spi.fWriteSPIdata8bits(GYRO_CONFIG, GYRO_FS_SEL_250DPS);
    vTaskDelay(1);
    _gyroScaleFactor = 250.0f / AtoDscaleFactor; // setting the gyro scale to 250DPS
    return SPI_Err;
  }
  if ( GYRO_RANGE_500DPS == range )
  {
    // setting the gyro range to 500DPS
    SPI_Err = _spi.fWriteSPIdata8bits( GYRO_CONFIG, GYRO_FS_SEL_500DPS );
    vTaskDelay(1);
    _gyroScaleFactor = (500.0f / AtoDscaleFactor) * _d2r; // setting the gyro scale to 500DPS
    return SPI_Err;
  }
  if ( GYRO_RANGE_1000DPS == range )
  {
    // setting the gyro range to 1000DPS
    SPI_Err = _spi.fWriteSPIdata8bits( GYRO_CONFIG, GYRO_FS_SEL_1000DPS );
    vTaskDelay(1);
    _gyroScaleFactor = (1000.0f / AtoDscaleFactor) * _d2r; // setting the gyro scale to 1000DPS
    return SPI_Err;
  }
  if ( GYRO_RANGE_2000DPS == range )
  {
    // setting the gyro range to 2000DPS
    SPI_Err = _spi.fWriteSPIdata8bits( GYRO_CONFIG, GYRO_FS_SEL_2000DPS );
    vTaskDelay(1);
    _gyroScaleFactor = (2000.0f / AtoDscaleFactor) * _d2r; // setting the gyro scale to 2000DPS
    return SPI_Err;
  }
} // int myMPU9250::setGyroRange( int range )
float myMPU9250::getGyroScaleFactor()
{
  return _gyroScaleFactor;
}
float myMPU9250::getGyroScale()
{
  return _gyroScaleFactor;
}
int myMPU9250::useGYRO_RANGE_250DPS()
{
  GyroRangeToUse = GYRO_RANGE_250DPS;
  return GyroRangeToUse;
}
int myMPU9250::useGYRO_RANGE_500DPS()
{
  GyroRangeToUse = GYRO_RANGE_500DPS;
  return GyroRangeToUse;
}
int myMPU9250::useGYRO_RANGE_1000DPS()
{
  GyroRangeToUse = GYRO_RANGE_1000DPS;
  return GyroRangeToUse;
}
int myMPU9250::useGYRO_RANGE_2000DPS()
{
  GyroRangeToUse = GYRO_RANGE_2000DPS;
  return GyroRangeToUse;
}
float myMPU9250::getMagScaleXFactor()
{
  return x_MSF.x;
}
float myMPU9250::getMagScaleYFactor()
{
  return x_MSF.y;
}
float myMPU9250::getMagScaleZFactor()
{
  return x_MSF.z;
}
int myMPU9250::setMagSensitivityValue( )
{
  SPI_Err = 0;
  // read the AK8963 ASA registers and compute magnetometer scale factors
  SPI_Err = fReadAK8963( AK8963_ASA, 3 );
  vTaskDelay( 1 );
  SPI_Err = _spi.fReadSPI ( 3, EXT_SENS_DATA_00 | SPI_READ );
  if (SPI_Err != 0 )
  {
    x_MSF.x =  (float)( _spi.get_rxData8bit(0) - 128 ) / 256.0f + 1.0f; // Return x-axis sensitivity adjustment values, etc.
    x_MSF.y =  (float)( _spi.get_rxData8bit(1) - 128 ) / 256.0f + 1.0f; // Return y-axis sensitivity adjustment values, etc.
    x_MSF.z  =  (float)( _spi.get_rxData8bit(2) - 128 ) / 256.0f + 1.0f; // Return z-axis sensitivity adjustment values, etc.
  }
  return SPI_Err;
}
int myMPU9250::getRegisteredError()
{
  return SPI_Err;
}
int myMPU9250::getAdata()
{
  SPI_Err = 0;
  SPI_Err = _spi.fReadSPI( 8 , 0X3A | SPI_READ );
  if (  SPI_Err == 0 )
  {
    x_Araw.x = 0.0;
    x_Araw.y = 0.0;
    x_Araw.z = 0.0;
    // transform
    x_Araw.y = ((float)(int16_t)(((int16_t)_spi.get_rxData8bit(2) << 8) | _spi.get_rxData8bit(3)));
    x_Araw.x = ((float)(int16_t)(((int16_t)_spi.get_rxData8bit(4) << 8) | _spi.get_rxData8bit(5)));
    x_Araw.z = ((float)(int16_t)(((int16_t)_spi.get_rxData8bit(6) << 8) | _spi.get_rxData8bit(7)));
    x_Araw.z *= -1;
    // scale and bias
    x_Ascaled.x = ( (x_Araw.x * _accelScaleFactor) - x_Abias.x ) * x_ASF.x;
    x_Ascaled.y = ( (x_Araw.y * _accelScaleFactor) - x_Abias.y ) * x_ASF.y;
    x_Ascaled.z = ( (x_Araw.z * _accelScaleFactor) - x_Abias.z ) * x_ASF.z;
  }
  // reads one address previous to the accelerometer data
  // found that from time to time only positive values returned if
  //  was read directly
  return SPI_Err;
}
float myMPU9250::getAxRaw()
{
  return x_Araw.x;
}
float myMPU9250::getAyRaw()
{
  return x_Araw.y;
}
float myMPU9250::getAzRaw()
{
  return x_Araw.z;
}
float myMPU9250::getAxScaled()
{
  return x_Ascaled.x;
}
float myMPU9250::getAyScaled()
{
  return x_Ascaled.y;
}
float myMPU9250::getAzScaled()
{
  return x_Ascaled.z;
}
void myMPU9250::setXbiasScale( float _bs )
{
  x_ASF.x = _bs;
}
void myMPU9250::setYbiasScale( float _bs )
{
  x_ASF.y = _bs;
}
void myMPU9250::setZbiasScale( float _bs )
{
  x_ASF.z = _bs;
}
int myMPU9250::getGdata()
{
  SPI_Err = 0;
  // SPI_Err = _spi.fReadSPI( 6 , GYRO_OUTX | SPI_READ );
  SPI_Err = _spi.fReadSPI( 8 , 0x41 | SPI_READ );
  if (  SPI_Err == 0 )
  {
    x_Graw.x = 0.0f;
    x_Graw.y = 0.0f;
    x_Graw.z = 0.0f;
    // transform
    x_Graw.y = ((float)(int16_t)(((int16_t)_spi.get_rxData8bit(2) << 8) | _spi.get_rxData8bit(3)));
    x_Graw.x = ((float)(int16_t)(((int16_t)_spi.get_rxData8bit(4) << 8) | _spi.get_rxData8bit(5)));
    x_Graw.z = ((float)(int16_t)(((int16_t)_spi.get_rxData8bit(6) << 8) | _spi.get_rxData8bit(7)));
    x_Graw.z = (-1 * x_Graw.z);
    // scale
    x_Gscaled.x = ( ( x_Graw.x * _gyroScaleFactor ) - x_Gbias.x) ;
    x_Gscaled.y = ( x_Graw.y * _gyroScaleFactor ) - x_Gbias.y;
    x_Gscaled.z = ( x_Graw.z * _gyroScaleFactor ) - x_Gbias.z;
  }
}
float myMPU9250::getGxScaled()
{
  return  x_Gscaled.x;
}
float myMPU9250::getGyScaled()
{
  return  x_Gscaled.y;
}
float myMPU9250::getGzScaled()
{
  return  x_Gscaled.z;
}
float myMPU9250::getGxRaw()
{
  return x_Graw.x;
}
float myMPU9250::getGyRaw()
{
  return x_Graw.y;
}
float myMPU9250::getGzRaw()
{
  return x_Graw.z;
}

cpp part 3

int myMPU9250::getMdata()
{
  SPI_Err = 0;
  SPI_Err = _spi.fReadSPI( 8 , 0x47 | SPI_READ );
  /*ST2 register has a role as data reading end register, also.
     When any of measurement data register is read in continuous measurement mode or external trigger measurement mode,
     it means data reading start and taken as data reading until ST2 register is read.
     Therefore, when any of measurement data is read, be sure to read ST2 register at the end.
     that's why reading the extra register
  */
  if (  SPI_Err == 0 )
  {
    magDataOverFlow = false;
    x_Mraw.x = 0.0;
    x_Mraw.y = 0.0;
    x_Mraw.z = 0.0;
    x_Mraw.x = ((float)(int16_t)(((int16_t)_spi.get_rxData8bit(3) << 8) | _spi.get_rxData8bit(2)));
    x_Mraw.y = ((float)(int16_t)(((int16_t)_spi.get_rxData8bit(5) << 8) | _spi.get_rxData8bit(4)));
    x_Mraw.z = ((float)(int16_t)(((int16_t)_spi.get_rxData8bit(7) << 8) | _spi.get_rxData8bit(6)));
    x_Mscaled.x = (x_Mraw.x * mRes * x_MSF.x) - x_Mbias.x;
    x_Mscaled.y = (x_Mraw.y * mRes * x_MSF.y) - x_Mbias.y;
    x_Mscaled.z = (x_Mraw.z * mRes * x_MSF.z) - x_Mbias.z;
    x_Mscaled.x *= x_Mscale.x; // poor man's soft iron calibration
    x_Mscaled.y *= x_Mscale.y;
    x_Mscaled.z *= x_Mscale.z;
  }
}
bool myMPU9250::getMagDataOverflow()
{
  return magDataOverFlow;
}
float myMPU9250::getMxRaw()
{
  return x_Mraw.x;
}
float myMPU9250::getMyRaw()
{
  return x_Mraw.y;
}
float myMPU9250::getMzRaw()
{
  return x_Mraw.z;
}
float myMPU9250::getMxScaled()
{
  return x_Mscaled.x;
}
float myMPU9250::getMyScaled()
{
  return x_Mscaled.y;
}
float myMPU9250::getMzScaled()
{
  return x_Mscaled.z;
}
int myMPU9250::fSetInterrupt()
{
  SPI_Err = 0;
  /* setting the interrupt */
  // INT_PIN_CFG,INT_PULSE_50US setup interrupt, 50 us pulse
  SPI_Err = _spi.fWriteSPIdata8bits( INT_PIN_CFG, INT_PULSE_50US );
  // INT_ENABLE,INT_RAW_RDY_EN set to data ready
  SPI_Err = _spi.fWriteSPIdata8bits( INT_ENABLE, INT_RAW_RDY_EN );
  return SPI_Err;
}
int myMPU9250::fQueueupReadAGMdata( )
{
  SPI_Err = _spi.fSPIqueueupTransactions_read( 8 , 0X3A | SPI_READ );
  SPI_Err = _spi.fReadSPI( 6 , GYRO_OUTX | SPI_READ );
  SPI_Err = _spi.fReadSPI( 6 , EXT_SENS_DATA_00 | SPI_READ );
}
void myMPU9250::setAXbias( float _ab )
{
  x_Abias.x = _ab;
}
void myMPU9250::setAYbias( float _ab )
{
  x_Abias.y = _ab;
}
void myMPU9250::setAZbias( float _ab )
{
  x_Abias.z = _ab;
}
float myMPU9250::getAXbias( )
{
  return x_Abias.x;
}
float myMPU9250::getAYbias( )
{
  return x_Abias.y;
}
float myMPU9250::getAZbias( )
{
  return x_Abias.z;
}
////////////////////////////////////////////////////////////////////////////////////////////
void myMPU9250::setGXbias( float _gb )
{
  x_Gbias.x = _gb;
}
void myMPU9250::setGYbias( float _gb )
{
  x_Gbias.y = _gb;
}
void myMPU9250::setGZbias( float _gb )
{
  x_Gbias.z = _gb;
}
float myMPU9250::getGXbias( )
{
  return x_Gbias.x;
}
float myMPU9250::getGYbias( )
{
  return x_Gbias.y;
}
float myMPU9250::getGZbias( )
{
  return x_Gbias.z;
}
////////////////////////////////////////////////////////////////////////////////////////////
void myMPU9250::setMXbias( float _mb )
{
  x_Mbias.x = _mb * mRes * x_MSF.x;
}
void myMPU9250::setMYbias( float _mb )
{
  x_Mbias.y = _mb * mRes * x_MSF.y;
}
void myMPU9250::setMZbias( float _mb )
{
  x_Mbias.z = _mb * mRes * x_MSF.z;
}
float myMPU9250::getMXbias( )
{
  return x_Mbias.x;
}
float myMPU9250::getMYbias( )
{
  return x_Mbias.y;
}
float myMPU9250::getMZbias( )
{
  return x_Mbias.z;
}
void myMPU9250::setMxScale( float _ms )
{
  x_Mscale.x = _ms;
}
void myMPU9250::setMyScale( float _ms )
{
  x_Mscale.y = _ms;
}
void myMPU9250::setMzScale( float _ms )
{
  x_Mscale.z = _ms;
}
////////////////////////////////////////////////////////////////////////////////////////////
void myMPU9250::fCalculate_GandAbias( )
{
  float tempGx = 0.0f;
  float tempGy = 0.0f;
  float tempGz = 0.0f;
  float tempAx = 0.0f;
  float tempAy = 0.0f;
  float tempAz = 0.0f;
  float tempMx = 0.0f;
  float tempMy = 0.0f;
  float tempMz = 0.0f;
  int numOfSamples = 100;
  x_Abias.x = 0.0f;
  x_Abias.y = 0.0f;
  x_Abias.z = 0.0f;
  setGXbias( 0.0f );
  setGYbias( 0.0f );
  setGZbias( 0.0f );
  //// do X,Y,Z gyro and accelerometer bias
  // take reading
  for ( int i = 0 ; i < numOfSamples; i++ )
  {
    // take reading
    fGetAll( ); 
    ////
    tempAx = ( tempAx + getAxScaled() ) / (float)numOfSamples;
    tempAy = ( tempAy + getAyScaled() ) / (float)numOfSamples;
    tempAz = ( tempAz + getAzScaled() ) / (float)numOfSamples;
    // getGdata();
    tempGx = ( tempGx + getGxScaled() ) / (float)numOfSamples;
    tempGy = ( tempGy + getGyScaled() ) / (float)numOfSamples;
    tempGz = ( tempGz + getGzScaled() ) / (float)numOfSamples;
    vTaskDelay( 20 );
  }
  // set accelrometer scale
  float _axmax = 0.0f, _aymax = 0.0f, _azmax = 0.0f;
  float _axmin = 0.0f, _aymin = 0.0f, _azmin = 0.0f;
  if ( tempAx > 9.0f )
  {
    _axmax = tempAx;
  }
  if ( tempAx < -9.0f )
  {
    _axmin = tempAx;
  }

  if ( tempAy > 9.0f )
  {
    _aymax = tempAy;
  }
  if ( tempAy < -9.0f )
  {
    _aymin = tempAy;
  }

  if ( tempAz > 9.0f )
  {
    _azmax = tempAz;
  }
  if ( tempAz < -9.0f )
  {
    _azmin = tempAz;
  }
  //// find bias and scale factor
  if ((abs(_axmin) > 9.0f) && (abs(_axmax) > 9.0f))
  {
    x_Abias.x = ( _axmin + _axmax ) / 2.0f;
    setXbiasScale( G / ((abs(_axmin) + abs(_axmax)) / 2.0f) );
  }
  else
  {
    x_Abias.x = tempAx; // transformed during get
  }
  //
  if ((abs(_aymin) > 9.0f) && (abs(_aymax) > 9.0f))
  {
    x_Abias.y = ( _aymin + _aymax ) / 2.0f;
    setYbiasScale( G / ((abs(_aymin) + abs(_aymax)) / 2.0f) );
  }
  else
  {
    x_Abias.y = tempAy;
  }
  if ((abs(_azmin) > 9.0f) && (abs(_azmax) > 9.0f))
  {
    x_Abias.z = (_azmin + _azmax) / 2.0f;
    setZbiasScale( G / ((abs(_azmin) + abs(_azmax)) / 2.0f) );
  }
  else
  {
    x_Abias.z = tempAz;
  }
  x_Gbias.x = tempGx; // transformed during get
  x_Gbias.y = tempGy;
  x_Gbias.z = tempGz;
} //void fCalculate_GandAbias( )
int myMPU9250::fGetAll( )
{
  SPI_Err = 0;
  SPI_Err = _spi.fReadSPI( 22 , GetAllDataAddress | SPI_READ );
  if (  SPI_Err == 0 )
  {
    x_Araw.x = 0.0;
    x_Araw.y = 0.0;
    x_Araw.z = 0.0;
    // transform or transpose x and y and multiply z by -1
    x_Araw.y = ((float)(int16_t)(((int16_t)_spi.get_rxData8bit(2) << 8) | _spi.get_rxData8bit(3)));
    x_Araw.x = ((float)(int16_t)(((int16_t)_spi.get_rxData8bit(4) << 8) | _spi.get_rxData8bit(5)));
    x_Araw.z = ((float)(int16_t)(((int16_t)_spi.get_rxData8bit(6) << 8) | _spi.get_rxData8bit(7)));
    x_Araw.z *= -1; // a transform operation
    // scale and bias
    x_Ascaled.x = ( (x_Araw.x * _accelScaleFactor) - x_Abias.x ) * x_ASF.x;
    x_Ascaled.y = ( (x_Araw.y * _accelScaleFactor) - x_Abias.y ) * x_ASF.y;
    x_Ascaled.z = ( (x_Araw.z * _accelScaleFactor) - x_Abias.z ) * x_ASF.z;
    //
    tempCount = ((int)(int16_t)(((int16_t)_spi.get_rxData8bit(8) << 8) | _spi.get_rxData8bit(9)));
    temperature = ((((float)tempCount) - _tempOffset) / _tempScale) + _tempOffset;
    //
    x_Graw.x = 0.0f;
    x_Graw.y = 0.0f;
    x_Graw.z = 0.0f;
    // transform, the x input axis is on the y plane
    x_Graw.y = ((float)(int16_t)(((int16_t)_spi.get_rxData8bit(10) << 8) | _spi.get_rxData8bit(11)));
    x_Graw.x = ((float)(int16_t)(((int16_t)_spi.get_rxData8bit(12) << 8) | _spi.get_rxData8bit(13)));
    x_Graw.z = ((float)(int16_t)(((int16_t)_spi.get_rxData8bit(14) << 8) | _spi.get_rxData8bit(15)));
    x_Graw.z = (-1 * x_Graw.z); // transformation
    // scale
    x_Gscaled.x = ( ( x_Graw.x * _gyroScaleFactor ) - x_Gbias.x);
    x_Gscaled.y = ( x_Graw.y * _gyroScaleFactor ) - x_Gbias.y;
    x_Gscaled.z = ( x_Graw.z * _gyroScaleFactor ) - x_Gbias.z;
    x_Mraw.x = 0.0;
    x_Mraw.y = 0.0;
    x_Mraw.z = 0.0;
    x_Mraw.x = ((float)(int16_t)(((int16_t)_spi.get_rxData8bit(17) << 8) | _spi.get_rxData8bit(16)));
    x_Mraw.y = ((float)(int16_t)(((int16_t)_spi.get_rxData8bit(19) << 8) | _spi.get_rxData8bit(18)));
    x_Mraw.z = ((float)(int16_t)(((int16_t)_spi.get_rxData8bit(21) << 8) | _spi.get_rxData8bit(20)));
    x_Mscaled.x = (x_Mraw.x * mRes * x_MSF.x) - x_Mbias.x;
    x_Mscaled.y = (x_Mraw.y * mRes * x_MSF.y) - x_Mbias.y;
    x_Mscaled.z = (x_Mraw.z * mRes * x_MSF.z) - x_Mbias.z;
    x_Mscaled.x *= x_Mscale.x; // poor man's soft iron calibration
    x_Mscaled.y *= x_Mscale.y;
    x_Mscaled.z *= x_Mscale.z;
  }
  return SPI_Err;
}

.h part 1

#ifndef ESP32_MPU9250
#define ESP32_MPU9250
////
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/timers.h"
#include "freertos/event_groups.h"
#include "myESP32_SPI.h"
////
class myMPU9250
{
  public:
    myMPU9250( int _queueSize );
    int fGetAll( );
    void fCalculate_GandAbias( );
    float getMxRaw();
    float getMyRaw();
    float getMzRaw();
    float getMxScaled();
    float getMyScaled();
    float getMzScaled();
    int getMdata();
    float getGxScaled();
    float getGyScaled();
    float getGzScaled();
    float getGxRaw();
    float getGyRaw();
    float getGzRaw();
    int getGdata();
    float getGyroScaleFactor();
    int getAdata();
    void setXbiasScale( float _bs );
    void setYbiasScale( float _bs );
    void setZbiasScale( float _bs );
    float getAxRaw();
    float getAyRaw();
    float getAzRaw();
    float getAxScaled();
    float getAyScaled();
    float getAzScaled();
    float getAccelScaleFactor();
    int fInit_MPU9250( bool resetMPU9250, bool resetAK8962 );
    int SPI_Error();
    bool isMPU9250_OK();
    bool isAK8963_OK();
    void fWrite_AK8963(  int subAddress, int dataAK8963 );
    int fReadAK8963( int subAddress, int count );
    int setDlpfBandwidthAccelerometer( int bandwidth);
    int setDlpfBandwidthGyro( int bandwidth);
    int useDLPFbandwidth184Hz();
    int useDLPFbandwidth92Hz();
    int useDLPFbandwidth41Hz();
    int useDLPFbandwidth20Hz();
    int useDLPFbandwidth10Hz();
    int useDLPFbandwidth5Hz();
    int setAccelRange( int range );
    int useAccelerometerRange_2G();
    int useAccelerometerRange_4G();
    int useAccelerometerRange_8G();
    int useAccelerometerRange_16G();
    void setACCEL_RANGE_2G();
    void setACCEL_RANGE_4G();
    void setACCEL_RANGE_8G();
    void setACCEL_RANGE_16G();
    int setGyroRange( int range );
    float getGyroScale();
    int useGYRO_RANGE_250DPS();
    int useGYRO_RANGE_500DPS();
    int useGYRO_RANGE_1000DPS();
    int useGYRO_RANGE_2000DPS();
    int setMagSensitivityValue();
    float getMagScaleXFactor();
    float getMagScaleYFactor();
    float getMagScaleZFactor();
    void setMxScale( float _ms );
    void setMyScale( float _ms );
    void setMzScale( float _ms );
    int getRegisteredError();
    int getByte( int _Byte );
    int fSetInterrupt();
    int fQueueupReadAGMdata( );
    int fReadQueuedAdata( );
    void setAXbias( float _ab );
    void setAYbias( float _ab );
    void setAZbias( float _ab );
    float getAXbias( );
    float getAYbias( );
    float getAZbias( );
    void setGXbias( float _gb );
    void setGYbias( float _gb );
    void setGZbias( float _gb );
    float getGXbias( );
    float getGYbias( );
    float getGZbias( );
    void setMXbias( float _mb );
    void setMYbias( float _mb );
    void setMZbias( float _mb );
    float getMXbias( );
    float getMYbias( );
    float getMZbias( );
    bool getMagDataOverflow();
    ////
  private:
    ////////////////////////////////
    //// mpu 9250 spi read registers safe up to 1Mhz.
    //////////////////////////////////////////
    const float _tempScale = 333.87f;
    const float _tempOffset = 21.0f;
    const uint8_t SPI_READ = 0x80;
    const uint8_t WHO_I_AMa = 0x73;
    const uint8_t WHO_I_AMb = 0x71;
    const uint8_t AK8963_IS = 0x48;
    const uint8_t ACCELX_OUT = 0x3B;
    const uint8_t ACCELY_OUT = 0x3D;
    const uint8_t ACCELZ_OUT = 0x3F;
    const uint8_t GYRO_OUTX = 0x43;
    const uint8_t GYRO_OUTY = 0x45;
    const uint8_t GYRO_OUTZ = 0x47;
    ////
    const int DLPF_BANDWIDTH_184HZ = 184;
    const int DLPF_BANDWIDTH_92HZ = 92;
    const int DLPF_BANDWIDTH_41HZ = 41;
    const int DLPF_BANDWIDTH_20HZ = 20;
    const int DLPF_BANDWIDTH_10HZ = 10;
    const int DLPF_BANDWIDTH_5HZ = 5;
    const int ACCEL_RANGE_2G = 2;
    const int ACCEL_RANGE_4G = 4;
    const int ACCEL_RANGE_8G = 8;
    const int ACCEL_RANGE_16G = 16;
    const int GYRO_RANGE_250DPS = 250;
    const int GYRO_RANGE_500DPS = 500;
    const int GYRO_RANGE_1000DPS = 1000;
    const int GYRO_RANGE_2000DPS = 2000;
    ////
    const uint8_t EXT_SENS_DATA_00 = 0x49;
    const float AtoDscaleFactor = 32767.5f;
    const float G = 9.807f;
    const float _d2r = 3.14159265358979323846f / 180.0f;
    const uint8_t ACCEL_CONFIG = 0x1C;
    const uint8_t ACCEL_FS_SEL_2G = 0x00;
    const uint8_t ACCEL_FS_SEL_4G = 0x08;
    const uint8_t ACCEL_FS_SEL_8G = 0x10;
    const uint8_t ACCEL_FS_SEL_16G = 0x18;
    const uint8_t GYRO_CONFIG = 0x1B;
    const uint8_t GYRO_FS_SEL_250DPS = 0x00;
    const uint8_t GYRO_FS_SEL_500DPS = 0x08;
    const uint8_t GYRO_FS_SEL_1000DPS = 0x10;
    const uint8_t GYRO_FS_SEL_2000DPS = 0x18;
    const uint8_t ACCEL_CONFIG2 = 0x1D;
    const uint8_t ACCEL_DLPF_184 = 0x01;
    const uint8_t ACCEL_DLPF_92 = 0x02;
    const uint8_t ACCEL_DLPF_41 = 0x03;
    const uint8_t ACCEL_DLPF_20 = 0x04;
    const uint8_t ACCEL_DLPF_10 = 0x05;
    const uint8_t ACCEL_DLPF_5 = 0x06;
    const uint8_t CONFIG = 0x1A;
    const uint8_t GYRO_DLPF_184 = 0x01;
    const uint8_t GYRO_DLPF_92 = 0x02;
    const uint8_t GYRO_DLPF_41 = 0x03;
    const uint8_t GYRO_DLPF_20 = 0x04;
    const uint8_t GYRO_DLPF_10 = 0x05;
    const uint8_t GYRO_DLPF_5 = 0x06;
    const uint8_t SMPDIV = 0x19;
    const uint8_t INT_PIN_CFG = 0x37;

.h part 2

 const uint8_t INT_ENABLE = 0x38;
    const uint8_t INT_DISABLE = 0x00;
    const uint8_t INT_PULSE_50US = 0x00;
    const uint8_t INT_WOM_EN = 0x40;
    const uint8_t INT_RAW_RDY_EN = 0x01;
    const uint8_t PWR_MGMNT_1 = 0x6B;
    const uint8_t PWR_CYCLE = 0x20;
    const uint8_t PWR_RESET = 0x80;
    const uint8_t CLOCK_SEL_PLL = 0x01;
    const uint8_t PWR_MGMNT_2 = 0x6C;
    const uint8_t SEN_ENABLE = 0x00;
    //////const uint8_t DIS_GYRO = 0x07;
    const uint8_t USER_CTRL = 0x6A;
    const uint8_t I2C_MST_EN = 0x20;
    const uint8_t I2C_MST_CLK = 0x0D;
    const uint8_t I2C_MST_CTRL = 0x24;
    const uint8_t I2C_SLV0_ADDR = 0x25;
    const uint8_t I2C_SLV0_REG = 0x26;
    const uint8_t I2C_SLV0_DO = 0x63;
    const uint8_t I2C_SLV0_CTRL = 0x27;
    const uint8_t I2C_SLV0_EN = 0x80;
    const uint8_t I2C_READ_FLAG = 0x80;
    //const uint8_t MOT_DETECT_CTRL = 0x69;
    //const uint8_t ACCEL_INTEL_EN = 0x80;
    //const uint8_t ACCEL_INTEL_MODE = 0x40;
    //const uint8_t LP_ACCEL_ODR = 0x1E;
    //const uint8_t WOM_THR = 0x1F;
    const uint8_t WHO_AM_I = 0x75;
    const uint8_t FIFO_EN = 0x23;
    //const uint8_t FIFO_TEMP = 0x80;
    //const uint8_t FIFO_GYRO = 0x70;
    //const uint8_t FIFO_ACCEL = 0x08;
    //const uint8_t FIFO_MAG = 0x01;
    //const uint8_t FIFO_COUNT = 0x72;
    //const uint8_t FIFO_READ = 0x74;
    //// AK8963 registers
    const uint8_t AK8963_I2C_ADDR = 0x0C;
    const uint8_t AK8963_HXL = 0x03;
    const uint8_t AK8963_CNTL1 = 0x0A;
    const uint8_t AK8963_PWR_DOWN = 0x00;
    const uint8_t AK8963_CNT_MEAS1 = 0x12;
    const uint8_t AK8963_CNT_MEAS2 = 0x16;
    const uint8_t AK8963_FUSE_ROM = 0x0F;
    const uint8_t AK8963_CNTL2 = 0x0B;
    const uint8_t AK8963_RESET = 0x01;
    const uint8_t AK8963_ASA = 0x10;
    const uint8_t AK8963_WHO_AM_I = 0x00;
    ////
    const uint8_t GetAllDataAddress = 0X3A;
    ///////////////////////////////////////////////////////////////////////////
    ESP32_SPI_API _spi;
    /////////////////////////////////////////////////////////////////////////////
    //    void fDoTempratureConversion( void * parameter );
    /////////////////////////////////////////////////////////////////////////////
    /////* define event bits */
    #define evtTempratureConversion               ( 1 << 0 ) // 1
    /////////////////////////////////////////////////////////////////////////////
    EventGroupHandle_t _hEG;
    float temperature;
    int tempCount;   // Stores the real internal chip temperature in degrees Celsius
    bool magDataOverFlow = false;
    bool MPU9250_OK = false;
    int a_bandwidth;
    int g_bandwidth;
    int SPI_Err;
    bool AK8963_OK = false;
    float mRes = 10.0*4219.0/32760.0; // Proper scale to return milliGauss, 16 bit res
    // float mRes = 10.0*4219.0/8190.0; // Proper scale to return milliGauss, 14 bit res
    float _gyroScaleFactor = 0.0f;
    float _accelScaleFactor = 0.0f;
    int AccellRangeToUse = ACCEL_RANGE_16G;
    int GyroRangeToUse = GYRO_RANGE_250DPS;
    ///////////////////////////////////////////////////////////////////////////
     struct stu_A_Scale_Factor
    {
      float x = 1.0f;
      float y = 1.0f;
      float z = 1.0f;
    } x_ASF;
    struct stu_Mag_Scale_Factor
    {
      float x = 1.0f;
      float y = 1.0f;
      float z = 1.0f;
    } x_MSF;
    struct stu_MagRaw
    {
      float x = 0.0f;
      float y = 0.0f;
      float z = 0.0f;
    } x_Mraw;
    struct stu_MagScaled
    {
      float x = 0.0f;
      float y = 0.0f;
      float z = 0.0f;
    } x_Mscaled;
     struct stu_MagScale
    {
      float x = 0.0f;
      float y = 0.0f;
      float z = 0.0f;
    } x_Mscale;
    struct stu_AccelerometerRaw
    {
      float x = 0.0f;
      float y = 0.0f;
      float z = 0.0f;
    } x_Araw;
    struct stu_AccelerometerScaled
    {
      float x = 0.0f;
      float y = 0.0f;
      float z = 0.0f;
    } x_Ascaled;
    struct stu_GyroRaw
    {
      float x = 0.0f;
      float y = 0.0f;
      float z = 0.0f;
    } x_Graw;
    struct stu_GyroScaled
    {
      float x = 0.0f;
      float y = 0.0f;
      float z = 0.0f;
    } x_Gscaled;
    struct stu_AccelerometerBias
    {
      float x = 0.0f;
      float y = 0.0f;
      float z = 0.0f;
    } x_Abias;
    struct stu_GyroBias
    {
      float x = 0.0f;
      float y = 0.0f;
      float z = 0.0f;
    } x_Gbias;
    struct stu_MagnetometerBias
    {
      float x = 0.0f;
      float y = 0.0f;
      float z = 0.0f;
    } x_Mbias;
};
#endif

use example:

void fGetIMU( void *pvParameters )
{
  mpu9250.fInit_MPU9250( false, false ); // the first few times of use, set these to true true.
  boolean DidBias = false;
  float TimePast = micros() / 1000000.0f;
  float TimeNow = micros() / 1000000.0f;
  TickType_t xLastWakeTime = xTaskGetTickCount();
  TickType_t xFrequency = 30;
  for (;;)
  {
    vTaskDelayUntil( &xLastWakeTime, xFrequency );
    // read the sensor
    if ( DidBias )
    {
      //TimeNow = xTaskGetTickCount();
      TimeNow = micros() / 1000000.0f;
      deltat = ( TimeNow - TimePast);
      mpu9250.fGetAll();
      MahonyQuaternionUpdate ( mpu9250.getAxScaled(), mpu9250.getAyScaled(), mpu9250.getAzScaled(), mpu9250.getGxScaled() * PI / 180.0f, mpu9250.getGyScaled() * PI / 180.0f, mpu9250.getGzScaled() * PI / 180.0f, mpu9250.getMxScaled(), mpu9250.getMyScaled(), mpu9250.getMzScaled() );
      yaw = atan2f(2.0f * (q[1] * q[2] + q[0] * q[3]), q[0] * q[0] + q[1] * q[1] - q[2] * q[2] - q[3] * q[3]);
      pitch = -asinf(2.0f * (q[1] * q[3] - q[0] * q[2]));
      roll = atan2f(2.0f * (q[0] * q[1] + q[2] * q[3]), q[0] * q[0] - q[1] * q[1] - q[2] * q[2] + q[3] * q[3]);
      if ( xSemaphoreTake( sema_X, xZeroTicksToWait ) == pdTRUE ) // grab semaphore, do not wait
      {
        xQueueOverwrite( xQ_X_INFO, (void *) &roll );
        xEventGroupSetBits( eg, evtTweakServoX );
      }
      if ( xSemaphoreTake( sema_Y, xZeroTicksToWait ) == pdTRUE ) // grab semaphore, do not wait
      {
        xQueueOverwrite( xQ_Y_INFO, (void *) &pitch );
        xEventGroupSetBits( eg, evtTweakServoY );
      }
      TimePast = TimeNow;
    } // if ( DidBias )
    else
    {
      // MPU calibration
      fCalculateM_offset( );
      DidBias = true;
      TimePast = micros();
      xEventGroupSetBits( eg, evtLIDAR_ServoAspectChange ); // start the LIDAR scanning
    }
    xLastWakeTime = xTaskGetTickCount();;
  } //  for (;;)
  vTaskDelete( NULL );
} // void fGetIMU( void *pvParameters )
1 Like