Utilisation MPU 6050

Bonjour ,
Je débute en Arduino et j'ai un petit soucis avec mon IMU j'utilise la SEN 11028 : https://www.sparkfun.com/products/11028 et j'ai essayé de voir si la carte fonctionnait en utilisant ce programme :

// MPU-6050 Short Example Sketch
// By Arduino User JohnChi
// August 17, 2014
// Public Domain
#include<Wire.h>
const int MPU_addr=0x68;  // I2C address of the MPU-6050
int16_t AcX,AcY,AcZ,Tmp,GyX,GyY,GyZ;
void setup(){
  Wire.begin();
  Wire.beginTransmission(MPU_addr);
  Wire.write(0x6B);  // PWR_MGMT_1 register
  Wire.write(0);     // set to zero (wakes up the MPU-6050)
  Wire.endTransmission(true);
  Serial.begin(9600);
}
void loop(){
  Wire.beginTransmission(MPU_addr);
  Wire.write(0x3B);  // starting with register 0x3B (ACCEL_XOUT_H)
  Wire.endTransmission(false);
  Wire.requestFrom(MPU_addr,14,true);  // request a total of 14 registers
  AcX=Wire.read()<<8|Wire.read();  // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)    
  AcY=Wire.read()<<8|Wire.read();  // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
  AcZ=Wire.read()<<8|Wire.read();  // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
  Tmp=Wire.read()<<8|Wire.read();  // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L)
  GyX=Wire.read()<<8|Wire.read();  // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L)
  GyY=Wire.read()<<8|Wire.read();  // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L)
  GyZ=Wire.read()<<8|Wire.read();  // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L)
  Serial.print("AcX = "); Serial.print(AcX);
  Serial.print(" | AcY = "); Serial.print(AcY);
  Serial.print(" | AcZ = "); Serial.print(AcZ);
  Serial.print(" | Tmp = "); Serial.print(Tmp/340.00+36.53);  //equation for temperature in degrees C from datasheet
  Serial.print(" | GyX = "); Serial.print(GyX);
  Serial.print(" | GyY = "); Serial.print(GyY);
  Serial.print(" | GyZ = "); Serial.println(GyZ);
  delay(333);
}

Mais lorsque je souhaite lire les variables , toutes celle ci sont à -1 (AcY AcZ GyZ GyX et GyZ , tmp a 376.53) et bouger l'imu n'y change rien ... ( j'utilise une arduino micro) est ce un problème de carte ? ou de branchements ? Le code est à la base pour arduino UNO est ce le problème ? Je vous joins le montage (pour l'instant je n'ai de connecté , uniquement la centrale inertielle et la carte arduino)

Bonjour,

J'ai l'impression que ton branchement de SCL et SDA sur la micro n'est pas correct. Vérifie le pinout de la carte et si tu es sûr de toi, envoi ce sur quoi tu te bases pour avoir fait ces branchements.

https://www.arduino.cc/en/Main/arduinoBoardMicro
Effectivement ils mettent TWI : 2 (SDA) 3(SCL) , je vais essayer comme ca merci et désolé si ca marche c'était vraiment stupide de ma part ...

Non cela ne marche toujours pas :confused: , je vous poste une photo directement de mon montage , étant mon premier montage cela ne m'étonnerait même pas que mon utilisation de la breadboard soit quelque peu questionable :smiley: , au niveau de la breadboard c'est sans soudures , il y a t il un moyen de savoir si au moins l'imu est détecté ?

Fais les branchements de SDA et SCL d'après ce schéma:

A part ça, tu es sûr que la carte MPU6050 soit compatible 5V, comme l'Arduino Micro ?

Oui normalement la carte est tout a fait compatible avec la Arduino, elle prend juste le 3V de la Arduino du coup je comprends pas trop d'ou ca vient :confused: mais je vais réessayer avec effectivement le schéma que tu m'a envoyé par contre juste une question idiote la masse je prends celle au niveau de d2 d3 ? ou de toute facon la masse n'a pas d'importance que je prenne celle au niveau de A1 etc ... ou D2 etc ...?

C'est bon ca marche merci beaucoup pour votre aide, je garde ce topic ouvert si jamais j'ai encore des questions pour mon projet plutôt que d'en ré ouvrir un :slight_smile:

cryser:
Oui normalement la carte est tout a fait compatible avec la Arduino, elle prend juste le 3V de la Arduino

Oui mais sur la micro les signaux sont en 5V alors que sur ta carte MPU6050 ils sont en 3.3V. Du coup ce serait mieux d'insérer un convertisseur de niveau de tension entre les SDA et SCL des deux cartes.

Ha oui effectivement , merci !

Du coup je continue d'avancer petits pas par petits pas dans mon projet et j'en suis a la partie commande de moteur/algorithmique , au niveau de l'alimentation le moteur a pour tension nominal 10V et pour le courant nominal c'est du 500mA mais je me demande si j'alimente la carte de commande de puissance en 12V et 1,5A par exemple , celle ci adapte le courant / la tension pour la moteur ? Ou faut il que je l'alimente avec juste ce qu'il y a besoin ?

Pour le côté algorithmique du coup j'ai fais un petit programme pour déterminer l'angle de roulis a partir de l’accélération gravitationnelle que subis la carte et du coup par soucis de simplification je me disais que j'allais fixer l'IMU a l'objet que je souhaitais stabiliser ( juste l'axe de roulis ) mais du coup je dois considérer l’accélération que subit la carte a cause de la mise en rotation du moteur , cela vous semble t-il viable ? Je pensais faire un programme a base de while l'angle de roulis est supérieur ou inférieur à +-1,8 degré on tourne dans le sens adapté et ainsi de suite

