Robot : Différence entre versions

De troyesGEII
Aller à : navigation, rechercher
m (Vidéos)
 
(27 révisions intermédiaires par 2 utilisateurs non affichées)
Ligne 1 : Ligne 1 :
Voici les explications concernant le projet de robotique de Blaise Barré, Julien Santa-Comba et Kévin Bruno.
+
[[Catégorie:Projets]]
Le robot que nous allons concevoir a pour but de participer à un concours à Vierzon. Pour cela, nous utiliserons en général des cartes Arduino qui facilitent la conception du robot et notamment des différentes parties délicates tel que les capteurs.
+
[[Fichier:Robots.png|vignette|gauche|Coupe robotique]]
 +
Compte-rendu et explications concernant le projet de robotique de GEII 2ème année de TR. Ce projet a été mené par Blaise Barré et Kévin Bruno, avec l'aide de Julien Santa Comba.
 +
 
 +
Le robot que nous allons concevoir a pour but de participer à un concours à Vierzon - nous n'y participerons malheureusement pas, car notre robot n'est pas totalement opérationnel.
 +
 
 +
Pour cela, nous utiliserons en général des cartes Arduino qui facilitent la conception du robot et notamment des différentes parties délicates tel que les capteurs :
 +
 
 +
[[Fichier:Espace_arduino.gif||vignette|droite||Liaison arduino/pc]]
  
 
Voici la liste du matériel que nous utiliserons pour construre notre robot :  
 
Voici la liste du matériel que nous utiliserons pour construre notre robot :  
Ligne 8 : Ligne 15 :
 
#Roues codeuses
 
#Roues codeuses
 
#Cartes Arduino
 
#Cartes Arduino
 +
 +
 +
=Vidéos et photos sur le robot=
 +
 +
Voici une vidéo qui explique comment est réalisé le robot et une autre qui montre une "battle" avec un autre robot à l'IUT de Troyes.
 +
S'en suit quelques photos de près et de loin du robot.
 +
 +
==Vidéos==
 +
 +
#[http://youtu.be/3USwTDypWYU Vidéo de présentation du robot] sur [http://www.youtube.com YouTube]
 +
#[http://youtu.be/fXdEtVQjRuA Vidéo de démonstration du robot] sur [http://www.youtube.com YouTube]
 +
 +
==Photos==
 +
 +
[[Fichier:Robot 1 .jpg|250px|vignette|centré|Photo du robot]]
 +
 +
[[Fichier:Robot 2 .jpg|250px|vignette|centré|Zoom sur le robot]]
  
 
=Première partie : conception des moteurs=
 
=Première partie : conception des moteurs=
Ligne 20 : Ligne 44 :
 
#le Diamètre de la roue du moteur : 52,6mm
 
#le Diamètre de la roue du moteur : 52,6mm
 
#le nombre de crans de roues codeuses : 60
 
#le nombre de crans de roues codeuses : 60
 +
#la distance entre les deux roues est de 20 cm
  
 
==Caractéristiques techniques de l'opto-coupleur==
 
==Caractéristiques techniques de l'opto-coupleur==
  
