How to Interpret MPU9250 Register Map and Self-Test Documentation

I need help understanding the information given in the table on page 13 of MPU9250 Register Map regarding the Gyroscope Bandwidth, Delay and Fs which are further reference in MPU9250 Self-Test Procedure on page 5.

The confusion is this, the chart specifies the results of setting the DLPF mode to 2 resulting in a 92Hz bandwidth with Fs of 1kHz, e.g.

The self-test documentation then specifies that 200 samples should be read at an output rate of 1kHz, e.g.

Then under 2) in the self-test documentation, I am supposed to "Read the gyroscope and accelerometer output at a 1kHz rate and average 200 readings."

The problem is I cannot physically read 200 samples of the 12 registers (6 unsigned short values with each reg holding a high or low byte) at 1000 samples per-second (all in 1/5th second). The MPS432 at 24MHz simply can't poll the MPU at 1000kHz and do the floating point calculations on each axis at that rate. (there are actually 14 registers that are read due to the High/Low byte of the Temp sensor being situated between the gyro and accel registers)

Now, I see a second interpretation of the self-test requirement to "Read the ... output at a 1kHz rate ..." that can be taken to mean "configure the DLPF as specified so the Fs rate is 1kHz (as shown in the chart) -- and then read 200 samples" at whatever actual polling rate your hardware will support.

The issue being, I can read the MPU reliably at 100Hz. I can get the raw data from all 12(14) registers and compute the actual values from the raw register values 100 times per-second. If I push the MSP timer CCR controlling the read to 120 or 140 Hz, eventually the processing stops as the interrupt is triggered faster than the data can be processed.

So is it valid to set the MPU9250 as specified in the self-test, but then interpret the "Read the ... output at a 1kHz rate ..." to mean, read the data from the registers with the output configured to 1kHz -- even if you can't read and process all registers at the configured rate?

I can probably tweak the MSP432 to get a slightly higher read rate, but if this second interpretation is valid, then I'm more than happy to have a 2-sec self-test and can avoid re-arranging code, etc.....

ST_OTP Self-Test Criteria Type Ambiguous

I have one other area of the documentation I am unclear on. It has to do with calculating the criteria used to determine self-test pass/fail based on an 8-bit value read from a register in the MPU9250. You read the ST_Code value and compute ST_OTP as shown below:

