Projet IMA3 P1, 2016/2017, TD2
Sommaire
Projet IMA3-SC 2016/2017 : Robot quadripode
Cahier des charges
Description du système
Notre projet est de réaliser un robot quadripode contrôlé par notre interface web. Celui ci aura pour objectif de :
- se déplacer sur ses pattes dans les directions indiquées par l'utilisateur.
- Se déplacer à la vitesse demandée par l'utilisateur qui sera plus ou moins rapide.
Chaque pattes possédera 3 articulations afin de faciliter le déplacement du robot. Un des servo-moteur permettra de faire avancer ou reculer la patte, le deuxième permettra au robot de se surélever ou de s'abaisser et le dernier permettra de poser la patte perpendiculaire par rapport au sol.
En fonction du temps que nous prendrons à réaliser notre projet, nous aurons peut être la possibilité d'ajouter une fonctionnalité de vidéo à notre robot. Nous aurons alors la possibilité de voir à travers le robot sur notre interface web.
Le matériel
Le matériel pour réaliser notre robot quadripode est relativement simple . Nous aurons besoin d'un accès a un ordinateur équipé d'un système linux . Pour le quadripode , nous aurons besoins de :
- Une raspberry Pi ( de préférence une raspberry pi zéro en raison de sa petite taille)
- 12 micro servos moteurs pour le mouvement des pattes , soit 2 servos-moteurs par patte .
- Un module wifi pour la raspberry Pi.
- Toutes sortes d'écrous et vis dont nous détaillerons le contenu dans le futur.
- En option , une caméra compatible raspberry pi , pour transmettre une vidéo en direct sur l'interface web, ainsi que son raccordement.
- Une breadboard pour tester les circuits .
- Un câble nappe pour raspberry pi .
La liste réalisée est provisoire et pourra subir de légers changement avant le début de projet (les types d'écrous et vis seront détaillés) . Nous aurons en plus des éléments précédents , besoin d'un accès a l'imprimante 3D afin d'imprimer les différentes parties du quadripode .
Séance 1
Partie électronique
La conclusion que nous pouvons apporter après cette première séance de projet est que la partie électronique de ce projet ne s’entendra pas sur les 3 seéances puisque, suite à des discussions avec les différents professeurs, nous avons vu qu'il était plus adéquat de ne pas utiliser de FPGA pour la construction de l'araignée vu que nous utilisons un grand nombre de moteurs. Nous allons donc utiliser une unique carte Arduino qui contrôlera l'intégralité des moteurs.
Pour répondre au cahier des charges du projet, nous avons donc, quand même, programmé un FPGA contrôlant un des moteurs afin de manipuler tous les outils mis à notre dispositions. Nous allons donc vous présenter, dans cette partie, comment nous avons fait fonctionné notre moteur grâce au FPGA.
Avant de pouvoir programmer notre FPGA, nous avons fait des recherches sur la data-sheet du moteur pour déterminer son mode de fonctionnement.
Nous pouvons voir grâce à la data-sheet que, pour que notre moteur fonctionne, il faut que le VCC(=5V) soit connecté au câble rouge, la masse au câble marron et le moduleur de largeur d'impulsion (PWM) au câble orange. On remarque également que notre moteur fonctionne à une fréquence de 50Hz (donc une période de 20 ms) et que le sens de rotation dépends du temps à l'état haut du signal. C'est à dire que pour que le moteur tourne dans le sens anti-horaire, il faut que le duty cycle (rapport cyclique) soit à 1 ms, pour aller dans le sens horaire, il doit être de 2 ms et pour que le moteur s'arrête au centre, le rapport cyclique doit être de 1.5ms. Nous allons donc jouer sur ce rapport cyclique afin de changer le sens de rotation du moteur.
Le problème qui s'est posé à nous est d'être assez précis pour pouvoir modifier de manière efficace le rapport cyclique. Étant donné que nous souhaitons avoir une précision de 0.1 ms sur une période de 20 ms, il nous faut donc 200 coups d'horloge (20/0.1). Comme nous fonctionnons à 50Hz, la fréquence du FPGA sera de 50*200=10000 Hz.
Pour faire fonctionner le moteur dans les 2 sens, nous devons maintenant "dire" au FPGA que quand notre compteur arrive a 200, il passe à 1. Il reste à 1 jusqu'a la valeur choisie puis passe à 0 jusque 200.
Comme vous pouvez le voir sur l'image ci-dessus, nous avons fixé le BUS_JS à la valeur 200, ce bus est connecté à un comparateur et au compteur afin de compter jusque 200. Nous avons ensuite défini le Configurable Digital IO pour mettre la valeur souhaitée pour le fonctionnement du moteur (comprise entre 10 et 20). Cette valeur est mise dans le second comparateur (avec la valeur 200) et nous envoyons ceci dans le moteur qui nous donne la courbe suivante.
Nous avons donc, dans la vidéo ci-dessous, mis la valeur 10 et 20 dans le Configurable Digital IO et nous remarquons que le moteur tourne bien dans les 2 sens.
Partie informatique
Pour l'application web, nous avons décidé d'utiliser Node ainsi que Angular et les modules socket.IO, serialport de Node pour envoyer nos données vers l'arduino via une Raspberry. Nous voulions utiliser ces technologies récentes afin d'avoir une petite expériences avec celles ci et pour pouvoir apprendre à les utiliser. Angular nous permettant de créer une applicaton dynamique aisément. Cette application web représente un joystick qui nous servira à faire déplacer notre robot. Celui ci devra permettre de dire au robot dans quelle direction il doit se déplacer et à quelle vitesse. De plus, il affichera sur la page web la direction que l'utilisateur est en train de donner.
Nous avons tout d'abord réalisé le joystick avec angular. Celui ci est réalisé grâce à 2 images. Une pour l’arrière plan du joystick qui est fixe et l'autre pour le joystick en lui même qui se déplace lorsque l'utilisateur clic sur celui ci et déplace la souris. Lorsque l'utilisateur reclic sur le joystick, celui ci se repositionne au centre.
Nous utilisons donc 2 événements :
- lors d'un clic : une variable est mise à jour "mouseIsDown" pour savoir si le joystick doit suivre la souris ou si il doit aller se repositionner en (0,0).
- lors d'un mouvement de la souris si "mouseIsDown" est égale à 1 : On va alors faire modifier le css de l'image pour faire en sorte que celle ci suive la souris. Celle ci fût la plus complexe à réaliser car il fallait bien calculer la position de l'image en fonction de celle de la souris mais aussi faire en sorte que l'image ne sorte pas de la zone délimitée par le socle du joystick. Nous avons pour cela utilisé beaucoup de formules de trigonométrie.
La taille du socle de notre joystick étant de 200px x 200px, pour vérifier si nous somme bien dans le cercle, nous testons si la norme entre la position x et la position y est bien inférieur à 100. Si nous sommes bien dans le cercle, il suffit de donner la position de la souris à l'image. Cependant, si la souris n'est pas dans les limites du cercle, nous devons recalculer la position de l'image afin qu'elle se positionne dans la même direction que la souris mais à la limite de la zone du joystick. Nous avons donc calculer l’hypoténuse puis l'angle par rapport à 0 sur le cercle trigonomètrique. pour repositionner le joystick au même angle mais avec une norme de 100 (le maximum sur le cercle que nous avons).
Séance 2
Partie électronique
Partie mécanique
Le but premier de ce projet n'était pas de faire de la mécanique mais nous devions passer obligatoirement par cette étape pour que l'araignée puisse se déplacer. Cette partie nous a pris énormément de temps en dehors des séances.
- Réalisation des pièces nécessaires à la construction de l'araignée :
Nous avons décidé d'imprimer les pattes de notre araignée avec l'imprimante 3D du fabricarium en nous aidant d'un projet du même type trouvé sur internet : [1]. Cependant, les servos-moteurs mis à notre disposition pour ce projet étant de dimensions différentes de ceux utilisés sur le projet précédemment cité, nous avons du redimmensionner les différents pièces sur Freecad. Voici un aperçu des pièces finales Freecad :
PHOTO DES PIECES FREECAD
Nous avons du réaliser de nombreux tests d'impression avant de parvenir à la taille idéale pour l'assemblage des différentes pièces. Une fois les pièces nécessaires à l'assemblage des pattes imprimées, il nous fallait le corps de l'araignée. Nous avons alors pour cela découpé une forme simple en Plexiglas (Nous remerçions d'ailleurs M. Redon pour son Plexiglas) à l'aide de la découpe laser du Fabricarium.
Partie informatique
ajout des sockets
main.js :
angular.module('spiderApp') .controller('MainCtrl', function () { this.awesomeThings = [ 'HTML5 Boilerplate', 'AngularJS', 'Karma' ]; });
deplacement.js :
angular.module('spiderApp').controller('deplacementCtrl', function($scope) { $scope.positionX=200; $scope.positionY=200; $scope.mouseIsDown=false; posXstr=$scope.positionX.toString(); posYstr=$scope.positionY.toString(); $scope.posjoy = { "left" : posXstr+"px", "top" : posYstr+"px", "position" : "absolute", "height" : "100px" }; var socket = io.connect('http://172.26.79.4:8080'); $scope.clickDown = function(event){ if($scope.mouseIsDown==false) { $scope.mouseIsDown = true; $scope.positionX = event.target.offsetLeft+(event.offsetX-50); $scope.positionY = event.target.offsetTop+(event.offsetY-50); posXstr=$scope.positionX.toString(); posYstr=$scope.positionY.toString(); $scope.posjoy = { "left" : posXstr+"px", "top" : posYstr+"px", "position" : "relative", "height" : "100px" }; } else { $scope.mouseIsDown = false; $scope.positionX = 200; $scope.positionY = 200; console.log($scope.mouseIsDown); posXstr=$scope.positionX.toString(); posYstr=$scope.positionY.toString(); $scope.posjoy = { "left" : posXstr+"px", "top" : posYstr+"px", "position" : "relative", "height" : "100px" }; } socket.emit('message', ($scope.positionX-200)+','+(-($scope.positionY-200))+';'); }; $scope.moveJoystickOutside = function(event) { if ($scope.mouseIsDown == true) { window.setTimeout(function() { ecartX=parseInt(getComputedStyle(joystick).left, 10); ecartY=parseInt(getComputedStyle(joystick).top, 10); //on retranche 200 la marge du boutton araigné jusqu'au bord du div #joystick + 50 pour arriver au centre de l'image //+20 en Y à cause du footer qui sera toujours de taille constante positionXProvisoire = event.clientX - ecartX -250; positionYProvisoire = -(event.clientY - ecartY-330); console.log("posi prov X: "+positionXProvisoire); console.log("posi prov Y: "+positionYProvisoire); //partie dans le cercle if ( Math.sqrt(Math.pow(positionXProvisoire/100,2)+Math.pow(positionYProvisoire/100,2)) >= 0 && Math.sqrt(Math.pow(positionXProvisoire/100,2)+Math.pow(positionYProvisoire/100,2)) < 1) { //50=moitié de la dimension de l'image du bouton avec l'araignée. //a retrancher car on veut le centre de l'image et pas le coin supérieur gauche. $scope.positionX=event.clientX-ecartX-50; $scope.positionY=event.clientY-ecartY-130; console.log("posi X: "+$scope.positionX); console.log("posi Y: "+$scope.positionY); posXstr = $scope.positionX.toString(); posYstr = $scope.positionY.toString(); $scope.posjoy = { "left": posXstr + "px", "top": posYstr + "px", "position": "relative", "height": "100px" }; } //partie en dehors du cercle else { hypothenuse=Math.sqrt(Math.pow(positionXProvisoire,2)+Math.pow(positionYProvisoire,2)); angle=Math.acos(positionXProvisoire/hypothenuse); if(-(event.clientY - ecartY-330)<0) { $scope.positionX=parseInt((Math.cos(angle)*100)+200); $scope.positionY=parseInt((Math.sin(angle)*100)+200); } else { $scope.positionX=parseInt((Math.cos(angle)*100)+200); $scope.positionY=parseInt((-Math.sin(angle)*100)+200); } posXstr = $scope.positionX.toString(); posYstr = $scope.positionY.toString(); $scope.posjoy = { "left": posXstr + "px", "top": posYstr + "px", "position": "relative", "height": "100px" }; } //attendre un peu pour ne pas embrouiller la transmition du signal socket.emit('message', ($scope.positionX-200)+','+(-($scope.positionY-200))+';'); }, 10);//delay en millisecondes } }; });
server.js
var express = require('express');
var app = express();
var server = require('http').Server(app);
var io = require('socket.io')(server);
var SerialPort = require("serialport");
var port = new SerialPort("/dev/ttyUSB1",{baudRate: 115200, parity : 'none', autoOpen :false});
app.use(express.static(__dirname+"/../.."));
app.use(express.static(__dirname+"/../../../bower_components/"));
port.open(function (error){
if(error) { console.log('Error while opening the port ' + error); } else { io.on('connection', function(socket) { console.log('new connection');
socket.on('message', function (message) { port.write(message, function(err) { if (err) { return console.log('Error on write: ', err.message); } else { console.log('Position : ' + message); } }); });
}); }
}); server.listen(8080, function() {
console.log('server up and running at 8080 port');
});
Séance 3
Partie électronique
Partie informatique
envoi des données sur le port série
Configuration de la Raspberry :
- Configuration IP :La Raspberry doit pouvoir communiquer avec l'ordinateur de la salle de projet pour pouvoir avoir accès à l'application web ainsi qu'au réseau de Polytech pour pouvoir installer les différents paquetages de Node. Pour cela, on modifie le fichier /etc/network/interfaces en remplaçant l'IP présente dans le fichier par celle de notre ordinateur de salle de projet et on configure en static. La Raspberry peut ainsi communiquer avec l'ordinateur. Ensuite, on indique le serveur DNS dans le fichier /etc/resolv.conf par : nameserver 193.48.57.34 La Raspberry peut ainsi communiquer avec le réseau Polytech
- Installation de Node sur la Raspberry et déplacement des fichiers de code. Nous avons été confronté à de nombreuses difficultés pour cette partie. En effet, notre code faisant intervenir de nombreux modules, il a fallu tous les installer et nous avons rencontré des problèmes de version entre node lui même et les modules. Nous sommes finalement parvenu à l'installation en installant des versions compatibles entre elles. On introduit les fichiers de code sur la Raspberry
- Configuration de la Raspberry pour que le serveur se lance au démarrage. Pour pouvoir lancer le serveur au démarrage, on déplace les fichiers d'installation de Node dans /usr/local/sbin ainsi que nos programmes puis on modifie le fichier /etc/rc.local dont le contenu est exécuté à chaque démarrage de la Raspberry. On ajoute alors la ligne : /usr/local/sbin/node /usr/local/sbin/spiderS6/app/scripts/controllers/server.js & Ainsi, le serveur est lancé à chaque démarrage de la Raspberry.
Partie mécanique
Assemblage des pièces :
Une fois en possession de toutes les pièces, nous avons procédé à l'assemblage. Nous avons alors, pour chaque patte :
- Placer les servos-moteurs à leur emplacement destiné en les collant pour ne pas qu'ils bougent - Fixer le tibia sur le coude à l'aide d'une vis d'un coté et de colle de l'autre - Fixer l'ensemble tibia-coude sur l'épaule à l'aide d'une vis d'un coté et de colle de l'autre
Voici le rendu des pattes assemblées :
Une fois les pattes assemblées, nous devions les fixer sur le corps. Nous voulions au départ les coller mais même avec de la superglue, elles ne tenaient en raison de la différence de matériau entre les pattes et le corps. Nous avons alors percer le corps à quatres emplacements pour y visser les pattes avec l'aide de M.Thierry Flamen, responsable du labo d'électronique de Polytech (que nous remerçions grandement).
La partie mécanique de notre araignée est ainsi terminée. Malheuresement, nous n'avons pas pris de photo une fois cette phase finie.
Séance supplémentaire 1
Partie électronique
La partie mécanique étant terminée, nous avons pu procéder au câblage des servos-moteurs sur l'arduino et la bread-board.
Voici une photo du rendu de l'araignée câblée :
Partie informatique
Conclusion
En ayant apporté beaucoup de notre temps-libre, nous sommes finalement parvenus à faire fonctionner notre araignée. Cependant, par manque de temps, notre araignée ne remplit pas complètement le cahier des charges. En effet, nous n'utilisons pas les modules XBee puisque nous avons rencontré des problèmes pour les configurer et notre araignée ne se déplace que dans une seule direction et à une vitesse constante. Ayant sous estimé l'épaisseur et le poids de l'ensemble arduino + bread-board + câbles, nous n'avons pas pu les fixer en dessous du corps comme prévu et cette ensemble traîne donc par terre... Voici le rendu vidéo de notre projet :
METTRE LA VIDEO
Ce projet de Systèmes-communicants nous a tout d'abord permis d'avoir une idée de ce qu'est la filière système communicants (QUE NOUS CHOISIRONS!). Ensuite il nous a permis de nous améliorer sur la méthodologie de la gestion de projet en terme de gestion du temps, de tests, de répartition des tâches. Enfin, la pluralité disciplinaire de ce projet a permis de satisfaire tous les membres du groupe.
En ayant eu plus de temps, nous aurions pu répondre complètement au cahier des charges, à savoir profiter pleinement de la définition d'un joystick pour contrôler notre araignée. Nous aurions aussi pu réaliser une carte électronique afin de ne pas être encombré par tous les câbles, ce qui aurait enrichi la partie électronique et amélioré l'esthétique de notre projet en évitant que notre araignée ait à tracter des composants.