Compter en binaire et algo à gogo avec le robot Thymio

Apprendre à compter
lundi 10 novembre 2014
par  Nathalie CARRIÉ

Le robot Thymio permet de découvrir la programmation de manière très progressive, grâce à une interface de programmation visuelle, couplée à une interface textuelle.

Le robot Thymio II est produit et vendu par l’association Mobsya, et, pour environ une centaine d’euros, on peut le commander ici.
Ce petit robot permet une réelle approche scientifique de la robotique pour nos élèves, possédant de nombreux capteurs (capteurs infrarouge, capteur de température, micro, capteurs mesurant les 3 composantes de l’accélération, 5 boutons on-off) et de nombreux actuateurs (nombreuses leds dont une led RGB qui permet donc d’appréhender le mélange des couleurs, un moteur sur chaque roue, un haut-parleur). L’apprentissage de sa programmation se fait de manière très progressive, grâce à une interface de programmation visuelle, qui crée les lignes de codes correspondantes, ce qui permet d’affiner ensuite le code.

Son site de présentation - et de référence d’ailleurs -, permet assez rapidement de réaliser le champ d’applications potentielles qu’il vous sera possible de réaliser grâce à ce petit robot.

Au lycée Antoine Roussin, nous en avons commandé 5 afin de pouvoir les utiliser dès la rentrée 2013 en spécialité ISN en Terminale S.
Un projet Bac a d’ailleurs été réalisé sur Thymio. Les élèves ont réalisé un suivi de ligne à l’aide du robot. Une vidéo est visible ici.


Vous pouvez voir ce schéma pour avoir une liste complète de ses capteurs et actuateurs.
Thymio permet une approche multi-disciplinaire de la robotique, et c’est ce qui nous a réellement séduits, mon collègue de physique et moi-même.

Et, cerise sur le gâteau, Thymio II est un projet open source et open hardware !

Nous venons d’en commander 6 de plus, afin de les utiliser dès la seconde...

Balbutiements

Au démarrage, le Thymio possède un certain nombre de comportements usines.

Au début de l’utilisation du Thymio avec les élèves, nous leur avons demandé d’illustrer au maximum de commentaires les programmes qu’ils lisaient, et d’écrire dans la mesure du possible des algorithmes décrivant les comportements du robot.
PNG

Voici un exemple de programme du Thymio parlant anglais illustré de commentaires :
PNG
La deuxième page de commentaires se trouve ici.

Je voudrais maintenant simplement illustrer le tutoriel de prise en mains du robot.

Ballets en couleur


Grâce à la led RGB, on pourra commencer à mélanger les couleurs.

On pourra aussi faire des programmes de base qui consistent à tester divers comportements du Thymio.
Il peut vous suivre comme un petit chien, ou au contraire Thymio vous fuira comme la peste.
Il peut éviter de tomber de la table, etc...

Premier ballet...
... ou Première implémentation du Si... Alors... , avec activation des moteurs.

Le code source sur l’image ci-dessus est automatiquement généré, dès que l’on active des couples d’événements-action dans l’interface de programmation visuelle (VPL). Il peut bien évidemment être nettoyé.

En activant le mode avancé de programmation visuelle du Thymio, on a accès à un minuteur, et à des boutons d’état (qui activent en fait des leds). Cela va nous permettre d’améliorer le programme précédent et d’amorcer un ballet du Thymio qui devient petit à petit un petit robot danseur...

