ChocoBot

Le robot suiveur de ligne qui transporte des chocolats d’un bureau à l’autre :

Mes activités de Maker (livres, blog, vidéo, bricolages…) occupent une grosse partie de mon temps libre, mais comme tout le monde j’ai un vrai travail qui me permet de vivre (avec des chefs, des collègues, des bureaux, des horaires etc…). J’ai la chance de travailler dans une très bonne ambiance avec des collègues sympa et une direction bienveillante (et je sais que c’est loin d’être le cas partout).

Une entreprise bienveillante

Bien sûr tout le monde est au courant de mes bricolages, j’ai mis à contributions mes collègues pour collecter des bouteilles de couleur lorsque j’ai reproduit le Recreator de Josh Taylor, je leur ai déjà parlé de ma cafetière commandée par Minitel, et j’apporte de temps en temps un petit robot pédagogique pour animer les bureaux.

Fabrication d'un robot pédagogique

Il y a quelques années, je suis tombé sur la vidéo d’un petit robot suiveur de ligne qui parcourait les couloirs (d’une école ou d’une entreprise) pour livrer un chocolat à un collègue. J’aurais bien mis un lien pour citer cette vidéo mais je ne l’ai pas retrouvé, alors si vous la connaissez n’hésitez pas à le signaler dans les commentaires.

Robot distributeur de chocolats

Pour plaisanter, j’ai montré la vidéo à mes chefs en leur disant qu’on devrait faire ça dans les bureaux et ils ont trouvé l’idée aussi amusante que moi. Alors, j’ai décidé de l’ajouter à ma longue liste de projets en cours…

Cet été j’ai trouvé un peu de temps, alors j’ai relancé le projet. Après avoir vérifié que les chefs étaient toujours d’accord, je suis resté sur mon lieu de travail dans l’heure de midi et avec quelques collègues (aussi enthousiastes que moi) nous avons tracé la piste du robot en posant du Scotch noir.

Installation de la piste du robot sur le lino des bureaux

J’ai récupéré les LEGO du dernier Team building pour décorer un peu le circuit.

Décoration de la piste du robot

Et enfin, j’ai installé le robot sur la piste.

Installation du robot Zumo

Dans cet exemple, j’utilise le robot Zumo de Pololu mais n’importe quel robot suiveur de ligne fera aussi bien l’affaire.

Le robot Zumo avec sa coupelle et ses KitKat

La coupelle qui contient les chocolats est maintenue par des aimants néodyme à support vissé à l’Arduino. Si ça vous intéresse, j’ai partagé tous les fichiers STL sur Printables.

J’ai aussi prévu des versions saisonnières pour Halloween

Le robot Chocobot en version Halloween

Et pour Noël, que vous pouvez télécharger ici…

Le robot Chocobot en version Noël

Vous trouverez plus de détails sur l’utilisation du robot Zumo dans mon livre sur l’Arduino (à partir de la 2ème édition). Mais pour la programmation du robot, j’ai utilisé une version légèrement modifiée du code fourni en exemple par Pololu (les moteurs se mettent en pause si j’appuie sur le bouton). Je vous donne le programme complet avec les commentaires en français (mais bien sûr, n’hésitez pas à l’adapter à vos besoins) :

// Zumo_Suivi_de_ligne_PID

/* Ce programme est basé sur l'exemple fourni par Pololu :
 * "Demo line-following code for the Pololu Zumo Robot"
 * Il utilise un algorithme PID (Proportional-Integral-Derivative)
 * pour suivre une ligne noire sur un fond blanc à l'aide
 * des capteurs de réflectance infrarouge intégrés au robot.
 */

#include <Wire.h>
#include <ZumoShield.h>

ZumoBuzzer buzzer;
ZumoReflectanceSensorArray reflectanceSensors;
ZumoMotors motors;
Pushbutton button(ZUMO_BUTTON);
int lastError = 0;

// C'est la vitesse maximale à laquelle les moteurs seront autorisés
// à tourner.(400 permet aux moteurs d'atteindre leur vitesse maximale
// réduisez pour imposer une limite de vitesse)
const int MAX_SPEED = 400;


