// lineFollowerBot.ino // Programme basique permettant à un robot de suivre une ligne dessinée au sol. // // Un projet du hackerspace Ventres Mous. // ============================================================================= // // IDENTIFICATION DES BROCHES DE L’ARDUINO UTILISÉES PAR LE PROJET // // ============================================================================= // Chaque broche de l’Arduino est identifiée par un numéro. Afin de faciliter // la lecture du code, on leur donne des noms parlants. // Broches sur lesquelles les moteurs sont connectés. // Ce sont des broches de sortie numériques. #define MOTEUR_GAUCHE 2 #define MOTEUR_DROITE 8 // Broches sur lesquelles les capteurs sont connectés. // Ce sont des broches de lecture analogique. #define CAPTEUR_GAUCHE A0 #define CAPTEUR_DROITE A1 // Broches sur lesquelles les leds de suivi d’étalonnage sont connectées. // Ce sont des broches de sortie numériques. #define ETALONNAGE_LED_GAUCHE 4 #define ETALONNAGE_LED_DROITE 5 // Broche sur laquelle le bouton d’étalonnage est connecté. // C’est une broche de lecture numérique. #define ETALONNAGE_BOUTON 12 // Les 2 états possible du bouton d’étalonnage : pressé et relevé. #define BOUTON_PRESSE 1 #define BOUTON_RELEVE 0 // Variables utilisées pour définir les seuils de détection des capteurs. Les // seuils sont réglés à 200 par défaut. int seuil_gauche = 200; int seuil_droite = 200; // ============================================================================= // // INITIALISATION DES BROCHES DE L’ARDUINO // // ============================================================================= // Cette fonction est exécutée une seule fois lors de l’allumage de l’Arduino. // Son rôle consiste à configurer l’Arduino pour un usage précis, dans le cas // présent pour un robot suiveur de ligne. void setup() { // Configure les broches des moteurs en sortie numérique. Ces broches seront // soit à 0 volt, soit à 5 volts. Les broches de l’Arduino ne sont pas faites // pour alimenter un moteur, elles serviront à piloter des transistors qui, // eux, alimenteront les moteurs. pinMode(MOTEUR_GAUCHE, OUTPUT); pinMode(MOTEUR_DROITE, OUTPUT); // Configure les broches des leds de suivi d’étalonnage en sortie numérique. // Les leds consomment très peu d’énergie, elles seront directement pilotées // par les broches de l’Arduino. pinMode(ETALONNAGE_LED_GAUCHE, OUTPUT); pinMode(ETALONNAGE_LED_DROITE, OUTPUT); // Configure la broche du bouton d’étalonnage en entrée numérique. pinMode(ETALONNAGE_BOUTON, INPUT); // Les broches analogiques des capteurs sont obligatoirement en mode lecture // analogique. Il n’y a donc pas de réglage à faire sur ces broches. Serial.begin(9600); } // ============================================================================= // // GESTION DU BOUTON D’ÉTALONNAGE // // ============================================================================= // Attend jusqu’à ce que le bouton d’étalonnage soit enfoncé ou relaché. // Le paramètre etat peut prendre 2 valeurs : BOUTON_PRESSE et BOUTON_RELEVE. // Si la fonction est appelée avec BOUTON_PRESSE, elle ne laissera le programme // continuer que si le bouton est enfoncé. Si elle est appelée avec // BOUTON_RELEVE, elle ne laissera le programme continuer que si le bouton est // relevé. void continuer_si(int etat) { while(digitalRead(ETALONNAGE_BOUTON) != etat) delay(1); } // ============================================================================= // // GESTION DES LEDS D’ÉTALONNAGE // // ============================================================================= // Fait clignoter les leds d’étalonnage pour indiquer à l’utilisateur que // l’étalonnage est terminé. void clignoter() { // Fait clignoter 5 fois les leds. Clignoter consiste à allumer puis éteindre. for(int b = 0; b < 5; b++) { // Allume les leds d’étalonnage (les broches sont réglées à 5 volts). digitalWrite(ETALONNAGE_LED_GAUCHE, HIGH); digitalWrite(ETALONNAGE_LED_DROITE, HIGH); // Attend 0,2 secondes (200 millisecondes). delay(200); // Éteint les leds d’étalonnage (les broches sont réglées à 0 volt). digitalWrite(ETALONNAGE_LED_GAUCHE, LOW); digitalWrite(ETALONNAGE_LED_DROITE, LOW); // Attend 0,2 secondes (200 millisecondes). delay(200); } } // Éteint les deux leds d’étalonnage. void eteindre() { // Éteint les 2 leds de débogage en mettant leurs broches à 0 volt. digitalWrite(ETALONNAGE_LED_GAUCHE, LOW); digitalWrite(ETALONNAGE_LED_DROITE, LOW); } // ============================================================================= // // ÉTALONNAGE DES CAPTEURS DU ROBOT // // ============================================================================= // Étalonne les capteurs pour établir la différence entre la ligne et le sol. void etalonnage() { // Variables qui vont recevoir les valeurs minimales et maximales des capteurs // gauche et droite (L’unité importe peu). Elles permettent de garder en // mémoire l’état du capteur afin de pouvoir effectuer des calculs plus tard. int min_gauche; int min_droite; int max_gauche; int max_droite; // Arrête les 2 moteurs, le robot ne bouge plus. moteur_arret(); // L’étalonnage est déclenché quand l’utilisateur appuie sur le bouton // d’étalonnage. On attend que le bouton soit relaché pour étalonner. continuer_si(BOUTON_RELEVE); Serial.println("BOUTON_RELEVE"); // Lit l’état des deux capteurs. min_gauche = analogRead(CAPTEUR_GAUCHE); min_droite = analogRead(CAPTEUR_DROITE); // Éteint les deux leds d’étalonnage. eteindre(); // Attend que l’utilisateur clique sur le bouton (clic = appui + relache). continuer_si(BOUTON_PRESSE); continuer_si(BOUTON_RELEVE); Serial.println("BOUTON_PRESSE_RELEVE"); // Lit l’état des deux capteurs. max_gauche = analogRead(CAPTEUR_GAUCHE); max_droite = analogRead(CAPTEUR_DROITE); // Le seuil correspond à la valeur située entre les valeurs minimales et // maximales que le capteur retourne. seuil_gauche = (min_gauche + max_gauche) / 2; seuil_droite = (min_droite + max_droite) / 2; Serial.println("FIN_ETALONNAGE"); clignoter(); } // ============================================================================= // // GESTION DES DEUX MOTEURS // // ============================================================================= // Arrête les deux moteurs. Le robot ne bouge plus. void moteur_arret() { Serial.println("ARRET_MOTEUR"); digitalWrite(MOTEUR_GAUCHE, LOW); digitalWrite(MOTEUR_DROITE, LOW); } // Fait tourner le robot à droite. void moteur_droite() { // Pour tourner à droite, on bloque le côté droit et on fait avancer le côté // gauche. Serial.println("MOTEUR_DROITE"); digitalWrite(MOTEUR_GAUCHE,HIGH); digitalWrite(MOTEUR_DROITE,LOW); } // Fait tourner le robot à gauche. void moteur_gauche() { // Pour tourner à gauche, on bloque le côté gauche et on fait avancer le côté // droit. Serial.println("MOTEUR_GAUCHE"); digitalWrite(MOTEUR_GAUCHE, LOW); digitalWrite(MOTEUR_DROITE, HIGH); } // Fait tourner les deux moteurs. Le robot avance. void moteur_avance() { Serial.println("MOTEUR_AVANCE"); digitalWrite(MOTEUR_GAUCHE, HIGH); digitalWrite(MOTEUR_DROITE, HIGH); } // ============================================================================= // // BOUCLE PRINCIPALE // // ============================================================================= // La fonction loop est appelée en boucle par l’Arduino. Un Arduino est prévu // pour ce genre de tâche : exclusive et répétitive. // Le programme considère que le robot démarre la ligne entre les deux capteurs. void loop() { // Variables qui vont recevoir les valeurs des capteurs. int valeur_gauche; int valeur_droite; // Si le bouton d’étalonnage est pressé, on lance l’étalonnage. if(digitalRead(ETALONNAGE_BOUTON) == 1) etalonnage(); // Lit l’état des deux capteurs. valeur_gauche = analogRead(CAPTEUR_GAUCHE); valeur_droite = analogRead(CAPTEUR_DROITE); // Fait avancer le robot si les deux capteurs identifient le sol. if((valeur_gauche < seuil_gauche) && (valeur_droite < seuil_droite)) { moteur_avance(); return; } // Tourne à droite si le capteur de gauche identifie le sol et le capteur de // droite identifie la ligne. Cela veut dire que le robot dévie à gauche par // rapport à la ligne qu’il doit suivre. On corrige en tournant à droite // jusqu’à ce que la ligne soit à nouveau entre les deux capteurs. if((valeur_gauche < seuil_gauche) && (valeur_droite > seuil_droite)) { moteur_droite(); // Attend que le capteur de droite identifie le sol. while(analogRead(CAPTEUR_DROITE) > seuil_droite) delay(1); return; } // Tourne à gauche si le capteur de gauche identifie la ligne et le capteur de // droite identifie le sol. Cela veut dire que le robot dévie à droite par // rapport à la ligne qu’il doit suivre. On corrige en tournant à gauche // jusqu’à ce que la ligne soit à nouveau entre les deux capteurs. if((valeur_gauche > seuil_gauche) && (valeur_droite < seuil_droite)) { moteur_gauche(); // Attend que le capteur de gauche identifie le sol. while(analogRead(CAPTEUR_GAUCHE) > seuil_gauche) delay(1); return; } // Arrête le robot si les deux capteurs identifient chacun le sol. Cela veut // dire que le robot a perdu la ligne, il est plus prudent de l’arrêter. if((valeur_gauche > seuil_gauche) && (valeur_droite > seuil_droite)) { moteur_arret(); return; } }