Première boucle infinie
Faisons tout d’abord réaliser une boucle infinie au robot, rendue possible grâce au timer (premier exercice sur les boucles du tutoriel) :

  1. var state[4] = [0,0,0,0]
  2. var new_state[4] = [0,0,0,0]
  3.  
  4. timer.period[0] = 0
  5. call sound.system(-1)
  6. call leds.top(0,0,0)
  7. call leds.bottom.left(0,0,0)
  8. call leds.bottom.right(0,0,0)
  9. call leds.circle(0,0,0,0,0,0,0,0)
  10.  
  11. sub display_state
  12.         call leds.circle(0,state[1]*32,0,state[3]*32,0,state[2]*32,0,state[0]*32)
  13.  
  14. onevent buttons
  15.         if state[0] == 0 then
  16.                 motor.left.target = -500
  17.                 motor.right.target = 0
  18.                 timer.period[0] = 2000
  19.         end
  20.         if state[0] == 1 then
  21.                 motor.left.target = 0
  22.                 motor.right.target = -500
  23.                 timer.period[0] = 3000
  24.         end
  25.  
  26.         call math.copy(state, new_state)
  27.         callsub display_state
  28.  
  29. onevent timer0
  30.         timer.period[0] = 0
  31.         if state[0] == 0 then
  32.                 new_state[0] = 1
  33.         end
  34.         if state[0] == 1 then
  35.                 new_state[0] = 0
  36.         end
  37.  
  38.         call math.copy(state, new_state)
  39.         callsub display_state

Deuxième ballet

Et voici un début de programme pour un joli ballet :

  1. var state[4] = [0,0,0,0]
  2. var new_state[4] = [0,0,0,0]
  3.  
  4. timer.period[0] = 0
  5. call sound.system(-1)
  6. call leds.top(0,0,0)
  7. call leds.bottom.left(0,0,0)
  8. call leds.bottom.right(0,0,0)
  9. call leds.circle(0,0,0,0,0,0,0,0)
  10.  
  11. sub display_state
  12.         call leds.circle(0,state[1]*32,0,state[3]*32,0,state[2]*32,0,state[0]*32)
  13.  
  14. onevent buttons
  15.         if button.center == 1 then
  16.                 call leds.top(0,0,0)
  17.                 call leds.bottom.left(0,0,0)
  18.                 call leds.bottom.right(0,0,0)
  19.                 motor.left.target = 0
  20.                 motor.right.target = 0
  21.         end
  22.         if button.forward == 1 and state[0] == 0 and state[1] == 0 and state[2] == 0 and state[3] == 0 then
  23.                 timer.period[0] = 1000
  24.                 motor.left.target = 500
  25.                 motor.right.target = 500
  26.                 call leds.top(0,32,0)
  27.         end
  28.         if state[0] == 1 and state[1] == 1 and state[2] == 1 and state[3] == 1 then
  29.                 timer.period[0] = 1000
  30.                 call leds.top(0,0,0)
  31.                 call leds.bottom.left(0,0,0)
  32.                 call leds.bottom.right(0,0,0)
  33.                 motor.left.target = 0
  34.                 motor.right.target = 0
  35.         end
  36.         if button.backward == 1 and state[0] == 0 and state[1] == 0 and state[2] == 0 and state[3] == 0 then
  37.                 timer.period[0] = 1000
  38.                 motor.left.target = -500
  39.                 motor.right.target = -500
  40.                 call leds.top(0,0,32)
  41.         end
  42.         if button.right == 1 and state[0] == 0 and state[1] == 0 and state[2] == 0 and state[3] == 0 then
  43.                 timer.period[0] = 1000
  44.                 motor.left.target = 500
  45.                 motor.right.target = 0
  46.                 call leds.bottom.left(0,32,16)
  47.                 call leds.bottom.right(0,32,16)
  48.         end
  49.         if button.left == 1 and state[0] == 0 and state[1] == 0 and state[2] == 0 and state[3] == 0 then
  50.                 timer.period[0] = 1000
  51.                 motor.left.target = 0
  52.                 motor.right.target = 500
  53.                 call leds.bottom.left(0,16,32)
  54.                 call leds.bottom.right(0,16,32)
  55.         end
  56.  
  57.         call math.copy(state, new_state)
  58.         callsub display_state
  59.  
  60. onevent timer0
  61.         timer.period[0] = 0
  62.         if state[0] == 0 and state[1] == 0 and state[2] == 0 and state[3] == 0 then
  63.                 new_state[0] = 1
  64.                 new_state[1] = 1
  65.                 new_state[2] = 1
  66.                 new_state[3] = 1
  67.         end
  68.         if state[0] == 1 and state[1] == 1 and state[2] == 1 and state[3] == 1 then
  69.                 new_state[0] = 0
  70.                 new_state[1] = 0
  71.                 new_state[2] = 0
  72.                 new_state[3] = 0
  73.         end
  74.  
  75.         call math.copy(state, new_state)
  76.         callsub display_state

