MPU-9250 Teensy Library

Hi jpatrick62
I'll try to answer until Brian has a chance to respond.
I'll assume each call was for an bias and scale factor on each axis. However I am a bit confused by physically what to do with the 9250, mine being breadboarded temporarily.
If you look at the calibrateAccel function in the MPU9250.cpp file it doesn't matter which axis you do first. It looks for the min/max in each orientation for ax, ay, az and then does the scale and bias calculation. So you do not have to worry about which axis you do first or what order.

Once we get the 9250 calibrated, I'll assume the scale and bias factors (x,y,z) can then be applied to the raw data from the sensor? Can you provide an example of such an operation?
Take a look at the readSensor function in the MPU9250.cpp file. I shows you how Brian used the scale/bias to get the calibrated values.

Mike
 
Thanks for the reply mjs513,

If you look at the calibrateAccel function in the MPU9250.cpp file it doesn't matter which axis you do first. It looks for the min/max in each orientation for ax, ay, az and then does the scale and bias calculation. So you do not have to worry about which axis you do first or what order.

OK, thanks for that, so I just move the sensor to a new axis for each of the 6 measurements. i.e. x+,x-,y+....


Take a look at the readSensor function in the MPU9250.cpp file. I shows you how Brian used the scale/bias to get the calibrated values.


Ah - so it appears Brian already takes into account the bias and scale (for accelerometer and magnetometer) via calls such as
setAccelCalX(float bias,float scaleFactor) and setMagCalX(float bias,float scaleFactor), whose bias and scale we saved from the initial calibration and
put into EEPROM?
 
Short answer - yep. Once you run the calibrate sketch the values are set in the eeprom. Then in the 9250 sketches you see that in retrieves the values from the eeprom and sets them with the commands you noted.
 
Thanks mjs513, appreciate that.
So my next task is to take the calibrated values and input that info into a WPF 3D model via the Quaternion APIs.
Looks like a lot of fun!
 
Hello, when I use status = IMU.calibrateAccel(); and other calibration functions nothing really happens. For example ayb = IMU.getAccelBiasY_mss() just shows 0.00 like and the acceleration is still off by a bit; Anyone knows why this happens?
 
Last edited:
Hello, when I use status = IMU.calibrateAccel(); and other calibration functions nothing really happens. For example ayb = IMU.getAccelBiasY_mss() just shows 0.00 like and the acceleration is still off by a bit; Anyone knows why this happens?

You need to call calibrateAccel() 6 times, once for each axis facing down, in order for the library to calibrate the accelerometer. Only after the library calibrates the accelerometer will calling the getAccelBias functions return the estimated bias for each axis (and similar with the scale factor functions).
 
You need to call calibrateAccel() 6 times, once for each axis facing down, in order for the library to calibrate the accelerometer. Only after the library calibrates the accelerometer will calling the getAccelBias functions return the estimated bias for each axis (and similar with the scale factor functions).

I see thanks it works but it still seem to be off by a bit. Shouldnt x and y be pretty close to 0 while z around 9,8. Mine shows accel in Y to be corrected to around 1 when stationary on a flat surface and x: 0 , z: 9,8 like it should be, do you have any idea why it would correct Y to 1 and not 0?
 
I see thanks it works but it still seem to be off by a bit. Shouldnt x and y be pretty close to 0 while z around 9,8. Mine shows accel in Y to be corrected to around 1 when stationary on a flat surface and x: 0 , z: 9,8 like it should be, do you have any idea why it would correct Y to 1 and not 0?

The only reason I can think of is if the MPU-9250 was not well aligned vertically during the +/-Y axis calibration. In other words, if you were holding the Y axis slightly off vertical during calibration.
 
The only reason I can think of is if the MPU-9250 was not well aligned vertically during the +/-Y axis calibration. In other words, if you were holding the Y axis slightly off vertical during calibration.

Ya makes sense I'll try to get a better reading when I have it mounted better. Another question do you know how to get the the yaw readings to 0 when initializing the sensor. Using the magnometer the yaw reads 0 at around true North. Is there a Quick way to get the yaw value to 0 when the sensor is first initialized.
 
