Aller au contenu


Photo
- - - - -

Problème programmation arduino :roby amélioré


  • Veuillez vous connecter pour répondre
12 réponses à ce sujet

#1 cooljfo

cooljfo

    Nouveau membre

  • Membres
  • 14 messages

Posté 10 décembre 2010 - 04:07

salut!

voila, je travaille depuis un momant à fabriquer mon robot. tout comme roby il évite des obstacle grace à un capteur de distance, mais la tete de mon robot tourne en continu sur 180 degré et observe tout autour de lui pour mieu réagir à différente situation, malheureusement j'ai un petit problème avec mon code. Je voudrait que mon robot puisse recevoir les info de mon capteur de distance pendant qu'il tourne la tete ,alors qu'en se moment il tourne la tete ,puis reçoit les info. Je ne sait pas si j'ai été assez claire n'ésitez pas à me demander d'autres information

voici mon code actuelle:



#define AVANT 1
#define ARRIERE 0
#define GAUCHE 2
#define DROITE 3

#define SERVOG 1
#define SERVOD 0

#define VMAX 5

Servo tete;




// tourner tete
void RotTete (int pos = 0)
{

for(pos = 0; pos < 180; pos += 1)
{
tete.write(pos);
delay(15);
}
for(pos = 180; pos>=1; pos-=1)
{
tete.write(pos);
delay(15);
}
}




//avant,gauche,droite,arrière
Servo servog;
Servo servod;

int getNeutral(int s)
{
if(s == SERVOG)
return 86;
else
return 84;
}


void handleS(int s, int speed)
{
//Vitesse :
// 0 -> 0; 1 -> 1; 2 -> 3; 3 -> 8; 4 -> 10; v => 5 -> 30
int tab[6] = {0,1,3,8,10,30};
int pos = getNeutral(s);

int acc;
if (speed < 0)
acc = - tab[abs(speed)];
else
acc = tab[speed];

if(s == SERVOG)
servog.write(pos += acc);
else
servod.write(pos -= acc);
}


void move(int direction)
{
int m1 = 0, m2 = 0;
switch(direction)
{
case DROITE: m1 = 1; m2 = -1; break;
case GAUCHE: m1 = -1; m2 = 1; break;
case AVANT: m1 = 1; m2 = 1; break;
case ARRIERE: m1 = -1; m2 = -1; break;
}
handleS(SERVOG, m1*VMAX);
handleS(SERVOD, m2*VMAX);
}



//agir selon les situations
void action()
{ int yeux = analogRead(5); //capteur de distance
int cou = analogRead(4);//potentiomètre du servomoteur

if (cou >=0 <=45 && yeux >=0 <=300) // && veut dire ''et''
{digitalWrite(11, LOW);
move (GAUCHE);}
}



void setup()
{
tete.attach(11);
servog.attach(9);
servod.attach(10);
move (AVANT);
}

void loop()
{
RotTete ();
action ();
move (AVANT);
delay(100);[/code]



#2 Jbot

Jbot

    Membre passionné

  • Membres
  • PipPipPip
  • 801 messages
  • Gender:Male
  • Location:Paris
  • Interests:Robotics

Posté 10 décembre 2010 - 09:35

int yeux;

// tourner tete
void RotTete (int pos = 0)
{

for(pos = 0; pos < 180; pos += 1)
{
tete.write(pos);
delay(15);
yeux = analogRead(5); //capteur de distance
}
for(pos = 180; pos>=1; pos-=1)
{
tete.write(pos);
delay(15);
yeux = analogRead(5); //capteur de distance
}
}
[/code]

Avec ce code ton capteur sera lu a chaque degrés de rotation (je ne sais pas si la donnée peut etre actualisée aussi vite par contre).

Aprés tu peux mettre tout ça dans un tableau (au lieu d'un unique entier) pour garder les valeurs de la distance a chaque degrés (ca te fait une espece de carte de ce qu'il y a devant toi), ce qui te permet de faire le traitement aprés dans ta fonction action().

#3 cooljfo

cooljfo

    Nouveau membre

  • Membres
  • 14 messages

Posté 12 décembre 2010 - 06:55

merci, ton aide m'a beaucoup aidé même si je l'ai un peu modifié. Au lieu de mettre analog read yeux a chaque degré j'ai mit directement la fonction action et sa fonctionne très bien :D mais il me reste un dernier problème à régler j'aimerais que mon servo tete puisse s'arrêter lorsqu'un évènement de la fonction action se produit. j'ai essayer avec digitalWrite mais sa ne semble pas fonctionner. est ce que quelqu'un connaiterais une solution?

#4 Hexa Emails

Hexa Emails

    Habitué

  • Membres
  • PipPip
  • 439 messages
  • Gender:Male

Posté 12 décembre 2010 - 08:54

Il faudrait en fait que tu sortes du "for" si ta valeur analogRead est suffisamment grande c'est ça? (a supposer que + l'obstacle est proche, plus le capteur renvoie une grande tension)

