ZHomeSlice / Simple_MPU6050

Going Live
MIT License
88 stars 24 forks source link

Calibration OFFSETS in the serial output produce Garbage #26

Open ZHomeSlice opened 2 years ago

ZHomeSlice commented 2 years ago

it works perfectly also with my Teensy 4.1 (the microcontroller I use for this project) . The only thing that I cannot see is the calibration OFFSETS in the serial output, because I see: // X Accel Y Accel Z Accel X Gyro Y Gyro Z Gyro

define OFFSETS l, �, x, Z, �, �

(just symbols)

And Changing +-2g to +-16g accelerometer sensitivity with 3-degree of freedom mode on the dDMP firmware.

ZHomeSlice commented 2 years ago

I'm looking to a fix for the dtostrf() function spitting out �, x, Z, �, �

but until then this should be the mods to the code for your rocket :) Try this out: If it maxes out at 2 G Let me know I have another idea...

#include "Simple_MPU6050.h"
#define MPU6050_DEFAULT_ADDRESS     0x68 // address pin low (GND), default for InvenSense evaluation board
#define Three_Axis_Quaternions 3
#define Six_Axis_Quaternions 6  // Default
Simple_MPU6050 mpu(Three_Axis_Quaternions);

void print_Values (int16_t *gyro, int16_t *BadAccel, int32_t *quat) {
  Quaternion q;
  VectorFloat gravity;
  float ypr[3] = { 0, 0, 0 };
  float xyz[3] = { 0, 0, 0 };
  mpu.GetQuaternion(&q, quat);
  mpu.GetGravity(&gravity, &q);
  mpu.GetYawPitchRoll(ypr, &q, &gravity);
  mpu.ConvertToDegrees(ypr, xyz);
  Serial.print(F("Y "));   Serial.print(xyz[0]);   Serial.print(F(", "));
  Serial.print(F("P ")); Serial.print(xyz[1]);   Serial.print(F(", "));
  Serial.print(F("R "));  Serial.print(xyz[2]);   Serial.print(F(","));
  Serial.print(F("\t "));
}

void setup() {
  // initialize serial communication
  Serial.begin(115200);
  while (!Serial); // wait for Leonardo enumeration, others continue immediately
  Serial.println(F("Start: "));

  // Setup the MPU
  mpu.Set_DMP_Output_Rate_Hz(100);           // Set the DMP output rate from 200Hz to 5 Minutes.
  mpu.SetAddress(MPU6050_DEFAULT_ADDRESS); //Sets the address of the MPU.
  mpu.CalibrateMPU();                      // Calibrates the MPU.
  mpu.load_DMP_Image();                    // Loads the DMP image into the MPU and finish configuration.
  mpu.ACCEL_CONFIG_WRITE_ACCEL_FS_SEL(3);//  Accel Full Scale Select: 16g (11B)
  mpu.on_FIFO(print_Values);               // Set callback function that is triggered when FIFO Data is retrieved
  // Setup is complete!
}

void loop() {
  static unsigned long FIFO_DelayTimer;
  if ((millis() - FIFO_DelayTimer) >= (9)) {
    if ( mpu.dmp_read_fifo(false)) {
      int16_t ZAccellRaw;
      float ZAccell;
      mpu.ACCEL_ZOUT_H_READ_ACCEL_ZOUT(&ZAccellRaw);// Passing the pointer to the variable ZAccellRaw into the function. this will fill in the value from the MPU6050
      float Gravity = 1.0; // we are removing 1 g to only show z accelleration
      ZAccell = (((float) ZAccellRaw) / 8192.0f) - Gravity; // and just divide it.
      Serial.print(F("Z "));Serial.print(ZAccell, 4); Serial.println();
      FIFO_DelayTimer = millis() ; // false = no interrupt pin attachment required and When data arrives in the FIFO Buffer reset the timer
    }
  }
}
ossvale commented 2 years ago

Thanks Homer! good idea to move to your github... I tried your script, it works but I have some doubts... why do you divide the Z by 8192? Shouldn't it be by 2048 since the sensitivity is now at 16g? And do you think it's possible to get also the x and y values of accel and the gyro x, y, z? I also tried to move very quickly my sensor and the graph shows this:

