Proposition de solution sortie Labyrinthe
Exemples
l_algorithme_de_pledge_-_interstices_-_interstices.pdf
Initialisation :
*1 Démarrage du robot MBot.
*2 Activation des capteurs de distance (Yeux).
*3 Configuration des paramètres de vitesse et de détection.
*Détection d'obstacle :
*4 Si la distance est supérieure à 20 cm, le robot accélère.
*5 Si la distance est entre 20 cm et 10 cm, le robot maintient une vitesse constante.
*6 Si la distance est inférieure à 10 cm mais supérieure à 5 cm, le robot ralentit.
*7 Si la distance est inférieure à 5 cm, le robot s'arrête.
*Orientation pour trouver la sortie :
*8 Si le robot est arrêté à cause d'un obstacle à 5 cm, il effectue une séquence d'orientations pour trouver la sortie.
*9 Si après un virage à droite de 90°, il n'y a pas d'obstacle proche, le robot avance.
*10 Sinon, s'il effectue un demi-tour (180°) et ne détecte pas d'obstacle proche, le robot avance.
*11 Sinon, après un virage à gauche de 90°, le robot avance (car il aura effectué un demi-tour).
*Répétition du processus :
*12 Le robot continue à avancer tout en détectant les obstacles et ajustant sa vitesse en conséquence.
*13 En cas d'obstacle à 5 cm, il effectue les étapes d'orientation pour trouver la sortie.
*Fin :
*14 Arrêt du robot lorsque la sortie du labyrinthe est détectée.
il ne suffit pas de marcher en ligne droite. Il faut compter les changements de
direction.
Supposons que, comme dans les exemples précédents, tous les angles soient droits.
On n’a alors que deux possibilités, tourner à droite ou à gauche selon un angle
de 90°. On compte les changements de direction en augmentant d’un point lorsque
l’on tourne à gauche et en diminuant d’un point lorsque l’on tourne à droite
(y compris la première fois que l’on tourne à droite quand on atteint un mur).
Au début, le décompte est à zéro. Les deux instructions sont alors les suivantes :
*1 Aller tout droit jusqu’au mur, passer à l’instruction 2 ;
*2 Longer le mur par la droite (ou par la gauche, mais toujours dans le même
sens) jusqu’à ce que le décompte des changements de direction atteigne zéro,
passer à l’instruction 1 ;
Il faut répéter ces actions jusqu’à ce que l’on revienne à la lumière du jour.
Voici une présentation claire des principaux algorithmes de résolution de labyrinthe pour un robot, du plus simple au plus avancé. J’indique à chaque fois le principe, les avantages et les limites, avec un peu de pseudo-code quand c’est utile.
Le robot garde toujours la main droite en contact avec un mur. Tant que le labyrinthe est simplement connexe, il finira par trouver la sortie.
tant que sortie non trouvée :
si mur à droite absent :
tourner à droite
avancer
sinon si devant libre :
avancer
sinon :
tourner à gauche
Le robot marque les passages déjà visités :
Il évite de repasser inutilement au même endroit.
Le robot explore un chemin jusqu’au bout, puis revient en arrière quand il est bloqué.
fonction DFS(case):
marquer case visitée
si case = sortie :
fin
pour chaque voisin libre :
si non visité :
DFS(voisin)
Le robot explore niveau par niveau toutes les possibilités.
Algorithme intelligent utilisant :
| Algorithme | Mémoire | Chemin optimal | Complexité |
|---|---|---|---|
| Main droite | Très faible | ❌ | Très simple |
| Trémaux | Faible | ❌ | Simple |
| DFS | Moyenne | ❌ | Moyenne |
| BFS | Élevée | ✅ | Moyenne |
| A* | Élevée | ✅ | Complexe |
Voici l’ajout de la gestion des angles et des virages précis pour un robot de labyrinthe avec capteurs IR / ultrasons, adapté à un robot à deux roues motrices (différentiel).
Pour tourner proprement à 90°, le robot ne se contente pas d’un délai (delay) :
il utilise soit :
Je te montre les 3 niveaux, du plus simple au plus avancé.
Vue de dessus
AVANT
↑
│
┌───┴───┐
│ ROBOT │ → rotation
└───┬───┘
│
↓
Roue gauche : AVANCE
Roue droite : RECULE (ou arrêt)
Tourner à droite : - Moteur gauche : ON - Moteur droit : OFF - Temps ≈ 400 ms → 90°
void tournerDroite90() {
moteurGauche(AVANCE);
moteurDroit(ARRET);
delay(400); // à calibrer
arret();
}
Chaque roue a un encodeur → nombre de ticks = angle.
Angle = (ticks mesurés / ticks par tour) × 360°
void tournerDroite90() {
resetEncodeurs();
moteurGauche(AVANCE);
moteurDroit(RECULE);
while (encodeurGauche < TICKS_90) {
// attendre
}
arret();
}
Le robot mesure directement l’angle de rotation (yaw).
Angle cible = angle actuel ± 90°
void tournerDroite90() {
float angleInitial = lireYaw();
moteurGauche(AVANCE);
moteurDroit(RECULE);
while (lireYaw() < angleInitial + 90) {
// rotation
}
arret();
}
Mur à droite trop proche → corriger à gauche Mur à droite trop loin → corriger à droite
erreur = distanceD - distanceConsigne; vG = vBase - Kp * erreur; vD = vBase + Kp * erreur;
👉 C’est un contrôle proportionnel (P).
Lire capteurs
↓
Décision (droite / avant / gauche)
↓
Si virage :
→ rotation 90° précise
Sinon :
→ avance + correction mur
↓
Répéter
| Méthode | Précision | Complexité |
|---|---|---|
| Temps | ⭐⭐ | ⭐ |
| Encodeurs | ⭐⭐⭐⭐ | ⭐⭐⭐ |
| Gyroscope | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ |
Voici un code Arduino COMPLET pour un robot résolveur de labyrinthe utilisant :
ENA → pin 5 (PWM) IN1 → pin 6 IN2 → pin 7 ENB → pin 9 (PWM) IN3 → pin 10 IN4 → pin 11
Avant : TRIG → 2 ECHO → 3 Droit : TRIG → 4 ECHO → 8
Encodeur gauche → pin 18 (INT) Encodeur droit → pin 19 (INT)
#define DIST_MUR 15 // cm #define VITESSE 150 #define TICKS_90 120 // À CALIBRER
// ===== MOTEURS =====
#define ENA 5
#define IN1 6
#define IN2 7
#define ENB 9
#define IN3 10
#define IN4 11
// ===== ULTRASONS =====
#define TRIG_AV 2
#define ECHO_AV 3
#define TRIG_D 4
#define ECHO_D 8
// ===== ENCODEURS =====
volatile long ticksG = 0;
volatile long ticksD = 0;
#define DIST_MUR 15
#define VITESSE 150
#define TICKS_90 120
// ===== FONCTIONS ENCODEURS =====
void isrG() { ticksG++; }
void isrD() { ticksD++; }
// ===== SETUP =====
void setup() {
pinMode(ENA, OUTPUT);
pinMode(IN1, OUTPUT);
pinMode(IN2, OUTPUT);
pinMode(ENB, OUTPUT);
pinMode(IN3, OUTPUT);
pinMode(IN4, OUTPUT);
pinMode(TRIG_AV, OUTPUT);
pinMode(ECHO_AV, INPUT);
pinMode(TRIG_D, OUTPUT);
pinMode(ECHO_D, INPUT);
attachInterrupt(digitalPinToInterrupt(18), isrG, RISING);
attachInterrupt(digitalPinToInterrupt(19), isrD, RISING);
}
// ===== ULTRASON =====
long distanceCM(int trig, int echo) {
digitalWrite(trig, LOW);
delayMicroseconds(2);
digitalWrite(trig, HIGH);
delayMicroseconds(10);
digitalWrite(trig, LOW);
long duree = pulseIn(echo, HIGH, 20000);
return duree * 0.034 / 2;
}
// ===== MOTEURS =====
void avance(int v) {
digitalWrite(IN1, HIGH);
digitalWrite(IN2, LOW);
digitalWrite(IN3, HIGH);
digitalWrite(IN4, LOW);
analogWrite(ENA, v);
analogWrite(ENB, v);
}
void recule(int v) {
digitalWrite(IN1, LOW);
digitalWrite(IN2, HIGH);
digitalWrite(IN3, LOW);
digitalWrite(IN4, HIGH);
analogWrite(ENA, v);
analogWrite(ENB, v);
}
void stopMot() {
analogWrite(ENA, 0);
analogWrite(ENB, 0);
}
// ===== ROTATION PRECISE =====
void tournerDroite90() {
ticksG = 0;
ticksD = 0;
digitalWrite(IN1, HIGH);
digitalWrite(IN2, LOW);
digitalWrite(IN3, LOW);
digitalWrite(IN4, HIGH);
analogWrite(ENA, VITESSE);
analogWrite(ENB, VITESSE);
while (ticksG < TICKS_90) {}
stopMot();
delay(50);
}
void tournerGauche90() {
ticksG = 0;
ticksD = 0;
digitalWrite(IN1, LOW);
digitalWrite(IN2, HIGH);
digitalWrite(IN3, HIGH);
digitalWrite(IN4, LOW);
analogWrite(ENA, VITESSE);
analogWrite(ENB, VITESSE);
while (ticksD < TICKS_90) {}
stopMot();
delay(50);
}
// ===== BOUCLE PRINCIPALE =====
void loop() {
long dAvant = distanceCM(TRIG_AV, ECHO_AV);
long dDroit = distanceCM(TRIG_D, ECHO_D);
if (dDroit > DIST_MUR) {
tournerDroite90();
avance(VITESSE);
}
else if (dAvant > DIST_MUR) {
avance(VITESSE);
}
else {
tournerGauche90();
}
delay(20);
}
Remplace les fonctions tournerDroite90() et tournerGauche90() par :
delay(400); // à calibrer
TICKS_90DIST_MUR (12–20 cm)VITESSE✅ Le robot :
Parfait 👍 Voici un schéma électrique détaillé (texte + explications claires) pour ton robot résolveur de labyrinthe Arduino avec :
Batterie 7–12V
+ -----------+
| |
| +--+--> L298N +12V
| |
| +--------> Arduino Vin
|
+------------------> GND commun
⚠️ Toutes les masses (GND) DOIVENT être communes
L298N
┌───────────────────┐
│ │
ENA──┤5 OUT1 ─── Moteur gauche +
IN1──┤6 OUT2 ─── Moteur gauche -
IN2──┤7
│
ENB──┤9 OUT3 ─── Moteur droit +
IN3──┤10 OUT4 ─── Moteur droit -
IN4──┤11
│
GND──┤GND
+12V─┤+12V
└───────────────────┘
| Arduino | L298N |
|---|---|
| 5 (PWM) | ENA |
| 6 | IN1 |
| 7 | IN2 |
| 9 (PWM) | ENB |
| 10 | IN3 |
| 11 | IN4 |
| GND | GND |
HC-SR04 ┌──────────┐ │ VCC → 5V│ │ TRIG → Dx│ │ ECHO → Dx│ │ GND → GND│ └──────────┘
| HC-SR04 | Arduino |
|---|---|
| VCC | 5V |
| TRIG | D2 |
| ECHO | D3 |
| GND | GND |
| HC-SR04 | Arduino |
|---|---|
| VCC | 5V |
| TRIG | D4 |
| ECHO | D8 |
| GND | GND |
Encodeur ┌──────────┐ │ VCC → 5V │ │ GND → GND│ │ OUT → INT│ └──────────┘
| Encodeur | Arduino UNO |
|---|---|
| Gauche OUT | D18 (INT) |
| Droit OUT | D19 (INT) |
| VCC | 5V |
| GND | GND |
⚠️ D18 et D19 = Arduino MEGA 👉 Si tu as UNO, utilise D2 et D3 (changer le code).
+--------------------+
| Arduino UNO |
| |
| D2 <--- TRIG AV |
| D3 <--- ECHO AV |
| D4 <--- TRIG D |
| D8 <--- ECHO D |
| |
| D5 ---> ENA L298N |
| D6 ---> IN1 |
| D7 ---> IN2 |
| D9 ---> ENB |
| D10 ---> IN3 |
| D11 ---> IN4 |
| |
| 5V ---> Capteurs |
| GND ---> GND COMMUN|
+--------------------+
|
|
+----+----+
| L298N |
+----+----+
|
Moteur G Moteur D
✔ Masse commune partout ✔ Ne pas alimenter moteurs depuis le 5V Arduino ✔ Mettre le jumper ENA/ENB (ou PWM Arduino) ✔ Batterie assez puissante (≥ 1500 mAh)
Ce schéma permet :
la version texte simulée des blocs mBlock
+-----------------------------------------------------+ | [quand Arduino démarre] | | +---------------------------------------------+ | | | [répéter indéfiniment] | | | | +-------------------------------------+ | | | | | [mettre distance_avant à (ultrason D2/D3)] | | | | [mettre distance_droite à (ultrason D4/D8)] | | | | [si (distance_droite > SEUIL)] | | | | | +-------------------------------+ | | | | | | [tourner_droite_90] | | | | | | | [avancer] | | | | | | +-------------------------------+ | | | | | [sinon] | | | | | +-------------------------------+ | | | | | | [si (distance_avant > SEUIL)] | | | | | | | [avancer] | | | | | | | [sinon] | | | | | | [tourner_gauche_90] | | | | | +-------------------------------+ | | | | | [attendre 0.02 s] | | | | +-------------------------------------+ | | +---------------------------------------------+ | +-----------------------------------------------------+
Pour ton robot suiveur de mur et résolveur de labyrinthe, la variable SEUIL représente la distance minimale (en cm) à laquelle le robot considère qu’il y a un mur. Elle dépend de :
| Capteur | SEUIL recommandé (cm) | Remarques |
|---|---|---|
| HC-SR04 (ultrasons) | 12 – 20 | 15 cm est un bon point de départ |
| Capteurs IR | 5 – 12 | IR détecte de plus près, car moins précis à longue distance |
Teste le robot dans ton labyrinthe :
SEUIL = 15
distance_avant > SEUIL → voie libre devantdistance_droite > SEUIL → mur droit libre
Voici un mini guide visuel explicatif pour comprendre comment le robot utilise la variable SEUIL pour suivre les murs et décider de ses mouvements dans le labyrinthe.
Mur avant
|
|
+------+------+
| |
| ROBOT |
| |
+------+------+
|
distance_avant
|
SEUIL ?
distance_avant → mesure devant le robotdistance_droite → mesure sur le côté droit| Capteur | Lecture < SEUIL | Lecture > SEUIL | Action du robot |
|---|---|---|---|
| Droite | Mur proche | Mur libre | Tourner à droite si libre |
| Avant | Mur proche | Voie libre | Avancer si libre |
Si distance_droite > SEUIL → tourner à droite puis avancer Sinon si distance_avant > SEUIL → avancer Sinon → tourner à gauche
Avant (distance_avant)
15 cm SEUIL
┌─────────────┐
Mur │ │ Mur
│ ROBOT │
│ │
└─────────────┘
Droite (distance_droite)
15 cm SEUIL