#5 cooljfo

cooljfo

    Nouveau membre

  • Membres
  • 14 messages

Posté 12 décembre 2010 - 09:39

désolé si je n'ai pas bien compris je débute en programmation mais il me semble qu'avec for une fois que la boucle stop, elle ne recommence jamais.. moi je voudrait que le servo tourne sur 180 degré jusqu'a se qu'il détecte un obstacle avec le capteur de distance et qu'il se remette a tourner lorsque l'obstacle est assez loin

#6 Hexa Emails

Hexa Emails

    Habitué

  • Membres
  • PipPip
  • 439 messages
  • Gender:Male

Posté 12 décembre 2010 - 10:02

et si tu fais:
{
tete.write(pos);
delay(15);
yeux = analogRead(5);
while(yeux>= seuil)
{actionevitement(); //à créer ^^
yeux = analogRead(5); //pour réactualiser la mesure, car sinon on reste bloqué!
}
}
for(pos = 180; pos>=1; pos-=1)
{
tete.write(pos);
delay(15);
yeux = analogRead(5); //capteur de distance
while(yeux>= seuil)
{actionevitement(); // à créer
yeux = analogRead(5); //pour réactualiser la mesure, car sinon on reste bloqué!
}
}
[/code]

avec un seuil correspondant à ta valeur limite de proximité, et ton "actionevitement" se servirait de "pos" pour savoir où est l'obstacle!
qu'en penses tu?

en gros ça fonctionnerait comme ça:
-le robot fait défiler sa tête de 0 à 180°, dans les 2 sens, pour cahque °, il regarde si il y a un obstacle: si il y a:
-appel d'une fonction qui:
peut utiliser la variable "pos" pour savoir si l'obstacle est à gauche où à droite (si pos < 90 ° , à gauche par exemple, à
vérifier)
évite l'obstacle, en faisant par exemple tourner le robot sur lui même (après il faut réfléchir: "pos" doit t'indiquer comment le
faire tourner)
remarque: si pos est de 10 ou 170°, tu as vraiment besoin d'éviter l'obstacle? il n'est pas sur le chemin du robot...
-une fois l'évitement fais, ton programme retourne dans la boucle while, actualise la mesure et si l'obstacle a bien été évité,
on retourne dans le "if" (ouf ça en fait!) et la tete continue de tourner exactement comme avant!

qu'est-ce que tu en penses?

#7 cooljfo

cooljfo

    Nouveau membre

  • Membres
  • 14 messages

Posté 13 décembre 2010 - 05:03

je suis désolé, mais je ne suis pas trop sur de comprendre :/

voici mon code pour le moment

#include

#define AVANT 1
#define ARRIERE 0
#define GAUCHE 2
#define DROITE 3

#define SERVOG 1
#define SERVOD 0

#define VMAX 5



/////////////////////////////////////////////////////////

//avant,gauche,droite,arrière

Servo servog;
Servo servod;

int getNeutral(int s)
{
if(s == SERVOG)
return 90;
else
return 90;
}


void handleS(int s, int speed)
{
//Vitesse :
// 0 -> 0; 1 -> 1; 2 -> 3; 3 -> 8; 4 -> 10; v => 5 -> 30
int tab[6] = {0,1,3,8,10,30};
int pos = getNeutral(s);

int acc;
if (speed < 0)
acc = - tab[abs(speed)];
else
acc = tab[speed];

if(s == SERVOG)
servog.write(pos += acc);
else
servod.write(pos -= acc);
}


void move(int direction)
{
int m1 = 0, m2 = 0;
switch(direction)
{
case DROITE: m1 = 1; m2 = -1; break;
case GAUCHE: m1 = -1; m2 = 1; break;
case AVANT: m1 = 1; m2 = 1; break;
case ARRIERE: m1 = -1; m2 = -1; break;
}
handleS(SERVOG, m1*VMAX);
handleS(SERVOD, m2*VMAX);
}

///////////////////////////////////////////////////////////


//agir selon les situations

void action()
{ int yeux = analogRead(5); //capteur de distance
int cou = analogRead(4); // potentiomètre du servo: tete

if ( yeux >=300 && cou >=275) // && veut dire ''et''
{move (GAUCHE);}
else if (yeux >=300 && cou <= 274)
{move (DROITE);}
else
{move (AVANT);}
}

/////////////////////////////////////////////////////////

// tourner tete

Servo tete;

