Club robotique de Sophia-Antipolis

Accueil > Projets, études > Nos robots > Robots du club > Robots spéciaux > Nono, le robot d’animation pédagogique (2012) > Programmes de tests de Nono

Programmes de tests de Nono

lundi 25 juin 2012, par Julien H.

Notre robot Nono dispose de plusieurs systèmes, il est donc important de pouvoir tous les tester régulièrement :
- il peut tourner la tête
- il peut éclairer différentes parties de sa tête
- il peut se dandiner sur son socle
- il peut mesurer une distance devant lui (télémètre infra-rouge)
- il peut détecter une présence à gauche ou à droite (capteurs infra-rouge)
- il peut cracher de l’eau (mécanique absente, non câblé)
- il peut détecter 3 pressions sur ses doigts (non câblé)

Liste des ports utilisés

Patte Rôle
D0 liaison série
D1 liaison série
D2 contact du cou à gauche (interruption 0)
D3 contact du cou à droite (interruption 1)
D4 direction du moteur de socle
D5 vitesse du moteur de socle
D6 vitesse du moteur du cou
D7 direction du moteur du cou
D8
D9 bouche
D10 bouche
D11 bouche
D12 bouche
D13 bouche
14 capteur TOR oreille
15 capteur TOR oreille
16 lumière
17 lumière
18 lumière
19 lumière

Note : les numéros 14 à 19 correspondent aux pattes A0 à A5 quand on les utilise en numérique, pour allumer des leds ou pour des capteurs tout ou rien (TOR).

Tests sur Arduino

Retrouvez les codes sources sur GitHub. On peut ainsi charger la carte Romeo qui équipe la tête de Nono avec l’un des codes pour Arduino qui effectue des actions programmées. Pour le contrôle depuis la carte Raspberry Pi, on peut utiliser Firmata ou un autre programme générique de pilotage par commandes séries.

Les contacts par micro-switch

Le cou est équipé de deux contacts. Voici un premier code pour tester facilement un des contacts, connecté sur l’entrée numérique n°2.

Le contact est fermé au repos (NC sur le micro-switch) et se coupe lorsqu’il y a contact. L’entrée doit donc être câblée avec une résistance de pull-down (ou push-down) soit un signal bas (la masse). On peut utiliser la résistance interne mais personnellement ça n’a jamais marché : j’utilise une résistance de 10k.

  1. void setup()
  2. {
  3.   Serial.begin(9600);
  4.   Serial.println("Nono test contacts");
  5.  
  6.   pinMode(2,INPUT);
  7.   digitalWrite(2,LOW);
  8.    
  9.   Serial.println("Pret...");
  10. }
  11.  
  12. void loop()
  13. {
  14.   Serial.println(digitalRead(2));
  15.   delay(200);
  16.  
  17. }

Télécharger

Ce qui affiche des 1 en répétition, sauf lorsque le contact est appuyé sur le microrupteur.

Voici le même test avec une interruption :

  1. void setup()
  2. {
  3.   Serial.begin(9600);
  4.   Serial.println("Nono test contacts");
  5.  
  6.   pinMode(2,INPUT);
  7.   digitalWrite(2,LOW);
  8.  
  9.   attachInterrupt(0,contactGauche,CHANGE);
  10.    
  11.   Serial.println("Pret...");
  12. }
  13.  
  14. void contactGauche()
  15. {
  16.   if (digitalRead(2) == HIGH) {
  17.      Serial.println("ouvert");
  18.   } else {
  19.      Serial.println("ferme");
  20.   }  
  21.   delay(200);
  22. }
  23.  
  24.  
  25. void loop()
  26. {
  27.  
  28. }

Télécharger

Rotation de la tête

Le moteur du cou est le moteur 2. Il utilise deux pattes logiques : 7 pour la direction et 6 pour la vitesse (sachant qu’on l’utilisera en tout ou rien).

