Finding out the offsets
First of all we need to work out the offset errors and remove them from our data. Offsets are caused by a number of factors such as mechanical assembly, mounting, package damage and temperature fluctuations. So we need to work out what the offsets of our chip are and then remove them before processing the data.I am getting all of my methods and theory from this application note from Freescale.
So what we need to do is to place the sensor level on a table (use a spirit level or something to make sure it is actually level), then we need to:
- Measure the average acceleration/angle in the X, Y and Z axis over 10-20 samples
- These values should be 0G in the X and Y axis and will be 1G in the Z axis
- Anything over 0G in the X and Y and 1G in Z will be our offsets
So after keeping the device level and leaving a large (0.5 second) delay in between each sample (to let temperature stabilise) my average values are as shown below.
Don't worry if yours were different we are going to incorporate the calibration into our future code so that the device can auto zero regularly.
So from now on when we measure we will need to remove those offsets from our values before we process them.
The offset testing program is available on my Github under "CalibrateOffsets"
Test finished, offset values are shown below
AXoff:435, AYoff:-352, AZoff:15236 || GXoff:74, GYoff:131, GZoff:-126,
Don't worry if yours were different we are going to incorporate the calibration into our future code so that the device can auto zero regularly.
So from now on when we measure we will need to remove those offsets from our values before we process them.
The offset testing program is available on my Github under "CalibrateOffsets"
Getting some G's
Now we know what our offsets are but we don't know what they mean in the form of angles and G's so lets do some scaling and conversion to get the real values.Understanding the scaling
As Jeff Rowberg said in his own i2cdevlib forums
"The accelerometer and gyroscope measurements are explained in the MPU-6050 datasheet in the GYRO_CONFIG and ACCEL_CONFIG register descriptions (sections 4.4 and 4.5 on pages 14 and 15). The scale of each depends on the sensitivity settings chosen, which can be one of +/- 2, 4, 8, or 16g for the accelerometer and one of +/- 250, 500, 1000, or 2000 deg/sec for the gyroscope. The accelerometer produces data in units of acceleration (distance over time2), and the gyroscope produces data in units of rotational velocity (rotation distance over time). The output scale for any setting is [-32768, +32767] for each of the six axes. The default setting in the I2Cdevlib class is +/- 2g for the accel and +/- 250 deg/sec for the gyro. If the device is perfectly level and not moving, then:So first of all we need to know the sensitivity of our sensor. The default is +/-2G and +/-250deg/sec but where do we confirm we are running the default settings and how do we change the values.
- X/Y accel axes should read 0
- Z accel axis should read 1g, which is +16384 at a sensitivity of 2g
In reality, the accel axes won't read exactly 0 since it is difficult to be perfectly level and there is some noise/error, and the gyros will also not read exactly 0 for the same reason (noise/error)."
- X/Y/Z gyro axes should read 0
If you look in mpu6050.c at line 66 you will find the function
Here you can see that we are running at the default selection of 2G for the accelerometer and 250 for the gyro, If you look at the defines in mpu6050.h you can change these to whatever you want.
So we know we are running at a sensitivity of +/-2G and +/- 250deg/s but how do our values correspond to those accelerations/angles.
These are both straight line graphs and we can work out from them that for 1G we will read 16384 and for 1degree/sec we will read 131.07 (Although the .07 will get ignore due to binary) these values were just worked out by drawing the straight line graph with 2G at 32767 and -2G at -32768 and 250/-250 at the same values.
So now we know our sensitivity values (16384 and 131.07) we just need to minus the offsets from our values and then devide by the sensitivity as it explains in the freescale application note.
These will work fine for the X and Y values but as the Z was recorded at 1G and not 0 we will need to minus off 1G (16384) before we divide by our sensitivity. This is explained in the freescale note.
I have written a project which calculates the values in G's and angles and it can be found on my GitHub under "GetG's"
Thank u very much. it helped me
ReplyDeleteThank you for your article. But I have a problem on my MPU9255 (InvenSense said this chip is completely the same as MPU6050 in acceleration and gyroscope).
ReplyDeleteWell, following your calibration steps, my raw Gyro X always output value 65xxx. Do you know why ?
Below is my program's output.
Rxx is the output value from registers, ex: RGX, RAY
(AX, AY, AZ) = (RAX, RAY, RAZ) / 16384
(GX, GY, GZ) = (RGX, RGY, RGZ) / 131.0
Temperature: 29.60 C
Pressure : 1003.65 hPa
Altitude : 00.17 m
CPU Temperature : 53.7
CPU Core Voltage : 1.2625
Who Am I=115
getAccelCfgFsSel=0, sensitivity=16384
getGyroCfgFsSel=0, sensitivity=131.0
RGX RGY RGZ , GX GY GZ | RAX RAY RAZ , AX AY AZ
65469 105 6 , 499.763 0.802 0.046 | 616 1296 17688 , 0.038 0.079 1.080
65497 99 41 , 499.977 0.756 0.313 | 632 1304 17620 , 0.039 0.080 1.075
65481 102 62 , 499.855 0.779 0.473 | 652 1356 17464 , 0.040 0.083 1.066
65512 73 30 , 500.092 0.557 0.229 | 604 1328 17560 , 0.037 0.081 1.072
65521 87 32 , 500.160 0.664 0.244 | 588 1236 17636 , 0.036 0.075 1.076
65471 101 52 , 499.779 0.771 0.397 | 596 1308 17576 , 0.036 0.080 1.073
65516 89 59 , 500.122 0.679 0.450 | 564 1212 17488 , 0.034 0.074 1.067
65479 91 74 , 499.840 0.695 0.565 | 616 1252 17524 , 0.038 0.076 1.070
65533 85 64 , 500.252 0.649 0.489 | 600 1276 17528 , 0.037 0.078 1.070
65479 52 67 , 499.840 0.397 0.511 | 664 1324 17480 , 0.041 0.081 1.075
Thanks you very much,it is useful.
ReplyDeleteThanks! This was super helpful.
ReplyDeleteVery helpful. Thank You.
ReplyDelete