Ici, l’intervention de l’humain est nécessaire, mais on peut très rapidement améliorer ce programme pour qu’une intervention humaine ne soit plus nécessaire, en mixant par exemple les deux programmes précédents...
Le ballet complet se trouve dans le port-folio de cet article car, seule une direction est implémentée sur l’image ci-dessus.

Exercice : Créer un comportement du robot correspondant à cette image puis simplifier le code source au maximum, car l’interface VPL crée des redondances dans le code, à chaque fois par exemple que l’on teste la même condition (plusieurs if pour la même condition, c’est inutile, il faudra tout mettre dans le même bloc).

Compter avec le Thymio


Ce qui m’intéresse ici, c’est de compter avec Thymio. Le Thymio possède un cercle de 8 leds sur sa face supérieure. Avec 4 leds seulement, on peut décrire 16 états différents, et donc compter en binaire (led éteinte = 0, led allumée = 1) en base 16.

Compter en unaire modulo 2

On va afficher le reste de la division euclidienne d’un nombre par 2.
On choisit une led. Elle sera éteinte (blanc) si on tape dans les mains un nombre pair de fois et allumée (orange) si on tape dans les mains un nombre impair de fois.

  1. var state[4] = [0,0,0,0]
  2. var new_state[4] = [0,0,0,0]
  3.  
  4. mic.threshold = 250
  5. call sound.system(-1)
  6. call leds.top(0,0,0)
  7. call leds.bottom.left(0,0,0)
  8. call leds.bottom.right(0,0,0)
  9. call leds.circle(0,0,0,0,0,0,0,0)
  10.  
  11. sub display_state
  12.         call leds.circle(0,state[1]*32,0,state[3]*32,0,state[2]*32,0,state[0]*32)
  13.  
  14. onevent mic
  15.         if state[0] == 0 then
  16.                 new_state[0] = 1
  17.         end
  18.         if state[0] == 1 then
  19.                 new_state[0] = 0
  20.         end
  21.  
  22.         call math.copy(state, new_state)
  23.         callsub display_state
  24.  
  25. onevent buttons
  26.         if button.center == 1 then
  27.                 new_state[0] = 0
  28.         end
  29.  
  30.         call math.copy(state, new_state)
  31.         callsub display_state

Compter en unaire modulo base 4

On va afficher le reste de la division euclidienne d’un nombre par 4.
Il faut donc falloir choisir 3 leds car il y a quatre états possibles : 0, 1, 2, 3.

  1. var state[4] = [0,0,0,0]
  2. var new_state[4] = [0,0,0,0]
  3.  
  4. mic.threshold = 250
  5. call sound.system(-1)
  6. call leds.top(0,0,0)
  7. call leds.bottom.left(0,0,0)
  8. call leds.bottom.right(0,0,0)
  9. call leds.circle(0,0,0,0,0,0,0,0)
  10.  
  11. sub display_state
  12.         call leds.circle(0,state[1]*32,0,state[3]*32,0,state[2]*32,0,state[0]*32)
  13.  
  14. onevent buttons
  15.         if button.center == 1 then
  16.                 new_state[0] = 0
  17.                 new_state[1] = 0
  18.                 new_state[2] = 0
  19.                 new_state[3] = 0
  20.         end
  21.  
  22.         call math.copy(state, new_state)
  23.         callsub display_state
  24.  
  25. onevent mic
  26.         if state[0] == 0 and state[1] == 0 and state[2] == 0 and state[3] == 0 then
  27.                 new_state[0] = 0
  28.                 new_state[1] = 1
  29.                 new_state[2] = 0
  30.                 new_state[3] = 0
  31.         end
  32.         if state[0] == 0 and state[1] == 1 and state[2] == 0 and state[3] == 0 then
  33.                 new_state[0] = 0
  34.                 new_state[1] = 1
  35.                 new_state[2] = 0
  36.                 new_state[3] = 1
  37.         end
  38.         if state[0] == 0 and state[1] == 1 and state[2] == 0 and state[3] == 1 then
  39.                 new_state[0] = 0
  40.                 new_state[1] = 1
  41.                 new_state[2] = 1
  42.                 new_state[3] = 1
  43.         end
  44.         if state[0] == 0 and state[1] == 1 and state[2] == 1 and state[3] == 1 then
  45.                 new_state[0] = 0
  46.                 new_state[1] = 0
  47.                 new_state[2] = 0
  48.                 new_state[3] = 0
  49.         end
  50.  
  51.         call math.copy(state, new_state)
  52.         callsub display_state
  53.  

