NoRobo, simplifions le sketch !

NoRobo, simplifions le sketch !

Dans l’article précédent de cette série , j’ai enfin réussi à calculer l’angle définissant la verticalité du NoRobo. Cet angle est stable et paraît juste. Mais le code est monstrueusement long (plus de 1500 lignes) et il est très difficile de s’y retrouver. En cherchant à comprendre la régulation PID – qui sera indispensable pour le NoRobo balance enfin – je suis tombée sur du code beaucoup plus simple. J’ai donc décidé de travailler tout de suite à la simplification du code(suite…)

NoRobo : mesurer l’angle en avant ou en arrière, pas facile…

NoRobo : mesurer l’angle en avant ou en arrière, pas facile…

Dans l’article précédent de cette série, « « , j’ai vu comment lire les données d’un gyroscope avec un arduino. Aujourd’hui, cinquième article, je place ce gyroscope sur le NoRobo et je prépare le code pour connaitre l’inclinaison du robot vers l’avant ou vers l’arrière. Il a toujours 3 roues et cette fonction est inutile pour l’instant. Mais c’est le préalable pour que le robot tienne « debout » sur deux roues !  (suite…)

Ajouter un gyroscope à mon robot arduino

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 :

Wire.write(0);     // set to zero (wakes up the MPU-6050)

AcX=Wire.read()<<8|Wire.read();  // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)

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 ?

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)

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 :

Wire.write(0x3B); // starting with register 0x3B (ACCEL_XOUT_H)
Wire.endTransmission(false);
Wire.requestFrom(MPU6050, 4, true);

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 :

Wire.write(0x47);
Wire.endTransmission(false);
Wire.requestFrom(MPU6050, 2, true); // request a total of 2 registers

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 « « .