samedi 24 décembre 2011

LBOTTI suiveur de ligne

Donc voilà lbotti un robot suiveur de ligne il n'est pas très rapide, d'ailleurs son nom indique ça bien mais en revanche il est très stable.
Il n'est pas très joli aussi :))
J'ai crée ce robot dans le but pour participé à la 2ème édition de robocomp avec le Team MAZON http://robocomp.ieee-enis.org/?page_id=216 et j'ai pu à travers lbotti d'apporter la 5ème place avec un temps environ de 34sec.
Schéma synoptique

Tableau de capteurs de lumières
Le tableau de capteurs est composé de 9 led rouges émettrices et 8 photorésistances.
J'ai choisi le couleur rouge car il est le plus adapté pour les circuit dont le contraste est faible (exemple ligne bleu sur fond rouge) et bien sure ce qui marche pour un contraste faible marche encore mieux avec un contraste fort, qui est le cas pour la compétition.
J'ai choisi les Ldr car ils sont disponibles dans le marché tunisien.

Comparateurs:


J'ai utilisé des comparateurs pour deux raisons:
-pour s'adapter aux variations de la lumière ambiante en changeant la valeur de la tension Vref de comparateurs
-pour minimiser le temps de traitement et donc le temps de réponse. puisque les variables numériques sont interpréter plus rapidement que les variables analogique.
Les comparateurs sont des LM324

Microcontrolleur:
 PIC 16F877:
code:
unsigned char lastturn=3;
void init(){
     pwm1_init(20000);
     pwm2_init(20000);
     pwm1_start();
     pwm2_start();
     pwm1_set_duty(0);
     pwm2_set_duty(0);
     portd=0X00;
     trisd=0XFF;
}
void setPWM(unsigned char r,unsigned char l){
     pwm1_set_duty(r);
     pwm2_set_duty(l);
}
void rightr(){
     setPWM(0,180);
     while((portd.RD4==1)||(portd.RD5==1));
     setPWM(0,0);
     delay_ms(20);
}
void leftr(){
     setPWM(180,0);
     while((portd.RD3==1)||(portd.RD2==1));
     setPWM(0,0);
     delay_ms(20);
}
void main() {
init();
while(1){
if((portd.RD7==1)&&(portd.RD0==1)){//reglage fine
 if(portd.RD6==0){setPWM(188,112);lastturn=2;}
  if(portd.RD1==0){setPWM(112,188);lastturn=1;}

if(portd.RD5==0){setPWM(175,125);lastturn=2;}
if(portd.RD2==0){setPWM(125,175);lastturn=1;}

if(portd.RD4==0){setPWM(150,150);lastturn=2;}
if(portd.RD3==0){setPWM(150,150);lastturn=1;}
}
else if((portd.RD7==0)&&(portd.RD6==0))leftr();
else if((portd.RD0==0)&&(portd.RD1==0))rightr();
else if((portd.RD7==0)||(portd.RD6==0)||(portd.RD5==0)||(portd.RD4==0)){setPWM(180,0);lastturn=2;}
else if((portd.RD0==0)||(portd.RD1==0)||(portd.RD2==0)||(portd.RD3==0)){setPWM(0,180);lastturn=1;}

else if(portd==0XFF){if (lastturn==1) rightr();
                if(lastturn==2)leftr();
                }
else {
setPWM(250,250);
}
}
}

Interface de puissance:
j'ai utilisé un L293D qui est un double pont en H  qui supporte un ampérage maximal de 1.2A

 Moteurs:
2 micro moteurs DC.
http://www.mechs.fr/product.php?id_product=61

La régulation PID:
Je ne suis pas très sure du code pour le moment mais il sera mis à jours bientôt avec des explication

#define TARGET 50;
unsigned char read=0;
unsigned char Kp=0,Ti=0,Td=0;
int commande=0, error=0, lasterror=0, proportional=0,integrator=0, derivator=0, correction=0;

void init(){
     portd=0X00;
     trisd=0XFF;
     uart1_init(9600);//initialize baude rate
}
void backline(){
     uart1_write(10);
     uart1_write(13);
}
void printMenu(){
uart1_write_text("Welcome to Robot BOTTI :)))");
backline();
uart1_write_text("PID Tuning!");
backline();
uart1_write_text("1: KP proportional");
backline();
uart1_write_text("2: Ti integrator");
backline();
uart1_write_text("3: Td Derivator");
backline();
uart1_write_text("4: vitesse maximal");
backline();
uart1_write_text("5: Go BOTTI");
backline();
uart1_write_text("Your choice");
}
void setPIDvalues(){
 printMenu();
 while(!uart1_data_ready());
 read=uart1_read();
 uart1_write(read);
switch(read){
              case '1':
              backline();
              uart1_write_text("Kp= ");
              while(!uart1_data_ready());
              Kp=uart1_read();
              uart1_write(Kp);
              break;
             
              case '2':
              backline();
              uart1_write_text("Ti= ");
              while(!uart1_data_ready());
              Ti=uart1_read();
              uart1_write(Ti);
              break;
             
              case '3':
              backline();
              uart1_write_text("Td= ");
              while(!uart1_data_ready());
              Td=uart1_read();
              uart1_write(Td);
              break;
             
              case '4':
              backline();
              uart1_write_text("commande= ");
              while(!uart1_data_ready());
              commande=uart1_read();
              uart1_write(commande);
              break;
             
              case '5':
              backline();
              uart1_write_text("Good luck");
              break;


 }
}
unsigned char sensVAl(){

      if(portd==0B11100111)return 50;
      if(portd==0b11001111)return 58;
      if(portd==0B11011111)return 64;
      if(portd==0B10011111)return 72;
      if(portd==0B10111111)return 80;
      if(portd==0B00111111)return 92;
      if(portd==0B01111111)return 100;
      if(portd==0b11110011)return 42;
      if(portd==0b11111011)return 36;

}
unsigned char start(){
unsigned char sensorValue;
sensorValue=sensVal();
error=sensorValue - TARGET;
integrator=error+lasterror;
if(integrator>=2)integrator=0;//en cas de stauration
derivator=(error-lasterror)/2;
correction=kp*error+Ti*integrator+Td*derivator;
pwm1_set_duty(commande+correction);
pwm2_set_duty(commande-correction);

}
void main() {
     init();
     setPIDvalues();
     while(!portb.RB0);
     while(1){
     start();
     }

}


Aucun commentaire:

Enregistrer un commentaire