MPU 6050; strange effects in normal distribution of raw data

In order to obtain a better understanding of the MPU6050, I performed a simple test. The test results were more or less as expected, with the exception of 2 strange effects. I cannot explain these effects. Hopefully someone on this forum can. I also would appreciate it, if someone could reproduce my test and let me know whether or not the same effects are observed. Thanks in advance!

I connected a MPU6050 sensor to my Arduino UNO (ADO = high => address = 0X69 instead of 0X68) The Uno was next connected to my computer by means of an USB-cable. I loaded the sketch presented below and ran it. While the sketch was running, I did not touch the MPU6050 and made sure it was as best as possible isolated from movements, shocks and vibrations . After running the sketch, I selected all raw data which was printed in the serial monitor (ctrl a), copied it (ctrl c) and pasted it (ctrl v) in an empty MS/excel file. Next, I used the convert text to column option. I first considered column B, which contains raw acceleration output data related to the x-axis. I determined the maximum (276) en minimum value (-556) as well as the average value (23.05) of the 50000 raw output values. Next, I used the countif function in excel to determine how many times every possible output value (= 16 bit integer) in the range [-556, 276] had occurred. I presented this data graphically in an x-y scatter plot. Raw output data related to ay, az, gx, gy and gz was subsequently considered in an analogue manner.

The plot related to gx (see attached jpg-image) clearly shows the ‘bell-curve’ I expected. In the plot related to ax, you can still recognise the expected ‘bell curve’, but there are also 2 strange effects:
1- Only raw output values in the min-max range which are a multiple of 4 have a non-zero number count. For example raw output values 103,105,106,107 were never found in the 50000 samples; raw values 104 and 108 were found 423 and 504 times respectively. It appears that the last 2 bits of the 16-bit output value are always low (?)
2- There are some raw values that occur significantly more than expected, yielding clear peaks in the ‘bell curve’ e.g. raw values 16, 20,24 occur 1298, 1772 and 1343 times respectively.

Some additional results / remarks:
1- Distribution of ay and az is similar to that of ax; distribution of gy and gz is similar to that of gx
2- Changing the sensor sensitivity to +/- 8g (accelgyrooo.setFullScaleAccelRange(2)) or +/-16g ‘solved’ the problem: no significant peaks and no ‘value skipping’
3- I performed the test several times: always same results
4- I performed a similar test in which the raw data was written to a SD card and the Arduino was powered by a 9v battery: same results

// raw data MPU6050

#include "Wire.h"
#include "I2Cdev.h"
#include "MPU6050.h"

MPU6050 accelgyrooo (0X69);

int16_t ax, ay, az;
int16_t gx, gy, gz;
long i =0;

void setup() {
   Serial.println("Initializing I2C devices...");
   Serial.println("Testing device connections...");
   Serial.println(accelgyrooo.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed");
   accelgyrooo.setFullScaleAccelRange(0); // 0=> +-250deg/s ; 1=> +-500deg/s ; 2=> +-1000deg/s ; 3=> 2000deg/s
   accelgyrooo.setFullScaleGyroRange(0);  // 0=> +-2g ; 1=> +-4g ; 2=> +-8g ; 3=> +-16g

while (i<500) {
  i++ ;

  accelgyrooo.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
  Serial.print(i); Serial.print(" ; ");
  Serial.print(ax);  Serial.print(" ; ");
  Serial.print(ay);  Serial.print(" ; ");
  Serial.print(az);  Serial.print(" ; "); 
  Serial.print(gx);  Serial.print(" ; ");
  Serial.print(gy);  Serial.print(" ; ");
  Serial.print(gz);  Serial.print(" ; ");


void loop() {




Very nice plots, thank you. It shows what I was thinking for some time.

The gyro plot is beautiful.

The acceleration is 16 bits, but the sensor cheats a little. It is not the full 16 bits. That is normal. This "cheating" is less obvious with a lower sensitivity. I have noticed the peaks for certain values myself. I have no explanation for that. Perhaps it is partly due to missing lower bits and partly because noise would make some bits in the ADC to set to certain values.

You wrote that the sensor is isolated from movement, shocks and vibration. Well, don't count on it. I tried to place the sensor on something soft, but that didn't work. I tried a hard surface away from my computer, that did work. For example the vibration of a very silent computer fan can already have influence on the sensor.

If you look at datasheets for ADCs, the manufacturers usually go to quite a bit of trouble to verify that there are no missing steps and that the overall conversion is linear. Your nice data suggest that this is not the case for that particular MEMS sensor, but does it really matter? MEMS sensors are noisy and invariably, quite a bit of effort has to be expended to process the data into a usable form.

You cannot assume that a sensor is accurate to an LSB. You can only assume what is in the spec. For instance, on the most sensitive scale for the gyro the spec gives 131 LSBs per degree per sec. This translates to 7.63 milli degrees per second per LSB. [u]This does not mean that the gyro readings are accurate to within 7.63 mdps[/u]. You never really know how many of the lowest bits carry no useful information. Still, do not make the mistake of dropping the lower bits because you suspect that they are inaccurate. If you are not absolutely sure they are inaccurate you run the risk of adding quantization noise by dropping the bits.

Update : I mailed the manufacturer of the MPU-6050 (Invensense), hoping that they could clarify the strange effects I found. No answer yet. If I receive an answer from Invensense, I’ll post it here.

I did some additional testing and found out that bit 0 and bit 1 of the raw accelerometer output is always low in case the sensitivity is set to +/- 2g. In case it is set to +/- 4g, only bit 0 is always low. In case the sensitivity is set to +/-8 g or +/- 16g all of the 16 bits of the raw data have a low or a high value. Hence, in case of the +/- 2g setting only 14 bits are effectively used to represent the raw output value, which translates to a sensitivity of 2^14 / (+2 - -2) = 4096 LSB/g . The product spec (rev. 3.4) wrongly (?) specifies a sensitivity of 2^16 / (+2 - -2) = 16384 LSB /g.

Taking into account the effect of noise on the raw output signal, it is probably more than sufficient to have a sensitivity of 4096 LSB/g. I now think the sensor was designed ‘on purpose’ with a maximum sensitivity of 4096 LSB. The strange peaks are still a mystery to me, although Caltoa’s suggestion sounds very plausible to me.

I've searched through the datasheet pdf for "lsb" and haven't find any spec on linearity or missing codes. The only indication relevant to that issue is something like "Gyroscope ADC Word Length", the same for Accelerometer.. :)