Binome2017-4 : Différence entre versions

De Wiki de bureau d'études PeiP
(Code)
(Code)
Ligne 211 : Ligne 211 :
 
       push = 0;  
 
       push = 0;  
 
     }
 
     }
 
+
 
   void setUp() {
 
   void setUp() {
 
     pinMode(Ain1, OUTPUT);
 
     pinMode(Ain1, OUTPUT);
Ligne 217 : Ligne 217 :
 
     pinMode(Ain2, OUTPUT);
 
     pinMode(Ain2, OUTPUT);
 
     digitalWrite(Ain2, HIGH);
 
     digitalWrite(Ain2, HIGH);
     pinMode(APWM, OUTPUT);
+
     pinMode(APWM, OUTPUT);  
   
 
 
     pinMode(Bin1, OUTPUT);
 
     pinMode(Bin1, OUTPUT);
 
     digitalWrite(Bin1, LOW);
 
     digitalWrite(Bin1, LOW);
Ligne 224 : Ligne 223 :
 
     digitalWrite(Bin2, HIGH);
 
     digitalWrite(Bin2, HIGH);
 
     pinMode(BPWM, OUTPUT);
 
     pinMode(BPWM, OUTPUT);
   
 
 
     pinMode(STBY, OUTPUT);
 
     pinMode(STBY, OUTPUT);
 
   }
 
   }
 
+
 
   void demarrer() {
 
   void demarrer() {
 
     analogWrite(APWM, vi);
 
     analogWrite(APWM, vi);
Ligne 233 : Ligne 231 :
 
     digitalWrite(STBY, HIGH);
 
     digitalWrite(STBY, HIGH);
 
   }
 
   }
 