void RotTete (int pos = 0)
{

for(pos = 10; pos < 170; pos += 1)
{
tete.write(pos);
delay(7);
action(); // executer la fonction action à chaque degré
}
for(pos = 170; pos>=10; pos-=1)
{
tete.write(pos);
delay(7);
action(); // executer la fonction action à chaque degré
}

}


void setup()
{
tete.attach(11);
servog.attach(9);
servod.attach(10);
move (AVANT);
}

void loop()
{
RotTete ();
delay(100);
}[/code]

Je ne comprend pas quel doit etre la différence entre la fonction action et la fonction actionevitement. Je ne comprend pas vraiment nomplu a quoi sert le while et au lieu d'utiliser pos pour savoir à quel degré se trouve mon servo j'ai branché diractement son potentiomètre sur une entré analogique.

#8 Hexa Emails

Hexa Emails

    Habitué

  • Membres
  • PipPip
  • 439 messages
  • Gender:Male

Posté 13 décembre 2010 - 07:18

Ton programme fait plus ou moins la même chose que le mien. Attention toutefois, il vaudrait mieux ne pas réutiliser les variables ailleurs (par exemple pos est utilisé 2 fois) quand c'est bien fait comme ici il n'y a pas de problème mais si tu oublie de réinitialiser les valeurs de tes variables tu auras des résultats surprenants.

#9 cooljfo

cooljfo

    Nouveau membre

  • Membres
  • 14 messages

Posté 13 décembre 2010 - 07:36

Mais je ne suis toujours pas capable d'arrêter de faire tourner mon servo tête :/

#10 Hexa Emails

Hexa Emails

    Habitué

  • Membres
  • PipPip
  • 439 messages
  • Gender:Male

Posté 13 décembre 2010 - 08:42

quand est-ce qu'il doit s'arrêter? si tu fais comme moi un "while" il reste bloqué dans le "while" tant que le télémètre capte un obstacle, donc le "if" est "en pause" et la tete ne tourne pas... désolé pour tous les "guillemets" :)

#11 cooljfo

cooljfo

    Nouveau membre

  • Membres
  • 14 messages

Posté 14 décembre 2010 - 12:04

bon je sent qu'on y arrive :P dans la fonction action j'ai remplacer les if par while ,mais je ne comprend pas comment réinitialiser la boucle lorsqu'une condition devien fausse.
voici ce que j'ai changé:
{ int yeux = analogRead(5);
int cou = analogRead(4);

while ( yeux >=300 && cou >=275)
{move (GAUCHE);}

while (yeux >=300 && cou <= 274)
{move (DROITE);}

}
[/code]


#12 Hexa Emails

Hexa Emails

    Habitué

  • Membres
  • PipPip
  • 439 messages
  • Gender:Male

Posté 14 décembre 2010 - 07:40

attention: voilà ce qsue fait ton programme:
=300 && cou >=275, il éxécute "move(gauche)"[/code]
ce qui veut dire qu'il le fait une fois, puis il re-compare yeux et cou avant de le refaire... Tu ne vois pas un léger problème? Il faut réactualiser tes valeurs, car il va garder la valeur stockée de "yeux, qui est forcément >300! fais quelque chose comme

=300 && cou >=275)
{move (GAUCHE);
yeux = analogRead(5);
}[/code]
ainsi il va tourner à gauche JUSQU'A ce qu'il évite l'obstacle. Par contre ce n'est peut être pas nécessaire de créer une fonction toutes les 2 instructions, tu gagnera peut être en clarté à faire moins de fonctions plus complètes(ça ne changera pas le principe de fonctionnement)


#13 cooljfo

cooljfo

    Nouveau membre

  • Membres
  • 14 messages

Posté 15 décembre 2010 - 12:50

Merci beaucoup pour ton aide MrAlexis, mais je n'ai vraiment pas réussit a faire fonctionner ta solution, je restait toujours bloquer une fois que le servo s'arrêtais. Mais j'ai trouver une autre solution un peu par hasard. En regardant les info sur la librairie servo j'ai lu que lorsqu'on l'utilisait la fonction digitalRight ne fonctionnais plus et que pour l'utiliser on devait utiliser la fonction detach pour désasocier le servo de sa pin. j'ai donc essayer et sa à fonctionner!

voici se que j'ai modifié au code si sa intéresse quelqu'un:
{ tete.attach(11);
int yeux = analogRead(5);
int cou = analogRead(4);

if ( yeux >=300 && cou >=275)
{move (GAUCHE); tete.detach();}
else if (yeux >=300 && cou <= 274)
{move (DROITE);tete.detach();}
else
{move (AVANT);}
} [/code]





1 utilisateur(s) li(sen)t ce sujet

0 members, 1 guests, 0 anonymous users