jrowberg / i2cdevlib

I2C device library collection for AVR/Arduino or other C++-based MCUs
http://www.i2cdevlib.com
3.91k stars 7.52k forks source link

Yaw value received using DMP6 code is unstable #225

Open sanatmharolkar opened 8 years ago

sanatmharolkar commented 8 years ago

Hi, I'm new at using the MPU-6050, but from what I've read online, the ypr values should stabilise after a few seconds. The pitch and roll do stabilise, more or less, but the yaw value is not stabilising at all. Even after leaving the board static for more than a minute, the yaw value just oscillates steadily from -180 to 180. Any ideas why this might be happening?

eadf commented 8 years ago

Well, -180° and +180° is just as stable as +0° and -0°. After a miniscule increment of 180° the value turns up as -180° and vice versa.

But then again, without a magnetometer the yaw offset is kind of arbitrary. So it could just as well be centred at 0°. I'm currently looking at another issue regarding yaw,pich&roll (#222 & #216) so I'll take a look at this as well.

udawat commented 8 years ago

I think what the OP means is that the readings show all the values between -180 to +180 degree showing a complete rotation even when the sensor is flat. While evaluating the MPU-9150 modules, i faced similar problems with yaw readings. The yaw values kept on changing abruptly from 10,20,30,...150 degree; then linearly decreasing again to 10 degree (all this while the sensor was rotated just a few degrees). Ultimately, it was due to bad sensors. Specifically on the MPU-9150 ICs, the problem was found on many samples.

sanatmharolkar commented 8 years ago

Yes, it's showing a complete rotation, at quite a steady rate. One thing I noticed was changing the offsets to values obtained from a code I found online that calculates the offsets required reduced the rate of the drift quite significantly. There's a drift nevertheless. It may be usable with the right offsets. Also, for my current application, I need rotation about one axis only. I'm a little confused as to whether I can attach the GY-521 breakout board vertically and use the pitch or roll values? Can I use it like that?

yonoodle commented 8 years ago

Try this code and reset the correction first ,though the code is quite messy , i clean the fifo count every time for time independent value reading for code which is not necessary in this program , and get the average of 20 data of the angular velocity ten times and auto re-calibrate according to it , and output the value and respondent error to console for further use ,this program is for AD0 =high module , just delete the address for an AD0=low module.

remember to put the mpu6050 steady on table before and during running this code.

this can find the good calibration value , but will not write anything to mpu6050 firmware , so we have to manually key in the value for setXGyroOffset() in other project code first.

this will make the mpu yaw rotating at a very small speed or even stable , but can not absolutely steable the value due to the mpu6050 has no external reference for yaw such like earth magnet field data... and the pitch and row is stable because the algorithm use gravity as external reference.


include

include "MPU6050_6Axis_MotionApps20.h"

if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE

include "Wire.h"

endif

MPU6050 OBJ_1(0x69); bool VAR_1 = false ;uint8_t mpuIntStatus_OBJ_1 ;uint8_t devStatus_OBJ_1 ;uint16_t packetSize_OBJ_1 ;uint16_t fifoCount_OBJ_1 ;uint8_t fifoBuffer_OBJ_1[64];;Quaternion q_OBJ_1;VectorFloat gravity_OBJ_1; volatile bool mpuInterrupt_OBJ_1 = false ;void dmpDataReady_OBJ_1(){ mpuInterrupt_OBJ_1 = true;} int16_t ax_OBJ_1, ay_OBJ_1, az_OBJ_1; int16_t gx_OBJ_1, gy_OBJ_1, gz_OBJ_1; float wx = 0; float wy = 0; float wz = 0; void setup() {

if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE

Wire.begin(); TWBR = 24;

elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE

Fastwire::setup(400, true);

endif

      Serial.begin(9600);
      OBJ_1.initialize();

OBJ_1.dmpInitialize(); if (devStatus_OBJ_1 == 0) { OBJ_1.setDMPEnabled(true); attachInterrupt(0, dmpDataReady_OBJ_1, RISING); mpuIntStatus_OBJ_1 = OBJ_1.getIntStatus(); VAR_1 = true; packetSize_OBJ_1 = OBJ_1.dmpGetFIFOPacketSize(); } for( int dummy_3d2a = 0 ; dummy_3d2a<10 ; dummy_3d2a ++ ) {
delay(500); for( int dummy_3d2a = 0 ; dummy_3d2a<20 ; dummy_3d2a ++ ) {
OBJ_1.resetFIFO(); fifoCount_OBJ_1 = 0; while (fifoCount_OBJ_1 < 2_packetSize_OBJ_1) { fifoCount_OBJ_1 = OBJ_1.getFIFOCount();} OBJ_1.getFIFOBytes(fifoBuffer_OBJ_1, packetSize_OBJ_1);OBJ_1.getMotion6(&ax_OBJ_1, &ay_OBJ_1, &az_OBJ_1, &gx_OBJ_1, &gy_OBJ_1, &gz_OBJ_1); wx=wx+gx_OBJ_1; wy=wy+gy_OBJ_1; wz=wz+gz_OBJ_1;
} wx=wx/20; wy=wy/20; wz=wz/20; OBJ_1.setXGyroOffset(OBJ_1.getXGyroOffset()-wx); OBJ_1.setYGyroOffset(OBJ_1.getYGyroOffset()-wy); OBJ_1.setZGyroOffset(OBJ_1.getZGyroOffset()-wz); Serial.print(" set_wx= "); Serial.print(OBJ_1.getXGyroOffset()); Serial.print(" set_wy= "); Serial.print(OBJ_1.getYGyroOffset()); Serial.print(" set_wz= "); Serial.println(OBJ_1.getZGyroOffset()); for( int dummy_3d2a = 0 ; dummy_3d2a<20 ; dummy_3d2a ++ ) {
OBJ_1.resetFIFO(); fifoCount_OBJ_1 = 0; while (fifoCount_OBJ_1 < 2_packetSize_OBJ_1) { fifoCount_OBJ_1 = OBJ_1.getFIFOCount();} OBJ_1.getFIFOBytes(fifoBuffer_OBJ_1, packetSize_OBJ_1);OBJ_1.getMotion6(&ax_OBJ_1, &ay_OBJ_1, &az_OBJ_1, &gx_OBJ_1, &gy_OBJ_1, &gz_OBJ_1); wx=wx+gx_OBJ_1; wy=wy+gy_OBJ_1; wz=wz+gz_OBJ_1;
} wx=wx/20; wy=wy/20; wz=wz/20; Serial.print(" err_wx= "); Serial.print(wx); Serial.print(" err_wy= "); Serial.print(wy); Serial.print(" err_wz= "); Serial.println(wz); Serial.println(" "); Serial.println(" ");
} } void loop() { }

yonoodle commented 8 years ago

if your project won't encounter magnet field interference ,get the Yaw value using a cheap magnet field sensor such as HMC5883L can solve this problem beautifully~