Brian (or anyone else that could answer this) - sorry for this question but since I am new to AHRS I wanted to ensure I had the correct idea while working with the MPU9250.

So the MPU9250 seems to work OK, created a WPF Widows program to help the user view the results and calibrate the unit for each vector AX/AY/AZ etc - the MPU talks to Windows
via RawHID. In Windows, I want my 3D model to move in step with the gyroscopic motion of the MPU9250 - this I can do using either WPF's Transform functions for the GX/GY/GZ vectors
or via quaternions.

Here's my question: the gyro outputs I am seeing don't seem to be consistent to how I position the MPU9250 in space. I assumed if I tilted the MPU to one side or another the outputs for the gyro's
X/Y/Z vectors (GX/GY/GZ) should be consistent relative to the position in space. Is this correct? Now I have not done a calibration on this particular MPU, but I assumed the outputs should be roughly
consistent if I position the unit the same way.
 
Well I guess reading the InvenSense manual should have been my first approach - so the gyroscopic output is angular rate in rads/sec.
 
Hello, hoping someone can point me in the right direction here as I am a newbie to AHRS system. Just playing around with Brian's library which works well for Teensy 3.2 using SPI. My issue
deals mainly with the readings I get while moving the MPU9250 around in space. Below is a sample showing the readings AX/AY/AZ/GX/GY/GZ (magnetometer readings work as well but for brevity I left
them out of the debug). Some of my debug output is shown below:


============================================DEBUG====================================
Readings for AX is -5.143007 , AY is -4.874843 , AZ is 6.680163 GX is 11.352876 rads/sec, GY is -3.535188 rads/sec , GZ is -1.300443 rads/sec

Readings for Q1 is 1.000000 ,Q2 is 0.000032 ,Q3 is -0.000008 , Q4 is -0.000002

----------------------
Readings for AX is -5.913980 , AY is -4.395978 , AZ is 9.270822 GX is 4.746005 rads/sec, GY is -0.495943 rads/sec , GZ is -0.015714 rads/sec

Readings for Q1 is 1.000000 ,Q2 is 0.000010 ,Q3 is 0.000001 , Q4 is -0.000001

----------------------
Readings for AX is -5.775109 , AY is -0.258587 , AZ is -2.174046 GX is -0.490915 rads/sec, GY is 3.693806 rads/sec , GZ is -0.247945 rads/sec

Readings for Q1 is 1.000000 ,Q2 is -0.000002 ,Q3 is 0.000015 , Q4 is -0.000002

----------------------
Readings for AX is -3.112621 , AY is -1.666449 , AZ is -8.423231 GX is -6.820812 rads/sec, GY is 6.381509 rads/sec , GZ is -1.894869 rads/sec

Readings for Q1 is 1.000000 ,Q2 is -0.000022 ,Q3 is 0.000022 , Q4 is -0.000008

----------------------
Readings for AX is -3.184451 , AY is -4.932307 , AZ is -16.425060 GX is -11.939486 rads/sec, GY is 7.704588 rads/sec , GZ is -2.749224 rads/sec

Readings for Q1 is 1.000000 ,Q2 is -0.000032 ,Q3 is 0.000020 , Q4 is -0.000008

====================================END DEBUG====================================

My simplistic test code is shown below.

Code:
#include <SPI.h>
#include <WireKinetis.h> 
#include <Wire.h>
#include <MPU9250.h>

// MPU-9250 sensor on SPI bus 0 and chip select pin 10
const int MPU9250_INT_PIN = 20;
const int WAKE_ON_MOTION_PIN = 21;
const int TEENSY_SPI_CS_PIN = 10;

//EEPROM consts
const uint8_t ACCEL_BIAS_X = 0;
const uint8_t ACCEL_SCALE_X = 4;
const uint8_t ACCEL_BIAS_Y = 8;
const uint8_t ACCEL_SCALE_Y = 12;
const uint8_t ACCEL_BIAS_Z = 16;
const uint8_t ACCEL_SCALE_Z = 20;
const uint8_t MAG_BIAS_X = 24;
const uint8_t MAG_SCALE_X = 28;
const uint8_t MAG_BIAS_Y = 32;
const uint8_t MAG_SCALE_Y = 36;
const uint8_t MAG_BIAS_Z = 40;
const uint8_t MAG_SCALE_Z = 44;