Merci d'avance !

cryser:
Du coup je continue d'avancer petits pas par petits pas dans mon projet et j'en suis a la partie commande de moteur/algorithmique , au niveau de l'alimentation le moteur a pour tension nominal 10V et pour le courant nominal c'est du 500mA mais je me demande si j'alimente la carte de commande de puissance en 12V et 1,5A par exemple , celle ci adapte le courant / la tension pour la moteur ? Ou faut il que je l'alimente avec juste ce qu'il y a besoin ?

Dans les deux cas (courant et tension) l'alimentation doit pouvoir fournir plus que ce dont le moteur a besoin. Mais attention, ce n'est pas le courant nominal qu'il faut considérer mais le courant de blocage. Ce que je dis mériterait de tenir en beaucoup plus que deux lignes, mais tu trouveras sur Internet plein de ressources qui expliquent comment on pilote un moteur à courant continu.

cryser:
du coup par soucis de simplification je me disais que j'allais fixer l'IMU a l'objet que je souhaitais stabiliser

C'est pas par soucis de simplification qu'il faut le faire. C'est une obligation. Tu as zéro chance de stabiliser un truc si la mesure de stabilité n'est pas liée à l'objet à stabiliser. C'est comme pour faire la régulation de température d'un four: tu la fais en mesurant la température dans le four, pas celle à l'extérieur.

Pour le reste, il faut en dire plus sur ton système: de quoi s'agit-il ? Pourquoi uniquement le roulis ? Sur quel axe agit le moteur ?

Mon système doit être un "prototype" de stabilisateur de caméra (sachant que je ne suis pas sur d'utiliser une caméra pour mon oral mais juste un objet fixé au rotor style polystyrène avec un point marqué au crayon comme repère juste pour montrer que l'asservissement remplis le cahier des charges ) , je m'occupe uniquement de l'axe de roulis car je n'ai que peu de temps pour le projet et du coup le moteur agira sur l'axe de roulis.

Effectivement je me sens un peu con du coup pour l'histoire de placer ou non l'imu sur la caméra ou non, ça risque d'être compliqué de corriger une position si je n'ai pas l'information sur celle ci :slight_smile:

cryser:
Je pensais faire un programme a base de while l'angle de roulis est supérieur ou inférieur à +-1,8 degré on tourne dans le sens adapté et ainsi de suite

Pourquoi 1.8 degrés ?

Ceci étant, la bonne approche me semble être de faire un asservissement. Tu as un angle de roulis de consigne qui doit être nul, a priori, et dès que l'angle mesuré s'en éloigne, le moteur corrige la rotation pour revenir à 0. La correction doit se faire en continu, avec par exemple un PID, mais pas avec une série de while.

