i2cdevlib icon indicating copy to clipboard operation
i2cdevlib copied to clipboard

MPU-6050 - Problem with Accelerometer

Open cherbin opened this issue 4 years ago • 19 comments

Hi,

I'm using your code for the MPU-6050 on the Pi 4.

I'm having a very hard time getting correct results and not sure who else to ask. I'de really appreciate any help. It seems I'm getting random data. Also the programs say failed to connect.

I' ve also tried to use some other MPU-6050 python code and it always has 0's for the accelerometer data. The gyro data always seems to count down from some value.

I've got the following GND -> GND SLC -> SLC SDA -> SDA VCC -> 3.3V AD0 -> Gnd

i2cdetect -y 1

 0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f

00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- --

demo_raw :

Initializing I2C devices... Testing device connections... MPU6050 connection failed a/g: 8 32 0 2048 0 2 a/g: 8 36 0 2049 2 0 a/g: 0 0 0 2048 0 0 a/g: 0 36 0 2305 0 0 a/g: 8 0 0 2305 2 2 a/g: 0 4 0 2048 2 1 a/g: 0 4 256 2304 2 3

./demo_dmp

Initializing I2C devices... Testing device connections... MPU6050 connection failed Initializing DMP... DMP Initialization failed (code 1)

thanks Coby

cherbin avatar Jan 15 '20 02:01 cherbin

VCC -> 3.3V Does you breakout board have a 3.3v voltage regulator on it? You may be getting less than 3.3v to the i2c bus and your chip if your supplying the 3.3v regulator with 3.3v causing your problems.

ZHomeSlice avatar Jan 15 '20 14:01 ZHomeSlice

Hi

I’m using this mpu HiLetgo 3pcs GY-521 MPU-6050 MPU6050 3 Axis Accelerometer Gyroscope Module 6 DOF 6-axis Accelerometer Gyroscope Sensor Module 16 Bit AD Converter Data Output IIC I2C for Arduino https://www.amazon.com/dp/B00LP25V1A/ref=cm_sw_r_cp_api_i_DVZhEbV9N8HFZ

With a raspberry pi 4

Sent from my iPhone

On Jan 15, 2020, at 07:43, Homer Creutz [email protected] wrote:

VCC -> 3.3V Does you breakout board have a 5v voltage regulator on it?

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub, or unsubscribe.

cherbin avatar Jan 15 '20 16:01 cherbin

Also.. I'm using the demo_raw...

I'm getting this as an output, but I'm not sure if its correct, and if it is correct, how do I convert the numbers to something measurable ?

a/g: 8 36 2308 6176 12544 3 a/g: 8 32 2304 6180 12546 3 a/g: 0 4 2308 6144 12546 0 a/g: 8 4 2080 6144 12546 1 a/g: 0 36 2084 6144 12544 3 a/g: 0 0 2084 6144 12288 3 a/g: 8 36 2052 6176 12544 0 a/g: 0 32 2308 6176 12546 3 a/g: 8 32 2048 6400 12544 0 a/g: 0 4 2084 6432 12546 2 a/g: 8 32 32 8224 12546 2 a/g: 0 4 32 8224 12544 2 a/g: 0 0 4 8228 12546 0 a/g: 0 0 4 8192 12544 2 a/g: 8 32 36 8224 12546 1 a/g: 8 4 4 8228 12546 1 a/g: 8 4 32 8196 12546 1 a/g: 8 4 32 8192 12544 0 a/g: 0 36 36 8228 12546 1 a/g: 0 0 0 8228 12546 1 a/g: 0 4 4 8224 12546 0 a/g: 0 4 4 8196 12544 2 a/g: 8 32 0 8192 12544 0 a/g: 0 4 0 8224 12546 1 a/g: 8 0 32 8228 12546 3 a/g: 8 36 4 8228 12546 0 a/g: 8 0 4 8228 12544 1 a/g: 0 0 32 8192 12546 0 a/g: 0 32 32 8196 12546 3 a/g: 0 32 32 8196 12544 2 a/g: 8 32 32 8224 12546 3 a/g: 8 36 0 8196 12546 1 a/g: 8 32 32 8192 12546 2 a/g: 0 0 36 8192 12544 3 a/g: 0 36 4 8224 12546 0 a/g: 8 32 32 8228 12546 1 a/g: 0 0 32 8196 12544 1 a/g: 8 36 4 8192 12544 3 a/g: 8 4 36 8224 12544 3 a/g: 8 4 4 8224 12546 1

cherbin avatar Jan 16 '20 02:01 cherbin

They are rates. Havre you discovered and set the offsets for your mpu6050