float eInt[3] = { 0.0f, 0.0f, 0.0f };       // vector to hold integral error for Mahony method
#define Kp 2.0f * 5.0f						// These are the free parameters in the Mahony filter and fusion scheme, Kp for proportional feedback, Ki for integral
#define Ki 0.0f
float GyroMeasError = PI * (40.0f / 180.0f);   // gyroscope measurement error in rads/s (start at 40 deg/s)
float GyroMeasDrift = PI * (0.0f / 180.0f);   // gyroscope measurement drift in rad/s/s (start at 0.0 deg/s/s)
float beta = sqrt(3.0f / 4.0f) * GyroMeasError;   // compute beta
float zeta = sqrt(3.0f / 4.0f) * GyroMeasDrift;   // compute zeta, the other free parameter in the Madgwick scheme usually set to a small or zero value
char charBuff[200] = { 0 };

//Quaterion vector values
float quaternion[4] = { 1.0f, 0.0f, 0.0f, 0.0f };    // vector to hold quaternion
uint32_t lastUpdate = 0, firstUpdate = 0; // used to calculate integration interval
uint32_t Now = 0;        // used to calculate integration interval
float deltat = 0.0f, sum = 0.0f;			// Integration interval for both filter schemes

void waitOnError();

volatile float fVectorAX;
volatile float fVectorAY;
volatile float fVectorAZ;
volatile float fVectorGX;
volatile float fVectorGY;
volatile float fVectorGZ;
volatile float fVectorMX;
volatile float fVectorMY;
volatile float fVectorMZ;

//MPU - 9250 object on SPI bus 0
MPU9250 IMU(SPI, TEENSY_SPI_CS_PIN);
int status;
bool bRead = false;

bool testStatus(int Value);
void clearQuaternionBuffer();
void printYPR();
void MadgwickQuaternionUpdate(float ax, float ay, float az, float gx, float gy, float gz, float mx, float my, float mz, float deltat);

void setup() 
{
	pinMode(MPU9250_INT_PIN, INPUT);					
	delay(5000);

	Serial.println("IMU initialization starting...");

	status = IMU.begin();

	while (status < 0)
	{
		status = IMU.begin();	//ACCEL_RANGE_2G, GYRO_RANGE_250DPS);
		if (status < 0) 
		{
			delay(1000);
			Serial.println("IMU initialization unsuccessful, please wait...");
		}
	}

	Serial.println("IMU initialization Successful...");

	status = IMU.setDlpfBandwidth(MPU9250::DLPF_BANDWIDTH_5HZ);
	if (testStatus(status) == false)
	{
		Serial.println("setDlpfBandwidth FAILED");
		waitOnError();
	}
	
	status = IMU.setSrd(49);
	if (testStatus(status) == false)
	{
		Serial.println("setSrd FAILED");
		waitOnError();
	}

	
	status = IMU.setAccelRange(MPU9250::ACCEL_RANGE_16G);
	if (testStatus(status) == false)
	{
		Serial.println("setAccelRange FAILED");
		waitOnError();
	}

	status = IMU.setGyroRange(MPU9250::GYRO_RANGE_2000DPS);
	if (testStatus(status) == false)
	{
		Serial.println("setGyroRange FAILED");
		waitOnError();
	}

	attachInterrupt(MPU9250_INT_PIN, packReadings, RISING);
	
	status = IMU.enableDataReadyInterrupt();
	if (testStatus(status) == false)
	{
		//Do something to alarm the operators...
		Serial.println("enableDataReadyInterrupt FAILED");
		waitOnError();
	}
}
/*------------------------------------------------------------------
loop
------------------------------------------------------------------*/
void loop() 
{
	Now = micros();
	deltat = ((Now - lastUpdate) / 1000000.0f); // set integration time by time elapsed since last filter update
	lastUpdate = Now;
}