Voici le code qui met en mouvement la tête dans le sens horaire (de gauche à droite), change le sens quand le contact gauche (tête visant à droite) est déclenché, et change le sens quand le contact droit (tête visant à gauche) est déclenché.

  1. void setup()
  2. {
  3.   Serial.begin(9600);
  4.   Serial.println("Nono test contacts");
  5.  
  6.   // les contacts
  7.   pinMode(2,INPUT);
  8.   digitalWrite(2,LOW);
  9.   pinMode(3,INPUT);
  10.   digitalWrite(3,LOW);
  11.  
  12.   attachInterrupt(0,contactGauche,CHANGE);
  13.   attachInterrupt(1,contactDroite,CHANGE);
  14.  
  15.   // le moteur du cou
  16.  
  17.   pinMode(7,OUTPUT); // la direction
  18.   pinMode(6,OUTPUT); // la vitesse
  19.  
  20.   digitalWrite(6,HIGH);
  21.   digitalWrite(7,HIGH); // on débute dans le sens horaire
  22.  
  23.   Serial.println("Pret...");
  24. }
  25.  
  26. void contactDroite()
  27. {
  28.   if (digitalRead(3) == HIGH) {
  29.     Serial.println("ouvert");
  30.   }
  31.   else {
  32.     Serial.println("ferme");
  33.     // change la direction --> horaire
  34.     digitalWrite(7,HIGH);
  35.   }  
  36.   delay(200);
  37. }
  38.  
  39. void contactGauche()
  40. {
  41.   if (digitalRead(2) == HIGH) {
  42.     Serial.println("ouvert");
  43.   }
  44.   else {
  45.     Serial.println("ferme");
  46.     // change la direction --> antihoraire
  47.     digitalWrite(7,LOW);
  48.   }  
  49.   delay(200);
  50. }
  51.  
  52. void loop()
  53. {
  54.  
  55. }

Télécharger

Faire bouger le socle

Le moteur connecté sur le premier contrôleur de moteur à courant continu de la carte Arduino Romeo est situé dans le socle de Nono, faisant tourner une tige qui peut varier de hauteur en fonction de deux obstacles situés de part et d’autre. Cette tige est tenue par une vis (attention, ne la vissez pas complètement, il faut laisser du jeu !!) pour ne pas tomber. Lorsqu’elle passe sur les obstacles, le socle de Nono bouge et les ressorts accentuent ce tressautement. Une astuce de notre ami Jean-Pierre, le papa de Nono.

Ce code très simple fait tourner le moteur dans un sens puis dans l’autre.

  1. // Test du socle bougeant de Nono
  2.  
  3. void setup()
  4. {
  5.    // rien de spécial ici, tout est géré dans la boucle
  6. }
  7.  
  8. void loop()
  9. {
  10.     // changer le sens de rotation du moteur
  11.     digitalWrite(4,LOW);
  12.  
  13.     // mettre en marche à vitesse maximum (il y a une démultiplication)
  14.     digitalWrite(5,HIGH);
  15.     delay(1000);
  16.  
  17.     // arrêter
  18.     digitalWrite(5,LOW);
  19.     delay(1000);
  20.    
  21.     // changer le sens
  22.     digitalWrite(4,HIGH);
  23.  
  24.     // mettre en marche
  25.     digitalWrite(5,HIGH);
  26.     delay(1000);
  27.  
  28.     // arrêter
  29.     digitalWrite(5,LOW);
  30.     delay(1000);
  31. }

Télécharger

Tourner la tête vers le public

