Retour à la page d'accueilHackerspace Ventres mous

main(){

Robot suiveur de ligne (doc)

Voici (enfin) les schémas et explications pour le robot suiveur de ligne, qu'on a (tenté) de faire construire aux participants de l'atelier d'initiation à l'électronique il y a déjà plusieurs semaines.

Afin que vous compreniez certains choix, voici un rappel des contraintes: Le but n'était pas de faire le méga robot suiveur de ligne, mais de concevoir un kit qui pourrait être monté en une soirée par des novices. D'où certains choix allant vers la simplicité au détriment des capacités.

Le voici une fois monté:

P_20190220_230656.jpg

Principe de fonctionnement

Deux photoresistances frôlent le sol. Pour chacune d'entre elles: Lorsqu'elle est au dessus de la ligne noire, elle reçoit moins de lumière. Sa valeur de résistance est modifiée.

principe.svg

En fonction des situations l'arduino déclenchera les moteurs de manière à avancer ou tourner.

Le diaporama d'introduction lors de la soirée peut être consulté ici.

Châssis

Les fichiers 3d Pour imprimer le châssis sont disponible par là:

https://git.ventresmous.fr/VentresMous/lineFollowerBot/src/master/chassis

chassis.png

Électronique

Voici le schéma électronique recto verso (pour assemblage sur une plaque de prototypage à pastilles):

robot-soudure-composants-v2.svg

Ce PDF contient des instructions pas à pas.

Code arduino

Le code arduino très simplifié et très commenté:

// 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){
      if(digitalRead(ETALONNAGE_BOUTON) == 1){ 
        etalonnage(); 
        break;
      }
      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){
      if(digitalRead(ETALONNAGE_BOUTON) == 1){ 
        etalonnage(); 
        break;
      }
      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;
  }
}