Calibration Best Practises

By rover_shie , 10 April 2014

I would be grateful if knowledgably folks could verify my understanding gleaned from the docs and MotionApps/Drive code.

I'm working on producing rock-solid calibration for our MPU-6050 based device. We will do this post-assembly but also offer it in our host app so end-user may perform it if necassary.

So;

All MPU6050's are factory calibrated. There are some 3rd party libs out the wild that enable read/write of these non-volatile values. I'm not sure why this is needed.

The sensor has a DMP-based gyro calibration mode. When enabled DMP will calculate gyro bias after 8 seconds of no motion and write these values into DMP memory (D_EXT_GYRO_BIAS_X/Y/Z). On startup, with the sesnsor not moving, the DMP outputs can take 15 seconds or so to stabilise (8 s of which is the 'no motion' window).

The new gyro bias values are volatile but can be queried and persisted by the host (e.g. in EEPROM) and then pushed to DMP on startup (dmp_set_gyro_bias). This would reduce the settling time (with DMP Gyro Calibration disabled).

Accelerometer calibration can also be performed by the client code and pushed to DMP (dmp_set_accel_bias). Again these can be calculated by the host (or queried via 'self test') and stored in EEPROM to be pushed to DMP on startup.

Accelerometer calibration would ideally be done in zero-g :) But since we're stuck on Earth we need to account for gravity. By placing the sensor flat we ensure only one axis (z) experiences g. So bias for z we have to subtract g in order to take it out of the equation. We DONT want the final Z bias value to bias out gravity.

The mpu_run_self_test function in inv_mpu.c runs the built in self-test routines and returns new bias values for gyro and accel based on raw gyro and accel data. If self-test has passed (which it should) then the new bias values can be scaled and pushed down to DMP (as described above).

In summary;

mpu_run_self_test provides fresh calibration bias values that the host can persist in EEPROM and push to DMP on startup.

There is no need to mess with factory bias values.

Cheers,

Rob J.

emmanuelsantiago

11 years 11 months ago

I'll add in my 2 cents as I am also in the process of identifying a 'rock-solid' calibration method for the MPU9150. I am not the most knowledgeable person on the subject but from what I know you are correct. Except for in the version of the MotionApps library I'm using there is the option to calibrate the gyro using 'fast-no-motion' in which new bias values are calculated each time a no motion event is detected. Alternatively you can set the time of no motion so you are not governed by a fixed 8 seconds.

Can I ask, have you/anyone figured out how the self-test can be run with the MPU turned upside down rather then right-side up (as it is my device)?

Mark

phpbb Post ID
24846

emmanuelsantiago

11 years 11 months ago

To answer my own question I think I found it. By adding a 2g offset to the z axis bias after the self-test is run this seems to do the trick. So...

result = gyro_run_self_test(gyro_bias, accel_bias);
accel_bias[2] += 2 * 65536;

@robjames66, have you tried to explore the other features of the motionapp library like temperature compensation? I'm in the process of trying to identify the exact breakdown of the bytes that are stored to the EEPROM. I think that the contents are listed in data_builder.c. I'm looking to store/read these bytes to/from an SDcard instead of the EEPROM.

Mark

phpbb Post ID
24849

rover_shie

11 years 11 months ago

Hi Mark,

Not looked into other features yet. I'm hoping DMP does temp compensation out the box. Will check out 'fast no motion'.

I'm suprised self test doesn work upside down - there's a bit of code in
inv_mpu.c get_st_bias that subtracts or adds g to remove it from the bias depending on the sign of the measured value.

Rob

phpbb Post ID
24852

emmanuelsantiago

11 years 11 months ago

If that facility is there it's not working properly for me. My fix was more of a work around rather then a solution. Thanks in either case, you've pointed me towards the line where the action happens in inv_gyro.c

/* Don't remove gravity! */
accel[2] -= 65536L;

I think if I changed that to a '+=' it would be the same as my previous comment (untested). Also I think we're using different version of the motion library as you mention inv_mpu.c rather then my inv_gyro.c.

Gyro compensation upon temperature change is performed automatically after inv_enable_gyro_tc() is initiated.

The inv_enable_fast_nomot() function turns on fast gyro calibration, it works quite well for me but have not tested over a long period of time.

Mark

phpbb Post ID
24855
phpbb Topic ID
16065