With nothing moving and it is flat, the first 2 numbers and the last 3 should be near zero. The third should represent 1g of gravity. If this isn't the case calibrating is needed to correct for factory defects. Z

ZHomeSlice avatar Jan 16 '20 03:01 ZHomeSlice

Hi,

How do I set the offsets ? Can you please give an exact example?

Thanks

cherbin avatar Jan 16 '20 11:01 cherbin

Also I'm still getting these errors when running ./demo_dmp

Initializing I2C devices... Testing device connections... MPU6050 connection failed Initializing DMP... DMP Initialization failed (code 1)

demo_raw output

./demo_raw | more Initializing I2C devices... Testing device connections... MPU6050 connection failed a/g: 8 4 21760 22272 2 0 a/g: 0 4 21760 22272 0 3 a/g: 0 32 22016 22274 2 0 a/g: 8 0 21760 22272 2 2 a/g: 8 32 22016 22018 2 0 a/g: 0 0 21760 22018 2 2 a/g: 8 0 21760 22016 2 3 a/g: 8 0 22016 22016 0 2 a/g: 0 4 22016 22016 0 3 a/g: 8 36 22016 22018 0 1 a/g: 8 36 21760 22016 2 1

cherbin avatar Jan 16 '20 11:01 cherbin

I have not gone through the code for Demo_raw. so I am not familiar with the coding DMP is not needed for raw values but with that DMP does have raw values available for you to use

use this code https://github.com/jrowberg/i2cdevlib/tree/master/Arduino/MPU6050/examples/MPU6050_DMP6_using_DMP_V6.12

with the MPU6050_DMP6_using_DMP_V6.12 boilerplate,

Add this function to get the FIFO packet Seems bulletproof no more overflow errors etc and interrupts are not necessary but they do save time.

uint8_t GetCurrentFIFOPacket(uint8_t *data, uint8_t length) { // overflow proof
  int16_t fifoC;
  // This section of code is for when we allowed more than 1 packet to be acquired
  uint32_t BreakTimer = micros();
  do {
    if ((fifoC = mpu.getFIFOCount())  > length) {

      if (fifoC > 200) { // if you waited to get the FIFO buffer to > 200 bytes it will take longer to get the last packet in the FIFO Buffer than it will take to  reset the buffer and wait for the next to arrive
        mpu.resetFIFO(); // Fixes any overflow corruption
        fifoC = 0;
        while (!(fifoC = mpu.getFIFOCount()) && ((micros() - BreakTimer) <= (11000))); // Get Next New Packet
      } else { //We have more than 1 packet but less than 200 bytes of data in the FIFO Buffer
        uint8_t Trash[BUFFER_LENGTH];
        while (fifoC = mpu.getFIFOCount() > length) { // Test each time just in case the MPU is writing to the FIFO Buffer
          fifoC = fifoC - length; // Save the last packet
          uint16_t  RemoveBytes;
          while (fifoC) { // fifo count will reach zero so this is safe
            RemoveBytes = min((int)fifoC, BUFFER_LENGTH);
            mpu.getFIFOBytes(Trash, (uint8_t)RemoveBytes);
            fifoC -= RemoveBytes;
          }
        }
      }
    }
    if (!fifoC) return 0; // Called too early no data or we timed out after FIFO Reset
    // We have 1 packet
    if ((micros() - BreakTimer) > (11000)) return 0;
  } while (fifoC != length);
  mpu.getFIFOBytes(data, length); //Get 1 packet
  return 1;
}

Replace the main loop with this one to use the above function raw data is available, let me know if you need an example

// ================================================================
// ===                    MAIN PROGRAM LOOP                     ===
// ================================================================

void loop() {
// Place non blocking code here if possible delaying longer than about 70ms will cause a longr delay  up to 10ms when retrieving the packet as the FIFO buffer gets quite large
  if (!GetCurrentFIFOPacket(fifoBuffer, packetSize)) return;
// Triggers every 10ms
  mpu.dmpGetQuaternion(&q, fifoBuffer);
  mpu.dmpGetGravity(&gravity, &q);
  mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
  Serial.print(" ypr\t");
  Serial.print(ypr[0] * 180 / M_PI);
  Serial.print("\t");
  Serial.print(ypr[1] * 180 / M_PI);
  Serial.print("\t");
  Serial.print(ypr[2] * 180 / M_PI);
  Serial.println();
  return;
}

Z

ZHomeSlice avatar Jan 16 '20 16:01 ZHomeSlice

Hi.. The code above is for Arduino. I'm using a Raspberry Pi. Can you give me an example to modify this so it does the calibration on the Raspberry Pi ? The above output is also coming from this code.

