Ignorer la navigation

J'évite les obstacles sans les toucher

Voilà qui est plus ardu. Sans toucher veut dire que l'on doit pouvoir détecter un obstacle à distance et évaluer à quelle distance on se trouve de l'obstacle. Nous avons deux sortes de capteurs qui peuvent répondre à nos besoins. Il fonctionnent sur le même principe : capter un écho.

  • Le premier est le capteur infrarouge, qui va capter la lumière infrarouge qui rebondit sur l'obstacle.

  • Le second est le capteur à ultrasons, qui va capter un son qui rebondit sur un obstacle.

Le capteur de distance à infrarouge

Nous avons vu dans le cours d'initiation comment utiliser une photodiode (ou diode réceptrice infrarouge), voyons maintenant comment l'utiliser comme capteur de distance.

Il nous faut réaliser un montage qui envoie de la lumière infrarouge et qui la capte, dans le même temps. Voici le schéma de principe :

Principe de la détection de distance par réflexion de lumière infrarouge
Principe de la détection de distance par réflexion de lumière infrarouge

L'idéal est de prévoir une petite séparation entre la diode émettrice et la réceptrice, pour éviter qu'elles ne se "voient" directement (entourer la photodiode d'un petite tube en plastique noir genre paille est largement suffisant).

Voici un capteur de distance infrarouge tout fait :

Un capteur de distance infrarouge du commerce (www.robotshop.com)
Un capteur de distance infrarouge du commerce (www.robotshop.com)

Plus l'obstacle va être proche, plus la quantité de lumière infrarouge renvoyée par l'obstacle va être importante, donc plus la tension captée et numérisée par le CAN A0 va avoir une valeur élevée. Pour résumer, plus la valeur captée par A0 est élevée, plus l'objet est proche. Il suffit donc ensuite de programmer le robot pour qu'il agisse en fonction de la distance de l'objet. Nous allons le voir un peu plus loin.

Ça marche sur toutes sortes d'obstacles ? Parce que je croyais que le noir absorbait les ondes lumineuses ?

(Ha sacré Cunégonde ! Vous ne lâchez rien hein ?)

Alors en effet, il y a deux principaux inconvénients avec ce capteur :

  • La distance mesurable reste faible (environ 10 cm si le capteur est bien conçu) ce qui limite la vitesse de votre robot. En effet s'il arrive trop vite sur l'obstacle et que le capteur n'a pas eu le temps d'analyser la distance, vous risquez le choc.

  • La couleur de l'obstacle agit sur la distance mesurable. En effet, un objet de couleur noire ne va quasiment rien réfléchir, donc ne sera pas détecté par votre capteur (Lukas, rassurez-vous, même si vous ne réfléchissez pas souvent, vous seriez vus par le capteur).

Le cône de réception (la zone de détection) fait que votre robot pourra capter la présence d'un objet légèrement au-dessus ou en-dessous du capteur. C'est donc un peu mieux qu'une moustache. Mais pour une détection optimale, il faudrait presque trois capteurs (devant, devant-droite et devant-gauche) donc trois pins analogiques utilisés...

Évidemment, pour trouver le placement le plus efficace pour votre capteur, il vous faudra faire plusieurs tests et ajustements.

Avant de voir le code type, passons au capteur à ultrasons.

Le capteur de distance à ultrasons

Nous avons abordé dans le cours d'initiation ce capteur (SRF05) et les calculs de distances qui y sont liés. C'est d'ailleurs la grande différence entre le capteur de distance à  infrarouge (dont il est assez difficile de paramétrer une mesure de distance précise) et le capteur à ultrasons qui permet presque d'obtenir une mesure au centimètre (à condition que l'obstacle se situe entre 5cm et 150 cm, au-delà de ces limites la fiabilité diminue).

Le cône de détection est aussi plus important que le capteur infrarouge (entre 30 et 60° vers la zone concernée). Le robot détecte donc des objets plus haut, plus à droite, plus à gauche et plus bas.

Plusieurs méthodes de programmation sont possibles :

  • Soit on procède comme nous allons le voir ensuite, c'est-à-dire en réalisant une mesure régulière.

  • Soit on procède comme la chauve-souris (non Lukas, on ne dort pas la tête en bas) c'est-à-dire que plus on capte que l'objet se rapproche, plus on fait des mesures rapprochées dans le temps, et plus il s'éloigne, plus on espace les mesures. Cette méthode libère du temps processeur mais risque de ne pas détecter un objet qui surgirait dans le champs. Mais comme nos robots évoluent dans un milieu protégé...

Il est tout à fait possible de monter le capteur sur un servo-moteur, afin qu'il scanne de droite à gauche pendant qu'il roule en ligne droite. Ou bien, lors de l'approche d'un obstacle, plutôt que faire tourner le robot, on fait juste tourner la "tourelle" du capteur pour chercher le meilleur chemin.

Voyons maintenant le programme type permettant au robot d’éviter un obstacle, qu’il l’ait détecté à distance avec un capteur à infrarouge ou à ultrasons.

Programme d'évitement d'obstacle sans contact

La structure de ce programme est globalement la même pour le capteur infrarouge et pour le capteur à  ultrasons. Voici le principe :

  • Je roule tout droit (en mesurant)  tant que tout va bien.

  • Je détecte que je m'approche d'un obstacle.

  • Je ralentis (facultatif, mais permet d'observer si l'obstacle persiste ou s'il disparaît).

  • Je détecte que l'objet est trop près de moi, je m'arrête.

  • Je recule un peu (facultatif, mais permet de ne pas toucher pendant les rotations).

  • Je tourne sur moi-même (ou fais pivoter ma tourelle) à droite puis à gauche pour chercher un passage (mesure d'une distance assez grande).

  • Là, deux possibilités de programme : Soit je m'engage dans le passage dès que je le trouve, soit je m'engage dans le passage le "plus libre" (ce qui nécessite de stocker les mesures effectuées en fonction de la position, puis de s'orienter correctement).

  • Je reprends ma route.

Il vous faut donc créer des fonctions de mouvement (on peut ajouter une notion de vitesse en paramètre) comme pour les moustaches. Il est toujours préférable de créer une fonction de mesure de distance (qui renvoie soit une distance, soit un état, par exemple : ok, proche, stop).

Voici un exemple de code. Il utilise le capteur SRF05. J'ai ajouté la communication avec le moniteur série pour les tests, elle est bien sûr facultative (mais bien pratique pour tester son programme ;)) :

#define PROCHE 20
#define DANGER 10
#define AFOND 200
#define PRUDENT 50
#define NBMESURE 5
#define VSON 59
//initialisation
int pinSRF=2; //pin numérique utilisé pour le capteur ultrasons.
void setup() {
Serial.begin(9600);
avance(AFOND); //on démarre le robot
}
void loop() {
switch (mesure()){ //utilisation de la condition switch
case 0: //l'obstacle est dans la zone DANGER
Serial.println("*DANGER*");
arret(); // on arrête le robot
delay(200);
recule(PRUDENT); // on le fait reculer un peu
delay(200);
recherche(); // on recherche la bonne voie
break;
case 1: //l'obstacle est dans la zone PROCHE
Serial.println("Attention...");
avance(PRUDENT); // on ralentit la vitesse
default:
avance(AFOND);
}
}
//fonctions
int mesure(){
//fonction qui mesure une distance avec le capteur
unsigned long mesure = 0; // variable de mesure
unsigned long cumul = 0; //variable pour la moyenne
for (int t = 0; t < NBMESURE; t++) { // boucle pour effectuer les mesures
pinMode (pinSRF, OUTPUT); //on prépare le pin pour envoyer le signal
digitalWrite(pinSRF, LOW); //on commence à l'état bas
delayMicroseconds(2); //on attend que le signal soit clair
digitalWrite(pinSRF, HIGH);//mise à l'état haut
delayMicroseconds(10); //pendant 10 µs
digitalWrite(pinSRF, LOW); //mise à l'état bas
pinMode(pinSRF, INPUT); //on prépare le pin pour recevoir un état
mesure = pulseIn(pinSRF, HIGH); // fonction pulseIn qui attend un état haut et renvoie le temps d'attente
cumul+=mesure; //on cumule les mesures
delay(50); //attente obligatoire entre deux mesures
}
mesure=cumul/NBMESURE; //on calcule la moyenne des mesures
mesure=mesure/VSON;//on transforme en cm
if (mesure<=DANGER){//on teste si l'obstacle est dans la zone DANGER
return 0; //si oui, on retourne le code de danger
}
else if (mesure>DANGER && mesure<=PROCHE){//on teste s'il est dans la zone PROCHE
return 1; //si oui, on retourne le code de proche
}
return 2; // on retourne le code de sans risque
}
void recherche(){
//fonction pour rechercher un passage
tourneGauche(AFOND); //on positionne le robot à gauche (facultatif)
delay (300);
int etat=0; //variable de test de possibilité d'avancer
while (etat!=2){ // tant que la distance n'est pas suffisante
etat=mesure(); // on effectue la mesure
tourneDroite(PRUDENT); //on fait tourner le robot
}
Serial.println("La voie est libre !");
//retour au programme principal
}
void arret(){
Serial.println("Je stoppe");
//fonction d'arrêt des moteurs
}
void avance(int v){
Serial.print("J'avance");
affiche(v);
//fonctin de mise en route des deux moteurs dans le sens avant
// on utilise la variable v pour le pilotage PWM
}
void recule(int v){
Serial.print("Je recule");
affiche(v);
//fonctin de mise en route des deux moteurs dans le sens arrière
// on utilise la variable v pour le pilotage PWM
}
void tourneDroite(int v){
Serial.print("Je tourne a droite");
affiche(v);
//fonction de rotation à droite : un moteur dans un sens, l'autre dans le sens opposé
// on utilise la variable v pour le pilotage PWM
}
void tourneGauche(int v){
Serial.print("Je tourne a gauche");
affiche(v);
//fonction de rotation à gauche : un moteur dans un sens, l'autre dans le sens opposé
// on utilise la variable v pour le pilotage PWM
}
void affiche(int v){
//fonction complémentaire d'affichage
if (v==AFOND){
Serial.println(" a fond !");
}
else{
Serial.println(" prudemment...");
}
}

Ce code ne contient pas les commandes pour les moteurs, je vous laisse le faire .

J'attire tout de même votre attention sur le début du programme. Vous y trouvez la directive (car ce n'est pas une fonction) #define . C'est une directive qui permet de fixer des noms de constantes. Il faut penser à bien écrire les constantes en majuscule pour un meilleur repérage dans le code. On l'utilise comme suit :

#define NOMDECONSTANTE VALEUR

Lors de la compilation, à chaque fois que l'IDE trouvera NOMDECONSTANTE dans le code, il le remplacera par la valeur. Du coup, pas d'utilisation de mémoire dynamique ! Vous rencontrerez souvent cette directive dans les programmes (et ce, dans plusieurs langages !). N'hésitez pas à l'utiliser.

Bon, vous avez maintenant un robot qui évite les obstacles sans les toucher. Que pourrait-il faire d'autre ?

Je suis une ligne noire sur le sol

Ha ben oui ! En voilà une bonne idée !

(Non Lukas, le titre ne veut pas dire qu'il faut s'habiller en noir et s'aplatir par terre, il s'agit du verbe suivre !)

Comment notre robot peut-il réaliser ce tour de force ? Et bien rappelez-vous que la couleur noire réfléchit très mal la lumière.

Ben on peut utiliser une photodiode infrarouge alors ?

(Oui Cunégonde, mais la prochaine fois, laissez-moi le temps de le dire !)

En effet, notre problème de tout à l'heure devient une solution. En utilisant notre capteur de distance infrarouge et en le dirigeant vers le sol, nous obtiendrons une mesure très faible lorsque l'infrarouge rebondira sur du noir, et une mesure plus forte sur d'autres couleurs. Pour une efficacité totale, la couleur blanche est conseillée.

Comment va fonctionner un tel programme ?

Tout d'abord, ça dépend du matériel de l'épaisseur de la ligne.

Deux capteurs, ligne épaisse (plus de 5 cm)

C'est le cas le plus simple. Vos deux capteurs sont au dessus de la ligne. Ils renvoient chacun une valeur faible. Si en avançant, le robot s'éloigne de la ligne, l'un des deux capteurs va le remarquer.

Donc si une valeur forte est renvoyée par le capteur de droite, c'est qu'on quitte la ligne par la droite, on doit donc tourner à gauche. À l'inverse, une valeur forte renvoyée par le capteur de gauche signifie qu'il faut aller à droite.

On ajuste donc le mouvement dans la direction opposée du capteur qui détecte la sortie.

Si les deux capteurs envoient en même temps une valeur forte, on vient de sortir de la ligne en allant tout droit. Il faut faire demi-tour et chercher le passage.

Deux capteurs, ligne fine (de 5mm à 1 cm)

C'est déjà plus compliqué. Si la ligne est fine, il faut que les capteurs se situent de part et d'autre de celle-ci.

On teste cette fois-ci la chute de valeur (donc survol de la ligne noire).

Si le capteur de gauche "voit" la ligne noire, c'est qu'on se décale vers la droite et inversement, si le capteur de droite "voit" la ligne noire, c'est qu'on se décale à gauche. Donc on ajuste dans la direction du capteur qui repère la ligne.

Si les deux capteurs "voient" la ligne en même temps, c'est qu'on est à une intersection. Il faudra donc trouver un moyen de se retrouver avec une seule ligne entre les deux capteurs.

Il est important dans cette configuration, de faire vérifier au robot qu'il a bien une ligne noire entre ses deux capteurs (avec une rotation vers la droite, puis la gauche), sinon il pourrait quitter la ligne sans s'en apercevoir et aller batifoler n'importe où... ;)

Un capteur, une ligne de taille minimum (au moins 2 cm)

Là c'est plus difficile. Ça ne peut fonctionner qu'en contrôlant qu'on est sur la ligne. 

Tant que le capteur reçoit une valeur basse (il voit la ligne) tout est ok.

S'il reçoit une valeur haute, c'est qu'il vient de quitter la ligne. Le problème c'est qu'on ne sait pas de quel côté. Il faut dont stopper et faire un balayage droite/gauche pour la retrouver et le remettre en route.

Le mouvement du robot sera moins fluide, plus saccadé. Mais il réussira tout de même sa mission !

Les contraintes pour la construction

Pour que les données reçues soient claires (valeur haute hors ligne et valeur basse sur la ligne), il faut que le capteur soit situé à bonne distance du sol. C'est un réglage important à faire. Trop proche et la lumière infrarouge ne rebondira pas vers le capteur. Trop éloigné et le capteur donnera des variations trop faibles pour une analyse correcte. L'idéal c'est de concevoir un montage avec un capteur facilement réglable en hauteur.

L'autre point découle du premier. Le capteur étant proche du sol, le robot ne pourra pas se permettre d'évoluer dans un environnement chaotique. Bref, il faut que la zone soit plate et sans obstacles.

J'en profite pour vous montrer un nouveau composant qui est très efficace pour le suivi de ligne noire : le CNY70.

Le CNY70. Emetteur/récepteur infrarouge (http://5hertz.com)
Le CNY70. Émetteur/récepteur infrarouge (http://5hertz.com)

Il a l'air gros comme ça, mais il est tout petit (moins d'1 cm de côté) et il ne coûte par cher (1 à 3€). On le trouve facilement dans les magasins d'électronique ou sur des sites de vente en ligne (il suffit de taper sa référence dans un moteur de recherche). Voici comment le connecter à votre Arduino :

Connexion du CNY70 à l'Arduino
Connexion du CNY70 à l'Arduino

Le repérage des pattes est simple du fait de la différence de couleur.

Il faut le placer assez près du sol pour de bonnes mesures, mais vu le prix, ça vaut le coup de se faire un robot double capteur !