/*-----------------------------------------------------------
packReadings()
-------------------------------------------------------------*/
void packReadings()
{
	IMU.readSensor();
	fVectorAX = IMU.getAccelX_mss();
	fVectorAY = IMU.getAccelY_mss();
	fVectorAZ = IMU.getAccelZ_mss();
	fVectorGX = IMU.getGyroX_rads();
	fVectorGY = IMU.getGyroY_rads();
	fVectorGZ = IMU.getGyroZ_rads();
	fVectorMX = IMU.getMagX_uT();
	fVectorMY = IMU.getMagY_uT();
	fVectorMZ = IMU.getMagZ_uT();
	
	
	Serial.println("----------------------");
	//memset(charBuff, 0, sizeof(charBuff));
	sprintf(charBuff, "Readings for AX is %f\t, AY is %f\t, AZ is %f\t GX is %f rads/sec,\t GY is %f rads/sec\t, GZ is %f rads/sec\t\n", fVectorAX, fVectorAY, fVectorAZ, fVectorGX, fVectorGY, fVectorGZ);
	Serial.println(charBuff);
	

	clearQuaternionBuffer();
	MadgwickQuaternionUpdate(fVectorAX, fVectorAY, fVectorAZ, fVectorGX, fVectorGY, fVectorGZ, fVectorMX, fVectorMY, fVectorMZ, deltat);
	sprintf(charBuff, "Readings for Q1 is %f\t,Q2 is %f\t,Q3 is %f\t, Q4 is %f\n", quaternion[0], quaternion[1], quaternion[2], quaternion[3]);
	Serial.println(charBuff);

}

/*-----------------------------------------------------------------------------
clearQuaternionBuffer
-----------------------------------------------------------------------------*/
void clearQuaternionBuffer()
{
	quaternion[0] = 1.0f;
	quaternion[1] = 0.0f;
	quaternion[2] = 0.0f;
	quaternion[3] = 0.0f;
}

/*-------------------------------------------------------------
testStatus
-------------------------------------------------------------*/
bool testStatus(int value)
{
	if (value > 0)
		return true;
	else
		return false;
}

/*-------------------------------------------------------------
printYPR
-------------------------------------------------------------*/
void printYPR()
{
	
	float yaw = atan2(2.0f * (quaternion[1] * quaternion[2] + quaternion[0] * quaternion[3]), quaternion[0] * quaternion[0] + quaternion[1] * quaternion[1] - quaternion[2] * quaternion[2] - quaternion[3] * quaternion[3]);
	float pitch = -asin(2.0f*(quaternion[1] * quaternion[3] - quaternion[0] * quaternion[2]));
	float roll = atan2(2.0f*(quaternion[0] * quaternion[1] + quaternion[2] * quaternion[3]), quaternion[0] * quaternion[0] - quaternion[1] * quaternion[1] - quaternion[2] * quaternion[2] + quaternion[3] * quaternion[3]);
	pitch *= 180.0f / PI;
	yaw *= 180.0f / PI;
	yaw += 1.34; /* Declination at Potheri, Chennail ,India  Model Used:    IGRF12    Help
				 Latitude:    12.823640° N
				 Longitude:    80.043518° E
				 Date    Declination
				 2016-04-09    1.34° W  changing by  0.06° E per year (+ve for west )*/
	roll *= 180.0f / PI;
	Serial.print("Yaw, Pitch, Roll: ");
	Serial.print(yaw + 180, 2);
	Serial.print(", ");
	Serial.print(pitch, 2);
	Serial.print(", ");
	Serial.println(roll, 2);
}
	
