ENIB 2025 : TurboScoot : Différence entre versions
(→Auteurs) |
(→Description) |
||
(51 révisions intermédiaires par 2 utilisateurs non affichées) | |||
Ligne 9 : | Ligne 9 : | ||
Voici le modèle final du TurboScoot : | Voici le modèle final du TurboScoot : | ||
− | [[Fichier: | + | [[Fichier:Finitoooooo.JPG|600px]] |
==Auteurs== | ==Auteurs== | ||
Ligne 15 : | Ligne 15 : | ||
Jade Arnould | Jade Arnould | ||
+ | |||
Zahra El Bahloul | Zahra El Bahloul | ||
+ | |||
Marie Lehmann Gaumer | Marie Lehmann Gaumer | ||
− | == | + | ==Description== |
+ | |||
+ | Le TurboScoot avance jusqu'à ce qu'il rencontre un obstacle. Dès qu'un obstacle est détecté à 15 cm (grâce au capteur), la LED rouge s'allume, et le scooter tente de trouver un autre chemin, soit à droite, soit à gauche. Si le scooter tourne à gauche, la LED de gauche clignote pour prévenir et inversement si le scooter tourne à droite. | ||
+ | |||
+ | ==Outil et matériel== | ||
+ | Pour fabriquer le TurboScooter, il nous faut plusieurs éléments : | ||
+ | |||
+ | • 2 servos moteurs | ||
+ | • 2 roues imprimées en 3D | ||
+ | • 1 capteur de distance ultrason | ||
+ | • 1 microprocesseur ESP8266 | ||
+ | • 2 petites LED blanches | ||
+ | • 1 grande LED rouge | ||
+ | • 2 résistances de 220 Ω | ||
+ | • 1 résistance de 1 kΩ | ||
+ | • 1 Maquette | ||
+ | • 1 bille avec son support imprimé en 3D | ||
+ | • Plusieurs fils électriques | ||
+ | • Matériel décoratif | ||
+ | |||
+ | ==Étapes de fabrication== | ||
+ | Mode d'emploi : | ||
+ | |||
+ | ===étape 1=== | ||
+ | Dans un premier temps nous avons dessiné la maquette : | ||
+ | |||
+ | [[Fichier:Plan TurboScoot.jpg | 300px]] | ||
+ | |||
+ | ===étape 2=== | ||
+ | Dans un second temps, nous avons réalisé les différentes parties du TurboScoot : le corps, le siège et le guidon. | ||
+ | |||
+ | [[Fichier:Patron TS.jpg | 300px]] | ||
+ | [[Fichier:Patron corps TS.jpg | 300px]] | ||
+ | |||
+ | ===étape 3=== | ||
+ | Ensuite, nous avons procédé au montage des différentes parties, ainsi qu'à la découpe des trous nécessaires pour accueillir les éléments électroniques. | ||
+ | |||
+ | [[Fichier:Modélisation siège.jpg | 300px]] | ||
+ | [[Fichier:Modélisation guidon.jpg | 300px]] | ||
+ | [[Fichier:Corps TS.jpg | 300px]] | ||
+ | |||
+ | ===étape 4=== | ||
+ | Après avoir terminé les premières étapes du montage, nous avons programmé sur Arduino (voir code plus bas). Nous avons d'abord effectué des tests sur une plaque à part : d'abord avec les LED seules, puis avec les LED et le capteur de distance ultrason, et enfin le test final avec les servomoteurs. | ||
+ | |||
+ | [[Fichier:Test les TS.jpg | 300px]] | ||
+ | [[Fichier:Test complet TS.jpg | 350px]] | ||
+ | |||
+ | ===étape 5=== | ||
+ | Une fois les tests terminés et validés, nous avons réalisé les premiers essais sur le prototype initial. | ||
+ | |||
+ | ===étape 6=== | ||
+ | Après quelques ajustements, le premier prototype fonctionne parfaitement, ce qui nous a permis de concevoir le TurboScoot final et de le customiser. | ||
+ | |||
+ | [[Fichier:Finitoooooo.JPG | 300px]] | ||
+ | |||
+ | ==Fichiers à joindre== | ||
+ | Voici le code Arduino pour faire fonctionner le TurboScoot. | ||
− | |||
− | |||
− | |||
<syntaxhighlight lang="Arduino" line> | <syntaxhighlight lang="Arduino" line> | ||
− | + | #include <Servo.h> | |
− | #include < | + | |
+ | // Définition des broches | ||
+ | #define TRIG_PIN 5 // (D1) | ||
+ | #define ECHO_PIN 4 // (D2) | ||
+ | #define LED_LEFT 14 // (D5) | ||
+ | #define LED_RIGHT 12 // (D6) | ||
+ | #define LED_OBSTACLE 2 // (D4) | ||
+ | #define SERVO_LEFT_PIN 13 // (D7) | ||
+ | #define SERVO_RIGHT_PIN 15 // (D8) | ||
+ | |||
+ | long duration; | ||
+ | int distance; | ||
+ | int minDistance = 15; // Distance minimum pour arrêt en cm | ||
+ | int slowDistance = 30; // Distance pour ralentir en cm | ||
+ | |||
+ | Servo servoLeft; // Instance moteur gauche | ||
+ | Servo servoRight; // Instance moteur droit | ||
+ | |||
+ | // Mesurer la distance avec le capteur ultrason | ||
+ | int measureDistance() { | ||
+ | digitalWrite(TRIG_PIN, LOW); | ||
+ | delayMicroseconds(2); | ||
+ | digitalWrite(TRIG_PIN, HIGH); | ||
+ | delayMicroseconds(10); | ||
+ | digitalWrite(TRIG_PIN, LOW); | ||
+ | duration = pulseIn(ECHO_PIN, HIGH); | ||
+ | return duration * 0.034 / 2; // Conversion en cm | ||
+ | } | ||
void setup() { | void setup() { | ||
− | // | + | // Configuration des broches |
+ | pinMode(TRIG_PIN, OUTPUT); | ||
+ | pinMode(ECHO_PIN, INPUT); | ||
+ | pinMode(LED_LEFT, OUTPUT); | ||
+ | pinMode(LED_RIGHT, OUTPUT); | ||
+ | pinMode(LED_OBSTACLE, OUTPUT); | ||
+ | |||
+ | // Attacher les moteurs aux broches | ||
+ | servoLeft.attach(SERVO_LEFT_PIN); | ||
+ | servoRight.attach(SERVO_RIGHT_PIN); | ||
+ | |||
+ | // Initialiser les moteurs en position neutre (90 degrés) | ||
+ | servoLeft.write(90); | ||
+ | servoRight.write(90); | ||
+ | Serial.begin(115200); | ||
} | } | ||
void loop() { | void loop() { | ||
− | // | + | distance = measureDistance(); |
+ | Serial.println(distance); | ||
+ | |||
+ | if (distance < minDistance) { | ||
+ | // Arrêt complet et allumer la LED d'obstacle | ||
+ | servoLeft.write(90); // Position neutre (arrêt) | ||
+ | servoRight.write(90); // Position neutre (arrêt) | ||
+ | digitalWrite(LED_OBSTACLE, HIGH); | ||
+ | delay(500); | ||
+ | |||
+ | // Choisir aléatoirement de tourner à gauche ou à droite | ||
+ | int direction = random(0, 2); // 0 pour gauche, 1 pour droite | ||
+ | |||
+ | if (direction == 0) { | ||
+ | // Tourner à gauche | ||
+ | digitalWrite(LED_LEFT, HIGH); | ||
+ | digitalWrite(LED_RIGHT, LOW); | ||
+ | servoLeft.write(60); // Tourner à gauche | ||
+ | delay(1000); | ||
+ | servoRight.write(120); // Tourner à droite | ||
+ | delay(2000); | ||
+ | |||
+ | digitalWrite(LED_LEFT, LOW); | ||
+ | digitalWrite(LED_OBSTACLE, LOW); | ||
+ | } else { | ||
+ | // Tourner à droite | ||
+ | digitalWrite(LED_RIGHT, HIGH); | ||
+ | digitalWrite(LED_LEFT, LOW); | ||
+ | servoRight.write(120); // Tourner à droite | ||
+ | delay(1000); | ||
+ | servoLeft.write(60); // Tourner à gauche | ||
+ | delay(2000); | ||
− | } | + | digitalWrite(LED_RIGHT, LOW); |
+ | digitalWrite(LED_OBSTACLE, LOW); | ||
+ | } | ||
+ | } else if (distance < slowDistance) { | ||
+ | // Ralentir selon la distance | ||
+ | int angle = map(distance, minDistance, slowDistance, 90, 120); | ||
+ | servoLeft.write(angle); | ||
+ | servoRight.write(180 - angle); // Angle opposé pour symétrie | ||
− | + | // Éteindre LEDs | |
+ | digitalWrite(LED_RIGHT, LOW); | ||
+ | digitalWrite(LED_LEFT, LOW); | ||
+ | digitalWrite(LED_OBSTACLE, LOW); // Éteindre la LED d'obstacle | ||
+ | } else { | ||
+ | // Pleine vitesse (symétrique) | ||
+ | servoLeft.write(120); | ||
+ | servoRight.write(60); | ||
− | + | // LEDs éteintes | |
− | + | digitalWrite(LED_RIGHT, LOW); | |
+ | digitalWrite(LED_LEFT, LOW); | ||
+ | digitalWrite(LED_OBSTACLE, LOW); // Éteindre la LED d'obstacle | ||
+ | } | ||
− | + | delay(50); // Anti-rebond | |
− | + | } | |
− | + | </syntaxhighlight> | |
===Troubleshouting=== | ===Troubleshouting=== | ||
Quelles sont difficultés, les problèmes, quelles sont les solutions, les trucs et astuces pour que ça marche ? | Quelles sont difficultés, les problèmes, quelles sont les solutions, les trucs et astuces pour que ça marche ? | ||
Ligne 50 : | Ligne 194 : | ||
==Sources et documentation complémentaire== | ==Sources et documentation complémentaire== | ||
− | == | + | le détail de toutes le brochs du shield sont décrite dans ce code : https://github.com/julienrat/petitbot/blob/master/code_arduino/petitbot_v2/petitbot_v2.ino |
− | + | ||
+ | ===Code de base du petit bot === | ||
+ | <syntaxhighlight lang="Arduino" line> | ||
+ | /////////////// | ||
+ | // Petit Bot // | ||
+ | /////////////// | ||
+ | // MAJ 250121 | ||
+ | // Un programme pédagogique des petits débrouillards ?=+ pour gérer le robot "Petit Bot" | ||
+ | // Voir sur http://ancien.wikidebrouillard.org/index.php?title=Petit_Bot_un_robot_controlable_en_Wifi | ||
+ | // Ce programme est inspire de : http://www.esp8266.com/viewtopic.php?f=29&t=6419#sthash.gd1tJhwU.dpuf | ||
+ | // Sous licence CC-By-Sa | ||
+ | // Par des gens bien | ||
+ | |||
+ | /* Schéma | ||
+ | Lolin (Wemos) D1 mini | ||
+ | |||
+ | _________________ | ||
+ | / D1 mini \ | ||
+ | |[ ]RST TX[ ]| | ||
+ | |[ ]A0 -GPIO RX[ ]| | ||
+ | |[ ]D0-16 5-D1[X]|----\ | ||
+ | |[ ]D5-14 4-D2[X]|--\ \ | ||
+ | |[ ]D6-12 0-D3[ ]| | | | ||
+ | |[ ]D7-13 2-D4[ ]| | | | ||
+ | |[ ]D8-15 GND[X]| | | | ||
+ | |[ ]3V3 5V[ ]| | | | ||
+ | _ | +---+ | | | | ||
+ | | | |_______|USB|_______| | / _ | ||
+ | | | _ / / _ | | | ||
+ | | | _| |_________ _____/ / _________| |_ | | | ||
+ | | | | ______ |_data D1______________/ |_data D2_| ______ | | | | ||
+ | | | __| | SG90 | |_______________GND_______________________| | SG90 | |___ | | | ||
+ | | |_| |Servo | |_______________Vin_______________________| |Servo | |_| | | ||
+ | | |_| |Gauche| | | |Droit | |_| | | ||
+ | | | |__ |______| | | |______| ___| | | | ||
+ | | | |__ ________| |_________ __| | | | ||
+ | | | |_| |_| | | | ||
+ | | | | | | ||
+ | |_| |_| | ||
+ | |||
+ | ___ | ||
+ | / ___ \ | ||
+ | |_| | | | ||
+ | /_/ | ||
+ | _ ___ _ | ||
+ | |_| |___|_| |_ | ||
+ | ___|_ _| | ||
+ | |___| |_| | ||
+ | Les petits Débrouillards - CC-By-Sa http://creativecommons.org/licenses/by-nc-sa/3.0/ | ||
+ | Antony Le Goïc-Auffret janvier 2025 | ||
+ | */ | ||
+ | |||
+ | // on appelle la bibliothèque qui gère le Wemos D1 mini | ||
+ | #include <ESP8266WiFi.h> | ||
+ | |||
+ | // Gestion du Wifi | ||
+ | #include <ESP8266WebServer.h> | ||
+ | #include <DNSServer.h> | ||
+ | #include <ESP8266mDNS.h> | ||
+ | #include <WiFiClient.h> | ||
+ | |||
+ | // Definition du WiFi | ||
+ | const char *nomDuReseau = "petitbota"; // Nom du réseau wifi du petit bot | ||
+ | const char *motDePasse = ""; // Mot de passe du réseau wifi du petit bot | ||
+ | // ATTENTION - le mot de passe doit faire soit 0 caractères soit 8 ou plus sinon | ||
+ | // La configuration de votre réseau wifi ne se fera pas (ni mot de passe, ni nom de réseau !). | ||
+ | //création du monServeur | ||
+ | ESP8266WebServer monServeur(80); // Création de l'objet monServeur | ||
+ | |||
+ | //Gestion des servomoteurs | ||
+ | #include <Servo.h> //appel de la bibliothèque qui gère les servomoteurs | ||
+ | // création des servomoteurs | ||
+ | Servo servogauche; // Nom du servo qui gère la première roue | ||
+ | Servo servodroit; // Seconde roue | ||
+ | |||
+ | //déclaration des Variables | ||
+ | //int --- en cours | ||
+ | int val = -1; // Val nous sert à stocker la commande de l'utilisateur (stop, avance, ...). | ||
+ | |||
+ | void setup(){ | ||
+ | delay(1000); | ||
+ | Serial.begin(9600); // Ouvre une connexion série pour monitorer le fonctionnement du code quand on reste branché a l'ordinateur | ||
+ | Serial.println(); | ||
+ | Serial.println(); | ||
+ | configDuWifi(); | ||
+ | servodroit.detach(); // Place les servos hors tension | ||
+ | servogauche.detach(); | ||
+ | pinMode(LED_BUILTIN, OUTPUT); //met la led du Wemos en sortie | ||
+ | digitalWrite(LED_BUILTIN, LOW); //met la led du Wemos sur le niveau bas ce qui l'allume. | ||
+ | } | ||
+ | |||
+ | void loop(){ | ||
+ | val = -1; | ||
+ | monServeur.handleClient(); | ||
+ | } | ||
+ | |||
+ | ///////////////////////GESTION DES INSTRUCTIONS/////////////////////////// | ||
+ | void GestionDesClics() { | ||
+ | monServeur.on("/avance", HTTP_GET, []() { | ||
+ | val = 1; | ||
+ | Serial.println("avance"); | ||
+ | redactionPageWeb(); | ||
+ | }); | ||
+ | |||
+ | monServeur.on("/recule", HTTP_GET, []() { | ||
+ | val = 2; | ||
+ | Serial.println("recule"); | ||
+ | redactionPageWeb(); | ||
+ | }); | ||
+ | |||
+ | monServeur.on("/gauche", HTTP_GET, []() { | ||
+ | val = 4; | ||
+ | Serial.println("gauche"); | ||
+ | redactionPageWeb(); | ||
+ | }); | ||
+ | |||
+ | monServeur.on("/droite", HTTP_GET, []() { | ||
+ | val = 3; | ||
+ | Serial.println("droite"); | ||
+ | redactionPageWeb(); | ||
+ | }); | ||
+ | |||
+ | monServeur.on("/stop", HTTP_GET, []() { | ||
+ | val = 0; | ||
+ | Serial.println("stop"); | ||
+ | redactionPageWeb(); | ||
+ | }); | ||
+ | |||
+ | monServeur.on("/", HTTP_GET, []() { | ||
+ | val = -1; | ||
+ | redactionPageWeb(); | ||
+ | }); | ||
+ | |||
+ | } | ||
+ | |||
+ | ///////////////////////////LA PAGE WEB DE CONROLE DU PETIT BOT///////////////////////////////////////// | ||
+ | void redactionPageWeb(){ | ||
+ | // Prépare la page web de réponse (le code HTML sera écrit dans la chaine de caractère "pageWeb"). | ||
+ | String pageWeb = "<!DOCTYPE HTML>\r\n"; | ||
+ | pageWeb += "<html>\r\n"; | ||
+ | pageWeb += "<head>\r\n"; | ||
+ | pageWeb += "<meta charset=\"utf-8\">\r\n"; | ||
+ | pageWeb += "<title>Petit bot</title>\r\n"; | ||
+ | pageWeb += "</head>\r\n"; | ||
+ | pageWeb += "<body>\r\n"; | ||
+ | pageWeb += "<center>"; //On ouvre la balise qui va centrer les boutons | ||
+ | pageWeb += "<h1 style=\"font-size:300%;\"\> Le petit bot "; | ||
+ | pageWeb += "<style type=\"text/css\"> body { color: #212121; background-color: #CC0C59 } </style>"; | ||
+ | |||
+ | // On finalise l'écriture de la page Web et on donne les instructions aux servos | ||
+ | pageWeb += instruction(val); // pour cela on appelle la fonction "instruction" | ||
+ | |||
+ | // On termine l'écriture de la page Web | ||
+ | pageWeb += "</h1>"; | ||
+ | pageWeb += "<br>"; //aller à la ligne | ||
+ | pageWeb += "<br>"; //aller à la ligne | ||
+ | pageWeb += "<a href=\"/stop\"\"><button style=\"font-size:200%; width: 18%; background-color:#0CCC16; border-radius: 12px\"\>Stop </button></a>\r\n"; // créer un bouton "Stop", qui envoie sur l'URL /stop | ||
+ | pageWeb += "<a href=\"/avance\"\"><button style=\"font-size:200%; width: 18%; background-color:#0CCC16; border-radius: 12px\"\>Avance </button></a>\r\n"; // créer un bouton "Avance"... | ||
+ | pageWeb += "<a href=\"/recule\"\"><button style=\"font-size:200%; width: 18%; background-color:#0CCC16; border-radius: 12px\"\>Recule </button></a>\r\n"; | ||
+ | pageWeb += "<a href=\"/droite\"\"><button style=\"font-size:200%; width: 18%; background-color:#0CCC16; border-radius: 12px\"\>Droite </button></a>\r\n"; | ||
+ | pageWeb += "<a href=\"/gauche\"\"><button style=\"font-size:200%; width: 18%; background-color:#0CCC16; border-radius: 12px\"\>Gauche </button></a><br />\r\n"; | ||
+ | pageWeb += "</center>"; // tout est centré sur la page | ||
+ | pageWeb += "</body>\r\n"; | ||
+ | pageWeb += "</html>\n"; //Fin de la page Web | ||
+ | |||
+ | // On envoie la page web | ||
+ | monServeur.send(200, "text/html", pageWeb); | ||
+ | delay(1); | ||
+ | } | ||
+ | |||
+ | ///////////////////INSTRUCTIONS///////////////////////////////////////////////////////// | ||
+ | String instruction(int valeur){ //Cette fonction traite les instructions qui sont reçues | ||
+ | int gauche; // Variable dont la valeur 180 ou 0 fera tourner le servo gauche dans un sens ou l'autre | ||
+ | int droite; // Idem pour le servo droit | ||
+ | String completePage; // Déclaration de la chaine de caractère qui sera renvoyée par cette fonction pour compléter la page web | ||
+ | switch(valeur){ // En fonction de la variable valeur on va donner un ordre aux servos | ||
+ | case 0 : // et un texte à la chaine de caractère "completePage" | ||
+ | completePage = " est a l'arrêt "; | ||
+ | droite = 90; | ||
+ | gauche = 90; | ||
+ | break; | ||
+ | case 1 : | ||
+ | completePage = " avance "; | ||
+ | droite = 180; | ||
+ | gauche = 0; | ||
+ | break; | ||
+ | case 2 : | ||
+ | completePage = " recule "; | ||
+ | droite = 0; | ||
+ | gauche = 180; | ||
+ | break; | ||
+ | case 3 : | ||
+ | completePage = " tourne a gauche "; | ||
+ | droite = 180; | ||
+ | gauche = 180; | ||
+ | break; | ||
+ | case 4 : | ||
+ | completePage = " tourne a droite "; | ||
+ | droite = 0; | ||
+ | gauche = 0; | ||
+ | break; | ||
+ | // que faire du cas ou val = -1 ? marquer ici ce qui doit être fait. | ||
+ | } | ||
+ | servogauche.attach(D1); // Broche D1 | ||
+ | servodroit.attach(D2); // Broche D2 | ||
+ | servogauche.write(gauche); | ||
+ | servodroit.write(droite); | ||
+ | return completePage; // on renvoie la chaine de caractère pour compléter la page web | ||
+ | } | ||
+ | ////////////////////////CONFIGURATION WIFI/////////////////////////////////////////////// | ||
+ | void configDuWifi(){ // Fonction de configuratio du Wifi | ||
+ | WiFi.mode(WIFI_AP); // le wemos est en mode "Point d'Accès" (il déploie un réseau wifi) | ||
+ | WiFi.softAP(nomDuReseau, motDePasse, 2); // on démarre le "Point d'Accès". | ||
+ | MDNS.begin(nomDuReseau); // gérer les DNS ce qui rendra votre petit bot accessible | ||
+ | MDNS.addService("http", "tcp", 80); // via http://nomDuReseau.local | ||
+ | IPAddress monIP = WiFi.softAPIP(); // on récupère l'adresse IP du petit Bot | ||
+ | Serial.print("Adresse IP de ce Point d'Accès : "); | ||
+ | Serial.println(monIP); // on l'écrit sur le moniteur série | ||
+ | GestionDesClics(); | ||
+ | monServeur.begin(); //Démarrage du monServeur | ||
+ | Serial.println("Serveur HTTP démarré"); | ||
+ | return; // on retourne à l'endroit ou la fonction a été appelée. | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ==Élément de présentation== | ||
+ | [[Fichier:TurboSCOT.png | 650px]] | ||
− | ==ne pas modifier sous cette ligne== | + | ==Attention ne pas modifier sous cette ligne== |
[[Catégorie:Enib2024]] | [[Catégorie:Enib2024]] | ||
Version actuelle datée du 21 janvier 2025 à 16:08
Titre de la fiche expérience :
Sommaire
Introduction
Cette page est une fiche écrite dans le cadre de l'Inter-Semestre ENIB 2025.
Nous nous sommes inspirés du projet du Petit Bot pour construire notre TurboScoot.
Le TurboScoot est un robot en forme de scooter qui détecte et évite les obstacles. Il indique également s'il tourne à droite ou à gauche.
Voici le modèle final du TurboScoot :
Auteurs
Nous sommes une équipe de 3 :
Jade Arnould
Zahra El Bahloul
Marie Lehmann Gaumer
Description
Le TurboScoot avance jusqu'à ce qu'il rencontre un obstacle. Dès qu'un obstacle est détecté à 15 cm (grâce au capteur), la LED rouge s'allume, et le scooter tente de trouver un autre chemin, soit à droite, soit à gauche. Si le scooter tourne à gauche, la LED de gauche clignote pour prévenir et inversement si le scooter tourne à droite.
Outil et matériel
Pour fabriquer le TurboScooter, il nous faut plusieurs éléments :
• 2 servos moteurs • 2 roues imprimées en 3D • 1 capteur de distance ultrason • 1 microprocesseur ESP8266 • 2 petites LED blanches • 1 grande LED rouge • 2 résistances de 220 Ω • 1 résistance de 1 kΩ • 1 Maquette • 1 bille avec son support imprimé en 3D • Plusieurs fils électriques • Matériel décoratif
Étapes de fabrication
Mode d'emploi :
étape 1
Dans un premier temps nous avons dessiné la maquette :
étape 2
Dans un second temps, nous avons réalisé les différentes parties du TurboScoot : le corps, le siège et le guidon.
étape 3
Ensuite, nous avons procédé au montage des différentes parties, ainsi qu'à la découpe des trous nécessaires pour accueillir les éléments électroniques.
étape 4
Après avoir terminé les premières étapes du montage, nous avons programmé sur Arduino (voir code plus bas). Nous avons d'abord effectué des tests sur une plaque à part : d'abord avec les LED seules, puis avec les LED et le capteur de distance ultrason, et enfin le test final avec les servomoteurs.
étape 5
Une fois les tests terminés et validés, nous avons réalisé les premiers essais sur le prototype initial.
étape 6
Après quelques ajustements, le premier prototype fonctionne parfaitement, ce qui nous a permis de concevoir le TurboScoot final et de le customiser.
Fichiers à joindre
Voici le code Arduino pour faire fonctionner le TurboScoot.
1
2 #include <Servo.h>
3
4 // Définition des broches
5 #define TRIG_PIN 5 // (D1)
6 #define ECHO_PIN 4 // (D2)
7 #define LED_LEFT 14 // (D5)
8 #define LED_RIGHT 12 // (D6)
9 #define LED_OBSTACLE 2 // (D4)
10 #define SERVO_LEFT_PIN 13 // (D7)
11 #define SERVO_RIGHT_PIN 15 // (D8)
12
13 long duration;
14 int distance;
15 int minDistance = 15; // Distance minimum pour arrêt en cm
16 int slowDistance = 30; // Distance pour ralentir en cm
17
18 Servo servoLeft; // Instance moteur gauche
19 Servo servoRight; // Instance moteur droit
20
21 // Mesurer la distance avec le capteur ultrason
22 int measureDistance() {
23 digitalWrite(TRIG_PIN, LOW);
24 delayMicroseconds(2);
25 digitalWrite(TRIG_PIN, HIGH);
26 delayMicroseconds(10);
27 digitalWrite(TRIG_PIN, LOW);
28 duration = pulseIn(ECHO_PIN, HIGH);
29 return duration * 0.034 / 2; // Conversion en cm
30 }
31
32 void setup() {
33 // Configuration des broches
34 pinMode(TRIG_PIN, OUTPUT);
35 pinMode(ECHO_PIN, INPUT);
36 pinMode(LED_LEFT, OUTPUT);
37 pinMode(LED_RIGHT, OUTPUT);
38 pinMode(LED_OBSTACLE, OUTPUT);
39
40 // Attacher les moteurs aux broches
41 servoLeft.attach(SERVO_LEFT_PIN);
42 servoRight.attach(SERVO_RIGHT_PIN);
43
44 // Initialiser les moteurs en position neutre (90 degrés)
45 servoLeft.write(90);
46 servoRight.write(90);
47
48 Serial.begin(115200);
49 }
50
51 void loop() {
52 distance = measureDistance();
53 Serial.println(distance);
54
55 if (distance < minDistance) {
56 // Arrêt complet et allumer la LED d'obstacle
57 servoLeft.write(90); // Position neutre (arrêt)
58 servoRight.write(90); // Position neutre (arrêt)
59 digitalWrite(LED_OBSTACLE, HIGH);
60 delay(500);
61
62 // Choisir aléatoirement de tourner à gauche ou à droite
63 int direction = random(0, 2); // 0 pour gauche, 1 pour droite
64
65 if (direction == 0) {
66 // Tourner à gauche
67 digitalWrite(LED_LEFT, HIGH);
68 digitalWrite(LED_RIGHT, LOW);
69 servoLeft.write(60); // Tourner à gauche
70 delay(1000);
71 servoRight.write(120); // Tourner à droite
72 delay(2000);
73
74 digitalWrite(LED_LEFT, LOW);
75 digitalWrite(LED_OBSTACLE, LOW);
76 } else {
77 // Tourner à droite
78 digitalWrite(LED_RIGHT, HIGH);
79 digitalWrite(LED_LEFT, LOW);
80 servoRight.write(120); // Tourner à droite
81 delay(1000);
82 servoLeft.write(60); // Tourner à gauche
83 delay(2000);
84
85 digitalWrite(LED_RIGHT, LOW);
86 digitalWrite(LED_OBSTACLE, LOW);
87 }
88 } else if (distance < slowDistance) {
89 // Ralentir selon la distance
90 int angle = map(distance, minDistance, slowDistance, 90, 120);
91 servoLeft.write(angle);
92 servoRight.write(180 - angle); // Angle opposé pour symétrie
93
94 // Éteindre LEDs
95 digitalWrite(LED_RIGHT, LOW);
96 digitalWrite(LED_LEFT, LOW);
97 digitalWrite(LED_OBSTACLE, LOW); // Éteindre la LED d'obstacle
98 } else {
99 // Pleine vitesse (symétrique)
100 servoLeft.write(120);
101 servoRight.write(60);
102
103 // LEDs éteintes
104 digitalWrite(LED_RIGHT, LOW);
105 digitalWrite(LED_LEFT, LOW);
106 digitalWrite(LED_OBSTACLE, LOW); // Éteindre la LED d'obstacle
107 }
108
109 delay(50); // Anti-rebond
110 }
Troubleshouting
Quelles sont difficultés, les problèmes, quelles sont les solutions, les trucs et astuces pour que ça marche ?
Sources et documentation complémentaire
le détail de toutes le brochs du shield sont décrite dans ce code : https://github.com/julienrat/petitbot/blob/master/code_arduino/petitbot_v2/petitbot_v2.ino
Code de base du petit bot
1
2 ///////////////
3 // Petit Bot //
4 ///////////////
5 // MAJ 250121
6 // Un programme pédagogique des petits débrouillards ?=+ pour gérer le robot "Petit Bot"
7 // Voir sur http://ancien.wikidebrouillard.org/index.php?title=Petit_Bot_un_robot_controlable_en_Wifi
8 // Ce programme est inspire de : http://www.esp8266.com/viewtopic.php?f=29&t=6419#sthash.gd1tJhwU.dpuf
9 // Sous licence CC-By-Sa
10 // Par des gens bien
11
12 /* Schéma
13 Lolin (Wemos) D1 mini
14
15 _________________
16 / D1 mini \
17 |[ ]RST TX[ ]|
18 |[ ]A0 -GPIO RX[ ]|
19 |[ ]D0-16 5-D1[X]|----\
20 |[ ]D5-14 4-D2[X]|--\ \
21 |[ ]D6-12 0-D3[ ]| | |
22 |[ ]D7-13 2-D4[ ]| | |
23 |[ ]D8-15 GND[X]| | |
24 |[ ]3V3 5V[ ]| | |
25 _ | +---+ | | |
26 | | |_______|USB|_______| | / _
27 | | _ / / _ | |
28 | | _| |_________ _____/ / _________| |_ | |
29 | | | ______ |_data D1______________/ |_data D2_| ______ | | |
30 | | __| | SG90 | |_______________GND_______________________| | SG90 | |___ | |
31 | |_| |Servo | |_______________Vin_______________________| |Servo | |_| |
32 | |_| |Gauche| | | |Droit | |_| |
33 | | |__ |______| | | |______| ___| | |
34 | | |__ ________| |_________ __| | |
35 | | |_| |_| | |
36 | | | |
37 |_| |_|
38
39 ___
40 / ___ \
41 |_| | |
42 /_/
43 _ ___ _
44 |_| |___|_| |_
45 ___|_ _|
46 |___| |_|
47 Les petits Débrouillards - CC-By-Sa http://creativecommons.org/licenses/by-nc-sa/3.0/
48 Antony Le Goïc-Auffret janvier 2025
49 */
50
51 // on appelle la bibliothèque qui gère le Wemos D1 mini
52 #include <ESP8266WiFi.h>
53
54 // Gestion du Wifi
55 #include <ESP8266WebServer.h>
56 #include <DNSServer.h>
57 #include <ESP8266mDNS.h>
58 #include <WiFiClient.h>
59
60 // Definition du WiFi
61 const char *nomDuReseau = "petitbota"; // Nom du réseau wifi du petit bot
62 const char *motDePasse = ""; // Mot de passe du réseau wifi du petit bot
63 // ATTENTION - le mot de passe doit faire soit 0 caractères soit 8 ou plus sinon
64 // La configuration de votre réseau wifi ne se fera pas (ni mot de passe, ni nom de réseau !).
65 //création du monServeur
66 ESP8266WebServer monServeur(80); // Création de l'objet monServeur
67
68 //Gestion des servomoteurs
69 #include <Servo.h> //appel de la bibliothèque qui gère les servomoteurs
70 // création des servomoteurs
71 Servo servogauche; // Nom du servo qui gère la première roue
72 Servo servodroit; // Seconde roue
73
74 //déclaration des Variables
75 //int --- en cours
76 int val = -1; // Val nous sert à stocker la commande de l'utilisateur (stop, avance, ...).
77
78 void setup(){
79 delay(1000);
80 Serial.begin(9600); // Ouvre une connexion série pour monitorer le fonctionnement du code quand on reste branché a l'ordinateur
81 Serial.println();
82 Serial.println();
83 configDuWifi();
84 servodroit.detach(); // Place les servos hors tension
85 servogauche.detach();
86 pinMode(LED_BUILTIN, OUTPUT); //met la led du Wemos en sortie
87 digitalWrite(LED_BUILTIN, LOW); //met la led du Wemos sur le niveau bas ce qui l'allume.
88 }
89
90 void loop(){
91 val = -1;
92 monServeur.handleClient();
93 }
94
95 ///////////////////////GESTION DES INSTRUCTIONS///////////////////////////
96 void GestionDesClics() {
97 monServeur.on("/avance", HTTP_GET, []() {
98 val = 1;
99 Serial.println("avance");
100 redactionPageWeb();
101 });
102
103 monServeur.on("/recule", HTTP_GET, []() {
104 val = 2;
105 Serial.println("recule");
106 redactionPageWeb();
107 });
108
109 monServeur.on("/gauche", HTTP_GET, []() {
110 val = 4;
111 Serial.println("gauche");
112 redactionPageWeb();
113 });
114
115 monServeur.on("/droite", HTTP_GET, []() {
116 val = 3;
117 Serial.println("droite");
118 redactionPageWeb();
119 });
120
121 monServeur.on("/stop", HTTP_GET, []() {
122 val = 0;
123 Serial.println("stop");
124 redactionPageWeb();
125 });
126
127 monServeur.on("/", HTTP_GET, []() {
128 val = -1;
129 redactionPageWeb();
130 });
131
132 }
133
134 ///////////////////////////LA PAGE WEB DE CONROLE DU PETIT BOT/////////////////////////////////////////
135 void redactionPageWeb(){
136 // Prépare la page web de réponse (le code HTML sera écrit dans la chaine de caractère "pageWeb").
137 String pageWeb = "<!DOCTYPE HTML>\r\n";
138 pageWeb += "<html>\r\n";
139 pageWeb += "<head>\r\n";
140 pageWeb += "<meta charset=\"utf-8\">\r\n";
141 pageWeb += "<title>Petit bot</title>\r\n";
142 pageWeb += "</head>\r\n";
143 pageWeb += "<body>\r\n";
144 pageWeb += "<center>"; //On ouvre la balise qui va centrer les boutons
145 pageWeb += "<h1 style=\"font-size:300%;\"\> Le petit bot ";
146 pageWeb += "<style type=\"text/css\"> body { color: #212121; background-color: #CC0C59 } </style>";
147
148 // On finalise l'écriture de la page Web et on donne les instructions aux servos
149 pageWeb += instruction(val); // pour cela on appelle la fonction "instruction"
150
151 // On termine l'écriture de la page Web
152 pageWeb += "</h1>";
153 pageWeb += "<br>"; //aller à la ligne
154 pageWeb += "<br>"; //aller à la ligne
155 pageWeb += "<a href=\"/stop\"\"><button style=\"font-size:200%; width: 18%; background-color:#0CCC16; border-radius: 12px\"\>Stop </button></a>\r\n"; // créer un bouton "Stop", qui envoie sur l'URL /stop
156 pageWeb += "<a href=\"/avance\"\"><button style=\"font-size:200%; width: 18%; background-color:#0CCC16; border-radius: 12px\"\>Avance </button></a>\r\n"; // créer un bouton "Avance"...
157 pageWeb += "<a href=\"/recule\"\"><button style=\"font-size:200%; width: 18%; background-color:#0CCC16; border-radius: 12px\"\>Recule </button></a>\r\n";
158 pageWeb += "<a href=\"/droite\"\"><button style=\"font-size:200%; width: 18%; background-color:#0CCC16; border-radius: 12px\"\>Droite </button></a>\r\n";
159 pageWeb += "<a href=\"/gauche\"\"><button style=\"font-size:200%; width: 18%; background-color:#0CCC16; border-radius: 12px\"\>Gauche </button></a><br />\r\n";
160 pageWeb += "</center>"; // tout est centré sur la page
161 pageWeb += "</body>\r\n";
162 pageWeb += "</html>\n"; //Fin de la page Web
163
164 // On envoie la page web
165 monServeur.send(200, "text/html", pageWeb);
166 delay(1);
167 }
168
169 ///////////////////INSTRUCTIONS/////////////////////////////////////////////////////////
170 String instruction(int valeur){ //Cette fonction traite les instructions qui sont reçues
171 int gauche; // Variable dont la valeur 180 ou 0 fera tourner le servo gauche dans un sens ou l'autre
172 int droite; // Idem pour le servo droit
173 String completePage; // Déclaration de la chaine de caractère qui sera renvoyée par cette fonction pour compléter la page web
174 switch(valeur){ // En fonction de la variable valeur on va donner un ordre aux servos
175 case 0 : // et un texte à la chaine de caractère "completePage"
176 completePage = " est a l'arrêt ";
177 droite = 90;
178 gauche = 90;
179 break;
180 case 1 :
181 completePage = " avance ";
182 droite = 180;
183 gauche = 0;
184 break;
185 case 2 :
186 completePage = " recule ";
187 droite = 0;
188 gauche = 180;
189 break;
190 case 3 :
191 completePage = " tourne a gauche ";
192 droite = 180;
193 gauche = 180;
194 break;
195 case 4 :
196 completePage = " tourne a droite ";
197 droite = 0;
198 gauche = 0;
199 break;
200 // que faire du cas ou val = -1 ? marquer ici ce qui doit être fait.
201 }
202 servogauche.attach(D1); // Broche D1
203 servodroit.attach(D2); // Broche D2
204 servogauche.write(gauche);
205 servodroit.write(droite);
206 return completePage; // on renvoie la chaine de caractère pour compléter la page web
207 }
208 ////////////////////////CONFIGURATION WIFI///////////////////////////////////////////////
209 void configDuWifi(){ // Fonction de configuratio du Wifi
210 WiFi.mode(WIFI_AP); // le wemos est en mode "Point d'Accès" (il déploie un réseau wifi)
211 WiFi.softAP(nomDuReseau, motDePasse, 2); // on démarre le "Point d'Accès".
212 MDNS.begin(nomDuReseau); // gérer les DNS ce qui rendra votre petit bot accessible
213 MDNS.addService("http", "tcp", 80); // via http://nomDuReseau.local
214 IPAddress monIP = WiFi.softAPIP(); // on récupère l'adresse IP du petit Bot
215 Serial.print("Adresse IP de ce Point d'Accès : ");
216 Serial.println(monIP); // on l'écrit sur le moniteur série
217 GestionDesClics();
218 monServeur.begin(); //Démarrage du monServeur
219 Serial.println("Serveur HTTP démarré");
220 return; // on retourne à l'endroit ou la fonction a été appelée.
221 }