P25 Développement d'un cobot
Sommaire
Cahier des charges
Présentation du projet
Le Fablab Lille est un lieu de fabrication ouvert à tous permettant à toute personne ayant un projet de trouver les moyens de le réaliser grâce au nombreuses machines numériques mises à disposition. Impression 3D, découpe laser, personnalisation d'objet, électronique, sont quelques unes des possibilités offertes. C'est un lieu d'échange qui prône le Do It Yourself et où des "makers" d'horizons différents peuvent concrétiser leurs idées. Le but du Fablab : rendre accessible le protypage, l'expérimentation, la personnalisation, et la production en petites série. De ce fait, des personnes de formations et d’horizons différents viennent afin de réaliser leur projet.
L’utilisation d’un cobot, ou robot collaboratif, peut donc s’avérer utile afin d’assister les « makers » en effectuant des tâches simples programmables sans risques de blesser l’utilisateur ou sans endommager son environnement.
Objectif du projet
L'objectif de ce projet est de réaliser un cobot, ou robot collaboratif. Ce robot serait un démonstrateur de bras robotique pouvant être utilisé en interaction avec les humains.
La première étape de ce projet sera tout d'abord de terminer la conception du bras avant de commencer la programmation.
Deux modes de fonctionnement sont envisagés pour la réalisation de ce projet:
- Déplacement axe par axe puis global du bras.
- Mode d'aide permettant d'amplifier la force appliquée par un humain.
FP1: Assister l'utilisateur dans la réalisation d'une tâche.
FP2: Préserver l'environnement du bras (humain ou matériel).
FC1: Être programmable.
FC2: Interagir avec l'utilisateur.
FC3: Doit savoir soutenir une charge.
FC4: Protéger le câblage apparent.
Choix matériel et logiciel
Afin de réaliser ce projet, l'utilisation des composants suivants sera envisagé:
- Le bras robotique open source Moveo BC3ND partiellement monté.
- Une carte Arduino MEGA 2560afin de pouvoir modifier la position du robot.
- Un joystick shield arduino afin de pouvoir contrôler le robot et le faire bouger.
- Des moteurs pas-à-pas afin de motoriser le bras robotique de façon précise.
- Des cartes de commandes TB6560 afin de contrôler les moteurs par le biais de l'arduino.
- Des capteurs de types roues codeuses afin de pouvoir récupérer la position du robot.
- Un écran LCD pour arduino afin de renseigner l'utilisateur sur le mode de fonctionnement.
- Des capteurs de proximités afin de connaitre l’environnement du robot.
- Des sondes de courant, afin d'effectuer le monitoring du courant dans les moteurs et détecter une collision.
- Un accéléromètre afin de détecter une éventuelle détection.
Liste des tâches
La liste des tâches à effectuer pour réaliser ce projet au mieux est la suivante:
Tâches préliminaires:
- Terminer la conception du bras robotique.
- Motorisation du bras robotique.
Partie 1: Base du mouvement:
- Mouvement du bras sur 1 axe en boucle ouverte.
- Mouvement du bras en chaine cinématique directe.
Partie 2: Mode collaboratif sur 1 axe:
- Détection d'un obstacle sur le premier axe.
- Reprise du mouvement après obstacle.
Partie 3: Mode collaboratif sur 2 axes:
- Détection d'un obstacle sur le deuxième axe.
- Reprise du mouvement après obstacle.
- Combinaison programme pour les 2 axes simultanément.
Partie 4: Robot global:
- Détection sur les autres axes.
- Reprise du mouvement après obstacle.
- Combinaison des programmes pour détection sur le robot entier.
Calendrier prévisionnel
Pour la réalisation de ce projet, les tâches et leurs durées (exprimées en jours) sont les suivantes:
Le déroulement du projet complet comprenant la liste des tâches à effectuer ainsi que le diagramme de Gantt du projet sont visible sur le fichier PDF suivant:
Fichier:Gantt PFE.pdf
Des durées plus grandes sont accordées pour les premières phases du projet, c'est-à-dire pour le mode collaboratif sur le premier axe. L'hypothèse est faite qu'ensuite, il faudra moins de temps pour réitérer ces tâches sur les autres axes car la méthode pour détecter les obstacles et reprendre le programme sera alors connue.
Bibliographie
Afin de mieux savoir ce qu'est un "cobot" ou robot collaboratif, voici quelques articles intéressants à lire afin de mieux comprendre les avantages d'un robot collaboratif par rapport à un robot industriel:
- http://www.humarobotics.com/la-robotique-collaborative/
- http://www.mb-s.fr/robot-collaboratif-vs-robot-industriel-traditionnel.html
- https://www.generationrobots.com/blog/fr/2015/01/robots-collaboratifs-et-robots-traditionnels-les-5-differences-cles/
Les liens suivants présentent 3 robots collaboratifs commercialisés dans l'industrie:
Le robot 'Baxter' de l'entreprise Rethink Robotics:
'Sawyer', le deuxième robot collaboratif de rethink Robotics:
Le robot collaboratif de ABB Robotics, 'YuMi':
Travail Réalisé
Dans cette partie, je vais détailler l'ensemble du travail que j'ai réalisé lors de ces séances de projet.
Partie Préliminaire
Terminer la conception du bras robotique
Afin de terminer la conception du bras robotique Moveo BCN3D présent au Fabricarium, il convient d'achever la création de plusieurs éléments du bras. Il faut entre autre créer le préhenseur venant se placer au bout du bras ainsi que la base sur laquelle viendra se fixer notre robot démonstrateur.
Préhenseur
Pour le préhenseur du bras, je pensais réutiliser le préhenseur que j'ai dû designer lors des séances "d'initiation à la mécatronique" lors du dernier semestre. Ce préhenseur (présenté ci-dessous) à été réalisé sous le logiciel de CAD en ligne 'onshape'. Ce logiciel a pour intérêt de sauvegarder chacune des création sur un cloud, ce qui nous permet d’accéder à nos fichiers depuis n'importe quel PC.
Le point fort de ce type de préhenseur est qu'il peut prendre des objets ronds ou plats grâce aux biellettes qui permettent à la pince de se courber pour s'adapter à la forme de l'objet.
Ci-dessus, le préhenseur monté après que toutes les pièces aient été imprimé. Des vis sont utilisées afin de servir d'axes. De plus j'ai rajouté des capteurs de force au bout des doigts de la pince (photo de droite). Leur intérêt est de mesurer la force appliquée à l'objet entre les doigts et donc de savoir si on exerce une trop grosse pression sur l'objet. Les 2 câbles de chaque capteurs ont été collés ensemble avec du chatterton afin d'éviter leur dispersion et ainsi diminuer le risque qu'ils s'arrachent durant une tâche.
Cela conclut la partie "réalisation du préhenseur".
Base du robot
Pour ce projet, il faut également créer une base pour accueillir le bras. Cette base devra être assez lourde et assez solide afin de supporter le poids du robot ainsi que de sa charge.Cela devrait suivre l'exemple suivant:
Ci-dessous, le plan de menuiserie pour le perçage de la plaque qui servira de support pour le bras:
Fichier:Support Cobot.pdf
Réalisation des devis
-Devis du 16 octobre 2017:
Le bras robotique ayant déjà été commencé lors de l'année précédente par le fabricarium, une commande pour les moteurs avait déjà été faite. Malheureusement, le fournisseur de ces moteurs est devenu injoignable et n'a pas livré les moteurs. Je dois donc réaliser un devis afin d'acheter tout le nécessaire pour motoriser le bras ainsi que tous les capteurs dont j'aurai besoin pour le transformer en cobot.
Après quelques recherches, le devis qui est ressorti et qui a été validé par les tuteurs du projet est le suivant:
https://drive.google.com/open?id=0ByKP9w_p1fHAMUVXT2txS0hKT2s
Ce devis est également consultable dans la partie 'Matériel Emprunté' consultable en bas de page.
Motorisation du bras Robotique
La conception du bras étant terminée. Il faut désormais motoriser le bras afin de le faire bouger. Le bras bouge au travers de 6 moteurs, chacun contrôlé par un driver TB6560. L'ensemble des drivers est contrôlé par un RAMPS qui s'occupe de gérer les ordres pour chaque moteur, pour les ventilateurs mais il peut également gérer un servo-moteur.
Les drivers TB6560 ont pour particularité de laisser un couple de maintien dans les moteurs même lorsque ils ne sont pas utilisés. Cela permet donc que le bras robotique ne s’effondre pas lorsque nous ne commandons plus les moteurs.
Comme vous pouvez le voir sur la photo de gauche, chacun des moteurs entraine une poulie, également imprimée 3D. Cette poulie entraine une courroie synchrone dentée reliée aux secteurs dentés du bras robotique.
Pour une question d’esthétisme, le bloc d'alimentation 220V->24V a été fixé sous le socle du robot. Une boite a également été réalisée afin de stocker les 6 drivers ainsi que pour stocker le Ramps. Le but étant de cacher ces drivers entourés de câbles tout en les laissant à proximité du bras sans trop les éloigner.
Le schéma de montage adopté pour le branchement du moteur à la TB6560 et du TB6560 au Ramps 1.4 est le suivant:
Pour l'ensemble des moteurs, il a fallu agrandir la longueur des fils afin de pouvoir les relier jusque aux drivers.
Tous les moteurs possèdent 4 fils: un noir correspondant au A+, un vert correspondant au A-, un rouge correspondant au B+ et un bleu correspondant au B-. Mais pour deux moteurs, celui de la pronation/supination et le moteur du poignet. Il convient donc de faire un tableau d'équivalence des câbles pour signaler quel fil de couleur devient quelle couleur et à quelle phase ils correspondent:
Couleur du fil | Nouvelle couleur | Phase correspondante |
---|---|---|
Moteur Poignet: | ||
Rouge | Noir | A+ |
Jaune | Rouge | B+ |
Bleu | Vert | A- |
Blanc | Bleu | B- |
Couleur du fil | Nouvelle couleur | Phase correspondante |
---|---|---|
Moteur Pronation/Supination: | ||
Orange | Violet | A+ |
Orange & Blanc | blanc | A- |
Rouge | Rouge | B+ |
Rouge & Blanc | Marron | B- |
Noir | Noir | A- |
Noir & Blanc | Bleu | A+ |
Jaune | Jaune | B- |
Jaune & Blanc | Bleu | B+ |
Après discussions avec Monsieur FLAMEN, j'ai dû changer la position de mon bloc d'alimentation. En effet, celui-ci était placé trop proche du bord de la planche sous le robot et présentait des risques de blessures par électrocution. J'ai donc décider de la placer plus profondément sous la plaque de telle façon à ce que personne ne puisse toucher le bloc d'alimentation ou le convertisseur en voulant soulever le robot. Des cavaliers ont également installés afin de prévenir l'arrachage des câbles.
Les moteurs sont donc installés et le câblage fait et protégé. Le bras est donc prêt à être utilisé de façon perenne sans risque de dégradation matérielle. Il me faut maintenant commencer le codage du robot via ma carte arduino MEGA 2560.
Partie 1: Base du mouvement
Mouvement du bras sur 1 axe en boucle ouverte
Maintenant que le moteur de la base est reliée aux cartes de commandes, nous pouvons commencer à le faire bouger. Pour cela, nous nous servons d'une carte Arduino Mega 2560. Le programme sera implanté sur cette carte et commandera le Ramps 1.4 qui est un shield Arduino et qui vient donc se placer par dessus la carte.
Pour faire bouger le moteur pas-à-pas, une librairie 'stepper' est déjà présente dans les librairies par défaut Arduino, mais cette dernière n'est pas très adaptée pour la commande de plusieurs moteurs. C'est pour cela que je me sers de la librairie 'AccelStepper[1]' qui simplifie le code pour ajuster plus précisément la vitesse du moteur, l’accélération ou effectuer des mouvements complexes.
Le code et le résultat sortant est le suivant:
Ce programme fait bouger la base du bras. L'opérateur le met dans une position initiale prédéfinie, puis le bras fait une rotation pour se mettre dans la position 'HOME'. Un arrêt d'urgence a été implémenté afin de stopper le Homing en cas de problèmes. Il suffira à l'utilisateur d'envoyer un 1 sur le port série d'Arduino. Ce dernier est utilisé afin de visualiser la valeur des variables ainsi que l'avancée du programme.
Le problème majeur du moteur pas-à-pas, est qu'il ne connait pas sa position au démarrage. Ainsi lorsque le moteur démarre, sa position est donc considérée comme la position 0. Le robot ne peut donc pas bouger pour se mettre en position HOME quelle que soit sa position initiale. En effet, si le robot commence en bout de course, il cherchera à continuer à tourner, forçant sur la poulie et la courroie pour continuer sa rotation.
Mouvement du bras en chaine cinématique directe
Moteur | Code Switch TB6560 | Nombre de pas | nombre de degrés | vitesse | |
---|---|---|---|---|---|
Base | 111 101100 | 7800 | 180° | 2000 | |
Épaule | 100 001100 | 4360 | 180° | 1000 | |
Coude | 101 001000 | 5946 | 225° | 1000 | |
Rotation poignet | 101 001100 | 2100 | 450° | 500 | |
Poignet | 011 001100 | 4300 | 235° | 1000 |
Maintenant que le mouvement sur la base est maitrisé et que la bibliothèque AccelStepper est maitrisée. Je peux étendre mon programme à l'ensemble du bras robotique.
L'idée est, comme pour la base, de créer un programme où l'ensemble du robot se met en position HOME. Puis l'utilisateur peut faire bouger chacun des axes à son envie et peux également le faire revenir à sa position de repos. Il faudra également gérer les sorties de la zone d'activité.
Je décide donc de créer ma propre librairie arduino que je nomme 'Moveo'. Elle contiendra l'ensemble des fonctions dont j'aurai besoin pour faire bouger mon robot. Voici la classe que je créé:
On retrouve les fonctions suivantes:
- Une fonction de récupération de l'axe demandé.
- Les fonctions de mouvement de chaque axe.
- Les fonctions de récupération des positions des moteurs.
- Les fonctions de retour en position HOME et de repos.
- La fonction de calcul des zones impossible à atteindre pour les moteurs.
On peut donc appeler ces fonctions en écrivant 'moveo.PositionP()' pour récupérer la position du poignet.
L'utilisateur communique donc par le biais de la liaison série avec le bras robotique. Chacune des positions est rappelée et il n'y a aucun risque que le robot soit endommagé par un mauvais ordre de mouvement.
Au dessus, vous pouvez voir l'affichage sur le port série du début du programme jusque à la mise en position HOME. La vidéo ci-dessous montre quant à elle les mouvement du robot durant ces phases.
Video de mise en position HOME:
REMARQUE:Le robot rencontre un problème majeur, un souci thermique dû à l'échauffement des moteurs vient gêner la rotation des poulies. En effet, pour garder un couple de maintien, je dois continuer d'envoyer du courant dans les moteurs. Lorsque le moteur bouge, cette énergie est transformée majoritairement en mouvement, et un peu en chaleur. Mais lorsque le moteur est à l'arrêt, cette énergie est majoritairement dissipée en chaleur. Cela résulte en une grosse hausse de chaleur dans le moteur et dans son axe. Si le moteur est alimenté pendant trop longtemps, la poulie en PLA commence à se déformer et à se désaxer. Ce qui fait que je ne peux plus me servir des axes au poulies déformée.
La solution apportée est donc de monter un dissipateur sur le moteur couplé à un ventilateur. Le ventilateur serait commandé par le Ramps 1.4 qui possède des entrées de contrôle pour ventilateur.
C'est le robot avec le programme à cet avancement du projet qui sera présenté aux journées portes ouvertes de Polytech Lille ainsi qu'à l'évènement "Maker Faire" du 9-10-11 février 2018.
'Ce programme ainsi que la bibliothèque créée sont consultables dans la partie des livrables.
Partie 2: Mode collaboratif sur 1 axe
Détection d'un obstacle sur le premier axe
Le robot est désormais capable de se mouvoir comme voulu via la liaison série. Mais ce n'est pas encore un robot collaboratif. Pour cela, il doit être capable de détecter une collision, ce qui va maintenant être le nouvel objectif de mon projet.
Pour détecter ces collisions, je décide de regarder du coté des moteurs. En effet, en cas de rencontre avec un obstacle, il y aura forcement une hausse du couple dans le moteur de l'articulation. Je décide donc de monitorer mon courant via une sonde de courant. Ce dernier est relié au couple par la relation Cm = Kc.Im, avec Cm le couple moteur, Kc la constante de couple et Im le courant traversant le moteur.
Pour commencer, j'utilise un oscilloscope afin de voir "la tête" du courant présent dans l'une des phases du moteur du coude. Les résultats sont les suivants :
je vais maintenant mettre un obstacle sur la trajectoire de mon robot lors d'une levée du coude. Le but est de visualiser les hausses de courant dans le moteur.
On peut remarquer des sinusoïdes plus grandes que d'autres. Ce sont les hausses de couple qui l'entrainent. Mais ce pics ne reste pas sur plusieurs période car lorsque le moteur rencontre un obstacle en montant, il redescend puis remonte jusque à re-rencontrer l'obstacles. Ce pics d'une amplitude de 1.9A s'élève de 0.3A au dessus des cycles normaux (1.6A). Je vais donc essayer de détecter ces pics.
Je n'arrive pas encore a récupérer de données sur les PINs auxiliaires du Ramps. J'utilise donc une arduino UNO pour l'instant afin de récupérer les données des transducteurs de courant. En effet, les documentations restent assez vague quant aux numéros de PINs de la partie AUX ou SERVO ([2])
Je lance un programme qui fait tourner la base en continu. Puis je lance un programme sur mon arduino UNO qui est connectée au transducteur de courant qui visualise le courant de la base. J'utilise alors l'outil 'Traceur Série' de l'IDE arduino pour visualiser le courant mesuré. Le programme en question affiche les formes d'onde du courant dans le moteur ainsi qu'un signal d'alarme. Lorsque un pic de courant est détecté, le signal d'alarme passe à 255 comme sur l'image ci-dessous:
A gauche, en bleu, le courant dans le moteur, en rouge le signal d'alarme. Lorsque je place ma main pour bloquer le bras, un pic ( positif ou négatif selon le sens de rotation ) apparait. Le signal d'alarme rouge passe donc à 255.
La détection d'obstacle est donc réussie.
Pour clore cette partie, je vais me pencher sur un moyen de n'utiliser que le Ramps et non la carte arduino UNO couplée au ramps pour détecter l'obstacle. Je pourrai alors faire un programme combinant la détection d'obstacle sur la rotation de la base et le mouvement, sujet de la prochaine partie.
Remarque: Le monitoring du courant se fait via un capteur à induction LEM qui est installé sur la phase B- du moteur. Le fait de monitorer sur plusieurs phases ajoute du bruit dans le signal qui ne devient plus exploitable.
Reprise du mouvement après obstacle
J'ai fait plusieurs recherches autour du ramps, 4 possibilités s'offraient à moi pour récupérer le courant du moteurs:
- La première était d'utiliser une arduino UNO sur laquelle brancher toutes les sondes, puis si une collision était détectée, la carte enverrait une donnée à l'arduino MEGA pour lui dire de stopper le mouvement.
- La deuxième solution était d'utiliser des PINs inutilisés du ramps comme le X_MIN_PIN, de le convertir en entrée pour lire la donnée dessus.
- La troisième était d'utiliser les PINs AUX du ramps. Certains étant analogiques, la possibilité de récupérer la donnée semblait viable.
- La dernière solution était d'utiliser les entrées associées aux sondes de températures pour récupérer la mesure.
La solution que j'ai finalement retenu est la dernière. En effet la première est viable, mais l'utilisation d'une carte qui communiquerai avec la MEGA n'est pas optimale. Elle pourrait néanmoins selon moi être revue dans le cas où on utilise plus de capteurs. En rajoutant les capteurs de proximité, les capteurs laser, l'accéléromètre et les transducteurs, on peut facilement imaginer la UNO avec un programme interne qui gèrera les capteurs, calculera les risques et qui enverra les données si nécessaires à la MEGA. La deuxième solution n'a pas non plus été retenue car elle ne retourne rien, en effet j'ai essayé de tourner les PINs en sortie mais la seule chose que je pouvais lire n'était que du bruit. La troisième solution, qui était d'utiliser les AUX de la ramps pour lire les mesures, n'a pas été retenue car je n'arrivais pas à retrouver les PINs de la MEGA correspondants aux PINs de la ramps. Je n'ai donc pas pu utiliser cette solution car ces PINs sont pour la plupart utilisé pour le branchement de cartes SD, écrans LCD... La ramps étant principalement conçue pour les imprimante 3D, elle n'a pas été designé pour qu'on puisse rajouter des capteurs.
J'utilise donc les entrées faites pour les sondes de température sur la ramps. Le seul bémol étant que je n'ai que trois entrées, cela me permet d'au moins contrôler la rotation de la base, l'épaule et le coude. La rotation du poignet étant mécaniquement défectueux et le poignet étant hors service pour cause thermique. Les trois entrées sont donc largement suffisantes.
J'alimente donc ma sondes avec les 5V que fourni le ramps et je met le GND et la sortie sur les pins du premier capteur de température.
Je commence donc la création d'un programme simple pour la base: Une rotation de 90° dans un sens, puis de 90° dans l'autre en continu. Pour cela, aucun problèmes, je maitrise la bibliothèque de mouvement des moteurs.
Pour l'instant, j'utilisais la commande 'stepperX.move(value)' suivie d'un 'stepperX.run()' dans un while pour bouger le moteur. Le code que je vais rajouter va se trouver dans la boucle:
Le code est simple, je lui donne le nombre de pas à effectuer, ici 90 degrés (1 degré = 43.33 pas; cf: Mouvement du bras en chaine cinématique directe). Puis je lance le mouvement, dans la boucle, j'effectue un pas et je fais l'acquisition du courant. Si j'ai atteint la position voulue, je sors du while. Si un pic de courant est détecté, je le dis, j'affiche la position où a eu lieu la collision et je lance la fonction 'test_collision' d'où je ne sortirai que lorsque l'obstacle ne sera plus présent.
Le contenu de la fonction est le suivant:
Lorsque une collision est détectée, j'ai eu l'idée d'agir comme un aveugle le ferai. Une fois la collision détectée, je me stoppe pendant 1 seconde puis je regarde toutes les 500ms si l'obstacle est toujours présent. Ainsi le bras tourne et si il ne rencontre plus rien sur 300 pas, il considère l'obstacle comme disparu. Il reprend donc sa tâche. Si l'obstacle est toujours présent, il faudra quelques pas pour détecter de nouveau la hausse de courant dans le moteur. C'est pour cela que si l'obstacle est détecté dans les 400 pas, il est compté comme étant toujours présent, et la position est réinitialisée à sa position au départ qui est mise en entrée de la fonction.
Il faut maintenant vérifier que le robot répond bien aux normes en vigueur. Ces normes sont données par l'INRS au paragraphe 4.5 de la brochure: Fichier:Securité des equipements Prévention des risques mécaniques.pdf.
Ce paragraphe se résume dans le tableau suivant:
Dans notre cas, nous suivrons la série de valeurs 2 car le robot collaboratif est considéré comme compliant. Il faut donc calculer l'énergie à l'impact créée par le robot:
La vitesse du robot est de 0.24 m/s.
Son poids étant de 4.8 Kg pour la partie mobile.
Son énergie à l'impact est donc de 0.07J.
Le robot rentre donc plus que largement dans les normes. Une si faible énergie est due au fait que le robot soit en PLA et ne se déplace pas à si grande vitesse. La norme a quant à elle été faite pour des robots fait en matières métallique et se déplaçant à des vitesses supérieures au m/s.
Le robot peut donc être considéré comme collaboratif sur le premier axe.
Partie 3: Mode collaboratif sur 2 axes
Détection d'un obstacle sur le deuxième axe
Pour ajouter le mode collaboratif sur le deuxième axe, celui de l'épaule, il convient de suivre le même cheminement que pour le premier axe: détection d'obstacle, reprise de tâche puis fusion des 2 programmes.
Je visualise tout d'abord le courant qui passe dans le moteur par le biais de mon transducteur de courant. Ainsi je peux connaitre les valeurs Min et Max du courant dans mon moteur et fixer les seuils d'alarme. Ce seuils sont de à remplir pour la limite basse et à remplir pour la limite haut.
Une fois que je suis capable de détecter l'obstacle et d'arrêter le robot. Le programme pour la reprise de tâche reste fondamentalement le même.
Matériel emprunté
Livrable
Évaluation intermédiaire(21/12/2017):
- Mémoire Intermédiaire: Fichier:RapportIntermédiaire PFE25 HART.pdf
- Soutenance intermédiaire: Fichier:Soutenance Intermédiaire PFE25 HART.pdf
Évaluation finale(22/02/2018):
- Mémoire Final:Fichier:Mémoire Final PFE25 HART.pdf
- Soutenance Finale: Non disponible
Programme mouvement en cinématique directe:
Fichier:Programme PFE25 Moveo.zip
(Programme + bibliothèque <Moveo.h>)