Pour l'intervalle [-1,8;1,8] degrés je pensais que être pile à 0 degré allait être compliqué et que la résolution du moteur étant de 1,8degrés ça me semblait être pas mal.
Après pour le PID je vois ça dans le côté théorique avec marge de phase marge de gain etc... Pour la statibilite la rapidité etc... Mais pour le côté concret j'ai du mal à me représenter ce que c'est je vais essayer de me renseigner du coup, merci !

cryser:
mais du coup je dois considérer l’accélération que subit la carte a cause de la mise en rotation du moteur , cela vous semble t-il viable ...

Pour que votre accéléro (axe Z) ne ressente pas l'accélération du moteur, il faut que celui-ci soit sur l'axe du moteur. Il ne verra alors plus que la composante gravitationnelle, ce dont vous vous voulez vous servir pour votre asservissement.

cryser:
... Je pensais faire un programme a base de while l'angle de roulis est supérieur ou inférieur à +-1,8 degré on tourne dans le sens adapté et ainsi de suite

C'est un moteur pas à pas que vous avez ?

Cordialement.

Pierre

Merci pour votre réponse, oui c'est un petit moteur pas à pas bipolaire

Bonjour ,
Du coup je continue sur ce topic, j'ai donc essayé de trouver un exemple de PID pour un moteur pas à pas mais j'ai pas réussi à en trouver j'ai donc essayé de me dépatouiller sans PID , j'ai penser a un code dans ce style la :

#include<Wire.h>
 #define DIR_PIN 4
 #define STEP_PIN 5
    const int MPU=0x68;  // I2C address of the MPU-6050
    int16_t AcX,AcY,AcZ;
    float accel,ay,az,phi;
    void setup(){
      Wire.begin();
      Wire.beginTransmission(MPU);
      Wire.write(0x6B);  // PWR_MGMT_1 register
      Wire.write(0);     // set to zero (wakes up the MPU-6050)
      Wire.endTransmission(true);
      Serial.begin(9600);
      pinMode(DIR_PIN, OUTPUT); 
      pinMode(STEP_PIN, OUTPUT);
    }
    void loop(){
      Wire.beginTransmission(MPU);
      Wire.write(0x3B);  // starting with register 0x3B (ACCEL_XOUT_H)
      Wire.endTransmission(false);
      Wire.requestFrom(MPU,6,true);  // request a total of 6 registers
      AcX=Wire.read()<<8|Wire.read();  // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)    
      AcY=Wire.read()<<8|Wire.read();  // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
      AcZ=Wire.read()<<8|Wire.read();  // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
      Serial.print("AcX = "); Serial.print(AcX);
      Serial.print(" | AcY = "); Serial.print(AcY);
      Serial.print(" | AcZ = "); Serial.println(AcZ);
      // AcZ = 16350 au repos AcZ= -17300 à l’envers
      az = (float)(AcZ + 475 );
      //AcY = 16200 au repos AcX =-16700
      ay = (float)(AcY + 200);
      accel = sqrt(ay*ay+az*az);
      phi = atan2(ay,az)*(360/(2*3.14159265));
      Serial.print("Phi = "); Serial.println(phi);
      delay(100); // actualisation des données toutes les 100ms
      while (phi =!0) {
        rotateDeg(phi,1);
      }
    }
    void rotateDeg(float deg, float speed){ 
  //rotate a specific number of degrees (negitive for reverse movement)
  //speed is any number from .01 -> 1 with 1 being fastest - Slower is stronger
  int dir = (deg > 0)? HIGH:LOW;
  digitalWrite(DIR_PIN,dir); 

  int steps = abs(deg)*(1/0.225);
  float usDelay = (1/speed) * 70;

  for(int i=0; i < steps; i++){ 
    digitalWrite(STEP_PIN, HIGH); 
    delayMicroseconds(usDelay); 

    digitalWrite(STEP_PIN, LOW); 
    delayMicroseconds(usDelay); 
  }
  }

mais malheureusement je sais pertinemment que cela ne marchera pas car j'imagine bien que dans le while , le phi ne s'actualisera pas au cours du temps , il y aurait il moyen qu'il en soit autrement ?

Cordialement

Il suffit que tu supprimes le while.

La fonction loop() fait déjà une boucle infinie. Donc phi sera recalculé à chaque boucle.