void MadgwickQuaternionUpdate(float ax, float ay, float az, float gx, float gy, float gz, float mx, float my, float mz, float deltat)
{
	// short name local variable for readability
	float q1 = quaternion[0], q2 = quaternion[1], q3 = quaternion[2], q4 = quaternion[3];
	float norm;
	float hx, hy, _2bx, _2bz;
	float s1, s2, s3, s4;
	float qDot1, qDot2, qDot3, qDot4;

	// Auxiliary variables to avoid repeated arithmetic
	float _2q1mx;
	float _2q1my;
	float _2q1mz;
	float _2q2mx;
	float _4bx;
	float _4bz;
	float _2q1 = 2.0f * q1;
	float _2q2 = 2.0f * q2;
	float _2q3 = 2.0f * q3;
	float _2q4 = 2.0f * q4;
	float _2q1q3 = 2.0f * q1 * q3;
	float _2q3q4 = 2.0f * q3 * q4;
	float q1q1 = q1 * q1;
	float q1q2 = q1 * q2;
	float q1q3 = q1 * q3;
	float q1q4 = q1 * q4;
	float q2q2 = q2 * q2;
	float q2q3 = q2 * q3;
	float q2q4 = q2 * q4;
	float q3q3 = q3 * q3;
	float q3q4 = q3 * q4;
	float q4q4 = q4 * q4;

	// Normalise accelerometer measurement
	norm = sqrt(ax * ax + ay * ay + az * az);
	if (norm == 0.0f)
		return; // handle NaN
	norm = 1.0f / norm;
	ax *= norm;
	ay *= norm;
	az *= norm;

	// Normalise magnetometer measurement
	norm = sqrt(mx * mx + my * my + mz * mz);
	if (norm == 0.0f)
		return; // handle NaN
	norm = 1.0f / norm;
	mx *= norm;
	my *= norm;
	mz *= norm;

	// Reference direction of Earth's magnetic field
	_2q1mx = 2.0f * q1 * mx;
	_2q1my = 2.0f * q1 * my;
	_2q1mz = 2.0f * q1 * mz;
	_2q2mx = 2.0f * q2 * mx;
	hx = mx * q1q1 - _2q1my * q4 + _2q1mz * q3 + mx * q2q2 + _2q2 * my * q3 +
		_2q2 * mz * q4 - mx * q3q3 - mx * q4q4;
	hy = _2q1mx * q4 + my * q1q1 - _2q1mz * q2 + _2q2mx * q3 - my * q2q2 + my * q3q3 + _2q3 * mz * q4 - my * q4q4;
	_2bx = sqrt(hx * hx + hy * hy);
	_2bz = -_2q1mx * q3 + _2q1my * q2 + mz * q1q1 + _2q2mx * q4 - mz * q2q2 + _2q3 * my * q4 - mz * q3q3 + mz * q4q4;
	_4bx = 2.0f * _2bx;
	_4bz = 2.0f * _2bz;

	// Gradient decent algorithm corrective step
	s1 = -_2q3 * (2.0f * q2q4 - _2q1q3 - ax) + _2q2 * (2.0f * q1q2 + _2q3q4 - ay) - _2bz * q3 * (_2bx * (0.5f - q3q3 - q4q4) + _2bz * (q2q4 - q1q3) - mx) + (-_2bx * q4 + _2bz * q2) * (_2bx * (q2q3 - q1q4) + _2bz * (q1q2 + q3q4) - my) + _2bx * q3 * (_2bx * (q1q3 + q2q4) + _2bz * (0.5f - q2q2 - q3q3) - mz);
	s2 = _2q4 * (2.0f * q2q4 - _2q1q3 - ax) + _2q1 * (2.0f * q1q2 + _2q3q4 - ay) - 4.0f * q2 * (1.0f - 2.0f * q2q2 - 2.0f * q3q3 - az) + _2bz * q4 * (_2bx * (0.5f - q3q3 - q4q4) + _2bz * (q2q4 - q1q3) - mx) + (_2bx * q3 + _2bz * q1) * (_2bx * (q2q3 - q1q4) + _2bz * (q1q2 + q3q4) - my) + (_2bx * q4 - _4bz * q2) * (_2bx * (q1q3 + q2q4) + _2bz * (0.5f - q2q2 - q3q3) - mz);
	s3 = -_2q1 * (2.0f * q2q4 - _2q1q3 - ax) + _2q4 * (2.0f * q1q2 + _2q3q4 - ay) - 4.0f * q3 * (1.0f - 2.0f * q2q2 - 2.0f * q3q3 - az) + (-_4bx * q3 - _2bz * q1) * (_2bx * (0.5f - q3q3 - q4q4) + _2bz * (q2q4 - q1q3) - mx) + (_2bx * q2 + _2bz * q4) * (_2bx * (q2q3 - q1q4) + _2bz * (q1q2 + q3q4) - my) + (_2bx * q1 - _4bz * q3) * (_2bx * (q1q3 + q2q4) + _2bz * (0.5f - q2q2 - q3q3) - mz);
	s4 = _2q2 * (2.0f * q2q4 - _2q1q3 - ax) + _2q3 * (2.0f * q1q2 + _2q3q4 - ay) + (-_4bx * q4 + _2bz * q2) * (_2bx * (0.5f - q3q3 - q4q4) + _2bz * (q2q4 - q1q3) - mx) + (-_2bx * q1 + _2bz * q3) * (_2bx * (q2q3 - q1q4) + _2bz * (q1q2 + q3q4) - my) + _2bx * q2 * (_2bx * (q1q3 + q2q4) + _2bz * (0.5f - q2q2 - q3q3) - mz);
	norm = sqrt(s1 * s1 + s2 * s2 + s3 * s3 + s4 * s4);    // normalise step magnitude
	norm = 1.0f / norm;
	s1 *= norm;
	s2 *= norm;
	s3 *= norm;
	s4 *= norm;

	// Compute rate of change of quaternion
	qDot1 = 0.5f * (-q2 * gx - q3 * gy - q4 * gz) - beta * s1;
	qDot2 = 0.5f * (q1 * gx + q3 * gz - q4 * gy) - beta * s2;
	qDot3 = 0.5f * (q1 * gy - q2 * gz + q4 * gx) - beta * s3;
	qDot4 = 0.5f * (q1 * gz + q2 * gy - q3 * gx) - beta * s4;

	// Integrate to yield quaternion
	q1 += qDot1 * deltat;
	q2 += qDot2 * deltat;
	q3 += qDot3 * deltat;
	q4 += qDot4 * deltat;
	norm = sqrt(q1 * q1 + q2 * q2 + q3 * q3 + q4 * q4);    // normalise quaternion
	norm = 1.0f / norm;
	quaternion[0] = q1 * norm;
	quaternion[1] = q2 * norm;
	quaternion[2] = q3 * norm;
	quaternion[3] = q4 * norm;
}

