Library in a Library

Hello !
I work on a drone, and I'm using the MPU6050 library, but I think that the code is too long, and a little bit messy, so I've decided to make a library with two function : mpu.setup() and mpu.compute().
The problem is that I receive this error :

Arduino : 1.6.8 (Windows 10), Carte : "Arduino/Genuino MKR1000"

sketch\GY88.cpp.o: In function `MPU6050::dmpInitialize()':

C:\Users\quent\OneDrive\Documents\Arduino\libraries\MPU6050/MPU6050_6Axis_MotionApps20.h:325: multiple definition of `MPU6050::dmpInitialize()'

sketch\DroneV1.2.ino.cpp.o:C:\Users\quent\OneDrive\Documents\Arduino\libraries\MPU6050/MPU6050_6Axis_MotionApps20.h:325: first defined here

sketch\GY88.cpp.o: In function `MPU6050::dmpPacketAvailable()':

C:\Users\quent\OneDrive\Documents\Arduino\libraries\MPU6050/MPU6050_6Axis_MotionApps20.h:546: multiple definition of `MPU6050::dmpPacketAvailable()'

sketch\DroneV1.2.ino.cpp.o:C:\Users\quent\OneDrive\Documents\Arduino\libraries\MPU6050/MPU6050_6Axis_MotionApps20.h:546: first defined here

sketch\GY88.cpp.o: In function `MPU6050::dmpGetAccel(long*, unsigned char const*)':

C:\Users\quent\OneDrive\Documents\Arduino\libraries\MPU6050/MPU6050_6Axis_MotionApps20.h:575: multiple definition of `MPU6050::dmpGetAccel(long*, unsigned char const*)'

sketch\DroneV1.2.ino.cpp.o:C:\Users\quent\OneDrive\Documents\Arduino\libraries\MPU6050/MPU6050_6Axis_MotionApps20.h:575: first defined here

sketch\GY88.cpp.o: In function `MPU6050::dmpGetAccel(short*, unsigned char const*)':

C:\Users\quent\OneDrive\Documents\Arduino\libraries\MPU6050/MPU6050_6Axis_MotionApps20.h:583: multiple definition of `MPU6050::dmpGetAccel(short*, unsigned char const*)'

sketch\DroneV1.2.ino.cpp.o:C:\Users\quent\OneDrive\Documents\Arduino\libraries\MPU6050/MPU6050_6Axis_MotionApps20.h:583: first defined here

sketch\GY88.cpp.o: In function `MPU6050::dmpGetAccel(VectorInt16*, unsigned char const*)':

C:\Users\quent\OneDrive\Documents\Arduino\libraries\MPU6050/MPU6050_6Axis_MotionApps20.h:591: multiple definition of `MPU6050::dmpGetAccel(VectorInt16*, unsigned char const*)'

sketch\DroneV1.2.ino.cpp.o:C:\Users\quent\OneDrive\Documents\Arduino\libraries\MPU6050/MPU6050_6Axis_MotionApps20.h:591: first defined here

sketch\GY88.cpp.o: In function `MPU6050::dmpGetQuaternion(long*, unsigned char const*)':

C:\Users\quent\OneDrive\Documents\Arduino\libraries\MPU6050/MPU6050_6Axis_MotionApps20.h:599: multiple definition of `MPU6050::dmpGetQuaternion(long*, unsigned char const*)'

sketch\DroneV1.2.ino.cpp.o:C:\Users\quent\OneDrive\Documents\Arduino\libraries\MPU6050/MPU6050_6Axis_MotionApps20.h:599: first defined here

sketch\GY88.cpp.o: In function `MPU6050::dmpGetQuaternion(short*, unsigned char const*)':

C:\Users\quent\OneDrive\Documents\Arduino\libraries\MPU6050/MPU6050_6Axis_MotionApps20.h:608: multiple definition of `MPU6050::dmpGetQuaternion(short*, unsigned char const*)'

sketch\DroneV1.2.ino.cpp.o:C:\Users\quent\OneDrive\Documents\Arduino\libraries\MPU6050/MPU6050_6Axis_MotionApps20.h:608: first defined here

sketch\GY88.cpp.o: In function `MPU6050::dmpGetQuaternion(Quaternion*, unsigned char const*)':

C:\Users\quent\OneDrive\Documents\Arduino\libraries\MPU6050/MPU6050_6Axis_MotionApps20.h:615: multiple definition of `MPU6050::dmpGetQuaternion(Quaternion*, unsigned char const*)'

