kriswiner / MPU9250

Arduino sketches for MPU9250 9DoF with AHRS sensor fusion
1.03k stars 471 forks source link

yaw, pitch, roll between power cycles #20

Open howardmah opened 9 years ago

howardmah commented 9 years ago

Hello Kris,

Thank you for sharing you very nice project. It's awesome.

I have a question about changing of yaw, pitch, roll values between power cycles. I'm testing your code with MPU-9250 on Arduino MEGA 2560. I wanted to check if the values of yaw, pitch, roll kept the same between power cycles, so I pushed the reset button of my MEGA 2560 while reading the three values without moving the sensor. The following numbers are some of the reading in order of yaw, pitch and roll. I picked the lines after the values became stable and two lines just to show normal variations.

... -61.563 0.277 0.133 -61.469 -0.061 0.038 ...

... -70.416 0.192 -9.999 -70.378 0.113 -10.027 ... ... -55.291 8.587 -8.549 -55.127 8.289 -8.659 ... ... -40.901 8.688 -0.057 -40.719 8.436 -0.257 Because the sensor is laid flat on top of a desk, I think roll and pitch should be close to 0 like the top two lines. But they are not always zero after pushing reset button as you see, and yaw is also changed. I'm wondering if you have ever seen this problem before. Could you give me any advice on this problem? Thank you.
kriswiner commented 9 years ago

Hi Howard,

I usually don't press the reset button. But when I check the yaw, pitch and roll after turning on the Teensy 3.1 + MPU9250 sensor breakout that I use I get reproducible results. That is after I perform the usual accel and gyro bias calibrations at rest and the mag calibration with the sensor moving in a figure eight.

When you reset, the current changes, especially if the sensor is near the Mega, and if you are calculating bias values for the magnetometer this current change could affect the results. It would help to see the scaled sensor data under the same conditions you mentioned. Is the magnetic field changing? How are you accounting for the accel/gyro bias calibration?

If you measure the accel/gyro/mag bias, then put this into your code and don't do any further bias calibration I would expect that on subsequent power ons you would get the same scaled sensor output and heading, etc with a fixed orientation. Are you saying you do not? Then I cannot understand why not unless your sensor is faulty. Does it pass the self test? Which sensor breakout is it? The cheap purple boards from China are junk and you should throw them all away. Buy a quality board and your results might be different.

Kris

