Cet article est le quatrième de la série Un robot arduino. 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 :
- comprendre comment fonctionne un gyroscope (un gy-521, équipé d’un mpu6050) seul avec un arduino ;
- comprendre le code lié au gyroscope dans le programme du balancing robot qui me sert d’inspiration ;
- 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
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.
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 à
(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 :
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 :
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 :
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 « Un robot arduino« .
Bonjour,
j’ai un problème avec les valeurs du module.
C’est à dire que ça fonctionne jusqu’à ce que je bouge ce même module.
Après avoir commencé de mon coté a investiguer cet outils, Mon premier regret est que les valeurs de mesure sont très parasitées. Pour les axes Gyro et Accé c’est compréhensible (jusqu’à un certain point) et je ne suis pas assez expérimenté pour avoir un avis pertinent. En revanche pour la mesure de température c’est inacceptable. La résolution est sensée être 0.016°C (16 bits) mais les valeurs sortent avec un pas de 0.05°C et fluctuent de +/- 0.15°C. Vu les constantes de temps de ce capteur (d’un point de vue thermique) une filtration interne minimale aurait été un gros avantage :… Lire la suite »
bonjour
comment faire une sommes vectorielles de trois signaux accélérométriques sur arduino?
HELLO l’instabilité au repos est normale c’est des interférence il faut traiter au travers d’un filtre le plus simple Euler
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
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… Lire la suite »