The demo_raw.cpp I have is this:

demo_raw.cpp.txt

cherbin avatar Jan 16 '20 23:01 cherbin

try adding the following in the setup portion of your code mpu.CalibrateGyro(6 ); mpu.CalibrateAccel(6);

Also, you have a duplicate GetCurrentFIFOPacket function definition, I don't know if this will compile I haven't run this on a Rasberry Pi so your feedback is welcome. Z

ZHomeSlice avatar Jan 17 '20 00:01 ZHomeSlice

I used accelgyro instead of mpu , since accelgyro is defined.. but I get the following:

Where are the CalibrateGyro and CalibrateAccel defined ?

demo_raw.cpp: In function ‘void setup()’: demo_raw.cpp:20:11: error: ‘class MPU6050’ has no member named ‘CalibrateGyro’ accelgyro.CalibrateGyro(6 ); ^~~~~~~~~~~~~ demo_raw.cpp:21:11: error: ‘class MPU6050’ has no member named ‘CalibrateAccel’ accelgyro.CalibrateAccel(6); ^~~~~~~~~~~~~~ make: *** [: demo_raw.o] Error 1

cherbin avatar Jan 17 '20 00:01 cherbin

MPU6050.cpp it was updated a few months ago. CalibrateAccel and CalibrateGyro

ZHomeSlice avatar Jan 17 '20 05:01 ZHomeSlice

Where can I download the updated MPU6050.cpp for the raspberry pi that contains these functions? I cant find it anywhere.

cherbin avatar Jan 17 '20 11:01 cherbin

Here is my current MPU6050.cpp , but it does not contain the CalibrateAccel and CalibrateGyro. I do not see the update on github for Raspberry pi .. Can you please let me know where it's at.

MPU6050.cpp.txt

cherbin avatar Jan 17 '20 12:01 cherbin

Try adding these to your MPU6050 routine they should be generic enough to compile on your Pi For MPU6050.h

		// Calibration Routines
		void CalibrateGyro(uint8_t Loops = 15); // Fine tune after setting offsets with less Loops.
		void CalibrateAccel(uint8_t Loops = 15);// Fine tune after setting offsets with less Loops.
		void PID(uint8_t ReadAddress, float kP,float kI, uint8_t Loops);  // Does the math

For MPU6050.cpp

//***************************************************************************************
//**********************           Calibration Routines            **********************
//***************************************************************************************
/**
  @brief      Fully calibrate Gyro from ZERO in about 6-7 Loops 600-700 readings
*/
void MPU6050::CalibrateGyro(uint8_t Loops ) {
  double kP = 0.3;
  double kI = 90;
  float x;
  x = (100 - map(Loops, 1, 5, 20, 0)) * .01;
  kP *= x;
  kI *= x;
  
  PID( 0x43,  kP, kI,  Loops);
}

/**
  @brief      Fully calibrate Accel from ZERO in about 6-7 Loops 600-700 readings
*/
void MPU6050::CalibrateAccel(uint8_t Loops ) {

	float kP = 0.3;
	float kI = 20;
	float x;
	x = (100 - map(Loops, 1, 5, 20, 0)) * .01;
	kP *= x;
	kI *= x;
	PID( 0x3B, kP, kI,  Loops);
}