Compter en base 4 en représentation binaire

Il n’y a plus besoin que de deux leds pour représenter les nombres de 0 à 3 en base 2.

  1. var state[4] = [0,0,0,0]
  2. var new_state[4] = [0,0,0,0]
  3.  
  4. mic.threshold = 250
  5. call sound.system(-1)
  6. call leds.top(0,0,0)
  7. call leds.bottom.left(0,0,0)
  8. call leds.bottom.right(0,0,0)
  9. call leds.circle(0,0,0,0,0,0,0,0)
  10.  
  11. sub display_state
  12.         call leds.circle(0,state[1]*32,0,state[3]*32,0,state[2]*32,0,state[0]*32)
  13.  
  14. onevent buttons
  15.         if button.center == 1 then
  16.                 new_state[0] = 0
  17.                 new_state[1] = 0
  18.         end
  19.  
  20.         call math.copy(state, new_state)
  21.         callsub display_state
  22.  
  23. onevent mic
  24.         if state[0] == 0 and state[1] == 0 then
  25.                 new_state[0] = 0
  26.                 new_state[1] = 1
  27.         end
  28.         if state[0] == 0 and state[1] == 1 then
  29.                 new_state[0] = 1
  30.                 new_state[1] = 0
  31.         end
  32.         if state[0] == 1 and state[1] == 0 then
  33.                 new_state[0] = 1
  34.                 new_state[1] = 1
  35.         end
  36.         if state[0] == 1 and state[1] == 1 then
  37.                 new_state[0] = 0
  38.                 new_state[1] = 0
  39.         end
  40.  
  41.         call math.copy(state, new_state)
  42.         callsub display_state
  43.  

Compter en base 8 en représentation binaire

