MPU6050 sd card datalogger

I would first like to say that I know this has been asked numerous times, and either the person asking had no idea what they were doing to the point their code wouldn't even compile, or people stopped talking.
I am making a simple (HA!) datalogger for a rocket I will be building.
I have taken a sketch that read data from an altimeter, the MPL3115A2, to a micro SD card, which works fine.
I have the library from i2cdevlib for the MPU6050 and put it together with the sketch for reading all 6 axis from the DMP, which alone works very well. I also, in the setup, added a calibration program so it recalibrates every time.
All of this together does not work together at all, I run it and all I get is a single FIFO OVERFLOW message in the serial monitor.
Not even my altimeter data anywhere.
I leave it running for about 45 minutes and come back to "FIFO OVERFLOW \n 0, 0, 0 \n nan, 0, nan" and other outputs that are junk.
I understand that the DMP feeds data continuously and if you don't read it it causes major problems, but is there any way to make this work?

Edit:Also, from this it seems to me the DMP is not very use able unless using something like a RPi or something because of how fast you need to read it.

Note: I cannot put my code into a code tag because it then exceeds the maximum allowed characters..

MPL3115A2.h (1.68 KB)

sd.ino (720 Bytes)

FinalRocketComputer.ino (17.9 KB)

Hi,
Can you edit your post out to single sentences on separate lines so it is easier to read please.

Can you post your code in code tags also please?

Thanks.. Tom.. :slight_smile:

There you go, can't put it in code tags :confused:

I really need help I need this as quickly as possible, anyone?

ok:

* Get rid of dmpReady. Just hang in setup if it doesn't initialize:

    } else {
        // ERROR!
        // 1 = initial memory load failed
        // 2 = DMP configuration updates failed
        // (if it's going to break, usually the code will be 1)
        Serial.print(F("DMP Initialization failed (code "));
        Serial.print(devStatus);
        Serial.println(F(")"));
        for (;;); // stop here
    }

* Using the volatile bool mpuInterrupt is the correct technique, but just test it at the top of loop instead of blocking. You may want to do other things when !mpuInterrupt (hint, hint). Like check the Altimeter periodically, or toggle an LED periodically.

* You are using the MPU interrupt capability, but you also check the FIFO count. Don't you trust the chip to tell you the truth? :slight_smile: If it says DATA_READY, it really means DATA_READY. loop should be something like this:

void loop () {

    // reset interrupt flag and get INT_STATUS byte
    if (mpuInterrupt) {
        mpuInterrupt = false;
        mpuIntStatus = mpu.getIntStatus();

        // check for overflow (this should never happen unless our code is too inefficient)
        if (mpuIntStatus & 0x10) {
            // reset so we can continue cleanly
            mpu.resetFIFO();
            Serial.println(F("FIFO overflow!"));

        // otherwise, check for DMP data ready interrupt (this should happen frequently)
        } else if (mpuIntStatus & 0x02) {

            do {
                // read a packet from FIFO
                mpu.getFIFOBytes(fifoBuffer, packetSize);
                
                #ifdef OUTPUT_READABLE_YAWPITCHROLL
                    // display Euler angles in degrees
                    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.println(ypr[2] * 180/M_PI);
                #endif
        
                #ifdef OUTPUT_READABLE_REALACCEL
                    // display real acceleration, adjusted to remove gravity
                    mpu.dmpGetQuaternion(&q, fifoBuffer);
                    mpu.dmpGetAccel(&aa, fifoBuffer);
                    mpu.dmpGetGravity(&gravity, &q);
                    mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity);
                    Serial.print("areal\t");
                    Serial.print(aaReal.x);
                    Serial.print("\t");
                    Serial.print(aaReal.y);
                    Serial.print("\t");
                    Serial.println(aaReal.z);
                #endif
        
                #ifdef OUTPUT_READABLE_WORLDACCEL
                    // display initial world-frame acceleration, adjusted to remove gravity
                    // and rotated based on known orientation from quaternion
                    mpu.dmpGetQuaternion(&q, fifoBuffer);
                    mpu.dmpGetAccel(&aa, fifoBuffer);
                    mpu.dmpGetGravity(&gravity, &q);
                    mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity);
                    mpu.dmpGetLinearAccelInWorld(&aaWorld, &aaReal, &q);
                    Serial.print("aworld\t");
                    Serial.print(aaWorld.x);
                    Serial.print("\t");
                    Serial.print(aaWorld.y);
                    Serial.print("\t");
                    Serial.println(aaWorld.z);
                #endif

                // Are there more packets waiting?
                fifoCount = mpu.getFIFOCount();

            } while (fifoCount >= packetSize);
        }

        /*
        // other program behavior stuff here
        MPL3115A2_Read();
        #ifdef SERIAL_DEBUG
            Serial.print( F("Altitude (m): ") );
            Serial.println( altitude );
        #endif

        if (dataFile.isOpen()) {
            dataFile.print( F("Altitude (m): ") );
            dataFile.println( altitude );
        }

        // blink LED to indicate activity
        //    Add blinking of LED with my own library (?!?)
        blinkState = !blinkState;
        digitalWrite(LED_PIN, blinkState);
        */
}

* Don't block. Never, never, not ever.

* Don't print too much, because Serial.print will block when there are more than 64 characters to print. You can calculate the printing time with this:

   t = (MPU sample frequency) *
           (number of characters printed per packet) *
               (10 bits/char) / (115200 bits/s)

If this number is more than 1s, you are printing too much.

* Don't use the String class. There's no reason to assemble a String so you can print it. Just print the pieces:

        MPL3115A2_Read();
        #ifdef SERIAL_DEBUG
            Serial.print( F("Altitude (m): ") );
            Serial.println( altitude );
        #endif

        if (dataFile.isOpen()) {
            dataFile.print( F("Altitude (m): ") );
            dataFile.println( altitude );
        }

* Did I mention DON'T BLOCK?

//Returns the number of meters above sea level
float readAltitude()
{
     ...
  //Wait for data to become available
  int counter = 0;
  while(Wire.available() < 3)

While this is waiting for the altitude data the IMU is generating packets. -_- Instead, you have to quickly request a reading, then return. Then test if the reading is available back in loop. When all 3 bytes are finally ready, use them for a new altitude sample.

* You should read the "Blink without delay" or "How to do several things" examples in Useful Links. Use those techniques to blink the LED and get an altimeter reading periodically.

Cheers,
/dev

I don't want to have to explain why I haven't been here to reply. It seems to never reach the code that will read the altimeter. Sometimes it also hangs at setup for a very long time, is that in fact normal?

It seems to never reach the code that will read the altimeter. Sometimes it also hangs at setup for a very long time, is that in fact normal?

It's definitely that one line of code... right there.