SharedScreenshot

as you can see the upper level cuts at 3g, that shouldn't be right... Lower seems to be fine but I coudn't move the sensor faster to obtain a higher acceleration

Thank you again for your precious time!

Valerio

ZHomeSlice commented 2 years ago

let's see if we can focus on the accelerometer only and then add the DMP feature. I'll need a day or two. got a lot going on this weekend.

revell1 commented 2 years ago

Similar problem with OFFSET printout. This is for a PI PICO-W board. The #ifdef tests look for "AVR" or "ESP32", neither are defined for PI PICO-W (or probably any RP2040 based board), so a default def is used for the printfloatx() macro.

Not sure what test could be used as a test.

In the end I think I hacked the code and copied the printfloatx() macro from the AVR test.

I also found that your example code appears to have a global redefine of printfloatx() with no #ifdef tests, so also get complier warning about re-define of printfloatx().

I also have other issues with PI PICO but will create separate issue for that.

ossvale commented 2 years ago

let's see if we can focus on the accelerometer only and then add the DMP feature. I'll need a day or two. got a lot going on this weekend.

Sure, thank you, whenever you have time! V

ossvale commented 2 years ago

Hello Homer, did you have some time to look at the 16G setting for your library? thanks! Valerio

ZHomeSlice commented 2 years ago

I've had a little time to attempt setting the 16g setting but It doesn't hold when I start the DMP up for gyro only. this shouldn't need to be at +-2g I haven't had much time to attack this further. A possible solution is to have 2 mpu6050s attached. would that be easier? I have an easy solution for multiple MPU's attached to the same i2c bus. currently, I've tested 4 at once. 2 MPU's at once my solution keeps the active address the same and you swap the mpu you want to read into the active address all others remain on the inactive address. This would work until we can figure out how to set the accelerometer rate different than the requested DMP rate. Homer

ossvale commented 2 years ago

If I did understand well, there are two different "sections" of the 6050, one is dedicated to acceleration and the other to gyroscope, correct? If you try to switch to 16g the accel, then the gyro doesn't work anymore or soemthing like that? So the solution is using one 6050 for gyro purposes and the other one for acceleration (set to 16g)? At the moment I don't have another 6050 so I cannot say if this is a good solution. Of course the one board solution would be better. Thank you Vaerio

ZHomeSlice commented 2 years ago

Yes while they are separate they get integrated with the eDMP firmware. there is an option to only use Gyro for the eDMP firmware but I never planned to separate it with my initial programming attempts. I did put some time into tryals on this but I haven't succeeded in getting the ranges that match. instead of getting 1g in the +-16 g range, it gives me 8g which isn't the correct range for 1 g. I haven't had enough free time to break this down and find where the settings are getting reverted to +-2g Z

ossvale commented 2 years ago

Instead of buying another 6050 I decided to try this high g accelerometer that is ideal for rockets ADXL375 https://www.adafruit.com/product/5374 so I could use the ADXL375 accel for the high g and the 6050 for the gyroscope...

kamracin commented 1 year ago

Hey Zhomeslice great library!

I have been using Jeff Rowbergs libraries for quite a while on various projects but I found yours and decided to give it a try as I really like the idea of not having to use interrupts.

I'm using an STM32 Nucleo F446RE board for this project with your library.

I went to calibrate the MPU6050 and got the same symbols for the output on the calibration routine that you have above.

Serial Monitor

I was wondering if there has been any progress on the fix for the dtostrf() function?

If not is there a work around or another way to get the information for the calibration?

I have an older Jeff Rowbergs calibration sketch from 2019 but I'm unsure if the calibrations are the same between your library and Mr. Rowberg's.

Would it be an option to use Mr. Rowberg;s calibration library?

I know you are busy so please don't hurry on my part as I'm just a hobbiest/maker that enjoys tinkering especially with things that balance and use IMU's.

Thanks!

valnenov commented 1 year ago

I have a related clarification question. What is the proper way of using the offsets computed during the calibration in the setup_MPUs function?