On aura cette fois besoin de trois leds pour représenter les nombres de 0 à 7 en base 2.

  1. var state[4] = [0,0,0,0]
  2. var new_state[4] = [0,0,0,0]
  3.  
  4. mic.threshold = 250
  5. call sound.system(-1)
  6. call leds.top(0,0,0)
  7. call leds.bottom.left(0,0,0)
  8. call leds.bottom.right(0,0,0)
  9. call leds.circle(0,0,0,0,0,0,0,0)
  10.  
  11. sub display_state
  12.         call leds.circle(0,state[1]*32,0,state[3]*32,0,state[2]*32,0,state[0]*32)
  13.  
  14. onevent buttons
  15.         if button.center == 1 then
  16.                 new_state[0] = 0
  17.                 new_state[1] = 0
  18.                 new_state[2] = 0
  19.                 new_state[3] = 0
  20.         end
  21.  
  22.         call math.copy(state, new_state)
  23.         callsub display_state
  24.  
  25. onevent mic
  26.         if state[0] == 0 and state[1] == 0 and state[2] == 0 and state[3] == 0 then
  27.                 new_state[0] = 0
  28.                 new_state[1] = 1
  29.                 new_state[2] = 0
  30.                 new_state[3] = 0
  31.         end
  32.         if state[0] == 0 and state[1] == 1 and state[2] == 0 and state[3] == 0 then
  33.                 new_state[0] = 1
  34.                 new_state[1] = 0
  35.                 new_state[2] = 0
  36.                 new_state[3] = 0
  37.         end
  38.         if state[0] == 1 and state[1] == 0 and state[2] == 0 and state[3] == 0 then
  39.                 new_state[0] = 1
  40.                 new_state[1] = 1
  41.                 new_state[2] = 0
  42.                 new_state[3] = 0
  43.         end
  44.         if state[0] == 1 and state[1] == 1 and state[2] == 0 and state[3] == 0 then
  45.                 new_state[0] = 0
  46.                 new_state[1] = 0
  47.                 new_state[2] = 1
  48.                 new_state[3] = 0
  49.         end
  50.         if state[0] == 0 and state[1] == 0 and state[2] == 1 and state[3] == 0 then
  51.                 new_state[0] = 0
  52.                 new_state[1] = 1
  53.                 new_state[2] = 1
  54.                 new_state[3] = 0
  55.         end
  56.         if state[0] == 0 and state[1] == 1 and state[2] == 1 and state[3] == 0 then
  57.                 new_state[0] = 1
  58.                 new_state[1] = 0
  59.                 new_state[2] = 1
  60.                 new_state[3] = 0
  61.         end
  62.         if state[0] == 1 and state[1] == 0 and state[2] == 1 and state[3] == 0 then
  63.                 new_state[0] = 1
  64.                 new_state[1] = 1
  65.                 new_state[2] = 1
  66.                 new_state[3] = 0
  67.         end
  68.         if state[0] == 1 and state[1] == 1 and state[2] == 1 and state[3] == 0 then
  69.                 new_state[0] = 0
  70.                 new_state[1] = 0
  71.                 new_state[2] = 0
  72.                 new_state[3] = 0
  73.         end
  74.  
  75.         call math.copy(state, new_state)
  76.         callsub display_state
  77.  
  78.  

Compter en base 16 en représentation binaire !