Pour la détection des crans des roues codeuses(passage du noir au transparent, nous utiliserons des opto-coupleurs fixés sur la "carcasse" du robot, ce qui permettra de définir la vitesse du robot. Nous avons fait un montage temporaire dans lequel une led d'allume lorsque l'opto-coupleur n'est pas saturé, c'est-à-dire lorsque aucun objet n'entre entre l'émetteur et le récepteur. Nous avons donc mis une résistance de 100 Ohms en série avec la led de l'opto-coupleur. Nous avons par ailleurs recheché le  programme pour mettre ce montage pull-up sur la carte Arduino.
+
[[Fichier:Opto fourche.jpg|vignette|gauche|Un optocoupleur]]
 +
Pour la détection des crans des roues codeuses (passage du noir au transparent, nous utiliserons des optocoupleurs fixés sur la châssis du robot, ce qui permettra de définir la vitesse du robot.  
  
==Programme des opto-coupleurs==
+
===Montage temporaire===
  
Après plusieurs essais, nous avons établis le programme suivant
+
[[Fichier:Optocoupleur.png|vignette|droite|Le schéma d'un optocoupleur]]Nous avons fait un montage temporaire dans lequel une led s'allume lorsque l'opto-coupleur n'est pas saturé, c'est-à-dire lorsque aucun objet n'entre entre l'émetteur et le récepteur. Nous avons donc mis une résistance de 100 Ohms en série avec la led de l'opto-coupleur. Nous avons par ailleurs recherché le programme pour mettre ce montage pull-up sur la carte Arduino.
[Programme]
 
  
 +
===Montage final===
  
A partir de cet instant, le robot pouvait avancer à une vitesse établie (en faisant varier de 0 à 255) et établir un parcours prédéfini.
+
Après plusieurs essais réussi sur le montage temporaire, nous avons finalement mis en place le montage définitif permettant de gérer le robot à l'aide des opto-coupleurs et d'un programme associé (voir programme plus bas). Nous avons établis le programme permettant au robot d'avancer à une vitesse établie (en faisant varier de '''0 à 255''') et établir un parcours prédéfini.
  
 
=Deuxième partie : les capteurs=
 
=Deuxième partie : les capteurs=
  
La deuxième partie de la réalisation est consacrée aux capteurs. Pour cela, nous utiliserons des photodiodes de type BPW50
+
==Caractéristiques générales des capteurs==
http://www.datasheetarchive.com/photodiode%20BPW50-datasheet.html mais aussi des diodes infrarouges CQY89 http://www.datasheetarchive.com/cqy89-datasheet.html. Au total,
 
3 capteurs seront utilisés (1 sur chaque côté du robot et 1 sur la face avant) ce qui lui permettra de détecter les obstacles.
 
  Le schéma utilisé pour un capteur est :
 
  Après calcul nous avons déterminés qu'ils nous fallaient une résistance de 2.2kΩ branchée à la patte "base" du transistor et une résistance de 10Ω cablée en série avec
 
la diode à la patte "collectrice". La patte "émettrice" est reliée à la masse.
 
  Après plusieurs essais, nous arrivons, au maximum, à détecter un obstacle à partir d'environ 15 cm.
 
  
 +
La deuxième partie de la réalisation est consacrée aux capteurs infrarouge. Pour cela, nous utiliserons des [http://www.datasheetarchive.com/photodiode%20BPW50-datasheet.html photodiode de type BPW50] mais aussi des  [http://www.datasheetarchive.com/cqy89-datasheet.html diodes infrarouges CQY89]. Au total, 3 capteurs seront utilisés (1 sur chaque côté du robot et 1 sur la face avant) ce qui lui permettra de détecter les obstacles.
  
 +
==Caractéristiques techniques des capteurs==
  
PROGRAMME
+
Le schéma utilisé pour un capteur est :
 +
Après calcul nous avons déterminé qu'ils nous fallait une résistance de 2.2kΩ branchée à la patte "base" du transistor et une résistance de 10Ω câblée en série avec la diode à la patte "collectrice". La patte "émettrice" est reliée à la masse. Après plusieurs essais, nous arrivons, au maximum, à détecter un obstacle à partir d'environ 15 cm.
  
 +
 +
 +
==Programme final==
 +
 +
Le programme qui suit est celui qui nous permet d'utiliser les données recueillies par les capteurs. Voici quelques explications le concernant :
 +
 +
<source lang=c>
 
int testtimer=0;
 
int testtimer=0;
 
  
 
int pwm_a = 3;  
 
int pwm_a = 3;  
Ligne 83 : Ligne 112 :
 
int zero;
 
int zero;
  
 +
</source>
 +
 +
Toutes ces variables servent pour la suite du programmes. Elles sont initialisées en ce début de programme, certaines à des fins de conceptions (certains composants sont reliés à des ports précis du module arduino, nous les définissons ici, d'autres variables servent uniquement pour la logique du microprocesseur comme ça peut être le cas pour les compteurs de position  ou encore les valeurs des capteurs.
 +
 +
<source lang=c>
 
void setup() {
 
void setup() {
 
   Serial.begin(115200); // ouvre le port série, fixe le débit à 115200 bauds
 
   Serial.begin(115200); // ouvre le port série, fixe le débit à 115200 bauds
Ligne 101 : Ligne 135 :
 
   //si 0 recule,si 1 avance
 
   //si 0 recule,si 1 avance
 
   digitalWrite(Pindir_a, dir_a);
 
   digitalWrite(Pindir_a, dir_a);
   //si 0 recule,si 1 avance
+
   //si 1 recule, si 0 avance, c'est l'inverse du A
 
   digitalWrite(Pindir_b, dir_b);
 
   digitalWrite(Pindir_b, dir_b);
 
   cli();//stop interrupts
 
   cli();//stop interrupts
  
  /* //set timer0 interrupt at 2kHz
 
  TCCR0A = 0;// set entire TCCR2A register to 0
 
  TCCR0B = 0;// same for TCCR2B
 
  TCNT0  = 0;//initialize counter value to 0
 
  // set compare match register for 2khz increments
 
  OCR0A = 124;// = (16*10^6) / (2000*64) - 1 (must be <256)
 
  // turn on CTC mode
 
  TCCR0A |= (1 << WGM01);
 
  // Set CS11 and CS10 bits for 64 prescaler
 
  TCCR0B |= (1 << CS11) | (1 << CS10); 
 
  // enable timer compare interrupt
 
  TIMSK0 |= (1 << OCIE0A);
 
  */
 
 
   sei();//allow interrupts
 
   sei();//allow interrupts
  
 
}  
 
}  
 +
</source>
 +
 +
Ici nous concevons la fonction setup qui est exécutée une seule fois lors du lancement du robot et donc du programme.
 +
 +
Dans cette fonction, nous définissons les entrées et sorties (en INPUT et OUTPUT) du module arduino (notamment grâce aux variables définies précédemment que nous pouvons procéder à cette définition.
 +
 +
Enfin, nous configurons certaines boucles d'interruption (cli() et sei() et nous les déclarons (attachInterrupt) en fonction des valeurs recueillies dans les capteurs ("CHANGE" signifie "dès que la valeur change) et "test" est le nom de la fonction à exécuter à ce moment là).
 +
 +
<source lang=c>
 
ISR(TIMER0_COMPA_vect){//timer1 interrupt 1Hz toggles pin 13 (LED)
 
ISR(TIMER0_COMPA_vect){//timer1 interrupt 1Hz toggles pin 13 (LED)
  
Ligne 138 : Ligne 168 :
 
   }
 
   }
 
}
 
}
 +
</source>
 +
 +
Ici se trouve l'unique boucle d'interruption du programme. Nous pouvons en mettre autant que nous le souhaitons, attention cependant à ne pas trop surcharger le programme de boucles d'interruption au risque de ne pas allouer suffisamment de temps à la boucle loop de base, que nous verrons plus en dessous.
  
 +
<source lang=c>
  
 
void test(){
 
void test(){
Ligne 160 : Ligne 194 :
  
 
}
 
}
 +
</source>
  
 +
Ici se trouvent donc les boucles d'interruption du programme.
 +
Celles-ci sont exécutées dès que la valeur des opto-coupleurs montés sur les moteurs change de valeur. Nous incrémentons alors des compteurs qui nous permettent de savoir exactement la distance (ou en tous cas à la base la valeur en degré à laquelle à tournée le moteur) parcouru par les deux moteurs respectivement grâce aux fonctions test et test2.
 +
 +
<source lang=c>
 
void loop(){
 
void loop(){
  
Ligne 180 : Ligne 219 :
 
   Serial.print(" val 0 Droite ");  
 
   Serial.print(" val 0 Droite ");  
 
   Serial.println(val0);  
 
   Serial.println(val0);  
   /*   Serial.print('m');
+
 
 +
   /* Ces lignes servent uniquement à des fins de tests lors de la réalisation du programme
 +
 
 +
  Serial.print('m');
 
   Serial.println (val0); // debug valeur
 
   Serial.println (val0); // debug valeur
 
   Serial.print('g');  
 
   Serial.print('g');  
Ligne 223 : Ligne 265 :
 
     delay(500); } */
 
     delay(500); } */
 
   }
 
   }
  //}
 
  
   //if(compteura>=-40&compteurb>=-40){  
+
}
   // analogWrite(pwm_b,100);
+
</source>
   // analogWrite(pwm_a,0);
+
 
  // }
+
Ici se trouve la boucle principale du programme qui sera exécutée en boucle lorsque le robot sera en route. De nombreuses choses sont possibles. Voici dans l'ordre ce que nous faisons :
   //  if(compteura>=-50&compteurb>=-50){
+
#Nous allumons les leds infrarouge qui permettent la détection des obstacles. Elles sont situés sur la face avant du robot et sont allumés grâce à une tension envoyés sur les transistors qui les précèdent ;
  //  compteura=20;
+
#Nous allumons un biper, qui émettra un son lorsque nous le souhaiterons ;
  //    compteurb=20;
+
#Nous lisons la valeur des capteurs en façade ;
  // }
+
#Nous les affichons sur la console de l'ordinateur (lorsque le robot est connecté par USB sur l'ordinateur, sert uniquement lors de la phase de test) ;
 +
#Nous traitons ces valeurs : si elles sont supérieures à une certaine valeur (dans le cas où le robot détecte un obstacle, ces valeurs ont été testées auparavant) alors nous faisons reculer le robot et nous allumons le biper de manière à savoir qu'il a détecté un obstacle et qu'il recule ; sinon le robot avance.
 +
 
 +
 
 +
 
 +
=Troisième partie : prédéfinition du parcours du robot=
 +
 
 +
Grace aux roues codeuses, nous allons désormais coder un programmer qui nous permettra de définir un emplacement de destination au robot et auquel le robot se rendra.
 +
 
 +
<source lang=c>
 +
int compteura=0; // position a droite
 +
int compteurb=0; // position à gauche
 +
int compteurmoy = 0 ;
 +
int compteurteta = 0 ;
 +
int compteurdiff =0 ;
 +
int deltaX = 0 ; // Rajout des X
 +
int deltaY = 0 ; // Rajout des Y
 +
int XTotal = 0 ; // Position totale en X
 +
int YTotal = 0 ; // Position totale en Y
 +
int i=0;
 +
 
 +
 
 +
int pwm_a = 3;
 +
//PWM control for motor outputs 1 and 2 is on digital pin 10
 +
int pwm_b = 11;
 +
//PWM control for motor outputs 3 and 4 is on digital pin 11
 +
int Pindir_a = 12;
 +
int dir_a=0;
 +
//PWM control for motor outputs 1 and 2 is on digital pin 12
 +
int Pindir_b = 13;
 +
int dir_b=1;
 +
 
 +
char nouvellevaleur=0;
 +
 
 +
void test(){
 +
compteura=compteura+1;
 +
}
 +
 
 +
void test2(){
 +
compteurb=compteurb+1;
 +
}
 +
 
 +
 
 +
ISR(TIMER2_COMPA_vect){
 +
    
 +
  if(i==50) {
 +
      i=0;
 +
      compteurmoy = compteura;//((compteura+compteurb)/8);
 +
      compteurdiff= compteurb; //(compteura-compteurb)/4;
 +
      compteura=compteurb=0;
 +
      deltaX = compteurmoy*cos(compteurteta*100);
 +
      XTotal = XTotal+deltaX;
 +
      deltaY = compteurmoy*sin(compteurteta*100);
 +
      YTotal = YTotal+deltaY;
 +
      compteurteta=compteurteta+compteurdiff/2;
 +
      nouvellevaleur=1;
 +
  }
 +
  else i++;
 +
 
 +
}
 +
 
 +
void setup() {
 +
Serial.begin(115200); // ouvre le port série, fixe le débit à 115200 bauds
 +
attachInterrupt (0,test , CHANGE);//patte 2, moteur a
 +
attachInterrupt (1,test2 , CHANGE);//patte 3, moteur b
 +
 
 +
   pinMode(pwm_a, OUTPUT);  //vitesse
 +
  pinMode(pwm_b, OUTPUT); //vitesse
 +
   pinMode(Pindir_a, OUTPUT); //sens
 +
  pinMode(Pindir_b, OUTPUT); //sens
 +
  digitalWrite(Pindir_a, dir_a);
 +
    //si 0 recule,si 1 avance
 +
    digitalWrite(Pindir_b, dir_b);
 +
      analogWrite(pwm_b,0);
 +
      analogWrite(pwm_a,0);
 +
 
 +
 
 +
// Configuration Timer 2
 +
TCCR2A=B010;
 +
// Mode CTC (Clear Timer On Compare)
 +
OCR2A=700;
 +
// Registre de comparaison A = 156
 +
TCCR2B=B111;
 +
// Prescaler 1024 (Clock/1024)
 +
TIMSK2=B010;
 +
// IT Timer2 Quand TCNT2=OCR2A
 +
sei(); // activation des IT (SREG.7=1
 +
}
 +
 
 +
void loop()
 +
{
 +
   int x,y,t,cm,cd;
 +
 
 +
if (nouvellevaleur==1)
 +
{
 +
nouvellevaleur=0;
 +
x=XTotal;
 +
y=YTotal;
 +
t=compteurteta;
 +
cm=compteurmoy;
 +
cd=compteurdiff;
 +
 
 +
 
 +
Serial.print(" X Total :");
 +
Serial.print(x);
 +
Serial.print(" Y Total :");
 +
Serial.print(y);
 +
Serial.print(" Compteur Moyen :");
 +
Serial.print(cm);
 +
Serial.print(" Compteur Diff :");
 +
Serial.print(cd);
 +
Serial.print(" compteurteta :");
 +
Serial.println(t);
 +
}
 +
 
 +
}
 +
</source>
 +
 
 +
Voici le programme "nu" de détection de position. Il affiche donc sur la console de l'ordinateur la valeur finale de la position en X et en Y. Cette méthode de calcul est expliqué  [http://manubatbat.free.fr/doc/positionning/node5.html en ligne].
 +
 
 +
Ces informations permettent ensuite de pouvoir modifier la marche de manœuvre du robot, ce qui n'a pas encore été effectué de manière totalement opérationnelle malgré un essai peu concluant comme suit :
 +
 
 +
 
 +
<source lang=c>
 +
int testtimer=0;
 +
   
 +
int pwm_a = 3;
 +
//PWM control for motor outputs 1 and 2 is on digital pin 10
 +
int pwm_b = 11;
 +
//PWM control for motor outputs 3 and 4 is on digital pin 11
 +
int Pindir_a = 12;
 +
int dir_a=0;
 +
//PWM control for motor outputs 1 and 2 is on digital pin 12
 +
int Pindir_b = 13;
 +
int dir_b=1;
 +
//PWM control for motor outputs 3 and 4 is on digital pin 13
 +
int val0=0;//valuer sur1024 de capteur0 de la diode infrarouge
 +
int val1=0;//valuer sur1024 de capteur1
 +
int val2=0;//valuer sur1024 de capteur2
 +
int analogPin0 = 3;//capteur1(droite) broche5
 +
int analogPin1 = 4;//capteur0(millieu) broche5
 +
int analogPin2 = 5;//capteur2(gauche) broche5
 +
int on_InfraD = 9; //transistor droit
 +
int on_InfraC = 8; //transistor milieu
 +
int on_InfraG = 7; //transistor gauche
 +
int on_Bip = 10; //allume le bipper
 +
int L=23;
 +
   
 +
int compteura=20;
 +
int compteurb=20;
 +
int compteurPositionA=0;
 +
int compteurPositionB=0;
 +
int DeltaMoyN = 0 ;
 +
int DeltaTetaN = 0 ;
 +
int DeltaDiF=0 ;
 +
int anciencompteura ;
 +
char c;
 +
int zero;
 +
 
  
  
  
 +
int compteurmoy = 0 ;
 +
int compteurteta = 0 ;
 +
int compteurdiff =0 ;
 +
int deltaX = 0 ;
 +
int deltaY = 0 ;
  
  //aller tout droit
 
  /*  if(compteura<=5000){
 
  analogWrite(pwm_a,113);//attention toujours faire fonctionné le moteur >60  //bon commpromis a=113  b=100
 
  }
 
  if(compteurb<=5000){       
 
  analogWrite(pwm_b,100);
 
  }
 
  //Tourner à droite
 
  if(compteura>=5000&compteura<=5500){
 
  analogWrite(pwm_a, 0);}
 
  if(compteurb>=5000&compteurb<=5500){ 
 
  analogWrite(pwm_b, 0); 
 
  }
 
 
 
  //Aller tout droit
 
  if(compteurb>=5999&compteurb<=7000){
 
 
 
  analogWrite(pwm_a,113);
 
  analogWrite(pwm_b, 100);
 
  }
 
 
 
  //tourner a gauche
 
  if(compteurb>=7000&compteura>=7000&compteurb<=7500&compteura<=7500){ 
 
  analogWrite(pwm_a, 0);
 
  analogWrite(pwm_b, 100);
 
  }
 
  if(compteurb>=7500&compteurb<=9999){
 
 
 
  analogWrite(pwm_a, 113);
 
  analogWrite(pwm_b, 100); 
 
  }
 
  //S"arreter
 
  if(compteura>=10000){
 
  analogWrite(pwm_a, 0);
 
  }
 
  if(compteurb>=10000){
 
  analogWrite(pwm_b, 0);
 
  }*/
 
  
 +
 +
void setup() {
 +
  Serial.begin(115200); // ouvre le port série, fixe le débit à 115200 bauds
 +
 +
  pinMode(pwm_a, OUTPUT);  //vitesse
 +
  pinMode(pwm_b, OUTPUT);  //vitesse
 +
  pinMode(Pindir_a, OUTPUT); //sens
 +
  pinMode(Pindir_b, OUTPUT); //sens
 +
  pinMode(on_InfraG, OUTPUT); //transistor
 +
  pinMode(on_InfraC, OUTPUT);
 +
  pinMode(on_InfraD, OUTPUT);
 +
  pinMode(on_Bip, OUTPUT);
 +
  //capteur optique
 +
  attachInterrupt (0,test , CHANGE);//patte 2, moteur a
 +
  attachInterrupt (1,test2 , CHANGE);//patte 3, moteur b
 +
 +
  //sens du moteur
 +
  //si 0 recule,si 1 avance
 +
  digitalWrite(Pindir_a, dir_a);
 +
  //si 0 recule,si 1 avance
 +
  digitalWrite(Pindir_b, dir_b);
 +
  cli();//stop interrupts
 +
 +
  // Configuration Timer 2
 +
  TCCR2A=B010;
 +
  // Mode CTC (Clear Timer On Compare)
 +
  OCR2A=700;
 +
  // Registre de comparaison A = 156
 +
  TCCR2B=B111;
 +
  // Prescaler 1024 (Clock/1024)
 +
  TIMSK2=B010;
 +
  // IT Timer2 Quand TCNT2=OCR2A
  
 +
  sei();//allow interrupts
 +
 +
}
 +
ISR(TIMER0_COMPA_vect){//timer1 interrupt 1Hz toggles pin 13 (LED)
 +
 +
  testtimer++;
 +
  if (testtimer==5000)
 +
  {
 +
 +
 +
 +
    if( compteura=anciencompteura){
 +
      dir_a=1;
 +
      dir_b=0;
 +
      analogWrite(pwm_b,200);
 +
      analogWrite(pwm_a,100);
 +
      delay(500);
 +
    }
 +
  }
 +
}
  
 +
ISR(TIMER2_COMPA_vect){
 +
      Serial.print("a = ");   
 +
      Serial.print(compteura);
 +
      Serial.print(" b = ");
 +
      Serial.println(compteurb);
 +
      compteurmoy = ((compteura+compteurb)/2);
 +
      compteurdiff= compteura-compteurb;
 +
      deltaX = compteurmoy*cos(compteurteta) ;
 +
      deltaY = compteurmoy*sin(compteurteta) ;
 +
      compteurteta=compteurdiff/20 ;
 +
      Serial.print(deltaX);
 +
      Serial.print("deltaX");
 +
      Serial.print(deltaY);
 +
      Serial.print("deltaY");
 +
      Serial.print(compteurmoy);
 +
      Serial.print("compteurmoy");
 +
      Serial.print(compteurteta);
 +
      Serial.println("compteurteta");
 +
}
 +
 +
 +
void test(){
 +
  compteura=anciencompteura ;
 +
  if (dir_a==0){
 +
    compteura=compteura+1;
 +
  }
 +
  else{
 +
    compteura=compteura-1;
 +
  }
 +
 +
}
 +
 +
void test2(){
 +
  if (dir_b==1){
 +
    compteurb=compteurb+1;
 +
  }
 +
  else{
 +
    compteurb=compteurb-1;
 +
  }
 +
 +
}
 +
 +
void loop(){
 +
 +
 +
  digitalWrite(on_InfraG, 1);
 +
  digitalWrite(on_InfraC, 1);
 +
  digitalWrite(on_InfraD, 1);
 +
  digitalWrite(on_Bip, 0);
 +
  //afficher les valeurs
 +
 +
 +
  val0 = analogRead (analogPin0); // lecture de la broche d'entrée0
 +
  val1 = analogRead (analogPin1); // lecture de la broche d'entrée1
 +
  val2 = analogRead (analogPin2); // lecture de la broche d'entrée2 
 +
  Serial.print("val 1 Milieu ");
 +
  Serial.print(val1);
 +
  Serial.print(" val 2  Gauche ");
 +
  Serial.print(val2);
 +
  Serial.print(" val 0 Droite ");
 +
  Serial.println(val0);
 +
  /*  Serial.print('m');
 +
  Serial.println (val0); // debug valeur
 +
  Serial.print('g');
 +
  Serial.println (val1); // debug valeur
 +
  Serial.print('d');
 +
  Serial.println (val2); // debug valeur
 +
  */
 +
 +
  if(val0>=350||val1>=300||val2>=350)
 +
  {
 +
 +
    dir_a=1;
 +
    dir_b=0;
 +
    compteurPositionA=compteurPositionA+compteura;
 +
    compteurPositionB=compteurPositionB+compteurb;
 +
    compteura=0;
 +
    compteurb=0;
 +
    digitalWrite(Pindir_a, dir_a);
 +
    digitalWrite(Pindir_b, dir_b);
 +
    analogWrite(pwm_b,200);
 +
    analogWrite(pwm_a,100);
 +
    digitalWrite(on_Bip, 1);
 +
    delay(500);
 +
 +
  }
 +
 +
  else
 +
  {
 +
    analogWrite(pwm_b,200);
 +
    analogWrite(pwm_a,200);
 +
    dir_a=0;
 +
    dir_b=1;
 +
 +
    digitalWrite(Pindir_a, dir_a);
 +
    digitalWrite(Pindir_b, dir_b);
 +
  }
 +
 
 +
 
 +
  if(compteurteta >= 0)
 +
  {
 +
        analogWrite(pwm_b,200);
 +
        analogWrite(pwm_a,255);
 +
        delay(100);
 +
  }
 +
else if(compteurteta >= 0)
 +
  {
 +
      analogWrite(pwm_b,255);
 +
    analogWrite(pwm_a,200);
 +
    delay(100);
 +
  }
 
}
 
}
 +
</source>

Version actuelle datée du 29 mars 2013 à 16:41

Coupe robotique

Compte-rendu et explications concernant le projet de robotique de GEII 2ème année de TR. Ce projet a été mené par Blaise Barré et Kévin Bruno, avec l'aide de Julien Santa Comba.

Le robot que nous allons concevoir a pour but de participer à un concours à Vierzon - nous n'y participerons malheureusement pas, car notre robot n'est pas totalement opérationnel.

Pour cela, nous utiliserons en général des cartes Arduino qui facilitent la conception du robot et notamment des différentes parties délicates tel que les capteurs :

Liaison arduino/pc

Voici la liste du matériel que nous utiliserons pour construre notre robot :

  1. Carter
  2. Moteurs
  3. Capteurs fourche
  4. Roues codeuses
  5. Cartes Arduino


Vidéos et photos sur le robot

Voici une vidéo qui explique comment est réalisé le robot et une autre qui montre une "battle" avec un autre robot à l'IUT de Troyes. S'en suit quelques photos de près et de loin du robot.

Vidéos

  1. Vidéo de présentation du robot sur YouTube
  2. Vidéo de démonstration du robot sur YouTube

Photos

Photo du robot
Zoom sur le robot

Première partie : conception des moteurs

Caractéristiques générales des roues codeuses

La première partie de la concetion consiste à programmer les cartes pour permettre au robot, dans un premier temps, d'avancer en ligne droite. Pour cela, nous avons recherchés:

  1. le nombre de crans de l'engrenage de la roue : 60 au total ; 30 blancs et 30 noirs
  2. le diamètre de la roue codeuse : 55mm
  3. le nombre de cran de l'engrenage de la sortie du moteur : 12
  4. le rapport de réduction : Z1/Z2 = 60/12 = 5 ; 5/60 = 0,08
  5. le Diamètre de la roue du moteur : 52,6mm
  6. le nombre de crans de roues codeuses : 60
  7. la distance entre les deux roues est de 20 cm

Caractéristiques techniques de l'opto-coupleur

Un optocoupleur

Pour la détection des crans des roues codeuses (passage du noir au transparent, nous utiliserons des optocoupleurs fixés sur la châssis du robot, ce qui permettra de définir la vitesse du robot.

Montage temporaire

Le schéma d'un optocoupleur
Nous avons fait un montage temporaire dans lequel une led s'allume lorsque l'opto-coupleur n'est pas saturé, c'est-à-dire lorsque aucun objet n'entre entre l'émetteur et le récepteur. Nous avons donc mis une résistance de 100 Ohms en série avec la led de l'opto-coupleur. Nous avons par ailleurs recherché le programme pour mettre ce montage pull-up sur la carte Arduino.

Montage final

Après plusieurs essais réussi sur le montage temporaire, nous avons finalement mis en place le montage définitif permettant de gérer le robot à l'aide des opto-coupleurs et d'un programme associé (voir programme plus bas). Nous avons établis le programme permettant au robot d'avancer à une vitesse établie (en faisant varier de 0 à 255) et établir un parcours prédéfini.

Deuxième partie : les capteurs

Caractéristiques générales des capteurs

La deuxième partie de la réalisation est consacrée aux capteurs infrarouge. Pour cela, nous utiliserons des photodiode de type BPW50 mais aussi des diodes infrarouges CQY89. Au total, 3 capteurs seront utilisés (1 sur chaque côté du robot et 1 sur la face avant) ce qui lui permettra de détecter les obstacles.

Caractéristiques techniques des capteurs

Le schéma utilisé pour un capteur est : Après calcul nous avons déterminé qu'ils nous fallait une résistance de 2.2kΩ branchée à la patte "base" du transistor et une résistance de 10Ω câblée en série avec la diode à la patte "collectrice". La patte "émettrice" est reliée à la masse. Après plusieurs essais, nous arrivons, au maximum, à détecter un obstacle à partir d'environ 15 cm.


Programme final

Le programme qui suit est celui qui nous permet d'utiliser les données recueillies par les capteurs. Voici quelques explications le concernant :

int testtimer=0;

int pwm_a = 3; 
//PWM control for motor outputs 1 and 2 is on digital pin 10 
int pwm_b = 11; 
//PWM control for motor outputs 3 and 4 is on digital pin 11 
int Pindir_a = 12;
int dir_a=0;
//PWM control for motor outputs 1 and 2 is on digital pin 12 
int Pindir_b = 13;
int dir_b=1;
//PWM control for motor outputs 3 and 4 is on digital pin 13 
int val0=0;//valuer sur1024 de capteur0 de la diode infrarouge
int val1=0;//valuer sur1024 de capteur1
int val2=0;//valuer sur1024 de capteur2
int analogPin0 = 3;//capteur1(droite) broche5
int analogPin1 = 4;//capteur0(millieu) broche5
int analogPin2 = 5;//capteur2(gauche) broche5
int on_InfraD = 9; //transistor droit
int on_InfraC = 8; //transistor milieu
int on_InfraG = 7; //transistor gauche
int on_Bip = 10; //allume le bipper
int L=23;

int compteura=20;
int compteurb=20;
int compteurPositionA=0;
int compteurPositionB=0;
int DeltaMoyN = 0 ;
int DeltaTetaN = 0 ;
int DeltaDiF=0 ;
int anciencompteura ;
char c;
int zero;

Toutes ces variables servent pour la suite du programmes. Elles sont initialisées en ce début de programme, certaines à des fins de conceptions (certains composants sont reliés à des ports précis du module arduino, nous les définissons ici, d'autres variables servent uniquement pour la logique du microprocesseur comme ça peut être le cas pour les compteurs de position ou encore les valeurs des capteurs.

void setup() {
  Serial.begin(115200);	// ouvre le port série, fixe le débit à 115200 bauds

  pinMode(pwm_a, OUTPUT);  //vitesse
  pinMode(pwm_b, OUTPUT);  //vitesse
  pinMode(Pindir_a, OUTPUT); //sens
  pinMode(Pindir_b, OUTPUT); //sens
  pinMode(on_InfraG, OUTPUT); //transistor
  pinMode(on_InfraC, OUTPUT); 
  pinMode(on_InfraD, OUTPUT); 
  pinMode(on_Bip, OUTPUT); 
  //capteur optique
  attachInterrupt (0,test , CHANGE);//patte 2, moteur a
  attachInterrupt (1,test2 , CHANGE);//patte 3, moteur b

  //sens du moteur
  //si 0 recule,si 1 avance
  digitalWrite(Pindir_a, dir_a);
  //si 1 recule, si 0 avance, c'est l'inverse du A
  digitalWrite(Pindir_b, dir_b);
  cli();//stop interrupts

  sei();//allow interrupts

}

Ici nous concevons la fonction setup qui est exécutée une seule fois lors du lancement du robot et donc du programme.

Dans cette fonction, nous définissons les entrées et sorties (en INPUT et OUTPUT) du module arduino (notamment grâce aux variables définies précédemment que nous pouvons procéder à cette définition.

Enfin, nous configurons certaines boucles d'interruption (cli() et sei() et nous les déclarons (attachInterrupt) en fonction des valeurs recueillies dans les capteurs ("CHANGE" signifie "dès que la valeur change) et "test" est le nom de la fonction à exécuter à ce moment là).

ISR(TIMER0_COMPA_vect){//timer1 interrupt 1Hz toggles pin 13 (LED)

  testtimer++;
  if (testtimer==5000)
  {



    if( compteura=anciencompteura){
      dir_a=1;
      dir_b=0;
      analogWrite(pwm_b,200);
      analogWrite(pwm_a,100);
      delay(500); 
    }
  }
}

Ici se trouve l'unique boucle d'interruption du programme. Nous pouvons en mettre autant que nous le souhaitons, attention cependant à ne pas trop surcharger le programme de boucles d'interruption au risque de ne pas allouer suffisamment de temps à la boucle loop de base, que nous verrons plus en dessous.

void test(){
  compteura=anciencompteura ;
  if (dir_a==0){
    compteura=compteura+1;
  }
  else{
    compteura=compteura-1;
  }

}

void test2(){
  if (dir_b==1){
    compteurb=compteurb+1;
  }
  else{
    compteurb=compteurb-1;
  }

}

Ici se trouvent donc les boucles d'interruption du programme. Celles-ci sont exécutées dès que la valeur des opto-coupleurs montés sur les moteurs change de valeur. Nous incrémentons alors des compteurs qui nous permettent de savoir exactement la distance (ou en tous cas à la base la valeur en degré à laquelle à tournée le moteur) parcouru par les deux moteurs respectivement grâce aux fonctions test et test2.

void loop(){


  digitalWrite(on_InfraG, 1);
  digitalWrite(on_InfraC, 1);
  digitalWrite(on_InfraD, 1);
  digitalWrite(on_Bip, 0);
  //afficher les valeurs


  val0 = analogRead (analogPin0); // lecture de la broche d'entrée0
  val1 = analogRead (analogPin1); // lecture de la broche d'entrée1
  val2 = analogRead (analogPin2); // lecture de la broche d'entrée2  
  Serial.print("val 1 Milieu ");
  Serial.print(val1); 
  Serial.print(" val 2  Gauche ");
  Serial.print(val2);
  Serial.print(" val 0 Droite "); 
  Serial.println(val0); 

  /*  Ces lignes servent uniquement à des fins de tests lors de la réalisation du programme

   Serial.print('m');
   Serial.println (val0); // debug valeur
   Serial.print('g'); 
   Serial.println (val1); // debug valeur
   Serial.print('d');
   Serial.println (val2); // debug valeur 
   */

  if(val0>=350||val1>=300||val2>=350)
  {

    dir_a=1;
    dir_b=0;
    compteurPositionA=compteurPositionA+compteura;
    compteurPositionB=compteurPositionB+compteurb;
    compteura=0;
    compteurb=0;
    digitalWrite(Pindir_a, dir_a);
    digitalWrite(Pindir_b, dir_b);
    analogWrite(pwm_b,200);
    analogWrite(pwm_a,100);
    digitalWrite(on_Bip, 1);
    delay(500);

  }

  else 
  {
    analogWrite(pwm_b,200);
    analogWrite(pwm_a,200);
    dir_a=0;
    dir_b=1;

    digitalWrite(Pindir_a, dir_a);
    digitalWrite(Pindir_b, dir_b);
    /*    delay(2000); //
     if( compteura=anciencompteura){
     dir_a=0;
     dir_b=0;
     analogWrite(pwm_b,200);
     analogWrite(pwm_a,80);
     delay(500); } */
  }

}

Ici se trouve la boucle principale du programme qui sera exécutée en boucle lorsque le robot sera en route. De nombreuses choses sont possibles. Voici dans l'ordre ce que nous faisons :

  1. Nous allumons les leds infrarouge qui permettent la détection des obstacles. Elles sont situés sur la face avant du robot et sont allumés grâce à une tension envoyés sur les transistors qui les précèdent ;
  2. Nous allumons un biper, qui émettra un son lorsque nous le souhaiterons ;
  3. Nous lisons la valeur des capteurs en façade ;
  4. Nous les affichons sur la console de l'ordinateur (lorsque le robot est connecté par USB sur l'ordinateur, sert uniquement lors de la phase de test) ;
  5. Nous traitons ces valeurs : si elles sont supérieures à une certaine valeur (dans le cas où le robot détecte un obstacle, ces valeurs ont été testées auparavant) alors nous faisons reculer le robot et nous allumons le biper de manière à savoir qu'il a détecté un obstacle et qu'il recule ; sinon le robot avance.


Troisième partie : prédéfinition du parcours du robot

Grace aux roues codeuses, nous allons désormais coder un programmer qui nous permettra de définir un emplacement de destination au robot et auquel le robot se rendra.

int compteura=0; // position a droite
int compteurb=0; // position à gauche
int compteurmoy = 0 ;
int compteurteta = 0 ;
int compteurdiff =0 ;
int deltaX = 0 ; // Rajout des X
int deltaY = 0 ; // Rajout des Y
int XTotal = 0 ; // Position totale en X
int YTotal = 0 ; // Position totale en Y
int i=0;


int pwm_a = 3; 
//PWM control for motor outputs 1 and 2 is on digital pin 10 
int pwm_b = 11; 
//PWM control for motor outputs 3 and 4 is on digital pin 11 
int Pindir_a = 12;
int dir_a=0;
//PWM control for motor outputs 1 and 2 is on digital pin 12 
int Pindir_b = 13;
int dir_b=1;

char nouvellevaleur=0;

void test(){
compteura=compteura+1;
}

void test2(){
compteurb=compteurb+1;
}


ISR(TIMER2_COMPA_vect){
  
  if(i==50) {
      i=0;
      compteurmoy = compteura;//((compteura+compteurb)/8);
      compteurdiff= compteurb; //(compteura-compteurb)/4;
      compteura=compteurb=0;
      deltaX = compteurmoy*cos(compteurteta*100);
      XTotal = XTotal+deltaX;
      deltaY = compteurmoy*sin(compteurteta*100);
      YTotal = YTotal+deltaY;
      compteurteta=compteurteta+compteurdiff/2;
      nouvellevaleur=1;
  }
  else i++;

}

void setup() {
Serial.begin(115200); // ouvre le port série, fixe le débit à 115200 bauds
attachInterrupt (0,test , CHANGE);//patte 2, moteur a
attachInterrupt (1,test2 , CHANGE);//patte 3, moteur b

  pinMode(pwm_a, OUTPUT);  //vitesse
  pinMode(pwm_b, OUTPUT);  //vitesse
  pinMode(Pindir_a, OUTPUT); //sens
  pinMode(Pindir_b, OUTPUT); //sens
   digitalWrite(Pindir_a, dir_a);
    //si 0 recule,si 1 avance
    digitalWrite(Pindir_b, dir_b);
      analogWrite(pwm_b,0);
      analogWrite(pwm_a,0);


// Configuration Timer 2
TCCR2A=B010;
// Mode CTC (Clear Timer On Compare)
OCR2A=700;
// Registre de comparaison A = 156
TCCR2B=B111;
// Prescaler 1024 (Clock/1024)
TIMSK2=B010;
// IT Timer2 Quand TCNT2=OCR2A
sei(); // activation des IT (SREG.7=1
}

void loop()
{
  int x,y,t,cm,cd;
  
if (nouvellevaleur==1)
{
nouvellevaleur=0;
x=XTotal;
y=YTotal;
t=compteurteta;
cm=compteurmoy;
cd=compteurdiff;


Serial.print(" X Total :");
Serial.print(x);
Serial.print(" Y Total :");
Serial.print(y);
Serial.print(" Compteur Moyen :");
Serial.print(cm);
Serial.print(" Compteur Diff :");
Serial.print(cd);
Serial.print(" compteurteta :");
Serial.println(t);
}
  
}

Voici le programme "nu" de détection de position. Il affiche donc sur la console de l'ordinateur la valeur finale de la position en X et en Y. Cette méthode de calcul est expliqué en ligne.

Ces informations permettent ensuite de pouvoir modifier la marche de manœuvre du robot, ce qui n'a pas encore été effectué de manière totalement opérationnelle malgré un essai peu concluant comme suit :


int testtimer=0;
 
int pwm_a = 3; 
//PWM control for motor outputs 1 and 2 is on digital pin 10 
int pwm_b = 11; 
//PWM control for motor outputs 3 and 4 is on digital pin 11 
int Pindir_a = 12;
int dir_a=0;
//PWM control for motor outputs 1 and 2 is on digital pin 12 
int Pindir_b = 13;
int dir_b=1;
//PWM control for motor outputs 3 and 4 is on digital pin 13 
int val0=0;//valuer sur1024 de capteur0 de la diode infrarouge
int val1=0;//valuer sur1024 de capteur1
int val2=0;//valuer sur1024 de capteur2
int analogPin0 = 3;//capteur1(droite) broche5
int analogPin1 = 4;//capteur0(millieu) broche5
int analogPin2 = 5;//capteur2(gauche) broche5
int on_InfraD = 9; //transistor droit
int on_InfraC = 8; //transistor milieu
int on_InfraG = 7; //transistor gauche
int on_Bip = 10; //allume le bipper
int L=23;
 
int compteura=20;
int compteurb=20;
int compteurPositionA=0;
int compteurPositionB=0;
int DeltaMoyN = 0 ;
int DeltaTetaN = 0 ;
int DeltaDiF=0 ;
int anciencompteura ;
char c;
int zero;




int compteurmoy = 0 ;
int compteurteta = 0 ;
int compteurdiff =0 ;
int deltaX = 0 ;
int deltaY = 0 ;


 
void setup() {
  Serial.begin(115200);	// ouvre le port série, fixe le débit à 115200 bauds
 
  pinMode(pwm_a, OUTPUT);  //vitesse
  pinMode(pwm_b, OUTPUT);  //vitesse
  pinMode(Pindir_a, OUTPUT); //sens
  pinMode(Pindir_b, OUTPUT); //sens
  pinMode(on_InfraG, OUTPUT); //transistor
  pinMode(on_InfraC, OUTPUT); 
  pinMode(on_InfraD, OUTPUT); 
  pinMode(on_Bip, OUTPUT); 
  //capteur optique
  attachInterrupt (0,test , CHANGE);//patte 2, moteur a
  attachInterrupt (1,test2 , CHANGE);//patte 3, moteur b
 
  //sens du moteur
  //si 0 recule,si 1 avance
  digitalWrite(Pindir_a, dir_a);
  //si 0 recule,si 1 avance
  digitalWrite(Pindir_b, dir_b);
  cli();//stop interrupts
 
   // Configuration Timer 2
  TCCR2A=B010;
  // Mode CTC (Clear Timer On Compare)
  OCR2A=700;
  // Registre de comparaison A = 156
  TCCR2B=B111;
  // Prescaler 1024 (Clock/1024)
  TIMSK2=B010;
  // IT Timer2 Quand TCNT2=OCR2A

  sei();//allow interrupts
 
} 
ISR(TIMER0_COMPA_vect){//timer1 interrupt 1Hz toggles pin 13 (LED)
 
  testtimer++;
  if (testtimer==5000)
  {
 
 
 
    if( compteura=anciencompteura){
      dir_a=1;
      dir_b=0;
      analogWrite(pwm_b,200);
      analogWrite(pwm_a,100);
      delay(500); 
    }
  }
}

ISR(TIMER2_COMPA_vect){
       Serial.print("a = ");     
       Serial.print(compteura); 
       Serial.print(" b = ");
       Serial.println(compteurb);
       compteurmoy = ((compteura+compteurb)/2);
       compteurdiff= compteura-compteurb;
       deltaX = compteurmoy*cos(compteurteta) ;
       deltaY = compteurmoy*sin(compteurteta) ;
       compteurteta=compteurdiff/20 ;
       Serial.print(deltaX);
       Serial.print("deltaX");
       Serial.print(deltaY);
       Serial.print("deltaY");
       Serial.print(compteurmoy);
       Serial.print("compteurmoy");
       Serial.print(compteurteta);
       Serial.println("compteurteta");
}
 
 
void test(){
  compteura=anciencompteura ;
  if (dir_a==0){
    compteura=compteura+1;
  }
  else{
    compteura=compteura-1;
  }
 
}
 
void test2(){
  if (dir_b==1){
    compteurb=compteurb+1;
  }
  else{
    compteurb=compteurb-1;
  }
 
}
 
void loop(){
 
 
  digitalWrite(on_InfraG, 1);
  digitalWrite(on_InfraC, 1);
  digitalWrite(on_InfraD, 1);
  digitalWrite(on_Bip, 0);
  //afficher les valeurs
 
 
  val0 = analogRead (analogPin0); // lecture de la broche d'entrée0
  val1 = analogRead (analogPin1); // lecture de la broche d'entrée1
  val2 = analogRead (analogPin2); // lecture de la broche d'entrée2  
  Serial.print("val 1 Milieu ");
  Serial.print(val1); 
  Serial.print(" val 2  Gauche ");
  Serial.print(val2);
  Serial.print(" val 0 Droite "); 
  Serial.println(val0); 
  /*   Serial.print('m');
   Serial.println (val0); // debug valeur
   Serial.print('g'); 
   Serial.println (val1); // debug valeur
   Serial.print('d');
   Serial.println (val2); // debug valeur 
   */
 
  if(val0>=350||val1>=300||val2>=350)
  {
 
    dir_a=1;
    dir_b=0;
    compteurPositionA=compteurPositionA+compteura;
    compteurPositionB=compteurPositionB+compteurb;
    compteura=0;
    compteurb=0;
    digitalWrite(Pindir_a, dir_a);
    digitalWrite(Pindir_b, dir_b);
    analogWrite(pwm_b,200);
    analogWrite(pwm_a,100);
    digitalWrite(on_Bip, 1);
    delay(500);
 
  }
 
  else 
  {
    analogWrite(pwm_b,200);
    analogWrite(pwm_a,200);
    dir_a=0;
    dir_b=1;
 
    digitalWrite(Pindir_a, dir_a);
    digitalWrite(Pindir_b, dir_b);
  }
  
  
  if(compteurteta >= 0) 
  {
        analogWrite(pwm_b,200);
        analogWrite(pwm_a,255);
        delay(100);
  }
 else if(compteurteta >= 0)
  {
       analogWrite(pwm_b,255);
    analogWrite(pwm_a,200);
    delay(100);
  } 
}