void MPU6050::PID(uint8_t ReadAddress, float kP,float kI, uint8_t Loops){
	uint8_t SaveAddress = (ReadAddress == 0x3B)?((getDeviceID() < 0x38 )? 0x06:0x77):0x13;

	int16_t  Data;
	float Reading;
	int16_t BitZero[3];
	uint8_t shift =(SaveAddress == 0x77)?3:2;
	float Error, PTerm, ITerm[3];
	int16_t eSample;
	uint32_t eSum ;
	Serial.write('>');
	for (int i = 0; i < 3; i++) {
		I2Cdev::readWords(devAddr, SaveAddress + (i * shift), 1, (uint16_t *)&Data); // reads 1 or more 16 bit integers (Word)
		Reading = Data;
		if(SaveAddress != 0x13){
			BitZero[i] = Data & 1;										 // Capture Bit Zero to properly handle Accelerometer calibration
			ITerm[i] = ((float)Reading) * 8;
			} else {
			ITerm[i] = Reading * 4;
		}
	}
	for (int L = 0; L < Loops; L++) {
		eSample = 0;
		for (int c = 0; c < 100; c++) {// 100 PI Calculations
			eSum = 0;
			for (int i = 0; i < 3; i++) {
				I2Cdev::readWords(devAddr, ReadAddress + (i * 2), 1, (uint16_t *)&Data); // reads 1 or more 16 bit integers (Word)
				Reading = Data;
				if ((ReadAddress == 0x3B)&&(i == 2)) Reading -= 16384;	//remove Gravity
				Error = -Reading;
				eSum += abs(Reading);
				PTerm = kP * Error;
				ITerm[i] += (Error * 0.001) * kI;				// Integral term 1000 Calculations a second = 0.001
				if(SaveAddress != 0x13){
					Data = round((PTerm + ITerm[i] ) / 8);		//Compute PID Output
					Data = ((Data)&0xFFFE) |BitZero[i];			// Insert Bit0 Saved at beginning
				} else Data = round((PTerm + ITerm[i] ) / 4);	//Compute PID Output
				I2Cdev::writeWords(devAddr, SaveAddress + (i * shift), 1, (uint16_t *)&Data);
			}
			if((c == 99) && eSum > 1000){						// Error is still to great to continue 
				c = 0;
				Serial.write('*');
			}
			if((eSum * ((ReadAddress == 0x3B)?.05: 1)) < 5) eSample++;	// Successfully found offsets prepare to  advance
			if((eSum < 100) && (c > 10) && (eSample >= 10)) break;		// Advance to next Loop
			delay(1);
		}
		Serial.write('.');
		kP *= .75;
		kI *= .75;
		for (int i = 0; i < 3; i++){
			if(SaveAddress != 0x13) {
				Data = round((ITerm[i] ) / 8);		//Compute PID Output
				Data = ((Data)&0xFFFE) |BitZero[i];	// Insert Bit0 Saved at beginning
			} else Data = round((ITerm[i]) / 4);
			I2Cdev::writeWords(devAddr, SaveAddress + (i * shift), 1, (uint16_t *)&Data);
		}
	}
	resetFIFO();
	resetDMP();
}

I Created this for the MPU6050 and have only shared it here unless someone like you finds it and adds it to another library this is porbibly the only spot this specific calibration routine is located. If this works you should share it wherever the MPU6050 Pi version is shared :) Sorry, I can't help further I don't have a Raspberry Pi to test it on.

Z

ZHomeSlice avatar Jan 17 '20 16:01 ZHomeSlice

Hi, I'm using another card, the AdaFruit ESP32 Feather, and on the repo, some functions are missing, such as GetCurrentFIFOPacket. I've copied yours above, however, it seems that some definitions are still missing, such as mpu, BUFFER_LENGTH, Trash...

EwaldJa avatar Dec 16 '20 11:12 EwaldJa

The Trash variable requires the BUFFER_LENGTH define value so both problems are related.

The BUFFER_LENGTH define is in the I2Cdev.c file but the #INCLUDE points to the I2Cdev.h file.

When the BUFFER_LENGTH define is added to the header file it compiles fine.

#ifndef BUFFER_LENGTH // band-aid fix for platforms without Wire-defined BUFFER_LENGTH (removed from some official implementations) #define BUFFER_LENGTH 32 #endif

davewyers avatar Oct 29 '21 23:10 davewyers

Buffer length needs to match the i2c buffer length in your processor for most cases it is 32 but it can change. for the Arduino IDE when using the atmega328p chip BUFFER_LENGTH is given to us but for the ESP8266 and others, it is not. so I believe this has been resolved but are you still having problems with this?

ZHomeSlice avatar Oct 30 '21 14:10 ZHomeSlice

It looks like I2CDEVLIB_WIRE_BUFFER_LENGTH should be used instead of BUFFER_LENGTH.

eadf avatar Oct 30 '21 15:10 eadf

@eadf This is a good point Its Definition is as follows:

#ifndef I2CDEVLIB_WIRE_BUFFER_LENGTH
    #if defined(I2C_BUFFER_LENGTH)
        // Arduino ESP32 core Wire uses this
        #define I2CDEVLIB_WIRE_BUFFER_LENGTH I2C_BUFFER_LENGTH
    #elif defined(BUFFER_LENGTH)
        // Arduino AVR core Wire and many others use this
        #define I2CDEVLIB_WIRE_BUFFER_LENGTH BUFFER_LENGTH
    #elif defined(SERIAL_BUFFER_SIZE)
        // Arduino SAMD core Wire uses this
        #define I2CDEVLIB_WIRE_BUFFER_LENGTH SERIAL_BUFFER_SIZE
    #else
        // should be a safe fallback, though possibly inefficient
        #define I2CDEVLIB_WIRE_BUFFER_LENGTH 32
    #endif
#endif

would it be as simple as: #define BUFFER_LENGTH I2CDEVLIB_WIRE_BUFFER_LENGTH

Z

ZHomeSlice avatar Oct 30 '21 19:10 ZHomeSlice