sketch\DroneV1.2.ino.cpp.o:C:\Users\quent\OneDrive\Documents\Arduino\libraries\MPU6050/MPU6050_6Axis_MotionApps20.h:615: first defined here

sketch\GY88.cpp.o: In function `MPU6050::dmpGetGyro(long*, unsigned char const*)':

C:\Users\quent\OneDrive\Documents\Arduino\libraries\MPU6050/MPU6050_6Axis_MotionApps20.h:632: multiple definition of `MPU6050::dmpGetGyro(long*, unsigned char const*)'

sketch\DroneV1.2.ino.cpp.o:C:\Users\quent\OneDrive\Documents\Arduino\libraries\MPU6050/MPU6050_6Axis_MotionApps20.h:632: first defined here

sketch\GY88.cpp.o: In function `MPU6050::dmpGetGyro(short*, unsigned char const*)':

C:\Users\quent\OneDrive\Documents\Arduino\libraries\MPU6050/MPU6050_6Axis_MotionApps20.h:640: multiple definition of `MPU6050::dmpGetGyro(short*, unsigned char const*)'

sketch\DroneV1.2.ino.cpp.o:C:\Users\quent\OneDrive\Documents\Arduino\libraries\MPU6050/MPU6050_6Axis_MotionApps20.h:640: first defined here

sketch\GY88.cpp.o: In function `MPU6050::dmpGetGyro(VectorInt16*, unsigned char const*)':

C:\Users\quent\OneDrive\Documents\Arduino\libraries\MPU6050/MPU6050_6Axis_MotionApps20.h:648: multiple definition of `MPU6050::dmpGetGyro(VectorInt16*, unsigned char const*)'

sketch\DroneV1.2.ino.cpp.o:C:\Users\quent\OneDrive\Documents\Arduino\libraries\MPU6050/MPU6050_6Axis_MotionApps20.h:648: first defined here

sketch\GY88.cpp.o: In function `MPU6050::dmpGetLinearAccel(VectorInt16*, VectorInt16*, VectorFloat*)':

C:\Users\quent\OneDrive\Documents\Arduino\libraries\MPU6050/MPU6050_6Axis_MotionApps20.h:656: multiple definition of `MPU6050::dmpGetLinearAccel(VectorInt16*, VectorInt16*, VectorFloat*)'

sketch\DroneV1.2.ino.cpp.o:C:\Users\quent\OneDrive\Documents\Arduino\libraries\MPU6050/MPU6050_6Axis_MotionApps20.h:656: first defined here

sketch\GY88.cpp.o: In function `MPU6050::dmpGetLinearAccelInWorld(VectorInt16*, VectorInt16*, Quaternion*)':

C:\Users\quent\OneDrive\Documents\Arduino\libraries\MPU6050/MPU6050_6Axis_MotionApps20.h:664: multiple definition of `MPU6050::dmpGetLinearAccelInWorld(VectorInt16*, VectorInt16*, Quaternion*)'

sketch\DroneV1.2.ino.cpp.o:C:\Users\quent\OneDrive\Documents\Arduino\libraries\MPU6050/MPU6050_6Axis_MotionApps20.h:664: first defined here

sketch\GY88.cpp.o: In function `MPU6050::dmpGetGravity(VectorFloat*, Quaternion*)':

C:\Users\quent\OneDrive\Documents\Arduino\libraries\MPU6050/MPU6050_6Axis_MotionApps20.h:676: multiple definition of `MPU6050::dmpGetGravity(VectorFloat*, Quaternion*)'

sketch\DroneV1.2.ino.cpp.o:C:\Users\quent\OneDrive\Documents\Arduino\libraries\MPU6050/MPU6050_6Axis_MotionApps20.h:676: first defined here

sketch\GY88.cpp.o: In function `MPU6050::dmpGetEuler(float*, Quaternion*)':

C:\Users\quent\OneDrive\Documents\Arduino\libraries\MPU6050/MPU6050_6Axis_MotionApps20.h:687: multiple definition of `MPU6050::dmpGetEuler(float*, Quaternion*)'

sketch\DroneV1.2.ino.cpp.o:C:\Users\quent\OneDrive\Documents\Arduino\libraries\MPU6050/MPU6050_6Axis_MotionApps20.h:687: first defined here

