libdriver / mpu6050

MPU6050 full function driver library for general MCU and Linux.
https://www.libdriver.com
MIT License
372 stars 154 forks source link

DMP_FEATURE_SEND_RAW_GYRO is not catered for in dmp_read #13

Open btsimonh opened 1 year ago

btsimonh commented 1 year ago

Version

latest?

Describe the bug

ok, odd one, because I reporting this based on a javascript port that I am doing. So please test to see if you can reproduce.

If you set DMP_FEATURE_SEND_RAW_GYRO without DMP_FEATURE_SEND_CAL_GYRO, the dmp sends 8 + 6 bytes rather than 6 bytes of gyro data. Then dmp_read has a incorrect packet length and data postions.

e.g. data out for

        MPU6050.DMP_FEATURE_TAP | MPU6050.DMP_FEATURE_PEDOMETER | MPU6050.DMP_FEATURE_ORIENT |
        MPU6050.DMP_FEATURE_SEND_RAW_GYRO | MPU6050.DMP_FEATURE_GYRO_CAL

is 20 00 00 00 12 ec ef 17 + ff af 00 0d ff d6 + 00 00 00 02

If you add DMP_FEATURE_SEND_CAL_GYRO, then it reverts to 6 bytes only ff af 00 0d ff d6 + 00 00 00 02.

Suggest:

    if ((this.mask & MPU6050.DMP_FEATURE_SEND_ANY_GYRO) != 0)                                                          /* check the gyro */ {
        if ((this.mask & MPU6050.DMP_FEATURE_SEND_RAW_GYRO && !(this.mask & MPU6050.DMP_FEATURE_SEND_CAL_GYRO)))                                                          /* check the gyro */ {
            len += 8;                                                                                                         /* size += 8 */
        }
        len += 6;                                                                                                         /* size += 6 */
    }

and reading the 8 bytes first.

I do not know the nature of the 8 bytes..... and I do not know if this is an issue in the C driver.

Reproduce

run the dmp example, and ask for DMP_FEATURE_SEND_RAW_GYRO without DMP_FEATURE_SEND_CAL_GYRO. Data output may be incorrect. (check fifo size is a multiple of expected packet size, if not then there is an issue).

Expected behavior

calculated packet size in dmp_read should be correct, and data read from the right packet loactions.

Additional context

I have been porting the driver to Javascript using pigpio-client to drive the i2c, and came across this issue whilst trying to understand calibration, hence why the code above is not C :).

libdriver commented 1 year ago

Thank you very much for your suggestion. We will start to reproduce this bug and reply to you within a week.

libdriver commented 1 year ago

Hello, we did reproduce your feedback. According to the official instructions of TDK,DMP_FEATURE_SEND_RAW_GYRO and DMP_FEATURE_SEND_CAL_GYRO are mutually exclusive, DMP_FEATURE_LP_QUAT and DMP_FEATURE_6X_LP_QUAT are also mutually exclusive. We will add the check of mutually exclusive parameters. Thank you very much for your suggestion.

btsimonh commented 1 year ago

hi @hepingood,

The MPU6050 lack of docs drives me mad :). But yes, that was my reading of the docs too....

Question: I have worked on my MPU6050 code for a few weeks now - and despite the frustration and the fact that it's actually not very suited to my requirements, I have made a possibly unique discovery.

For calibration, there is a doc MPU HW Offset Registers 1.2.pdf which describes hardware offset registers, and how to set them.

The document is not incorrect as such, but it does not describe an accurate way to determine the offsets to write to the hardware registers, or exactly what the hardware registers do. The code in the document simply does not work well....

In the Arduino driver, the 'adjust' these hardware offsets using a PID loop, and this is one way of overcoming the shortcoming of the document. Read on to understand why a PID loop works...

The reason the document's approach to determining the offsets is incorrect is that MEASURED offsets have been scaled AFTER they have had the hardware offset applied.

The simple scheme to set the HW offsets correctly is to MEASURE the hardware scaling for acceleration X,Y,Z first, then measure the current offsets, then scale these offsets by the measured scale, and adjust the hardware offsets appropriately.

I do this by: 1/ read enough values of X,Y,Z to get an average (i.e. in your driver, call self_test. 2/ change the hardware offsets by 0.5g and measure again. 3/ subtract the readings and calculate the change in measured values, and divide by 0.5g - this gives us the scale for each of X,Y,Z. 4/ Scale the values obtained in (1), and adjust the hardware offsets by the scaled values.

Using this method, the hardware offset registers can be set relatively accurately, and from then on, the DMP will receive raw acceleration values close to 'zero'. The advantage here is that although the DMP ALSO has acc offset values which can be set the raw acceleration offsets output in the DMP fifo are not adjusted by the DMP offset values :(. Another consideration is that if the hardware scale is incorrect, then the offset for the direction of gravity will be incorrect by (scale error)x1g.

These hardware offsets could be stored and restored every boot. I assume that they should only change if the device is subjected to shock. However, considering that my factory offsets for Z result in an output of 0.3g, either invensense do a bad job of factory calibration, or they may change more frequently.

There is a hint somewhere of 'fine tune scale' registers (0-3?) but I have not played with those yet.

If you are using the MPU6050 in production, I hope the above is interesting and useful...

best regards, Simon

libdriver commented 1 year ago

Thank you very much.

btsimonh commented 1 year ago

it gets better.... See https://github.com/btsimonh/mpu6050-pigpio-client/wiki/MPU6050-Calibration-registers---including-Fine-Scale

You can read the fine tune registers, and so do not need to measure the scale factor (assuming fine scale scaling it is the same for every device). This means you only need to take one set of average readings to calibrate, multiply the differences you want to apply by the factory scale (read from the fine tune registers), and bingo, the calibration is perfect.

But note the notes on gyro scale and orientation. Using the gyro offsets is great if your device will primarily be in one orientation... but if using in all orientations, a much more complex calibration scheme may be beneficial for gyro values. br, Simon

libdriver commented 1 year ago

Thank you very much. We will carefully study your research and improve the MPU6050 driver in the next routine update.