intermittent crashing with MPU6050 DMP

Hello,

I am developing a rotation sensor project (one axis only) using the MPU6050 gyro/DMP and the amazing IC2 library from i2cdevlib/Arduino/MPU6050 at master · jrowberg/i2cdevlib · GitHub

Everything works great, except that the arduino seems to crash after a while every time. I can get it running for up to 20 minutes in one go, but sometimes the crash occurs really fast.

I'm pretty sure it's something to do with the FIFO buffer or other memory value becoming overloaded, but the librarys and supplied code are pretty impenetrable to a novice like myself.

I appreciate that this kind of crash could have so many things causing it, but if anyone has experience with increasing/decreasing the memory allowance (Fifo buffer?) on the MPU6050 I would greatly appreciate it. The project is for an exhibition, so will need to run for hours at a time without reset....

I am using an Arduino Uno

Sorry, but this is just a 'me too' post. I have MPU6050, Uno r3, and using same library as you, and I am experiencing the same behavior.

I am using the example code which comes with the library.

Can either of you describe exactly what happens when it crashes? The FIFO overflow condition should be handled gracefully if you're using the example code; ideally, I would love a logic capture of what happens on the SDA/SCL lines when the crash happens. I have left the DMP sketch running overnight before without issue, though I won't pretend the code is all bug-free. :slight_smile:

In a nutshell, the sketch stops. I added a blinking led in the main loop to ensure it was actually stopped, and not just the sensor going into sleep mode.
I'm very much a beginner with the Arduino, so I'm not sure what more I can derive from this.

If I close and reopen the serial terminal, it all comes back to life, just as if I had pushed the reset button.

When I move the sensor away from my servos (its in a model glider), it seems to be a lot happier, and has been running for quite a while now. :slight_smile:

Are these sensors usually effected by magnetic fields or motor noise?

Here is the top few lines of comments from the library (for version information)

// I2Cdev library collection - MPU6050 I2C device class
// Based on InvenSense MPU-6050 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00)
// 8/24/2011 by Jeff Rowberg <jeff@rowberg.net>
// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib
//
// Changelog:
//     ... - ongoing debug release

Here is my code, if that helps:

// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation
// is used in I2Cdev.h
#include "Wire.h"

// I2Cdev and MPU6050 must be installed as libraries, or else the .cpp/.h files
// for both classes must be in the include path of your project
#include "I2Cdev.h"
#include "MPU6050.h"

// Servo lib
#include <Servo.h>

// class default I2C address is 0x68
// specific I2C addresses may be passed as a parameter here
// AD0 low = 0x68 (default for InvenSense evaluation board)
// AD0 high = 0x69
MPU6050 accelgyro;

// Raw values from MPU6050
int16_t ax, ay, az;
int16_t gx, gy, gz;

// Raw values when at rest, and level
#define accXzero 0
#define accYzero 0
#define accZzero 2000

// Servo pin assignments
#define ROLL_SERVO_PIN 9

// Debug flashy LED
#define LED_PIN 13
bool blinkState = false;

Servo rollServo;
float rollServoPos = 80;

float filteredPitch = 0;
float filteredRoll = 0;

long time = millis();//Used to calculate delta time
long blinkTime = millis();//Used to track LED blinking during loop

