MPU6050 connection failed

Bonjour à tous,

Celà fait des heures maintenant que je visionne les vidéos sur youtube (il y en a plusieurs) et que j'essaie de m'en sortir. Je pense que je ne suis plus très loin de la solution, mais je bloque malgré tout.

J'essaie de réaliser ce projet :

Je bloque lorsque, dans le moniteur série, je reçois ce message : MPU6050 connection failed

On dirait qu'il ne reconnait pas le capteur et je ne comprends pas pourquoi.

J'utilise une Elegoo Mega2560 (dans la vidéo, il utilise une autre carte),
j'ai 5 connections (vérifiées et revérifiées) :

  • VCC au 5 volts
  • GND au GND
  • SCL à l'A5 analogique
  • SDA à l'A4 analogique
  • INT au digital 2

Le tout est directement relié à ma carte Elegoo, je ne passe pas par une breadboard.

le capteur fonctionne correctement puisque j'ai bien suivi la leçon 16 (sans la connection INT dans cette leçon).

Pfff je suis perdu, malgré tous les forums que j'ai pu lire en anglais où on y parle beaucoup d'adresse I2C 0x69 et 0x68.

Merci pour toute aide :slight_smile:

C'est probablement que tu n'utilises pas les bonnes pins pour ton bus I2C. Voici la liste :

Board I2C / TWI pins
Uno, Ethernet A4 (SDA), A5 (SCL)
Mega2560 20 (SDA), 21 (SCL)
Leonardo 2 (SDA), 3 (SCL)
Due 20 (SDA), 21 (SCL), SDA1, SCL1

J'imagine que ta board est comme un Mega2560 standard. C'est d'ailleurs écrit dessus (en haut à droite) :

Pfff je suis perdu, malgré tous les forums que j'ai pu lire en anglais où on y parle beaucoup d'adresse I2C 0x69 et 0x68.

Pour fixer l'adresse I2C du composant en 0x68 ou 0x69 ça dépend de comment vous câblez la broche AD0 sur votre module. Cette broche pilote le bit de poids faible de l'adresse du module:

  • si la broche AD0 est LOW, l'adresse est 0b0110100[color=blue]0[/color](bin) soit 0x68(hex)
  • si la broche AD0 est HIGH, l'adresse est 0b0110100[color=red]1[/color](bin) soit 0x69(hex)

--> Si vous laissez la broche en l'air on est à l'adresse par défaut en 0x68 et les librairies utilisent cette adresse donc il n'y a rien de particulier à faire.

cette adresse est à utiliser pour les discussions en I2C avec le module.

Généralement on passe par des librairies pour parler au PMU6050 et une des plus aboutie est la bibliothèqueI2Cdev de Jeff Rowberg (qui contient un module MPU6050.h).

Vous téléchargez son zip, et vous copiez dans le répertoire des libraries standard le sous répertoire i2cdevlib/Arduino/I2Cdev ainsi que i2cdevlib/Arduino/MPU6050

Cette librairie permet d'utiliser la puce de "fusion matérielle" (DMP = Digital Motion Processor ) des données de l'accéléromètre et du gyroscope pour compenser des dérives, ce qui permet d'obtenir de bons angles d'Euler ou de roulis, tangage, lacet - (YPR en anglais pour Yaw, Pitch, Roll)

Ce code (un peu ceinture brettelle, issus de diverses interactions de code pris sur internet, principalement adapté des exemples de Jeff avec des modifications pour ne pas saturer la pile FIFO) permet de vous afficher les angles de roulis, tangage, lacet.

#include "Wire.h"
#include "I2Cdev.h" //copier https://github.com/jrowberg/i2cdevlib/tree/master/Arduino/I2Cdev  dans le répertoire des librairies
#include "MPU6050_6Axis_MotionApps20.h" //copier https://github.com/jrowberg/i2cdevlib/tree/master/Arduino/MPU6050 dans le répertoire des librairies

MPU6050 mpu;  // <-- si vous avez connecté AD0 sur LOW ou si la broche n'est pas connectée (valeur par défaut 0x68)
// MPU6050 mpu(0x69); // <-- si vous avez connecté AD0 sur HIGH

