Ajouter un gyroscope à mon robot arduino

Cet article est le quatrième de la série . Le NoRobo fonctionne sur 3 roues mais mon objectif reste de le transformer en robot à balancier. Il va donc falloir qu’il utilise un autre capteur, un gyroscope, pour mesurer l’accélération et l’angle en x,y et z.

Je vais procéder en plusieurs étapes :

  1. comprendre comment fonctionne un gyroscope (un gy-521, équipé d’un mpu6050) seul avec un arduino ;
  2. comprendre le code lié au gyroscope dans le programme du balancing robot qui me sert d’inspiration ;
  3. intégrer le gyroscope à mon NoRobo à 3 roues.

Comment fonctionne un gyroscope

Présentation du gyro MPU-6050

Ma source principale d’information est le site arduino, ici, en anglais.

Le gyroscope que j’utilise est un « gy-521 », équipé d’un MPU-6050 (ici pour 2.29 € sur amazon.fr). Le MPU6050 est un circuit contenant deux « MEMS » (microsystème électromécanique – cf wikipedia). Ces deux MEMS ont deux fonctions distinctes :

  • un accéléromètre
  • un gyro

Les données sont calculées simultanément en x, y et z grâce à des convertisseurs 16-bits analogue à digital pour chaque canal.

Le capteur mesure également la température.

Le capteur communique avec l’arduino avec le protocole I2C.

Il existe aussi un autre circuit, le MPU-9150 qui combine le MPU-6050 avec un compas (un magnétomètre).

Premiers essais

Cablage Arduino uno et gyroscope gy-521

J’ai simplement connecté le gyro à un arduino uno pour voir les valeurs lues.

Le cablage est très simple : VCC — 5V Arduino, GND — GND Arduino, SCI — A5 Arduino et SDA — A4 Arduino.

Le schéma est également ici sur Fritzing.