void setup() {
    // join I2C bus (I2Cdev library doesn't do this automatically)
    Wire.begin();

    // initialize serial communication
    // (38400 chosen because it works as well at 8MHz as it does at 16MHz, but
    // it's really up to you depending on your project)
    Serial.begin(38400);

    // initialize device
    Serial.println("Initializing I2C devices...");
    accelgyro.initialize();

    // verify connection
    Serial.println("Testing device connections...");
    Serial.println(accelgyro.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed");

    // configure Arduino LED for
    pinMode(LED_PIN, OUTPUT);
    
    // configure servos
    rollServo.attach(ROLL_SERVO_PIN);
}

void loop() {
    // read raw accel/gyro measurements from device
    accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
    
    //Use raw values to get pitch and roll
    calcPitchRoll();
    Serial.print(filteredPitch); Serial.print("\t");
    Serial.print(filteredRoll); Serial.print("\t");
    Serial.println();   

    // blink LED to indicate activity
    if(millis() - blinkTime > 100) {
      blinkState = !blinkState;
      digitalWrite(LED_PIN, blinkState);
      blinkTime = millis();
    }
    
    // Adjust roll servo    
    int rollServoPos = map(filteredRoll,-90,90,179,0);
    if(rollServoPos < 0) {rollServoPos = 0;}
    if(rollServoPos > 179) {rollServoPos = 179;}
    rollServo.write(rollServoPos);
    
    delay(10);
}

/*
 * Use the raw values from the MPU6050 to calculate
 * and filter (Complementary Filter) the Pitch and Roll.
 */
void calcPitchRoll() {
  //Update delta time
  long timeNow = millis();
  float dTime = (timeNow - time) / 1000;//Delta time in seconds
  time = timeNow;//update time offset
  
  //Get Degrees per second for gyros 
  //(250 deg/s is max, +-32768 range raw)
  float xD = (float)gx * 250 / 32768;
  float yD = (float)gy * 250 / 32768;
  float zD = (float)gz * 250 / 32768;
  
  //Get pitch and roll from the accelerometers
  int accXval = ax - accXzero;
  int accYval = ay - accYzero;
  int accZval = az - accZzero;
  float accPitch = atan2(accXval, accZval)*180/PI;//Pitch in degrees
  float accRoll = atan2(accYval, accZval)*180/PI;//Roll in degrees
  
  //Apply complementary filter
  filteredPitch = (0.98f * (filteredPitch + yD*dTime)) - (0.02f * accPitch);//minus because the are opposing
  filteredRoll = (0.98f * (filteredRoll + xD*dTime)) + (0.02f * accRoll); 
}

Perhaps I've done something dumb? :roll_eyes:

Oh, I just noticed you're the library author!
Thanks man, your work is appreciated! :slight_smile:

I've noticed that the delay I have at the end of my loop seems to make a huge difference in the frequency of the crashes.

Hi Jeff - Thanks so much for replying!

I'm afraid I'm too inexperienced to know how to add a logic capture to the sketch. I'll try and figure it out tonight.

In the mean time, I tested your supplied code without my additions, and I think it works fine. All I add on top is a tiny function to convert the Yaw into 0-360º format, and then print to a bluetooth board instead of the USB serial. It doesn't seem like much!

Thanks again for your amazing libraries, I really appreciate the huge amounts of work you have put in to help people like myself.

It seems to me a power and voltage level problem, not a library problem.

If you have a MPU-6050 breakout board with a voltage regulator on board, you should use 5V and not 3.3V.
You could try a I2C level shifter if you use the Arduino Uno or Mega.

Any servo should be seperately powered. You can not use the 5V pin of the Arduino for a servo. The start current for a servo could be 0.5A to 1A, that is far too much for an Arduino.

Erdin:
You can not use the 5V pin of the Arduino for a servo. The start current for a servo could be 0.5A to 1A, that is far too much for an Arduino.

Thank you! This does seem to be the problem. Without a servo connected it runs for hours without any problem. I will use a separate supply for the servos. :slight_smile:

Hi everyone!

I am having the same problem. I am using a external font from PC, and 2 servos using the Servo.h library.
After some seconds, my Arduino Mega craching (the LED stops blinking), and it isn't the mpu6050, and all Arduino crashes.

Do you know what is the problem?

Thanks a lot.

I will try use a PULL UP resistor on SDA E SCL to my I2C com:

http://forum.arduino.cc/index.php?topic=132493.0

I put the 2k2 pull up resistor on SDA and SCL, and the arduino crashes yet...
Some onde can help-me?

It's very strange...
Now I test without servos!
The MPU6050_DMP6 example from Jeff library: if I use 115200 on bound of serial, it crashes. If I use 9600, it works fine...

I suspect of some delay() between some proccess on loop(), so with 9600 serial bound, and using serial.print() it works.

Is it necessary some delay() between any proccess?

Hi everyone!

I DISABLED THE DMP MODE and finally works fine, no crashing!

I dont know why, but now is working.

Here is the simple code using 2 servos.

#include "Wire.h"
#include "I2Cdev.h"
#include "MPU6050.h"
#include "Servo.h"
 
MPU6050 mpu;
 
int16_t ax, ay, az;
int16_t gx, gy, gz;
 
Servo servo1;
Servo servo2;
 
int val1;
int val2;
int prevVal1;
int prevVal2;
 
void setup()
{
    Wire.begin();

    mpu.initialize();
    mpu.setDMPEnabled(false);

    servo1.attach(9);
    servo2.attach(10);
}
 
void loop()
{
    mpu.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
 
    val1 = map(ay, -17000, 17000, 0, 180);
    val2 = map(az, -11300, 21200, 0, 180);
    
    // SERVO1
    if (val1 != prevVal1)
    {
        servo1.write(val1);
        prevVal1 = val1;
    }
    
    // SERVO2
    if (val2 != prevVal2)
    {
        servo2.write(val2);
        prevVal2 = val2;
    }

}

Hi, I am using MPU6050 for self balancing unicycle. I am using single axis of sensor. I am getting my tilt angle from following code.

double accXangle=(atan2(AcY,AcZ)+PI)RAD_TO_DEG;
// Convert gyro raw vlues to degrees!
double gyroXrate=(double)GyX/131.0;
// Complementary Filter!
double compAngleX = (0.97 * (compAngleX + (gyroXrate * dt))) + (0.03 * accXangle);
//Serial.println("AcX = ");
float a=31.142
(compAngleX-5.35);
float ang=a-90;
return ang;

But the problem is that due to sudden movements of sensor, it gives random values which have nothing to do with sensor movement. For example when sensor is suddenly moved in positive direction of angle measurement, it gives -ve values for angle which then effect on pwm and thus direction of motor.

Can any one tell me where i am going wrong or why this is happening.