Cette fois-ci, on utilise les capteurs.

  1. volatile boolean troploin = false;
  2.  
  3. boolean inactif = true;
  4. long last_actif;
  5.  
  6. void setup()
  7. {
  8.   Serial.begin(115200);
  9.   Serial.println("Robot Nono pret !");
  10.  
  11.   // led 13 à 9, la bouche
  12.   pinMode(13,OUTPUT);
  13.   pinMode(12,OUTPUT);
  14.   pinMode(11,OUTPUT);
  15.   pinMode(10,OUTPUT);
  16.   pinMode(9,OUTPUT);
  17.  
  18.   // les contacts
  19.   pinMode(2,INPUT);
  20.   pinMode(3,INPUT);
  21.  
  22.   attachInterrupt(1,contactGauche,CHANGE);
  23.   attachInterrupt(0,contactDroite,CHANGE);
  24.  
  25.   // le moteur du cou
  26.  
  27.   pinMode(7,OUTPUT); // la direction
  28.   pinMode(6,OUTPUT); // la vitesse
  29.  
  30.   digitalWrite(6,HIGH);
  31.   digitalWrite(7,HIGH); // on débute dans le sens horaire
  32.  
  33.   // les capteurs des oreilles
  34.   pinMode(14,INPUT);
  35.   pinMode(15,INPUT);
  36.  
  37.  
  38.  
  39.   // le moteur du bas
  40.  
  41.   pinMode(4,OUTPUT); // la direction
  42.   pinMode(5,OUTPUT); // la vitesse
  43.  
  44.  
  45. }
  46.  
  47. void contactDroite()
  48. {
  49.   if (digitalRead(2) == HIGH) {
  50.     digitalWrite(13,LOW);
  51.   }
  52.   else {
  53.     digitalWrite(13,HIGH);
  54.     troploin = true;
  55.   }  
  56. }
  57.  
  58. void contactGauche()
  59. {
  60.   if (digitalRead(3) == HIGH) {
  61.     digitalWrite(13,LOW);
  62.   }
  63.   else {
  64.     digitalWrite(13,HIGH);
  65.     troploin = true;
  66.   }
  67. }
  68.  
  69. void loop()
  70. {
  71.   // si on vient d'etre en blocage
  72.   if (troploin) {
  73.     if (digitalRead(3) == HIGH) {
  74.         Serial.println("Tourner à gauche");
  75.       // change la direction --> antihoraire
  76.       digitalWrite(7,LOW);
  77.     }
  78.     if (digitalRead(2) == HIGH) {
  79.         Serial.println("Tourner à droite");
  80.       // change la direction --> horaire
  81.       digitalWrite(7,HIGH);
  82.     }
  83.     digitalWrite(6,HIGH);
  84.     delay(6000);
  85.     digitalWrite(6,LOW);
  86.     troploin = false;
  87.   }
  88.  
  89.  
  90.   // si les deux capteurs captent : on s'arrete
  91.   if (digitalRead(14) == digitalRead(15))
  92.   {
  93.     digitalWrite(6,LOW);
  94.     digitalWrite(9,LOW);
  95.     digitalWrite(17,LOW);
  96.     digitalWrite(16,LOW);
  97.   }
  98.   else {
  99.     inactif = false;
  100.     // il faut tourner
  101.     digitalWrite(6,HIGH);
  102.     digitalWrite(9,HIGH);
  103.     // on détermine le sens
  104.     if (digitalRead(15) == HIGH) {
  105.       digitalWrite(16,HIGH);
  106.       digitalWrite(7,HIGH);
  107.     }
  108.     else {
  109.       digitalWrite(17,HIGH);
  110.       digitalWrite(7,LOW);
  111.     }
  112.  
  113.   }
  114.  
  115.   // détecte une inactivité
  116.   if (! inactif) {
  117.     last_actif = millis();
  118.   }
  119.   else {
  120.  
  121.     // que fait-on quand on est inactif ? on allume les leds
  122.  
  123.     if (millis()%2000<1000)
  124.     {
  125.       lumiere_off();
  126.       bouche_on();
  127.       digitalWrite(6,HIGH);
  128.       digitalWrite(7,HIGH); // on tourne dans le sens horaire
  129.     }
  130.     else {
  131.       bouche_off();
  132.       lumiere_on();
  133.       digitalWrite(6,HIGH);
  134.       digitalWrite(7,LOW); // on tourne dans le sens antihoraire
  135.     }
  136.  
  137.   }
  138.  
  139.   if (millis()-last_actif > 5000) {
  140.     inactif = true;    
  141.   }
  142.  
  143. }
  144.  
  145. void lumiere_on()
  146. {
  147.  
  148.   digitalWrite(16,HIGH);
  149.   digitalWrite(17,HIGH);
  150.   digitalWrite(18,HIGH);
  151.   digitalWrite(19,HIGH);
  152. }
  153.  
  154.  
  155. void lumiere_off()
  156. {
  157.   digitalWrite(16,LOW);
  158.   digitalWrite(17,LOW);
  159.   digitalWrite(18,LOW);
  160.   digitalWrite(19,LOW);
  161.  
  162. }
  163.  
  164. void bouche_off()
  165. {
  166.   digitalWrite(9,LOW);
  167.   digitalWrite(10,LOW);
  168.   digitalWrite(11,LOW);
  169.   digitalWrite(12,LOW);
  170.   digitalWrite(13,LOW);
  171. }
  172.  
  173. void bouche_on()
  174. {
  175.   digitalWrite(9,HIGH);
  176.   digitalWrite(10,HIGH);
  177.   digitalWrite(11,HIGH);
  178.   digitalWrite(12,HIGH);
  179.   digitalWrite(13,HIGH);  
  180. }

Télécharger

Et voilà, à vous de continuer ces petits tests !!

Un message, un commentaire ?

modération a priori

Attention, votre message n’apparaîtra qu’après avoir été relu et approuvé.

Qui êtes-vous ?

Pour afficher votre trombine avec votre message, enregistrez-la d’abord sur gravatar.com (gratuit et indolore) et n’oubliez pas d’indiquer votre adresse e-mail ici.

Ajoutez votre commentaire ici

Ce champ accepte les raccourcis SPIP {{gras}} {italique} -*liste [texte->url] <quote> <code> et le code HTML <q> <del> <ins>. Pour créer des paragraphes, laissez simplement des lignes vides.