+
 
   void update_(float dist, int current) {
 
   void update_(float dist, int current) {
 
     if(dist < 400) {
 
     if(dist < 400) {
Ligne 272 : Ligne 270 :
 
     if (flag == 2 and current - last > 1000) {flag = 1;}
 
     if (flag == 2 and current - last > 1000) {flag = 1;}
 
   }
 
   }
 
+
 
   void manuel(decode_results r) {
 
   void manuel(decode_results r) {
 
     if (lastCom != r.value and r.value != 295) {
 
     if (lastCom != r.value and r.value != 295) {

Version du 18 mai 2018 à 10:56

Séance 15/01

Objectif: Créer une proie petite et rapide

Pour ce faire nous aurons besoins d'un émetteur infrarouge, de trois récepteurs infrarouges, d'un sonar et de deux contrôleurs ainsi que leurs moteurs. Pour signifier lorsque l'on est attrapé il nous faudra un capteur de Hall et deux LED.


Séance 16/01

Nous allons utilisé notre propre circuit électrique, où nous nous baserons sur celle donnée sur la page du BE. Nous pensons à ajouter un capteur à effet Hall sur ce circuit. Recherches sur le capteur à effet Hall:

Capteur trouvé: US1881 fonctionne entre 0.5 et 9.5 mT.

Calculateur internet force d'un aimant : [1]


Séance du 18/01

Nous remplaçons le détecteur de ligne par la sonde de Hall. La carte est terminée et nous nous lançons donc sur la forme de notre robot. Nous avons aussi commencé le code sur le logiciel pour Arduino.


Séance du 19/01

Continuation de l'étude des fonctions de l'atmega et création du fichier CAD pour la découpe laser.


Séance du 25/01

Finalisation du fichier de découpe laser et du modèle 3D des pneux.

Pneu binome4 2017-2018.png CAD binome4 2017-2018.png


Séance du 05/02

Utilisation de la découpe laser : Nous avons fait une première découpe qui nous a montré que notre chassis avait des problèmes de dimension qui ne correspondaient pas aux composants comme le moteur. Le modèle du robot a été modifié en conséquence et nous lancerons l'impression du nouveau chassis à la prochaine séance.


Séance du 08/02

Impression de notre nouveau robot et assemblage, tout correspond cette fois-ci. Voici à quoi ressemble notre robot sans sa carte :


Robot APAL11.jpeg Robot APAL12.jpeg


Séances du 12/02 au 26/03

Soudage du circuits imprimés, plusieurs erreurs mais réussite au troisième essai:

Essai 1 : Mauvais régulateur de voltage

Mauvais régulateur de voltage

Essai 2 Impossible de mettre le bootloader sur la carte, la clock représente le principal suspect

Impossible de mettre le bootloader sur la carte, la clock représente le principal suspect


Séances du 09/04 à la fin

Le PCB est enfin terminé, nous avons transféré le code basique rédigé depuis plusieurs séances et testé avec le sonar et les moteurs. Nous avons ensuite ajouté et modifié petit a petit des morceaux de code pour ajuster notre robot.

Partie mécanique et électronique (Adrien Piednoel)

Synthèse

Au cours de ce bureau d'étude, je me suis principalement occupé de ce qui concerne la conception mécanique et l'électronique du robot. L'idée de départ étant d'avoir un robot petit et rapide, mon but était de faire tenir deux moteurs dans le plus petit espace possible. Pour éviter que le robot ne bascule en arrière lorsqu'il avance, j'ai préféré un design basé sur la longueur plutôt que sur la hauteur. Ainsi les piles se situent presque au même niveau que les moteurs et la hauteur est grandement minimisée et la stabilité améliorée. Les dimensions finales du robot sont donc de 17 cm de long pour 7 cm de large et une hauteur d'environ 7 cm définie par le diamètre des roues à l'arrière. Pour ce qui est des roues j'ai dessiné un model pour les découper au laser et modélisé en 3D des pneus adaptés destinés à être imprimés en 3D avec un plastique mou. Tous les fichiers pour la découpe laser et l'impression 3D ont été réalisés grâce aux logiciels de la suite Autodesk.

Pour l'électronique du robot, un Arduino muni d'un Shield adapté n'aurait pas convenu au vu des dimensions du robot, notre choix s'est donc porté sur un PCB fait maison bien plus petit qu'un Arduino. Pour faire ce PCB j'ai donc repris le model proposé sur le wiki que j'ai légèrement modifié pour convenir à nos besoins. Notre robot étant une proie il devait être équipé d'un capteur à effet Hall pour détecter si il se fait attraper. J'ai donc remplacé les sorties initialement prévues pour le détecteur de ligne par des sorties adaptées à un capteur à effet Hall. Au cours de cette opération j'en ai profité pour repositionner ces sorties afin qu'elles se retrouvent à l'arrière du robot, là où le capteur est le plus susceptible de se déclencher. Une fois la plaque reçue j'ai pu commencer à souder tous les composants nécessaires au bon fonctionnement du robot; après deux essais infructueux (le premier à cause d'un mauvais régulateur de voltage et le second à cause d'une clock défectueuse) nous avons enfin réussi à faire une plaque fonctionnelle.

Problèmes et résolution

Lors de la conversion du dessin pour la découpe laser du format...... supporté par Autodesk au format svg nécessaire à la découpe il y a eu un changement dans les dimensions du dessin, ce qui a fait que la première découpe était légèrement trop petite et nous avons du redécouper toute la structure principale à la bonne taille. Ayant sous estimé le poids des piles, leur positionnement s'est ensuite avéré être un problème car le poids se concentrait sur la roue avant, ce qui crée un problème d'adhérence des roues arrière.

Lors des premiers essais du PCB complété, le sonar fonctionnait normalement lorsque la carte était branchée en USB à l'ordinateur mais ne fonctionnait plus lorsque le robot n'utilisait que sa batterie. Ce disfonctionnement était dû à une diode qui provoquait une perte de 0,7 Volt en sortie du régulateur de voltage ce qui impliquait que tout le système ne fonctionnait plus qu'avec 4.5 Volts au lieu de 5. Ce problème a été réglé en cours circuitant cette diode grâce à un fil additionnel soudé sur la plaque. Lors de l'essai du TSOP il était impossible de le faire fonctionner sur les pins initialement prévu à cet effet, le problème proviens certainement du fait que sur le pin d'alimentation du TSOP se situe aussi une LED de test qui prendrait une partie du courant destinée à l'alimentation de récepteur infrarouge. Ce problème ayant été détecté tardivement, je n'ai pas eu le temps de dessouder la led pour vérifier cette hypothèse, nous avons donc contourné le problème en branchant le TSOP sur une des sorties destinées aux servomoteurs qui n'était pas utilisée.


Conclusion

Ce bureau d'étude a été pour moi très enrichissant car il m'a permis de découvrir de nombreux logiciels utiles pour le prototypage et la conception mécanique ou électronique. j'ai aussi beaucoup appris sur les différentes étages de conceptions d'un robot. Ces cours ont donc été extrêmement enrichissants et m'on confortés dans ma volonté de poursuivre mes études dans le domaine de la robotique.

Partie Informatique

Fonctionnement

Pour la partie informatique du robot, j'ai opté pour l'organisation du code en créant différentes classes, une pour chaque composant constituant notre robot; le but étant d'avoir une loop et un code plus lisibles. Nous avons donc une classe pour le sonar, une pour le TSOP et une pour le contrôleur moteur. Nous avons décidé d'utiliser la fonction "millis()" de la loop à la place d'utiliser le "delay" afin d'éviter de mettre notre programme en pause lors des virages ou autres opérations demandant d'attendre un certain temps. Cependant, nous étions contraints d'utiliser un delay dans le sonar car il faut nous faut un intervalle de temps précis et réduit (150 micro secondes) pour les mesures. La première idée était de créer un robot rapide et furtif, qui roule tranquillement quand il se sent en sécurité et accélère s'il aperçoit un prédateur. Initialement, il devait aussi tourner en continuant d'avancer, malheureusement, à cause de problèmes d'adhérence car trop rapide, nous n'obtenions jamais la même rotation lors d'un virage. Nous avons donc modifié le code pour qu'il tourne sur lui même et fasse une sorte de créneau, mais avec la vitesse que lui procurent ses moteurs, il s'est mis à effectuer des drifts de toute beauté ! Après l'ajout du TSOP, finalisant notre robot, et ne sachant plus comment l'améliorer, nous avons entrepris de le télécommander avec la télécommande de test. Nous avons donc ajouté une partie "prise manuelle" remplaçant la détection de prédateur du TSOP par celle du signal de la télécommande.

Code

La classe sonar contient juste une fonction measure qui renvoie une moyenne sur 10 mesures de la distance d'un obstacle face au robot :

class Sonar {
 public:
   unsigned int trigger, echo;
   float tot, mesure;
 public:
   Sonar(int tr, int e) {
     trigger = tr;
     echo = e;
     pinMode(echo, INPUT);
     pinMode(trigger, OUTPUT);
     digitalWrite(trigger, LOW);
   };
 float measure() {
   tot = 0.;
   for (int i=0; i<10; i++) {
     digitalWrite(trigger, HIGH);
     delayMicroseconds(150);
     digitalWrite(trigger, LOW);
     tot += pulseIn(echo, HIGH, 25000UL);
   }
   return tot/10;
 }
};

La classe du TSOP contient une fonction d'update prenant en paramètre le contrôleur moteur car la fonction change directement le comportement du robot. On utilise les fonctions de la bibliothèque pour récupérer la mesure mais je n'ai pas su les inclure directement dans la classe; il y a donc certaines fonctions pour le TSOP utilisées dans la loop.

class TSOP {
 public:
   int pin, com, last;
   decode_results results;
   int tele_last1, tele_last2;
 public:
   TSOP(int p) {
     int pin = p;
     tele_last1 = 0;
     tele_last2 = 0;
   }
 void update_(Controleur controleur, int res, int current) {
   if (res) {
     if (results.value > 2000) {results.value = results.value % 2048;}
     com = results.value;
     if (current - tele_last1 > 500 and (com == 775)) {
       if (controleur.state == 1) {digitalWrite(9, LOW); controleur.state = 0; tele_last1 = current;}
       else {digitalWrite(9, HIGH); controleur.state = 1; tele_last1 = current;}
     }
     if (current - tele_last2 > 500 and (com == 10)) {
       controleur.control *= -1;
       tele_last2 = current;
     }
     last = current;
     controleur.push = 1;
     }
   else if (current - last> 100) {
     controleur.push = 0;
   }
 }
};

La troisième et dernière classe est celle du contrôleur moteur, plus grande et plus incompréhensible que celle du TSOP. Elle contient une fonction setUp en plus car le composant demande plus d'inputs / outputs, une fonction démarrer qui servait plus dans les tests mais qu'on a décidé de garder, la fonction update qui est en fait la partie IA, automatique du robot et une fonction manuel qui permet de contrôler notre robot :

class Controleur {
 public :
   int vi, vA, Ain1, Ain2, APWM;
   int vB, Bin1, Bin2, turn;
   int BPWM, STBY, state, flag;
   int last, current, control; 
   float lastDist;
   int dir, acc, lastCom, push;
 public :
   Controleur(int vi_, int Ain1_, int Ain2_, int APWM_, int Bin1_, int Bin2_, int BPWM_, int STBY_) {
     vi = vi_;
     vA = vi_+10;
     Ain1 = Ain1_;
     Ain2 = Ain2_;
     APWM = APWM_;
     vB = vi_;
     Bin1 = Bin1_;
     Bin2 = Bin2_;
     BPWM = BPWM_;
     STBY = STBY_;
     turn = 0;
     state = 1;
     flag = 0;
     control = 1;
     dir = 0;
     acc = 1;
     lastCom = 0;
     push = 0; 
   }

 void setUp() {
   pinMode(Ain1, OUTPUT);
   digitalWrite(Ain1, LOW);
   pinMode(Ain2, OUTPUT);
   digitalWrite(Ain2, HIGH);
   pinMode(APWM, OUTPUT);   
   pinMode(Bin1, OUTPUT);
   digitalWrite(Bin1, LOW);
   pinMode(Bin2, OUTPUT);
   digitalWrite(Bin2, HIGH);
   pinMode(BPWM, OUTPUT);
   pinMode(STBY, OUTPUT);
 }

 void demarrer() {
   analogWrite(APWM, vi);
   analogWrite(BPWM, vi);
   digitalWrite(STBY, HIGH);
 }

 void update_(float dist, int current) {
   if(dist < 400) {
     digitalWrite(Ain1, HIGH);
     digitalWrite(Ain2, LOW);
     digitalWrite(Bin1, HIGH);
     digitalWrite(Bin2, LOW);
     delay(500);
     digitalWrite(Ain1, LOW);
     digitalWrite(Ain2, HIGH);
     analogWrite(APWM, 110);
     analogWrite(BPWM, 110);
     delay(1000);
     digitalWrite(Bin1, LOW);
     digitalWrite(Bin2, HIGH);
     analogWrite(APWM, 80);
     analogWrite(BPWM, 80);
   }
   else if(dist < 1000) {
     if (flag == 0) {
       digitalWrite(Ain1, HIGH);
       digitalWrite(Ain2, LOW);
       analogWrite(APWM, 110);
       analogWrite(BPWM, 110);
       flag = 2;
       last = current;
     }
   }
   else {
     if (flag == 1) {
       digitalWrite(Ain1, LOW);
       digitalWrite(Ain2, HIGH);
       analogWrite(APWM, 80);
       analogWrite(BPWM, 80);
       flag = 0;
     }
   }
   if (flag == 2 and current - last > 1000) {flag = 1;}
 }

 void manuel(decode_results r) {
   if (lastCom != r.value and r.value != 295) {
     lastCom = r.value;
   }
     if (lastCom == 2) {
       digitalWrite(Ain1, LOW);
       digitalWrite(Ain2, HIGH);
       digitalWrite(Bin1, LOW);
       digitalWrite(Bin2, HIGH);
       analogWrite(APWM, 80);
       analogWrite(BPWM, 80);
     }
     else if (lastCom == 5) {
       analogWrite(APWM, 0);
       analogWrite(BPWM, 0);
     }
     else if (lastCom == 8) {
       digitalWrite(Ain1, HIGH);
       digitalWrite(Ain2, LOW);
       digitalWrite(Bin1, HIGH);
       digitalWrite(Bin2, LOW);
       analogWrite(APWM, 80);
       analogWrite(BPWM, 80);
     }
     else if (lastCom == 4) {
       if (push == 1) {
         analogWrite(APWM, 210);
         analogWrite(BPWM, 70);
       }
       else {
         analogWrite(APWM, 80);
         analogWrite(BPWM, 80);
       }
     }
     else if (lastCom == 6) {
       if (push == 1) {
         analogWrite(APWM, 70);
         analogWrite(BPWM, 210);
       }
       else {
         analogWrite(APWM, 80);
         analogWrite(BPWM, 80);
       }
     }
 }
};

Et finalement, voici le code Arduino utilisant les classes et les fonctions setup() et loop() :

float dist = 0;
int currentTime = 0;
IRrecv irrecv(5);  

Sonar sonar(A4, A3);
Controleur controleur(80, 8, 7, 6, 4, A5, 10, 9);
TSOP tsop(5);

void setup() {
  controleur.setUp();
  controleur.demarrer();
  irrecv.enableIRIn();
  currentTime = millis();
}

void loop() {
  currentTime = millis();
  dist = sonar.measure();
  if (controleur.state == 1) {
    if (controleur.control == 1) {controleur.update_(dist, currentTime); }
    else {controleur.manuel(tsop.results); }
  }
  tsop.update_(controleur, irrecv.decode(&(tsop.results)), currentTime);
  irrecv.resume();
}