-----Original Message----- From: howardmah [mailto:notifications@github.com] Sent: August 27, 2015 3:21 PM To: kriswiner/MPU-9250 Subject: [MPU-9250] yaw, pitch, roll between power cycles (#20)

Hello Kris,

Thank you for sharing you very nice project. It's awesome.

I have a question about changing of yaw, pitch, roll values between power cycles. I'm testing your code with MPU-9250 on Arduino MEGA 2560. I wanted to check if the values of yaw, pitch, roll kept the same between power cycles, so I pushed the reset button of my MEGA 2560 while reading the three values without moving the sensor. The following numbers are some of the reading in order of yaw, pitch and roll. I picked the lines after the values became stable and two lines just to show normal variations.

... -61.563 0.277 0.133 -61.469 -0.061 0.038 ...

... -70.416 0.192 -9.999 -70.378 0.113 -10.027 ...

... -55.291 8.587 -8.549 -55.127 8.289 -8.659 ...

... -40.901 8.688 -0.057 -40.719 8.436 -0.257

Because the sensor is laid flat on top of a desk, I think roll and pitch should be close to 0 like the top two lines. But they are not always zero after pushing reset button as you see, and yaw is also changed.

I'm wondering if you have ever seen this problem before. Could you give me any advice on this problem?

Thank you.

Reply to this email directly or view it on GitHub https://github.com/kriswiner/MPU-9250/issues/20 . https://github.com/notifications/beacon/AGY1qkn9Lcoi1uv3HTtnnlBx6ETPZDJpks5 or4TDgaJpZM4FzsGZ.gif

howardmah commented 9 years ago

Hi Kris,

Thank you for your prompt answer.

I looked into the problem according to your explanation. I finally found that accel data caused the problem. When I pressed the reset button, some of ax, ay, and az were randomly off by about 3mg from their expected position (0mg, 0mg, 1000mg respectively). When there was no off, roll and pitch showed right values.

I also found that accel/gyro calibration routine generated different bias values whenever pressing reset, which caused the previously mentioned "off" problem. Following your advice, I measured accel/gyro bias with correct roll/pitch and put them into the code like below. I replace the body of calibrateMPU9250() with the below code:

uint8_t gyro_bias[6] = {0, 14, 255, 242, 255, 213}; uint8_t accel_bias[6] = {235, 166, 18, 120, 34, 244};

// Push gyro biases to hardware registers writeByte(MPU9250_ADDRESS, XG_OFFSET_H, gyro_bias[0]); writeByte(MPU9250_ADDRESS, XG_OFFSET_L, gyro_bias[1]); writeByte(MPU9250_ADDRESS, YG_OFFSET_H, gyro_bias[2]); writeByte(MPU9250_ADDRESS, YG_OFFSET_L, gyro_bias[3]); writeByte(MPU9250_ADDRESS, ZG_OFFSET_H, gyro_bias[4]); writeByte(MPU9250_ADDRESS, ZG_OFFSET_L, gyro_bias[5]);

// Push accelerometer biases to hardware registers writeByte(MPU9250_ADDRESS, XA_OFFSET_H, accel_bias[0]); writeByte(MPU9250_ADDRESS, XA_OFFSET_L, accel_bias[1]); writeByte(MPU9250_ADDRESS, YA_OFFSET_H, accel_bias[2]); writeByte(MPU9250_ADDRESS, YA_OFFSET_L, accel_bias[3]); writeByte(MPU9250_ADDRESS, ZA_OFFSET_H, accel_bias[4]); writeByte(MPU9250_ADDRESS, ZA_OFFSET_L, accel_bias[5]);

With fixed accel/gyro bias, my problem seems to be solved. Could you advice me if there is a better way to do it?

I got the consistency of yaw, pitch, and roll, but I still have some other issues. I think it is better to open a new issue with a proper title.

Thank you,

Howard

kriswiner commented 9 years ago

I think the basic solution is fine, but I would be careful about using the hardware register to hold the bias values for the accel bias. The accel bias has a temperature bit in the lowest byte and it is tricky to get this right. In fact, I think it is wrong in my code so this probably explains why the accel bias could be off by one bit. I recommend that you subtract off the accel bias in the main loop. The gyro bias is fine using the hardware registers.

Kris

-----Original Message----- From: howardmah [mailto:notifications@github.com] Sent: August 28, 2015 3:39 AM To: kriswiner/MPU-9250 Cc: Kris Winer Subject: Re: [MPU-9250] yaw, pitch, roll between power cycles (#20)

Hi Kris,

Thank you for your prompt answer.

I looked into the problem according to your explanation. I finally found that accel data caused the problem. When I pressed the reset button, some of ax, ay, and az were randomly off by about 3mg from their expected position (0mg, 0mg, 1000mg respectively). When there was no off, roll and pitch showed right values.

I also found that accel/gyro calibration routine generated different bias values whenever pressing reset, which caused the previously mentioned "off" problem. Following your advice, I measured accel/gyro bias with correct roll/pitch and put them into the code like below. I replace the body of calibrateMPU9250() with the below code:

uint8_t gyro_bias[6] = {0, 14, 255, 242, 255, 213}; uint8_t accel_bias[6] = {235, 166, 18, 120, 34, 244};

// Push gyro biases to hardware registers writeByte(MPU9250_ADDRESS, XG_OFFSET_H, gyro_bias[0]); writeByte(MPU9250_ADDRESS, XG_OFFSET_L, gyro_bias[1]); writeByte(MPU9250_ADDRESS, YG_OFFSET_H, gyro_bias[2]); writeByte(MPU9250_ADDRESS, YG_OFFSET_L, gyro_bias[3]); writeByte(MPU9250_ADDRESS, ZG_OFFSET_H, gyro_bias[4]); writeByte(MPU9250_ADDRESS, ZG_OFFSET_L, gyro_bias[5]);

// Push accelerometer biases to hardware registers writeByte(MPU9250_ADDRESS, XA_OFFSET_H, accel_bias[0]); writeByte(MPU9250_ADDRESS, XA_OFFSET_L, accel_bias[1]); writeByte(MPU9250_ADDRESS, YA_OFFSET_H, accel_bias[2]); writeByte(MPU9250_ADDRESS, YA_OFFSET_L, accel_bias[3]); writeByte(MPU9250_ADDRESS, ZA_OFFSET_H, accel_bias[4]); writeByte(MPU9250_ADDRESS, ZA_OFFSET_L, accel_bias[5]);

With fixed accel/gyro bias, my problem seems to be solved. Could you advice me if there is a better way to do it?

I got the consistency of yaw, pitch, and roll, but I still have some other issues. I think it is better to open a new issue with a proper title.

Thank you,

Howard

Reply to this email directly or view it on GitHub https://github.com/kriswiner/MPU-9250/issues/20#issuecomment-135733291 . https://github.com/notifications/beacon/AGY1qlcEoA81a8CeRL2eEELwn2vSZhIGks5 osDHPgaJpZM4FzsGZ.gif

howardmah commented 9 years ago

Kris,

I looked into calibrateMPU9250() function of your code, especially accel bias part. According to your comment in the code and some explanation, I modified a bit of code and got a better result.

reset_cycle_org2 This is a signal graph from original code. Red line is yaw and other two faded redish lines are roll and pitch. Red line varies from 0 to 100 degree. Green line is ax and dark green line is ay. Their base line is -100 lines. So those lines varies from 0 to -150mg. I pushed reset button every 10 seconds. You can see ax and ay change every time reset is pressed. So does yaw stable value.

reset_cycle_mod2 This is a signal graph from modified code. The variations of ax and ay are quite small and yaw value keeps consistency between reset cycles.

I removed 8 lines and modified 3 lines, adding "<< 1" The below is the original part of the code and modified one. I removed comments for easy comparison.

========= original code (MPU9250BasicAHRS.ino : line 876 - 896) ======================== uint32_t mask = 1uL; uint8_t mask_bit[3] = {0, 0, 0};

for(ii = 0; ii < 3; ii++) { if((accel_bias_reg[ii] & mask)) mask_bit[ii] = 0x01; }

// Construct total accelerometer bias, including calculated average accelerometer bias from above accel_bias_reg[0] -= (accel_bias[0]/8); accel_bias_reg[1] -= (accel_bias[1]/8); accel_bias_reg[2] -= (accel_bias[2]/8);

data[0] = (accel_bias_reg[0] >> 8) & 0xFF; data[1] = (accel_bias_reg[0]) & 0xFF; data[1] = data[1] | mask_bit[0]; data[2] = (accel_bias_reg[1] >> 8) & 0xFF; data[3] = (accel_bias_reg[1]) & 0xFF; data[3] = data[3] | mask_bit[1]; data[4] = (accel_bias_reg[2] >> 8) & 0xFF; data[5] = (accel_bias_reg[2]) & 0xFF; data[5] = data[5] | mask_bit[2];

========================= modified ========================================= accel_bias_reg[0] -= (accel_bias[0]/8 << 1); accel_bias_reg[1] -= (accel_bias[1]/8 << 1); accel_bias_reg[2] -= (accel_bias[2]/8 << 1);

data[0] = (accel_bias_reg[0] >> 8) & 0xFF; data[1] = (accel_bias_reg[0]) & 0xFF; data[2] = (accel_bias_reg[1] >> 8) & 0xFF; data[3] = (accel_bias_reg[1]) & 0xFF; data[4] = (accel_bias_reg[2] >> 8) & 0xFF; data[5] = (accel_bias_reg[2]) & 0xFF;

I think shifting one bit of accel_bias is enough to preserve lowest bit of accel_bias_reg. Also it corrects misalignment of the values.

Would it be OK for you to verify the code?

Thanks, Howard

kriswiner commented 9 years ago

I think a better solution would be to use 0xFE as the mask instead. See the discussion here:

https://github.com/kriswiner/MPU-9250/issues/16

I just haven't got around to fixing and testing this.

howardmah commented 9 years ago

I've read #16 issue and I think my modification may not be correct. I'm going to test it more.

By the way, while I tested reset cycles, I found that if yaw value is high angle i.e. near +-180 degree, it takes 5-6 seconds for the yaw value to be stable. You can see curves after reset button is pressed from the above graphs. Is it normal for Mega 2560's speed?

Thanks, Howard