sketch\GY88.cpp.o: In function `MPU6050::dmpGetYawPitchRoll(float*, Quaternion*, VectorFloat*)':

C:\Users\quent\OneDrive\Documents\Arduino\libraries\MPU6050/MPU6050_6Axis_MotionApps20.h:693: multiple definition of `MPU6050::dmpGetYawPitchRoll(float*, Quaternion*, VectorFloat*)'

sketch\DroneV1.2.ino.cpp.o:C:\Users\quent\OneDrive\Documents\Arduino\libraries\MPU6050/MPU6050_6Axis_MotionApps20.h:693: first defined here

sketch\GY88.cpp.o: In function `MPU6050::dmpProcessFIFOPacket(unsigned char const*)':

C:\Users\quent\OneDrive\Documents\Arduino\libraries\MPU6050/MPU6050_6Axis_MotionApps20.h:715: multiple definition of `MPU6050::dmpProcessFIFOPacket(unsigned char const*)'

sketch\DroneV1.2.ino.cpp.o:C:\Users\quent\OneDrive\Documents\Arduino\libraries\MPU6050/MPU6050_6Axis_MotionApps20.h:715: first defined here

sketch\GY88.cpp.o: In function `MPU6050::dmpReadAndProcessFIFOPacket(unsigned char, unsigned char*)':

C:\Users\quent\OneDrive\Documents\Arduino\libraries\MPU6050/MPU6050_6Axis_MotionApps20.h:716: multiple definition of `MPU6050::dmpReadAndProcessFIFOPacket(unsigned char, unsigned char*)'

sketch\DroneV1.2.ino.cpp.o:C:\Users\quent\OneDrive\Documents\Arduino\libraries\MPU6050/MPU6050_6Axis_MotionApps20.h:716: first defined here

sketch\GY88.cpp.o: In function `MPU6050::dmpGetFIFOPacketSize()':

C:\Users\quent\OneDrive\Documents\Arduino\libraries\MPU6050/MPU6050_6Axis_MotionApps20.h:742: multiple definition of `MPU6050::dmpGetFIFOPacketSize()'

sketch\DroneV1.2.ino.cpp.o:C:\Users\quent\OneDrive\Documents\Arduino\libraries\MPU6050/MPU6050_6Axis_MotionApps20.h:742: first defined here

collect2.exe: error: ld returned 1 exit status

exit status 1
Error compiling for board Arduino/Genuino MKR1000.

Ce rapport pourrait être plus détaillé avec
l'option "Afficher les résultats détaillés de la compilation"
activée dans Fichier -> Préférences.

But you're not going to show us the code or libraries? So you want a guess as to the nature of those errors? Do you have include guards on your library code.

.cpp

#include "Arduino.h"
#include <Wire.h>
#include <I2Cdev.h>
#include "GY88.h"



GY88 * GY88::pointeur = NULL;

GY88::GY88()
{
}

void GY88::ISR()
{
  GY88::pointeur->dmpDataReady();
}

void GY88::dmpDataReady() {
    mpuInterrupt = true;

}

void GY88::initialize()
{
    Wire.begin();
    Serial.begin(9600);

    GY88::pointeur = this;
    
    // initialize device
    Serial.println(F("Initializing I2C devices..."));
    mpu.initialize();
    
    // verify connection
    Serial.println(F("Testing device connections..."));
    Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));

    Serial.println(F("\nSend any character to begin DMP programming and demo: "));
    while (Serial.available() && Serial.read()); // empty buffer
    while (!Serial.available());                 // wait for data
    while (Serial.available() && Serial.read()); // empty buffer again
    
    // load and configure the DMP
    Serial.println(F("Initializing DMP..."));
    devStatus = mpu.dmpInitialize();

    // supply your own gyro offsets here, scaled for min sensitivity
    mpu.setXGyroOffset(166);
    mpu.setYGyroOffset(-79);
    mpu.setZGyroOffset(35);
    mpu.setZAccelOffset(1590);
    
    // make sure it worked (returns 0 if so)
    if (devStatus == 0) {
        // turn on the DMP, now that it's ready

        Serial.println(F("Enabling DMP..."));
        mpu.setDMPEnabled(true);

        // enable Arduino interrupt detection
        Serial.println(F("Enabling interrupt detection (Arduino external interrupt 0)..."));
        attachInterrupt(0, ISR, RISING);
        mpuIntStatus = mpu.getIntStatus();

        // set our DMP Ready flag so the main loop() function knows it's okay to use it
        Serial.println(F("DMP ready! Waiting for first interrupt..."));
        dmpReady = true;

        // get expected DMP packet size for later comparison
        packetSize = mpu.dmpGetFIFOPacketSize();
    } 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(")"));
    }

    // configure LED for output
    pinMode(LED_PIN, OUTPUT);
  
}