(note: you don't need to calculate ST_Code above, your read it directly, they are just showing how the value you read was arrived at.)

Where I am unclear is whether the calculation for ST_OTP is cast to an integer value before the lower 8-bits are used, or whether the lower 8-bits of the floating point value are used (that wouldn't make much sense -- but the procedure is silent on the issue).

The equation shown in 2) above results in a floating-point value. However, at the end of the calculation there is (lsb) and the note beneath says: "ST_OTP is then the value that is stored in OTP of the device."

Does (lsb) have some significance I am missing like an implied cast to an integer value and then saving the low-byte of the resulting integer value? After the calculation (done as float on the MSP432), I would normally be inclined to do:

ST_OTP = (int32_t)ST_OTP_RAW & 0xff;


That would give me the low-byte of the integer portion of the result. Which would make sense in the remaining pass/fail calculations where the ST_OTP values are used as the denominator. I can't see any way it would make sense to use 8-bits grabbed from the mantissa of the original floating-point result.

So is the cast to integer implied before the low-byte is saved?

What value of FS Is Used Calculating ST_OTP?

I am also unclear on what value for FS is used -- but that has to be the FS_SEL setting value 0, not the actual Full Scale value of 250 deg/sec -- that would result in a value of 1.8e+75 well exceeding the range for 32-bit float and leave the result of ST_OTP calculation as 0 for all practical purposes in every case -- leaving one-half of the pass/fail critera unused.

If I'm just missing which value for FS to use in the ST_OTP calculation, I'd appreciate help there too if the value is apparent from some other context.

• I will address just one point here. The MPS432 at 24MHz simply can't poll the MPU at 1000kHz and do the floating point calculations on each axis at that rate. There is no requirement to do the calculations at the time of getting the samples - it could just as effectively be done after reading 200 samples. Aug 16 '21 at 12:04
• Thank you Peter. I suspected that was the case. It's the configuration of the MPU9250 "to be read at" the 1KHz rate that seems to be the salient part. The others are a bit more vexing. 1) what is the (lsb) of the floating-point ST_OTP calculation? Cast to integer or do they really just want the first 8-bits of the mantissa? 2) What FS value do they want as the power-of-two in that calculation. Since the actual FS value is 250, I can't see it being the actual value. The setting value of 0 makes more sense, but the documentation is ambiguous on that point. Aug 16 '21 at 18:59

When All Else Fails -- Apply The Common Meaning / Common Sense Test

The ST_OTP Calculation Uses Lower 8-bits of Integer Part

Through a bit of experimentation on taking the lower 8-bits of the literal ST_OTP calculation, and then doing what would be normal and take taking the lower 8-bits of the integer part of the floating-point result, I can confirm that the common sense lower 8-bits of the integer part is what is intended.

The FS Value Used Is The Setting Value

Similarly, as to what FS is used in the ST_OTP calculation, it too must be the Full Scale Setting Value (e.g. 0, 1, 2, ... 7) which per the test procedure would be 0 in all cases. The Full Scale Value for the gyro is 250 deg/sec which would result in the 2 ^ FS component being 1.8e+75 and resulting in the overall calculation being on the order of 1.e-72 resulting in all gyro tests failing.

(now you could argue that would leave the value for ST_OTP as 0 for all tests invoking the else prong of the test where the magnitude of the difference of the average gyro readings is used, but that is just one more plausible calculation based on the state of the documentation)

Results Of Self-Test From Two MPU9250 Chips

The backstory to why this was important to figure out is that the manufacture has had a bad run on the MPU9250 chips. I have two that suffer. The first measures gravity on earth as 0.6g and the gyro is simply dead. On the second, gravity is measured as 0.81, and the X-axis and Y-axis gyros appear to respond fine. So I needed to run the self test and satisfy myself that the problem lay with the chips and not my code.

(I had already used a canned RaspberryPi python script to graph the axis-response so I had a good idea what was going on -- and after sending the Pi code and results to the manufacturer, the manufacturer had already refunded the cost of both chips -- and no, the folks I dealt with via e-mail could not answer this question either)

After using the lower 8-bits of the integer part and using the FS setting value the result of the self-test on the chip measuring gravity as 0.81g and showing gyro response on two axis was:

Starting Self-Test ... Done

MPU9250 Self-Test: FAILED

Average of 200 Samples:
GxST = GxST_OS -  Gx_OS
173 =    221 -     48
225 =    228 -      3
4 =     11 -      7
-10 =    106 -    116
-35 =     22 -     57
1 =    255 -    254

Factory Self-Test Values (ST_Code):
198,    215,    219
94,     95,    120

ST_OTP Values:
172,     17,    143
209,     19,    113

GxOFFSET Values:
0,      0,      0

Self-Test Axis Results:
gyro-x  : PASSED
gyro-y  : PASSED
gyro-z  : FAILED

accel-x : FAILED
accel-y : FAILED
accel-z : FAILED


(values are shown gyro axis x, y, z values first, followed by the accelerometer values where numbers are listed above)

That confirmed from a self-test standpoint what I was seeing as output on each axis.

Then for the other MPU9250 what was borked to begin with showing 0.6g acceleration and gyro values effectively dead, the results were:

Starting Self-Test ... Done

MPU9250 Self-Test: FAILED

Average of 200 Samples:
GxST = GxST_OS -  Gx_OS
-64 =      0 -     64
-88 =      0 -     88
-110 =      0 -    110
-20 =      0 -     20
-4 =    140 -    144
-13 =      0 -     13

Factory Self-Test Values (ST_Code):
193,    206,    224
102,     92,    127

ST_OTP Values:
37,    177,     33
245,     79,    218

GxOFFSET Values:
0,      0,      0

Self-Test Axis Results:
gyro-x  : FAILED
gyro-y  : FAILED
gyro-z  : FAILED

accel-x : FAILED
accel-y : FAILED
accel-z : FAILED


So based on working through the different plausible ways to calculate the self-test, and ultimately using the lower 8-bits of the integer part of ST_OTP and using the FS setting value of 0 and having the self-test results correlate to what was expected, I have a good degree of confidence that is the correct way to read the MPU9250 self-test document.

Hopefully this will help move the ball forward for someone else if they find themselves in the same situation.