void waitOnError()
{
	while (1)
	{
		Serial.println("--Error in setup!--");
		delay(2000);
	}
}

I've noticed that although the accelerometer/gyro/magnetometer readings vary as I move the MPU9250 around in space, the quaternion buffer outputs
(as shown near the top of this post) vary very little and in fact the quaternion[0] output sits at 1.000000. I know this is not expected behavior, but I don't
have enough practical experience in AHRS systems to know what to expect. Am I leaving off some processing that is required?
 
clearQuaternionBuffer();
MadgwickQuaternionUpdate(fVectorAX, fVectorAY, fVectorAZ, fVectorGX, fVectorGY, fVectorGZ, fVectorMX, fVectorMY, fVectorMZ, deltat);

I would say that you almost got it 100%. The filter is an iterative process for each loop and relies on the last values. To try and fix your problem remove the clearquaternionbuffer in your loop before you call the filter.
 
In the MadgwickQuaternionUpdate function, the last piece normalizes the resulting Quaternion.
Mathematically, a quaternion is w+xi + yj + zk where w is the real component.

quaternion[0] = q1 * norm;
quaternion[1] = q2 * norm;
quaternion[2] = q3 * norm;
quaternion[3] = q4 * norm;

So am I correct to assume quaternion[0] = x, quaternion[1] = y, quaternion[2] = z, and then quaternion[3] = w?

Sorry for the questions but just wanted to make sure.
 
