DMP gyro packet has much lower resolution than raw gyro values
The DMP gyro packet (from MPU6050::dmpGetGyro() for a VectorInt16 input) has around 23x lower resolution than raw gyro values (from MPU6050::getRotation()). Both are run with the same setup, the setup in the MPU6050_DMP6 example. This means that both have gyro full range set to ±2000º/s.
Here is a gist to reproduce this issue. It has the .ino scrpit, almost entirely untouched from the MPU6050_DMP6 except for what's printed in loop(), and a sample output showing the 23x discrepancy.
Is this expected? If so, what units are the values for the gyro packet coming out of the DMP? It doesn't look like º/s, and is coarser than all the gyro sensitivity options. Is there a way to get better resolution from DMP, or should we ignore the DMP gyro entirely and just get values out raw?
@acrylic-origami The proprietary pre-compiled DMP instance that is installed provides limited configuration. The DMP samples at 200Hz. Alternatively, you can pound the gyro and accelerometer directly and get values that change. I needed an additional 1ms delay to allow the Calibration routine to properly get updated values. Both are 16-bit integers. The DMP filters the readings out over time and provides a packet every 10 ms (100Hz). Does this help answer your question? Z
Hi @ZHomeSlice , I'm not as concerned about the time resolution (i.e the sampling rate as you mention) but rather the value resolution, i.e. the DMP gyro is scaled to be 23x smaller than raw values. I just wanted to know if this is expected and is just a quirk of the pre-compiled DMP code. The gyro resolution are even worse than 1º/sec/LSB which is too coarse for my use, but it would be nice to get filtered values from the DMP at full resolution (i.e. 16.3LSB/(º/sec) if possible).
I'm not sure what you're meaning. can you explain how you came up with this? I use the DMP for all my balancing bot creations so I'm not sure where the resolution difference is coming from. Z
@ZHomeSlice The gist I linked shows the outputs of mpu.dmpGetGyro() side by side with mpu.getRotation(), and they're different by a factor of 23 on average. For example, in the first line, you see the "Raw gyro" value from getRotation() is -340, while the DMP gyro value from mpu.dmpGetGyro() is -16.
The code is also there (you have to scroll a bit to get to it), and that code is just the DMP example in i2cdevlib with the mpu.getRotation() call added.
I'm glad to hear that we might be able to use DMP, would you mind verifying these outputs? Do you know what chip you have exactly? I have an MPU6050 04F974L81 EL 1532 E.
@acrylic-origami Try this for me Replace your loop with this one.
void loop() {
static unsigned long SpamTimer;
if (mpu.dmpGetCurrentFIFOPacket(fifoBuffer)) { // Get the Latest packet
int16_t gx, gy, gz;
int16_t x, y, z;
mpu.dmpGetGyro(&dmp_gyro, fifoBuffer);
mpu.getRotation(&gx, &gy, &gz);
x = (fifoBuffer[22] << 8) | fifoBuffer[23];
y = (fifoBuffer[24] << 8) | fifoBuffer[25];
z = (fifoBuffer[26] << 8) | fifoBuffer[27];
if ((millis() - SpamTimer) >= (50)) {
SpamTimer = millis();
Serial.print(gy); Serial.print("\t");
Serial.print(y); Serial.print("\t");
Serial.println(dmp_gyro.y);
}
}
}
I may have more... Thank you Z
@ZHomeSlice Those offsets don't match the FIFO buffer offsets documented in MPU6050_6Axis_MotionApps20.cpp:
/* ================================================================================================ *
| Default MotionApps v2.0 42-byte FIFO packet structure: |
| |
| [QUAT W][ ][QUAT X][ ][QUAT Y][ ][QUAT Z][ ][GYRO X][ ][GYRO Y][ ] |
| 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
| |
| [GYRO Z][ ][ACC X ][ ][ACC Y ][ ][ACC Z ][ ][ ] |
| 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
* ================================================================================================ */
so I think I'm reading Z when I use your code. When I readjust it to the offsets shown above, I get the same results as dmpGetGyro. Are you seeing different? Are your dmpGetGyro of similar magnitude to getRotation?
@acrylic-origami you shouldn't need to adjust the code. Please show me the adjusted code that gives you the same readings. This could be the clue that I need to fix your problem.
Version v2.0 has a 42-byte FIFO packet. I've stripped the V6.12 down removing the extra garbage to shrink the packet size. Now it only needs 28-bytes.
Here is how the InvenSense example code is written to allow for inserted features. This is simplified also. I've activated only 3 things so I removed the other features to help simplify how it shifts the pointer allowing for the FIFO packet to be different sizes.
uint8_t ii = 0;
quat[0] = ((int32_t)fifo_data[0] << 24) | ((int32_t)fifo_data[1] << 16) | ((int32_t)fifo_data[2] << 8) | fifo_data[3];
quat[1] = ((int32_t)fifo_data[4] << 24) | ((int32_t)fifo_data[5] << 16) | ((int32_t)fifo_data[6] << 8) | fifo_data[7];
quat[2] = ((int32_t)fifo_data[8] << 24) | ((int32_t)fifo_data[9] << 16) | ((int32_t)fifo_data[10] << 8) | fifo_data[11];
quat[3] = ((int32_t)fifo_data[12] << 24) | ((int32_t)fifo_data[13] << 16) | ((int32_t)fifo_data[14] << 8) | fifo_data[15];
ii += 16; // obviously 16
if (feature is activated false){
another feature is added here
ii += 8; // this would shift the buffer position ready for the next added feature
}
if (Accel feature activated true){
accel[0] = ((int16_t)fifo_data[ii + 0] << 8) | fifo_data[ii + 1];
accel[1] = ((int16_t)fifo_data[ii + 2] << 8) | fifo_data[ii + 3];
accel[2] = ((int16_t)fifo_data[ii + 4] << 8) | fifo_data[ii + 5];
ii += 6; // 22
}
if (feature is activated false){
another feature is added here
ii += 8; // this would shift the buffer position ready for the next added feature
}
// because of the features that are active the pointer for the fifo buffer is now at 22 ready to get the gyro values
if (Gyro feature is activated true){
gyro[0] = ((int16_t)fifo_data[ii + 0] << 8) | fifo_data[ii + 1];
gyro[1] = ((int16_t)fifo_data[ii + 2] << 8) | fifo_data[ii + 3];
gyro[2] = ((int16_t)fifo_data[ii + 4] << 8) | fifo_data[ii + 5];
}
if (feature is activated false){
another feature is added here
ii += 8; // this would shift the buffer position ready for the next added feature
}
V6.12 uses this FIFO packet structure because other features were not needed or likely used so they were disabled speeding up the FIFO packet retrieval.
/* ================================================================ *
| Default MotionApps v6.12 28-byte FIFO packet structure: |
| |
| [QUAT W][ ][QUAT X][ ][QUAT Y][ ][QUAT Z][ ] |
| 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
| |
| [ACC X][ACC Y][ACC Z][GYRO X ][GYRO Y ][GYRO Z ] |
| 16 17 18 19 20 21 22 23 24 25 26 27 |
* ================================================================ */
z
@ZHomeSlice Ah V6.12 is working properly! So this is an issue with V2.0 only. Thanks for bringing my attention to this version. This seems like a substantial change, perhaps this wants to be documented somewhere ~~or have the examples updated to use 6.12?~~ *edit: I just noticed the dedicated DMP example with V6.12, I suppose which one is authoritative is dependent on the actual differences between the two versions. I'll test it some but I think this will work for me. Just don't want others to run into the same issue.
Is there some documentation about the differences between V2 and V6.12?
v2.0 -->is Smaller in size... Only Advantage. V6.12
- Fixes Bugs.
- Gyro has an auto-calibration above and beyond my PID calibration.
- Has documentation available
- FIFO packet is almost 1/2 the size of V2
- If you are more skilled than I, you could integrate the other proprietory MPL pre-compiled library into your microcontroller code and get 9-Degrees of freedom with the magnetometer integration. "The Motion Driver 6.12 contains a binary library which contains InvenSense proprietary algorithms for sensor fusion and dynamic calibration. The MD 6.12 driver pushes the sensor data into the MPL and the MPL will handle the 9-axis sensor fusion including the compass integration." -->Motion Driver 6.12 – Features User Guide
Some Disabled features:
- Orientation Gesture Recognition
- Tap Gesture Recognition
- Pedometer Gesture Recognition
To get all the details and the MPL binary (Please let me know if you figure out how to get this MPL library working) https://invensense.tdk.com/developers/ you will need to login Once there look for eMD 6.12 you will also want to download the eMD 5.1.3 as there is additional documentation that is helpful
Z
@ZHomeSlice Thank you for linking me, these are just the feature descriptions that I'm looking for! If I do end up getting a 9-axis IMU I would be interested in looking at that integration. As for this limitation of 2.0, are there others that are known that affect the data this concretely? Or about 6.12 for that matter? I'm happy to have documentation to read for 6.12, I'm curious if you've found anything in particular. This change by the versions is just a bit surprising, so I am just guarded.
I am still not sure if it's reproduceable either, it just seems like a dangerous pitfall from the examples. Maybe being the first to report this going from the 2.0 example to using the DMP gyro packet speaks otherwise.
@acrylic-origami The Story goes :) I was developing a balancing bot (https://youtu.be/IKUlWqQC5w4) and needed a gyro/accelerometer to control it. I got one of the MPU6050's and started to try to figure it out. I initially used the V2.0 and got it to work but the documentation was non-existent. I got access to the developer side of Invensense and found only 6.12 available at this point in time 5.xx is now also available and V5.xx has documentation that is useful. I realized that they have example code that is compatible with the arduino UNO and after a bit of discovery I was able to get it to compile and run. So why don't we use that version... It is a mess, difficult to follow! and it is huge. It took up most of the UNO's memory to get it to work. So I decided to use an optimized version of it to use with my UNO. Once it was working correctly, I would create a stopping point where I would dump all the settings of the MPU and compare it to the default dump of memory. this gave me an idea as to what was modified. I also did this with the eEMP firmware as it is heavily tweaked before it workes as desired. once all the mods were made but before it was started I would grab this instance of the firmware and store it. Note that in Jeff's library MPU6050, both V2.0 and V6.12 have been captured this way. This shrank the MPU6050 library substantially. Now I didn't practice on Jeff's Version of the MPU6050 Library. I have my own version which uses Jeff's i2cdev library but is completely designed from the bottom up. My Library Simple_MPU6050 is only a V6.12 library and has some sweet additional features as well as compass access. Simple_MPU6050 Since they are similar in the setup you will find several of my code creations are in both libraries. both Jeffs and my version of the V6.12 firmware is as near to bug-free as I can make it. V2.0 is truly unknown and I am not planning on improving it. If you have the room in your processor switch to V6.12 you will like it. Z