I have 8 MPU6050s connected via I2C to a OLIMEX ESP32-DevKit_LiPo via Adafruit TCA548A I2C-Multiplexer. The calibration takes about 30 seconds if the 8 MPUs are completely still on a table and about 70 seconds when they are attached to my body and I am trying to hold as still as I can while standing. I want to eliminate repeated calibrations after the first one or two and to use the #define OFFSETS ...

Here is a code snippet of my setup_MPUs.


void setup_MPUs() {

/ Initialise the 1st sensor / Serial.println(""); Serial.println(""); Serial.println("mpu1 --------------------------------------------------- mpu1");

tcaselect(0); mpu1.Set_DMP_Output_Rate_Hz(100);

define OFFSETS 4294965492, 4294966718, 1250, 124, 4294967235, 22

//mpu1.CalibrateMPU().load_DMP_Image(); // Does it all for you with Calibration mpu1.CalibrateMPU().Enable_Reload_of_DMP(Six_Axis_Quaternions).load_DMP_Image(); mpu1.on_FIFO(print_Values);

/ Initialise the 2 sensor / Serial.println(""); Serial.println(""); Serial.println("mpu2 --------------------------------------------------- mpu2"); tcaselect(1); mpu2.Set_DMP_Output_Rate_Hz(100);

define OFFSETS 4294967202, 4294965016, 900, 4294967279, 0, 32

//mpu2.CalibrateMPU().load_DMP_Image(); mpu2.CalibrateMPU().Enable_Reload_of_DMP(Six_Axis_Quaternions).load_DMP_Image(); mpu2.on_FIFO(print_Values);

... and so on for the all 8 MPUs


I am using the OFFSETS computed during the first calibration but when I comment out the calibration calls the code fails to work.

ZHomeSlice commented 1 year ago

define OFFSETS 4294967202, 4294965016, 900, 4294967279, 0, 32

first I see that you have maxed out the limit for the offsets with the values of 4294967202 The goal of the offsets is to get each axis to read zero when the accelerometer is not experiencing any acceleration. The Z axis will read 1g with the X and Y axes horizontal and the Z axis pointing downward. The same is true for the gyro in any orientation as long as it is done motionless. any other position will cause the offsets to max out or not calibrate at all.

How to get good offsets:

#define OFFSETS 0, 0, 0, 0, 0, 0 // Zeroed offsets before calibration
mpu1.CalibrateMPU(); // run the calibration only

Run this with the MPU on a flat motionless surface with the Z axis pointing downward. take the results for this MPU and replace the #define OFFSETS

a little note: mpu1.CalibrateMPU().Enable_Reload_of_DMP(Six_Axis_Quaternions).load_DMP_Image(); is the same as

mpu1.CalibrateMPU();  // Calibration
mpu1.Enable_Reload_of_DMP(Six_Axis_Quaternions); //. unlatch the DMP load once routine
mpu1.load_DMP_Image(); // Load the DMP Firmware

When the offsets are maxed out it is difficult for the calibration routine to recover and correct the offsets

#define OFFSETS 4294965492, 4294966718, 1250, 124, 4294967235, 22 // maxed out offsets
mpu1.CalibrateMPU()

// it is better to start everything at zero
#define OFFSETS 0, 0, 0, 0, 0, 0// Zeroed offsets before calibration  may help
mpu1.CalibrateMPU()

skip the calibration if the MPU can't be placed on a level surface

Z

kamracin commented 1 year ago

Your help is very much appreciated!

Thanks!

valnenov commented 1 year ago

Thank you so much!. This is very helpful.

A quick followup. In the case of MPU9250 BMP280, when I get magnetometer readings like:

17:28:21.608 -> // X Accel Y Accel Z Accel X Gyro Y Gyro Z Gyro 17:28:21.608 -> #define OFFSETS 4294963016, 5182, 11498, 4294967119, 58, 4294967270 17:28:21.642 -> Found Magnetometer at Address: 0x0C With WhoAmI = 0x48 17:28:21.744 -> mag_sens_adj 2: 17:28:21.744 -> 1.18, 1.18, 1.14

are these magnetometer calibration values and if so how do I use them? Or is this just a printout for information purpose only?

Does the fidelity / quality of the computed attitude values PRY and quaternion get affected in any way when the magnetometer data is included in the calculations? How?

Thank again for your help!

GUIMINLONG commented 1 year ago

I have a related clarification question. What is the proper way of using the offsets computed during the calibration in the setup_MPUs function?

I have 8 MPU6050s connected via I2C to a OLIMEX ESP32-DevKit_LiPo via Adafruit TCA548A I2C-Multiplexer. The calibration takes about 30 seconds if the 8 MPUs are completely still on a table and about 70 seconds when they are attached to my body and I am trying to hold as still as I can while standing. I want to eliminate repeated calibrations after the first one or two and to use the #define OFFSETS ...

Here is a code snippet of my setup_MPUs.

void setup_MPUs() {

/ Initialise the 1st sensor / Serial.println(""); Serial.println(""); Serial.println("mpu1 --------------------------------------------------- mpu1");

tcaselect(0); mpu1.Set_DMP_Output_Rate_Hz(100);

define OFFSETS 4294965492, 4294966718, 1250, 124, 4294967235, 22

//mpu1.CalibrateMPU().load_DMP_Image(); // Does it all for you with Calibration mpu1.CalibrateMPU().Enable_Reload_of_DMP(Six_Axis_Quaternions).load_DMP_Image(); mpu1.on_FIFO(print_Values);

/ Initialise the 2 sensor / Serial.println(""); Serial.println(""); Serial.println("mpu2 --------------------------------------------------- mpu2"); tcaselect(1); mpu2.Set_DMP_Output_Rate_Hz(100);

define OFFSETS 4294967202, 4294965016, 900, 4294967279, 0, 32

//mpu2.CalibrateMPU().load_DMP_Image(); mpu2.CalibrateMPU().Enable_Reload_of_DMP(Six_Axis_Quaternions).load_DMP_Image(); mpu2.on_FIFO(print_Values);

... and so on for the all 8 MPUs

I am using the OFFSETS computed during the first calibration but when I comment out the calibration calls the code fails to work.

Hello Valnevon, did solve this problem? I also want try to sip the calibration, but it also turns out that the code show no response , expected serila.print result do no show up.

ZHomeSlice commented 1 year ago

there are 2 ways to use offsets. first is to just insert the calculated offsets and go which would closely calibrate the MPU6050 to the optimal settings Examples/Simple_MPU6050_Calibration

Then insert the calibration values into the mpu

/ _____/ // X Accel Y Accel Z Accel X Gyro Y Gyro Z Gyro //#define OFFSETS -5260, 6596, 7866, -45, 5, -9 // My Last offsets. // You will want to use your own as these are only for my specific MPU6050. /* mpu.load_DMP_Image(OFFSETS); // Load the offsets

Or you could add them directly: mpu.load_DMP_Image(-5260, 6596, 7866, -45, 5, -9 );


The second way would be to enhance the values that you have by calibrating it again with the current settings

for example, run the calibration routing and get the values. then

/ _____/ // X Accel Y Accel Z Accel X Gyro Y Gyro Z Gyro //#define OFFSETS -5260, 6596, 7866, -45, 5, -9 // My Last offsets. // You will want to use your own as these are only for my specific MPU6050. /* mpu.setMagOffsets(OFFSETS); // Load the offsets without loading the eDMP image mpu.CalibrateMPU(); .. Fine tune the calibration or if no offsets were provided this would calibrate the MPU6050 mpu.load_DMP_Image(); // resets the MPU, configures the MPU, loads the eDMP firmware and then Load the offsets that were stored in memory into the MPU6050 then starts the eDMP firmware all in one shot :)

This further calibrates the mpu starting from the given offsets and will take a shorter time than it would if the MPU was defaulted and calibrated.

The calibration requires that the MPU is level with the Z axis up.

If you only want to load the offsets without loading the eDMP image you would use this command mpu.setMagOffsets(OFFSETS); // Load the offsets without loading the eDMP image note: that the load_DMP_Image function loads the offsets at a specific point in the process of resetting the mpu6050 and prepping it for the embedded firmware upload process.

Z