If I remember right:
w = q0 = quaternion[0
x = q1 = quaternion[1]
y = q2 = quaternion[2]
z = q3 = quaternion[3]
 
Thanks mjs513, you've been very helpful.
That info means I can take each quaternion subsequent to the first one as a rotation quaternion for display purposes in WPF.
I needed to find out where the real component was and where the x/y/z imaginary vectors were. Bit of a learning curve for a newbie
to 3D graphics like myself. :cool:
 
FYI, it looks like the MPU-9250 IMU will have its last shipment from Invensense in February of 2019. This probably won't mean much in the short term - Digikey is currently reporting 60k units in stock and I'm sure breakout board sellers will have plenty in stock as well. Longer term, it looks like the ICM-20948 is the replacement for the MPU-9250. I'm not familiar yet with the differences between the ICM-20948 and MPU-9250.
 
Looks to have a little better sensitivity. I only found one breakout board company -- notwired.co (never heard of them) offering a board for $20US plus another $14US for shipping. More than I'm interesting in paying and I'm not in the mood to write a new software interface.
 
It also requires a new hardware interface as Vddio is limited. While the chip is happy running on up to 3.6V, the interface isn't.

For me this is a step down in capability. The maximum clock frequency for SPI is 7MHz instead of 20MHz. Which is fast enough since the maximum data rate from the gyros dropped from 32KSPS to 9KSPS.

But most people run at lower sample rates and will not be troubled too much by this.
 
It's very disappointing. I was sad to see that they're still using a separate, poorly matched magnetometer. I noticed the SPI speed drop, but not the VDDIO change. I'm not sure if I'll bother with the ICM-20948; I've been investigating other options, specifically I'm currently reading about the BNO085.

It's kind of sad to see that, as a whole, the industry used to have several high quality gyros, accels, and magnetometers for decent prices. Now it's moving toward more integrated units, while sacrificing data quality and providing fewer options. I understand the reasoning, smart phones are dominating the business, but it's still disappointing. Seems like a widening gap between the low cost components and the higher cost IMU's (i.e. $600 and up).
 
Morning Brian
Disappointed about the MPU-9250 and the ICM-20948. My favorite magnetometer was the HMC5883L but that kind of disappeared. Adafruit use to have a small break out board for the NXP sensors that are used on the PropShield and they are out of stock on it - not sure they are going to make it anymore. Like you said the industry focus shifted to cell phones and other wearables.

The one thing about the BNO055 is it update rates - think for the accel and gyro it maxes out at about 100hz and the mag at 20hz. This is off the top of my head. But you might want to check out some of the other Bosch motion sensors like the BMI160 accel/gyro and the BMM150 magnetometer. Was looking at them last night, then I remembered that the Arduino Curie had a BMI160 on the board. I forgot since I haven't touched it in over a year.

Mike
 
Morning Brian
Disappointed about the MPU-9250 and the ICM-20948. My favorite magnetometer was the HMC5883L but that kind of disappeared. Adafruit use to have a small break out board for the NXP sensors that are used on the PropShield and they are out of stock on it - not sure they are going to make it anymore. Like you said the industry focus shifted to cell phones and other wearables.

The one thing about the BNO055 is it update rates - think for the accel and gyro it maxes out at about 100hz and the mag at 20hz. This is off the top of my head. But you might want to check out some of the other Bosch motion sensors like the BMI160 accel/gyro and the BMM150 magnetometer. Was looking at them last night, then I remembered that the Arduino Curie had a BMI160 on the board. I forgot since I haven't touched it in over a year.

Mike

After reading the data sheet on the BNO085, I'm less enthusiastic about it. Seems like an interesting concept with data rates of 400 Hz and acting as a sensor hub (you communicate with the Cortex M0 onboard, which is communicating with and processing the individual sensors). It would be interesting as an application coprocessor that needed motion information, but less so from a hobbyist or flight control system standpoint where more control and insight would be better.

I remember the HMC5883 fondly.

I'm now reading up on the BMI088 gyro/accel and the BMM150 magnetometer.
 
Couldn't really find a breakout board for the BMI088 but did for the BMM150 and the BMI160. So I went ahead and ordered a couple to try out. Should get them in the next week or so. Will let you know.

As for the update rates I was talking about the sensor fusion rates for the accel/gyro and the magnetometer. It will also depend on the mode selected. The i2c bus can go up to 400hz. For my robotics projects I pretty much only use it for motion information. As you said: "less so from a hobbyist or flight control system standpoint where more control and insight would be better." Interesting that according to the datasheet that if you use it in non-fusion mode (which I never tried) the bandwidth for the individual sensors are quite a bit different (accel - 1000hz max (16max), gyro - 523hz(2000dps) max, mag - 30hz max).
If I am reading this wrong - please let me know.

Thanks
Mike
 
Back
Top