On aura cette fois besoin de quatre leds pour représenter les nombres de 0 à 15 en base 2.

  1. var state[4] = [0,0,0,0]
  2. var new_state[4] = [0,0,0,0]
  3.  
  4. mic.threshold = 250
  5. call sound.system(-1)
  6. call leds.top(0,0,0)
  7. call leds.bottom.left(0,0,0)
  8. call leds.bottom.right(0,0,0)
  9. call leds.circle(0,0,0,0,0,0,0,0)
  10.  
  11. sub display_state
  12.         call leds.circle(0,state[1]*32,0,state[3]*32,0,state[2]*32,0,state[0]*32)
  13.  
  14. onevent buttons
  15.         if button.center == 1 then
  16.                 new_state[0] = 0
  17.                 new_state[1] = 0
  18.                 new_state[2] = 0
  19.                 new_state[3] = 0
  20.         end
  21.  
  22.         call math.copy(state, new_state)
  23.         callsub display_state
  24.  
  25. onevent mic
  26.         if state[0] == 0 and state[1] == 0 and state[2] == 0 and state[3] == 0 then
  27.                 new_state[0] = 0
  28.                 new_state[1] = 1
  29.                 new_state[2] = 0
  30.                 new_state[3] = 0
  31.         end
  32.         if state[0] == 0 and state[1] == 1 and state[2] == 0 and state[3] == 0 then
  33.                 new_state[0] = 1
  34.                 new_state[1] = 0
  35.                 new_state[2] = 0
  36.                 new_state[3] = 0
  37.         end
  38.         if state[0] == 1 and state[1] == 0 and state[2] == 0 and state[3] == 0 then
  39.                 new_state[0] = 1
  40.                 new_state[1] = 1
  41.                 new_state[2] = 0
  42.                 new_state[3] = 0
  43.         end
  44.         if state[0] == 1 and state[1] == 1 and state[2] == 0 and state[3] == 0 then
  45.                 new_state[0] = 0
  46.                 new_state[1] = 0
  47.                 new_state[2] = 1
  48.                 new_state[3] = 0
  49.         end
  50.         if state[0] == 0 and state[1] == 0 and state[2] == 1 and state[3] == 0 then
  51.                 new_state[0] = 0
  52.                 new_state[1] = 1
  53.                 new_state[2] = 1
  54.                 new_state[3] = 0
  55.         end
  56.         if state[0] == 0 and state[1] == 1 and state[2] == 1 and state[3] == 0 then
  57.                 new_state[0] = 1
  58.                 new_state[1] = 0
  59.                 new_state[2] = 1
  60.                 new_state[3] = 0
  61.         end
  62.         if state[0] == 1 and state[1] == 0 and state[2] == 1 and state[3] == 0 then
  63.                 new_state[0] = 1
  64.                 new_state[1] = 1
  65.                 new_state[2] = 1
  66.                 new_state[3] = 0
  67.         end
  68.         if state[0] == 1 and state[1] == 1 and state[2] == 1 and state[3] == 0 then
  69.                 new_state[0] = 0
  70.                 new_state[1] = 0
  71.                 new_state[2] = 0
  72.                 new_state[3] = 1
  73.         end
  74.         if state[3] == 1 then
  75.                 new_state[1] = 1
  76.                 new_state[3] = 1
  77.         end
  78.         if state[1] == 1 and state[3] == 1 then
  79.                 new_state[0] = 1
  80.                 new_state[1] = 0
  81.                 new_state[3] = 1
  82.         end
  83.         if state[0] == 1 and state[3] == 1 then
  84.                 new_state[0] = 1
  85.                 new_state[1] = 1
  86.                 new_state[3] = 1
  87.         end
  88.         if state[0] == 1 and state[1] == 1 and state[3] == 1 then
  89.                 new_state[2] = 1
  90.                 new_state[3] = 1
  91.         end
  92.         if state[2] == 1 and state[3] == 1 then
  93.                 new_state[1] = 1
  94.                 new_state[2] = 1
  95.                 new_state[3] = 1
  96.         end
  97.         if state[1] == 1 and state[2] == 1 and state[3] == 1 then
  98.                 new_state[0] = 0
  99.                 new_state[1] = 1
  100.                 new_state[2] = 1
  101.                 new_state[3] = 1
  102.         end
  103.         if state[0] == 0 and state[1] == 1 and state[2] == 1 and state[3] == 1 then
  104.                 new_state[0] = 1
  105.                 new_state[1] = 1
  106.                 new_state[2] = 1
  107.                 new_state[3] = 1
  108.         end
  109.         if state[0] == 1 and state[1] == 1 and state[2] == 1 and state[3] == 1 then
  110.                 new_state[0] = 0
  111.                 new_state[1] = 0
  112.                 new_state[2] = 0
  113.                 new_state[3] = 0
  114.         end
  115.  
  116.         call math.copy(state, new_state)
  117.         callsub display_state
  118.  
  119.  
  120.  

Exercices :

  1. Pour compter en unaire modulo base 4, il suffit de trois leds. De combien de leds a-t-on besoin pour compter en base 8 ? Expliquer. Réaliser le programme.
  2. La partie « Compter en base 16 en représentation binaire » ne nécessite que quatre leds pour représenter les nombres de 0 à 15 en base 2. Que peut-on, faire si on utilise huit leds ? Expliquer le principe. (pas besoin du Thymio ici...)

Addition en binaire

Si on ajoute 1 à un nombre en binaire qui finit par 0, ce 0 devient 1.
Si on ajoute 1 à un nombre en binaire qui finit par 1, ce 1 devient 0, et il y a un effet sur les nombres précédents..
L’arbre ci-dessous montre les transitions 0 → 1 et 1 → 0 pour l’addition.
PNG

  1. var state[4] = [0,0,0,0]
  2. var new_state[4] = [0,0,0,0]
  3.  
  4. mic.threshold = 250
  5. call sound.system(-1)
  6. call leds.top(0,0,0)
  7. call leds.bottom.left(0,0,0)
  8. call leds.bottom.right(0,0,0)
  9. call leds.circle(0,0,0,0,0,0,0,0)
  10.  
  11. sub display_state
  12.         call leds.circle(0,state[1]*32,0,state[3]*32,0,state[2]*32,0,state[0]*32)
  13.  
  14. onevent buttons
  15.         if button.center == 1 then
  16.                 new_state[0] = 0
  17.                 new_state[1] = 0
  18.                 new_state[2] = 0
  19.                 new_state[3] = 0
  20.         end
  21.  
  22.         call math.copy(state, new_state)
  23.         callsub display_state
  24.  
  25. onevent mic
  26.         if state[1] == 0 then
  27.                 new_state[1] = 1
  28.         end
  29.         if state[0] == 0 and state[1] == 1 then
  30.                 new_state[0] = 1
  31.                 new_state[1] = 0
  32.         end
  33.         if state[0] == 1 and state[1] == 1 and state[2] == 0 then
  34.                 new_state[0] = 0
  35.                 new_state[1] = 0
  36.                 new_state[2] = 1
  37.         end
  38.         if state[0] == 1 and state[1] == 1 and state[2] == 1 and state[3] == 0 then
  39.                 new_state[0] = 0
  40.                 new_state[1] = 0
  41.                 new_state[2] = 0
  42.                 new_state[3] = 1
  43.         end
  44.         if state[0] == 1 and state[1] == 1 and state[2] == 1 and state[3] == 1 then
  45.                 new_state[0] = 0
  46.                 new_state[1] = 0
  47.                 new_state[2] = 0
  48.                 new_state[3] = 0
  49.         end
  50.  
  51.         call math.copy(state, new_state)
  52.         callsub display_state

Soustraction en binaire

Si on enlève 1 à un nombre en binaire qui finit par 1, ce 1 devient 0.
Si on enlève 1 à un nombre en binaire qui finit par 0, ce 1 devient 0, et il y a un effet sur les nombres précédents.
L’arbre ci-dessous montre les transitions 1 → 0 et 0 → 1 pour la soustraction.

  1. var state[4] = [0,0,0,0]
  2. var new_state[4] = [0,0,0,0]
  3.  
  4. mic.threshold = 250
  5. call sound.system(-1)
  6. call leds.top(0,0,0)
  7. call leds.bottom.left(0,0,0)
  8. call leds.bottom.right(0,0,0)
  9. call leds.circle(0,0,0,0,0,0,0,0)
  10.  
  11. sub display_state
  12.         call leds.circle(0,state[1]*32,0,state[3]*32,0,state[2]*32,0,state[0]*32)
  13.  
  14. onevent buttons
  15.         if button.center == 1 then
  16.                 new_state[0] = 1
  17.                 new_state[1] = 1
  18.                 new_state[2] = 1
  19.                 new_state[3] = 1
  20.         end
  21.  
  22.         call math.copy(state, new_state)
  23.         callsub display_state
  24.  
  25. onevent mic
  26.         if state[1] == 1 then
  27.                 new_state[1] = 0
  28.         end
  29.         if state[0] == 1 and state[1] == 0 then
  30.                 new_state[0] = 0
  31.                 new_state[1] = 1
  32.         end
  33.         if state[0] == 0 and state[1] == 0 and state[2] == 1 then
  34.                 new_state[0] = 1
  35.                 new_state[1] = 1
  36.                 new_state[2] = 0
  37.         end
  38.         if state[0] == 0 and state[1] == 0 and state[2] == 0 and state[3] == 1 then
  39.                 new_state[0] = 1
  40.                 new_state[1] = 1
  41.                 new_state[2] = 1
  42.                 new_state[3] = 0
  43.         end
  44.         if state[0] == 0 and state[1] == 0 and state[2] == 0 and state[3] == 0 then
  45.                 new_state[0] = 1
  46.                 new_state[1] = 1
  47.                 new_state[2] = 1
  48.                 new_state[3] = 1
  49.         end
  50.  
  51.         call math.copy(state, new_state)
  52.         callsub display_state

En pratique, il faut affiner les programmes précédents en ajoutant un timer d’enregistrement, afin qu’il n’y ait pas de bruits parasites, ou d’écho qui perturbent le fonctionnement du programme. (Voir par exemple l’addition binaire avec timer).