void GY88::compute()
{
  if (!dmpReady) return;

    // wait for MPU interrupt or extra packet(s) available
    while (!mpuInterrupt && fifoCount < packetSize) 
    {
      
    }
    

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

    // get current FIFO count
    fifoCount = mpu.getFIFOCount();

    // check for overflow (this should never happen unless our code is too inefficient)
    if ((mpuIntStatus & 0x10) || fifoCount == 1024) 
    {
        // 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) 
    {
        // wait for correct available data length, should be a VERY short wait
        while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();

        // read a packet from FIFO
        mpu.getFIFOBytes(fifoBuffer, packetSize);
        
        // track FIFO count here in case there is > 1 packet available
        // (this lets us immediately read more without waiting for an interrupt)
        fifoCount -= packetSize;

        // display Euler angles in degrees
        mpu.dmpGetQuaternion(&q, fifoBuffer);
        mpu.dmpGetGravity(&gravity, &q);
        mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
       
        blinkState = !blinkState;
        digitalWrite(LED_PIN, blinkState);
    }

    
    
    x++;
}

.h

#ifndef GY88_h
#define GY88_h

#include "Arduino.h"
#include <Wire.h>
#include <I2Cdev.h>
#include "MPU6050_6Axis_MotionApps20.h"

class GY88
{
  public:

    GY88();
    void initialize();
    void compute();

    #define LED_PIN 6
    float euler[3];
    float ypr[3];
 

  private:

    MPU6050 mpu;
    bool blinkState = false;
    bool dmpReady = false;
    uint8_t mpuIntStatus;
    uint8_t devStatus;  
    uint16_t packetSize;
    uint16_t fifoCount;
    uint8_t fifoBuffer[64];

    Quaternion q;
    VectorInt16 aa;
    VectorInt16 aaReal;
    VectorInt16 aaWorld; 
    VectorFloat gravity; 

    int x = 0;

    volatile bool mpuInterrupt = false;
    static GY88 *pointeur;
    static void ISR();

    void dmpDataReady();
};

#endif

Delta_G:
But you're not going to show us the code or libraries? So you want a guess as to the nature of those errors? Do you have include guards on your library code.

Sorry, I can't post more than 1post/ 5min, and I have the limit of 9000 character :confused:

Reply, and Attach your file using "Attachments and other options". 1MB limit there.
Don't zip it first, just attach the .ino file.

Is MPU6050_6Axis_MotionApps20.h missing its include guards?

Delta_G:
Is MPU6050_6Axis_MotionApps20.h missing its include guards?

No, the include guards are not missing.

I have include the Ic2dev library, the MPU6050 library, and my library.

LibraryInLibrary.zip (90 KB)

Ok, the problem was that I have declared an object MPU6050 mpu in my .cpp and in my sketch.
EDIT : not solved !
When I declare an object GY88 gy88, the debugger display the same errors as previously :confused:

Quentin92s:
Ok, the problem was that I have declared an object MPU6050 mpu in my .cpp and in my sketch.
EDIT : not solved !
When I declare an object GY88 gy88, the debugger display the same errors as previously :confused:

The compiler, not the debugger. You aren't using a debugger.

MarkT:
The compiler, not the debugger. You aren't using a debugger.

Yes... I'm french, and I didn't know if "compiler" exists in English :confused: But well, In my code, I have replace all the mpu.x() by MPU6050::x(), like I saw in the MPU6050.cpp file, when it need to call an I2Cdev function (it use I2Cdev::x() ).
But now, I have this error for all the MPU6050 function :

C:\Users\quent\OneDrive\Documents\Arduino\libraries\GY88\GY88.cpp:124:54: error: cannot call member function 'uint8_t MPU6050::dmpGetYawPitchRoll(float*, Quaternion*, VectorFloat*)' without object

         MPU6050::dmpGetYawPitchRoll(ypr, &q, &gravity);

Ok, I saw that I can't call function like this if they aren't static (all the I2Cdev function are static). I really don't know how to do it ... maybe I need to modify directly the MPU6050 library ?