const float RADIANS_TO_DEGREES = 180.0 / M_PI;

// MPU control/status vars
uint8_t mpuIntStatus;   // holds actual interrupt status byte from MPU
uint16_t packetSize;    // expected DMP packet size (default is 42 bytes)
uint16_t fifoCount;     // count of all bytes currently in FIFO
uint8_t fifoBuffer[64]; // FIFO storage buffer, doit être plus grand que packetSize

// variables d'orientation/mouvement
Quaternion q;
VectorFloat gravity;
float ypr[3];
float euler[3];

float lastYaw;
float lastPitch;
float lastRoll;

volatile bool mpuInterrupt = false;     // indicates whether MPU interrupt pin has gone high
void dmpDataReady() {
  mpuInterrupt = true;
}

void setup() {
  uint8_t dmpStatus;

  Wire.begin();
  Serial.begin(115200);

  mpu.initialize();
  if (!mpu.testConnection()) {
    Serial.println(F("pas de MPU"));
    while (true);
  }

  if (dmpStatus = mpu.dmpInitialize()) {
    Serial.print(F("Erreur DMP #"));
    Serial.println(dmpStatus);
    while (true);
  }

  mpu.setDMPEnabled(true);
  attachInterrupt(0, dmpDataReady, RISING);
  mpuIntStatus = mpu.getIntStatus();
  packetSize = mpu.dmpGetFIFOPacketSize(); // 42
}

void loop()
{
  if (mpuInterrupt || fifoCount >= packetSize) { // on a des données
    mpuInterrupt = false;
    mpuIntStatus = mpu.getIntStatus();
    fifoCount = mpu.getFIFOCount();
    if ((mpuIntStatus & 0x10) || fifoCount == 1024) {     // test si overflow (ne devrait pas arriver si on dépile vite la FIFO)
      mpu.resetFIFO();       // reset
    } else if (mpuIntStatus & 0x02) {       // verifie si on a le "DMP data ready interrupt" (this should happen frequently)
      while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount(); // on s'assure que le buffer est suffisant, ça devrait être le cas
      mpu.getFIFOBytes(fifoBuffer, packetSize); // read a packet from FIFO fifoBuffer
      fifoCount -= packetSize;

      mpu.dmpGetQuaternion(&q, fifoBuffer);

      mpu.dmpGetGravity(&gravity, &q);
      mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);

      float currentYaw = ypr[0] * RADIANS_TO_DEGREES;       // yaw: (about Z axis)
      float currentPitch = -ypr[1] * RADIANS_TO_DEGREES;    // pitch: (nose up/down, about Y axis)
      float currentRoll = ypr[2] * RADIANS_TO_DEGREES;      // roll: (tilt left/right, about X axis)

      if ((abs(currentYaw - lastYaw) > 1) || (abs(currentPitch - lastPitch) > 1) || (abs(currentRoll - lastRoll) > 1)) {
        Serial.print(F("YPR\t"));
        Serial.print(currentYaw, 0);
        Serial.write("\t");
        Serial.print(currentPitch, 0);
        Serial.write("\t");
        Serial.println(currentRoll, 0);
        lastYaw = currentYaw;
        lastPitch = currentPitch;
        lastRoll = currentRoll;
      }
    }
  }
}

Il faut éviter tout ce qui génère bcp d'interruptions (donc print) car ça peut mettre un peu le bazar sur la façon dont leur FIFO fonctionne et ensuite avoir des conséquences sur le bus I2C qui font que la librairie Wire se bloque...

Vous aurez à tenir compte du bug reporté dans cette file => rajoutez un 'L' après le 16384 dans le fichier MPU6050/MPU6050_6Axis_MotionApps20.h en ligne 522

    data[2] = ((int32_t)qI[0] * qI[0] - (int32_t)qI[1] * qI[1]
	       - (int32_t)qI[2] * qI[2] + (int32_t)qI[3] * qI[3]) / (2 * 16384L); // corrected 16384L to not overflow

il y aura pas mal de warning à la compilation que vous pourrez ignorer.