Le code arduino vient d’ici, je l’ai pris tel quel et il fonctionne correctement puisqu’il affiche des valeurs différentes lorsque je bouge le gyro. Voici un exemple de ce qui s’affiche (j’ai changé la vitesse de la liaison série dans le code pour qu’elle soit 57600 bauds, comme la console série.

Les données du gyroscope sur la console

Donc le gyro fonctionne. Reste maintenant à comprendre…

comprendre le protocole I2C

Pour une fois, je trouve une source d’information en français ! Il s’agit d’un excellent article expliquant le fonctionnement d’un capteur de température sur arduino et le protocole I2C. On peut le lire et comprendre comment fonctionne le code de lecture de notre prototype gyro-arduino.

Pour l’instant je n’ai qu’un capteur connecté en I2C à l’arduino. Je n’ai donc pas besoin d’ajouter des résistances. Je connecte donc directement A4 de l’arduino à SDA (les données) et A5 à SCL (l’horloge).

Par ailleurs l’adresse par défaut d’un gyro MPU-6050 est 0x68. On peut donc dire à l’arduino où il est puis, dans setup(), lancer la communication sachant qu’on a défini l’adresse du gyro par  const int MPU_addr=0x68;

Ici notre Arduino Uno est le « maître » et le gyro est « esclave ». L’Arduino écrira (write) pour envoyer des données au gyro, ou lira (read) pour en recevoir des données. Par exemple :

Pour communiquer en suivant le protocole I2C, on a inclus la  bibliothèque Arduino Wire, avec #include<Wire.h> .

comprendre la lecture du gyro

C’est assez compliqué car il faut lire dans des registres de 16 bits les valeurs mesurées.

int16_t AcX,AcY,AcZ,Tmp,GyX,GyY,GyZ;  définit que les variables mesurées sont des codés sur 16 bits et sont signées (peuvent être négatives). Elles peuvent donc prendre une valeur allant de -32 768 à 32 767, soit de -(2^{15}) à 2^{15}-1 (source wikipedia).

Que signifient les lignes de code suivantes , dans la boucle ?

Schématiquement (je ne suis pas sûre de tout comprendre), on doit lire dans un registre les valeurs stockées par le gyro.

On dit au gyro de commencer à fournir les données à partir du registre 0c3B qui contient une partie de l’accélération en x et on lui indique qu’on aura besoin de lire 14 registres en tout avec les lignes Wire.write(0x3B);   et   Wire.requestFrom(MPU_addr,14,true); .

Ensuite on lit les registres deux par deux car chaque valeur que l’on recherche est codée sur deux registres différents. Par exemple l’accélération en x est codée dans 0x3B (ACCEL_XOUT_H) et 0x3C (ACCEL_XOUT_L).

Pour les lire et les transformer en une seule valeur, on utilise, des « bit-shift », ou déplacements de bits comme expliqué  par Edgar Bonet dans arduino.stackexchange ici, en anglais.

Le premier Wire.read() lit le premier registre : 0x3B puisqu’on a dit que c’est là qu’il faut commencer avec la commande Wire.write(0x3B);  . Le deuxième lit le suivant (0x3C). L’accélération en x est calculée par la ligne  AcX=Wire.read()<<8|Wire.read();  .

Chaque Wire.read() renvoie un entier de 16 bits et le suivant se décale d’un registre. La ligne   AcX=Wire.read()<<8|Wire.read();  place aaaaaaaabbbbbbbb dans l’entier de 16 bits AcX par le mécanisme illustré dans cette image :

Opérations de bits sur les registres du MPU-6050

Le lien avec le programme du balancing robot

Il s’agit maintenant de comprendre le code lié au gyroscope dans le programme du balancing robot qui me sert d’inspiration ;

Dans ce programme, le setup() renvoit à une fonction, angle_setup(), qui réveille le gyro et lui donne quelques instructions.

On ne s’intéresse qu’à l’accélération en x et y et l’angle en z. On ne va donc lire que AcX, AcY et GyZ du programme précédent.

Pour celà, on se positionne d’abord sur le registre 0x3B, on déclare qu’on ne veut lire que 4 registres avec les lignes suivantes :

On lit AcX et AcY puis on passe à la lecture de GyZ, dont le premier registre est en 0x47, et on ne lit que les deux registres correspondants :

Le code correspondant est visible ici : gyro-gyrobo.ino et sur GitHub ici.

Il fonctionne :

La console arduino avec le code gyro du balancing robot

C’est un peu bizarre car je ne touchais pas au gyro, ni au bureau sur lequel il est posé. Je m’attendais donc à lire des valeurs stables…

Positionnement du gyro

Je vais profiter de ce prototype pour comprendre comment positionner le gyro sur le robot lorsque je l’intégrerai.

D’après les changements de valeur observés, voici les axes :

3 axes pour positionner le gyro

le gyro sera donc placé à l’horizontale, led vers le dessous, avec la flèche X pointant vers l’avant du robot et la flèche Y dans le même axe que les roues.

Et maintenant ?

La troisième étape de ces recherches sur le gyroscope va consister à l’intégrer à mon NoRobo à 3 roues. Ce sera l’objet de l’article suivant de cette série « « .

5 commentaires


  1. HELLO l’instabilité au repos est normale c’est des interférence il faut traiter au travers d’un filtre le plus simple Euler

    Répondre

    1. Merci pour ce commentaire. C’est effectivement ce que j’ai fini par comprendre en poursuivant mon projet, que je n’ai toujours pas finalisé.

      Répondre

  2. Pour faire suite à mon problème, j’ai essayé de charger le même programme sur la carte Arduino MEGA.
    J’ai l’erreur suivante:

    avrdude: atk500v2_set parameter():failed to set parameter 0x9e
    avrdude: atk500v2_command(): unknow status 0xc8
    avrdude: atk500v2_initialization failed,re=-1
    double check connections and try again,or use -F to override this check
    avrdude: atk500v2_command(): unknow status 0x01
    avrdude: atk500v2_disable(): failed to leave programming mode

    Je ne sais pas comment résoudre ce problème.
    merci de l’aide – jc

    Répondre

  3. Bonjour,
    Je bute depuis des mois sur le projet suivant:
    relier un MPU6050 à une carte Arduino MEGA et un écran TFT.
    C’est facile car l’écran se fixe directement sur la carte. Cela afin d’avoir sur l’écran ce petit avion qui bouge lorsqu’on déplace le capteur. Il y a plusieurs tutoriels qui expliquent ( comme sur DUMMY’S Codes) mais je n’y parviens pas.D’abord la carte MEGA a refusé tout programme. Je suis tombé sur votre site et changé la carte MEGA pour une UNO.
    J’ai copié le programme et c’est OKE. Par contre pas moyen de charger le programme. J’ai le message suivant:
    avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0x30
    avrdude: stk500_getsync() attempt 2 of 10: not in sync: resp=0x20
    avrdude: stk500_getsync() attempt 3 of 10: not in sync: resp=0x30
    avrdude: stk500_getsync() attempt 4 of 10: not in sync: resp=0x20
    avrdude: stk500_getsync() attempt 5 of 10: not in sync: resp=0x30
    avrdude: stk500_getsync() attempt 6 of 10: not in sync: resp=0x20
    avrdude: stk500_getsync() attempt 7 of 10: not in sync: resp=0x30
    avrdude: stk500_getsync() attempt 8 of 10: not in sync: resp=0x20
    avrdude: stk500_getsync() attempt 9 of 10: not in sync: resp=0x30
    avrdude: stk500_getsync() attempt 10 of 10: not in sync: resp=0x20
    An error occurred while uploading the sketch
    Je ne comprends l’erreur.
    Merci pour votre aide.
    En plus, comment devrais-je faire pour arriver à avoir cet avion sur l’écran TFT???

    Répondre

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *