Piloter un robot dans un labyrinthe sans capteur distance ultrason.

Signaler
Messages postés
5
Date d'inscription
samedi 29 mai 2021
Statut
Membre
Dernière intervention
5 juin 2021
-
Messages postés
7729
Date d'inscription
lundi 31 janvier 2011
Statut
Contributeur
Dernière intervention
10 juin 2021
-
Bonjour,
En fait, j'ai un projet sur un robot mobile avec des moustaches de déviation à piloter sous Arduino avec des obstacles à éviter.
J'ai réussit à faire fonctionner les moustaches mais c'est la notion de distance parcourue avec de prendre la droite qui me pose problème. Car j'avais fais à ce que mon robot tourne à droite en fonction du nombre de clignotement de ma Led (Branché au 13) . et ainsi de suite pour les autre distance. Problème lorsque le robot percute un des murs(balise), j'avais fais reculer et faire un pivotement d'un certain angle avant de continuer (si la mouche gauche touche le mur on pivote vers la droite et vis versa), et donc il ne sera plus à l'endroit où il devait se positionner pour tourner à gauche ou droite. J'avais pensais à l'odométrie mais mes roues n'ont pas de capteurs odométrique.
Donc je voudrais savoir si vous pouvez m'aider ou suggérez une méthode en tenant compte de la distance parcourue par le robot même si celui-ci à reculer (lorsqu'il y'a contact sur l'une des moustache) d'en tenir compte aussi.

Cordialement.



#include <Servo.h>                           // Include servo library
Servo servoLeft;                             // Declare left and right servos
Servo servoRight;

byte wLeftOld;                               // Previous loop whisker values
byte wRightOld;                              
byte counter;                                // For counting alternate corners
int count; // compte le nbre de clignotement de la LED rouge

unsigned long  currentTime =0;
unsigned long  previousTime =0;
bool ledstate=LOW;


void setup()                                 // Built-in initialization block
{ 
  Serial.begin(9600);
  pinMode(3, INPUT);                         // Set right whisker pin to input
  pinMode(2, INPUT);                         // Set left whisker pin to input  
  pinMode(13,OUTPUT);
  
/*
  tone(4, 3000, 1000);                       // Play tone for 1 second
  delay(1000);                               // Delay to finish tone
*/

  servoLeft.attach(10);                      // Attach left signal to pin 13 
  servoRight.attach(9);                     // Attach right signal to pin 12

  wLeftOld = 0;                              // Init. previous whisker states
  wRightOld = 1;  
  counter = 0;  
  count=0;
}  
 
void loop()                                  // Main loop auto-repeats
{

  byte wLeft = digitalRead(2);               // Copy left result to wLeft  
  byte wRight = digitalRead(3);              // Copy right result to wRight
  


 //---------------------------COMPTEUR AVEC LA LED----------------------------------------

 currentTime = millis();
 if((currentTime - previousTime)>1000) {
  previousTime=currentTime;
  ledstate=!ledstate;
  digitalWrite(13,!ledstate);
  count++;
 }

  
  // Whisker Navigation

  if((wLeft == 0) && (wRight == 0))          // If both whiskers contact
  {
    backward(1000);                          // Back up 1 second
    turnRight(800); // Turn left about 120 degrees
    turnRight(800);
    count=count-2;
  }
  else if(wLeft == 0)                        // If only left whisker contact
  {
    backward(1000);                          // Back up 1 second
    turnRight(200);                          // Turn right about 60 degrees
    count=count-2;
  }
  else if(wRight == 0)                       // If only right whisker contact
  {
    backward(1000);                          // Back up 1 second
    turnLeft(200);                           // Turn left about 60 degrees
    count=count-2;
  }
  else if(count==18){
    turnLeft(500);
  }

  else if (count==26){
    turnLeft(500);
  }
  else if(count==32){
    turnRight(500);
    delay(1000);
    forward(1000);
    delay(1000);
    turnRight(800);
    turnLeft(1600);
    detach();
  }
  else                                       // Otherwise, no whisker contact
  {
    forward(20);                             // Forward 1/50 of a second   
  }

}

void forward(int time)                       // Forward function
{
  servoLeft.writeMicroseconds(1000);         // Left wheel counterclockwise
  servoRight.writeMicroseconds(2000);        // Right wheel clockwise
  delay(time);                 // Maneuver for time ms
    
    
}

void turnLeft(int time)                      // Left turn function
{
  servoLeft.writeMicroseconds(1000);         // Left wheel clockwise
  servoRight.writeMicroseconds(1000);        // Right wheel clockwise
  delay(time);                               // Maneuver for time ms
}

void turnRight(int time)                     // Right turn function
{
  servoLeft.writeMicroseconds(2000);         // Left wheel counterclockwise
  servoRight.writeMicroseconds(2000);        // Right wheel counterclockwise
  delay(time);                               // Maneuver for time ms
  
}

void backward(int time)                      // Backward function
{
  servoLeft.writeMicroseconds(2000);         // Left wheel clockwise
  servoRight.writeMicroseconds(1000);        // Right wheel counterclockwise
  delay(time);                               // Maneuver for time ms
}

void stop()                      // Backward function
{
  servoLeft.writeMicroseconds(1500);         // Left wheel clockwise
  servoRight.writeMicroseconds(1500);        // Right wheel counterclockwise
  delay(5000);                               // Maneuver for time ms
}

void detach(){
    servoLeft.detach();                      
    servoRight.detach();                    
}

void attach(){
  servoLeft.attach(10);                    
  servoRight.attach(9);                
}

4 réponses

Messages postés
5
Date d'inscription
samedi 29 mai 2021
Statut
Membre
Dernière intervention
5 juin 2021

Parcours:




robot:

Messages postés
7729
Date d'inscription
lundi 31 janvier 2011
Statut
Contributeur
Dernière intervention
10 juin 2021
1 826
Bonjour,

Pour avoir testé et amélioré des scripts sur mbot, je me hasarde à avancer que vous ne pourrez pas obtenir un comportement adéquat en dehors de l'odométrie ou de méthodes de type reconnaissance de formes.

En effet, les procédés à base capteur ultra-son sont hautement imprécis, notamment à courte distance. Non pas que la détection ne se fasse pas, mais en fonction de la position de la forme et de l'angle de l'obstacle par rapport au capteur, la distance mesurée varie dans un intervalle qui ne permet que des mouvements à corriger au fur et à mesure de l'exploration du site.

L'utilisation de capteurs laser permettrait d'améliorer la précision, mais pour un coût sans doute rédhibitoire.

La méthode de comptage des clignotements de le LED 13 n'est pas plus adaptée car elle clignote à la fréquence fixe choisie alors que les actions sur les moteurs varient selon la charge des piles tandis que la vitesse dépend de l'adhérence par rapport à la surface du "sol" et le parcours du robot en virage varie en fonction de l'angle de la direction choisie.

De plus, il faudrait sans doute utiliser des interruptions car l'usage de delay() et le fait que les programmes doivent attendre l'exécution (la fin) d'une fonction en cours ne peuvent que ralentir le temps de réaction du robot.

Je peux comprendre qu'on vous impose l'utilisation de capteurs tout ou rien, mais cela ne me semble pas approprié à l'obtention des performances requises pour la commande d'un robot, sauf à se limiter à des actionneurs secondaires (lumière, son, etc.).

Vous pourriez néanmoins regarde les exemples et discussions du forum sur locoduino.fr (ils se limitent au ferroviaire

ou:

https://eskimon.fr
http://www.mon-club-elec.fr/pmwiki_reference_arduino/pmwiki.php?n=Main.ReferenceMaxi
https://zestedesavoir.com/tutoriels/686/arduino-premiers-pas-en-informatique-embarquee/
https://www.didel.com/c-arduino/arduinoc-avances/

Cordialement
Messages postés
5
Date d'inscription
samedi 29 mai 2021
Statut
Membre
Dernière intervention
5 juin 2021

Bonjour,
J'ai essayé de chercher tout la semaine mais malheureusement j'ai toujours pas de solution.
J'ai posé la question à notre prof sur comment utilisé l'odométrie sans capteur odométrique sur les roue et voici sa réponse:
<< Vous n'avez pas d'odomètre, mais vous pouvez compter le temps.
Et comme vous pouvez, par une expérimentation préalable, évaluer la vitesse de votre robot, vous pouvez en combinant vitesse et temps avoir une petite idée sur la distance qu'il parcourt.

Bien sûr, vous n'aurez pas une mesure très précise, mais ce devrait être suffisant pour lui faire franchir le premier mur de l'arène avec une basique commande boucle ouverte.
Son positionnement précis pour se mettre face à la cible se fera dans un second temps en boucle fermée en utilisant les informations renvoyées par la caméra. >>

En fait, j'ai procéder à des séries de mesure de la vitesse de rotation des roues et le temps que le robot met pour parcourir une distance de 125cm avant de tourner à droite pour poursuivre sa navigation.
Mais mon problème est que je n'ai aucune idée de comment l'implémenté sur Arduino?
voici mes expériences:



J'avais essayé de mettre des instruction if (distance >=125) on tourne vers la droite et ainsi de suite mais le robot réalisait autrement :) . Car notre objectif est de l'amener en position de tire et il sera guider par la suite grâce à une carte Raspberry pi3 et une caméra pi.
Merci d'avance
Messages postés
5
Date d'inscription
samedi 29 mai 2021
Statut
Membre
Dernière intervention
5 juin 2021

Bonjour,
Merci pour votre réponse. Je vais creuser sr les liens que vous m'avez envoyer pour voir si je pourrai avoir une solution adéquate.
Messages postés
7729
Date d'inscription
lundi 31 janvier 2011
Statut
Contributeur
Dernière intervention
10 juin 2021
1 826
Bonjour,
Je ne sais pourquoi, j'a raté votre réponse n°4.

Je m'inscris en faux contre l'assertion de votre prof:

Et comme vous pouvez, par une expérimentation préalable, évaluer la vitesse de votre robot, vous pouvez en combinant vitesse et temps avoir une petite idée sur la distance qu'il parcourt

C'et impossible pour les raisons que j'ai évoquées: d'une part parce que cela varie en fonction de l'état des piles et d'un mouvement en cours, d'autre part , un virage à gauche ou à droite ne se font pas obligatoirement à la même vitesse, donc le a distance parcourue ne sera pas la même.

Sans compter que les inévitables corrections en pseudo temps réel, dépendront de la succession des actions comme résultat des détections des capteurs, qui en fonctionnement normal (hors usage des interruptions) ont une certaine inertie pour ne pas dire une inertie certaine, si elles se déroulent à intervalle de moins d'une seconde.

Si j'interprète bien vos résultats, il y a une seconde de différence, en ligne droite sur12,5 cm. Cela me parait énorme et ingérable dès qu'interviennent des changements de direction, qui von prendre au minimum une demi-seconde entre chaque action.

Je n'en veux pour preuve que votre constatation J'avais essayé de mettre des instruction if (distance >=125) on tourne vers la droite et ainsi de suite mais le robot réalisait autrement

Et pour cause, si le robot rencontre un obstacle avant les 125 cm, il repart sur un nouveau parcours de 125 cm, avec ou sans obstacles, mais s'il va moins vite que prévu (piles, nature du sol) il va fair bien plus que 125 cm et donc se retrouver dans une position on prévue (à frotter contre un mur ou à se retrouver coincé dans un coin).

Par ailleurs, je découvre l'existence d'une caméra et d'un ordinateur de type raspberry pi par exemple. Et cela change la donne.

je n'ai aucune idée de comment l'implémenté sur Arduino?
comme indiqué par ailleurs, seul l'usage des interruptions permet de gérer des mouvements rapide et des actions "imbriquées qui correspondent aux obstacles détectés.

D'autre part, dans un labyrinthe, on ne tourne pas toujours à droite, sous peine de refaire en permanence le même parcours. On tourne à droite ou à gauche, en fonction de la moustache activée, ce qui permet de détecter le ouvertures et de relever le tracé du labyrinthe en actionnant des "drapeaux" logiques..

Bon courage pour la suite.
Messages postés
5
Date d'inscription
samedi 29 mai 2021
Statut
Membre
Dernière intervention
5 juin 2021

Merci pour votre réponse.
je vous l'accord ayant essayé, le branche dans le secteur et son fonctionnement avec une pile (la vitesse est totalement différente).
En fait, lorsque j'utilise que les moustache il me faudra par la suite s'arrêter ou aller sur la premier cible à abattre, pour nous la reconnaissance se fera avec Raspberry pi qui s'aura piloter les roue aussi pour balayer un certain angle de recherche de la cible à l'aide de openCV (par reconnaissance d'objet) . Du coup si je ne tiens plus compte de la distance parcourue, le robot risque d'aller ailleurs au lieu de ce mettre en position de tire :) . Pour l'interrupteur vous proposer quel genre s'il vous plait?
Encore merci.
Messages postés
7729
Date d'inscription
lundi 31 janvier 2011
Statut
Contributeur
Dernière intervention
10 juin 2021
1 826 >
Messages postés
5
Date d'inscription
samedi 29 mai 2021
Statut
Membre
Dernière intervention
5 juin 2021

D'accord avec vos explications. Pour l'interrupteur, si vous en avez le droit, l'ultra-son remplacera très bien le moustaches, avec l'avantage de pouvoir choisir la distance de déclenchement de l'action au centimètre près (en tenant compte du fait cependant que cette distance mesurée varie en fonction de l'angle par rapport à la surface détectée).

Sinon, vous avez les détecteurs de mouvement de type PIR:

https://www.v-labs.fr/tuto-capteur-de-mouvements-photos-sur-arduino-raspberry-b/

A un de ces jours, sans doute.