Thymio et son interface de programmation, un outil idéal pour faire des Sciences

Les nombreux capteurs du Thymio laissent notre imagination sans limite. Ainsi, mon collègue de physique François Ploteau a eu l’idée de demander aux élèves des étalonnages des capteurs de distance et d’accélération.

  1. Étalonnage des capteurs de distance
  2. Étalonnage des capteurs d’accélération du robot Thymio

Une description technique détaillée concernant les capteurs et actuateurs se trouve ici (page essentielle pour ce qui va suivre).
Pour suivre les variables liées aux capteurs, il suffit de regarder la fenêtre Variables de l’interface Aseba de programmation du Thymio, en laissant cochée la variable Auto.

Ces étalonnages ont donné lieu à un recueil de données que nous avons traitées avec une superbe bibliothèque Python : la bibliothèque Pygal (je dis superbe car elle fait de magnifiques courbes...).

L’interface de programmation du robot permet aussi de voir les graphiques des valeurs enregistrées par les capteurs.

Capteurs d'accélération
Capteur de température
Capteur de vitesse du moteur droit

Limite du langage Aseba, langage de programmation du robot Thymio ?

La description du langage Aseba est donnée dans sa page de référence :
« Aseba est un langage de programmation impératif avec un seul type simple (nombres entiers signés sur 16 bits) et des tableaux. Cette simplicité permet aux développeurs sans connaissances préalables d’un système de type de programmer des comportements ; les nombres entiers étant le type de variable le plus naturel. De plus, les nombres entiers sont particulièrement adaptés aux robots à micro-contrôleurs. »
Jusqu’ici tout va bien.
Aseba nous a aussi donné la possibilité de créer des sous-routines (mot clé sub) pour simplifier le code lorsqu’apparaît une même suite d’opérations à plusieurs endroits dans le code. Malheureusement, cette petite phrase donnée dans la documentation d’Aseba : « Les sous-routines peuvent accéder à toutes les variables. » laisse entendre que les variables du langage sont globales. C’est probablement la raison pour laquelle il n’y a pas la possibilité de créer des fonctions avec passage d’arguments. Personnellement, je trouve que cela complique l’écriture du code.
Par contre, évidemment, l’interface de programmation visuelle, fournie en surcouche pour l’écriture des programmes sur le Thymio est un plus inestimable puisqu’il permet à des enfants de 8 ans par exemple de programmer le robot. La prise en main - devant moi - de l’interface VPL et du robot par un enfant de 8 ans n’a duré que quelques minutes. En une heure, il avait déjà réalisé par lui-même un petit comportement simple, avec marche, recul, rotation du robot, changement de couleurs selon l’événement, timer et réaction sur clappement des mains.


Documents joints

PDF - 196.7 ko
PDF - 196.7 ko

Commentaires

Logo de Okimi
mercredi 25 novembre 2015 à 18h19 - par  Okimi

Bonjour,

Si vous vous intéressez aux robots Thymio II et aux moyens pour les programmer, je vous invite à regarder sur : www.blockly4thymio.net .
Blockly4Thymio est un nouvel environnement pour apprendre, tout en s’amusant, la programmation auprès du jeune publique.

Cet environnement est encore en développement, mais une version d’essai est disponible en téléchargement.

Logo de Sébastien
mercredi 12 novembre 2014 à 05h24 - par  Sébastien

Très bel article. Très complet, merci Nathalie.

Comme dit à la fin de ton article dommage que le langage soit peu abouti. Il faudrait qu’ils essaient de remplacer leur langage par du vrai python par exemple. Avec fonctions, paramètres, variables locales etc. En attendant je pense que Thymio est parfait pour : initiation niveau seconde (utilisation presqu’exclusive de l’interface graphique tout en réfléchissant à l’algorithme pour la résolution d’un problème) et utilisation en ISN sur des TPs croisés (comme celui du plan incliné qui mixe physique/math/info) et exploitation des données recueillies en python. Moins valable pour apprentissage de la programmation niveau ISN.