void setup(){
  // Jouer une petite mélodie pour indiquer que le robot est prêt.
  buzzer.play(">g32>>c32");

  // Initialiser le module de capteurs de réflectance
  reflectanceSensors.init();

  // Initialiser le module de capteurs de réflectance
  button.waitForButton();

  // Allumer la LED pour indiquer que nous sommes en mode de calibration.
  pinMode(13, OUTPUT);
  digitalWrite(13, HIGH);

  // Attendre 1 seconde, puis commencer la calibration automatique des capteurs
  // en faisant tourner le robot sur lui-même pour balayer les capteurs sur la ligne.
  delay(1000);
  int i;
  for(i = 0; i < 80; i++)
  {
    if ((i > 10 && i <= 30) || (i > 50 && i <= 70))
      motors.setSpeeds(-200, 200);
    else
      motors.setSpeeds(200, -200);
    reflectanceSensors.calibrate();

    // Puisque notre compteur va jusqu'à 80, le délai total sera de 80*20 = 1600 ms.
    delay(20);
  }
  motors.setSpeeds(0,0);

  // Éteindre la LED pour indiquer que la calibration est terminée.
  digitalWrite(13, LOW);
  buzzer.play(">g32>>c32");

  // Attendre que le bouton utilisateur soit pressé et relâché.
  button.waitForButton();

  // Jouer de la musique et attendre qu'elle se termine avant de commencer à conduire.
  buzzer.play("L16 cdegreg4");
  while(buzzer.isPlaying());
}

void loop(){
  unsigned int sensors[6];

  // Obtenir la position de la ligne. Notez que nous *devons* fournir l'argument "sensors"
  // à readLine() ici, même si nous ne nous intéressons pas aux lectures individuelles des capteurs.
  int position = reflectanceSensors.readLine(sensors);

  // Notre "erreur" est à quelle distance nous sommes du centre de la ligne, qui
  // correspond à la position 2500.
  int error = position - 2500;

  // Obtenir la différence de vitesse des moteurs en utilisant les termes PID proportionnel et dérivé
  // (le terme intégral n'est généralement pas très utile pour le suivi de ligne).
  // Ici, nous utilisons une constante proportionnelle de 1/4 et une constante dérivée de 6,
  // qui devraient fonctionner raisonnablement bien pour de nombreux choix de moteurs Zumo.
  // Vous voudrez probablement ajuster ces constantes en utilisant l'essai et l'erreur
  // pour votre Zumo et votre parcours particuliers.
  int speedDifference = error / 4 + 6 * (error - lastError);

  lastError = error;

  // Obtenir les vitesses individuelles des moteurs. Le signe de differenceVitesse
  // détermine si le robot tourne à gauche ou à droite.
  int m1Speed = MAX_SPEED + speedDifference;
  int m2Speed = MAX_SPEED - speedDifference;

  // Ici, nous limitons les vitesses des moteurs entre 0 et VITESSE_MAX.
  // En règle générale, un moteur tournera toujours à VITESSE_MAX
  // et l'autre sera à VITESSE_MAX-|differenceVitesse| s'il est positif,
  // sinon il sera immobile. Pour certaines applications, vous pouvez
  // permettre à la vitesse du moteur d'aller en négatif pour qu'il puisse tourner en arrière.
  if (m1Speed < 0)m1Speed = 0;
  if (m2Speed < 0)m2Speed = 0;
  if (m1Speed > MAX_SPEED)m1Speed = MAX_SPEED;
  if (m2Speed > MAX_SPEED)m2Speed = MAX_SPEED;

  motors.setSpeeds(m1Speed, m2Speed);
  // Si l'utilisateur presse et relache le bouton
  if (button.getSingleDebouncedRelease()){
    // Allumer la LED
    digitalWrite(13, HIGH);
    // Arret des moteurs
    motors.setSpeeds(0, 0);
    // Attendre que le bouton utilisateur soit pressé et relâché pour redémarrer le robot.
    button.waitForButton();
    // Éteindre la LED
    digitalWrite(13, LOW);
  }  
}

Alors, amusez vous bien avec votre ChocoBot et n’hésitez pas à me raconter ses exploits dans les commentaires ou sur les réseaux sociaux…

Le robot Zumo chargé de friandises

Sources et liens utiles


Laisser un commentaire