logo admiroutes Les automates intelligents
robotique, vie artificielle, réalité virtuelle


information, réflexion, discussion
logo automate © Anne Bedel
Jean-Paul Baquiast Jean-Paul.Baquiast@wanadoo.fr
Christophe Jacquemin christophe.jacquemin@admiroutes.asso.fr

31
Retour au sommaire
Programmer en legOS
(n°5)
La rubrique des passionnés Lego Mindstorms
Brique RCX
par Nanobapt nanobapt@nordnet.fr
http://home.nordnet.fr/%7Emdenayer/
(avec les conseils de Christophe Jacquemin)
05/05/02

NDLR : il est conseillé au lecteur un minimum de base en programmation et langage C. Sinon, il existe de bons bouquins en la matière ou des sites web traitant de la question - par exemple http://www.inf.enst.fr/~charon/CFacile/.

Après avoir vu comment donner de l'animation au robot, abordons maintenant le fonctionnement en multitâche, ce qui est très important en robotique.

Tout d'abord, présentons quelques fonctions d'attente. Elles sont par exemple utiles pour la commande des moteurs ; d'autres applications peuvent assez facilement être imaginées. Rappelons que nous avons déjà utilisé une de ces fonctions lors d'une précédente leçon concernant les moteurs (voir le programme présenté à la leçon n°3).

- Tout d'abord, voici deux fonctions principales à retenir (car nécessaires pour tout programme de robotique) :

- Signalons aussi la fonction d'attente d'événement : on peut en effet imaginer un programme qui nécessite, par exemple, l'attente d'un quelconque signal avant de faire effectuer une action spécifique au robot.
Pour cela, il faut déclarer au début du programme l'événement voulu, en d'autre terme ce que la fonction aura à comparer. Ceci se fait par l'intermédiaire de la fonction wakeup_t mon_nom(waekup_t donnée2).
Pour comparer la fonction, on utilise la fonction wait_event(mon_nom, donnée1). Les 2 paramètres de cette fonction sont le nom de l'événement appelé et les données. Lors de l'appel de wait_event, donnée2 dans la déclaration sera remplacé par donnée1.
Le programme ci-dessous explicite mieux l'utilisation de cette fonction.

/*wait.c*/

#include <dsensor.h>
#include <dlcd.h>
#include <unistd.h>
#include <conio.h>

wakeup_t toucher(wakeup_t data)

{
return(TOUCH_1) ;
}

int main()

{
cputs("touch") ;
msleep(500) ;
cputs("moi") ;

wait_event(toucher, 0) ;

cputs("OK") ;

return 0 ;
}





//NOTE : les fonctions d'attente sont déclarées dans le fichier unistd.h


//ici data ne servira pas

 

 


 

 



//0 est ignoré

 

Le multitâche :

Le multitâche est une notion finalement assez difficile à comprendre (le dictionnaire terminologique classe ce terme sous l'entrée "informatique", avec la définition suivante : "Mode d'exploitation dans lequel plusieurs tâches sont exécutées simultanément dans la mesure où elles ne font pas appel aux mêmes ressources").
On pourrait pavoiser des heures sur les termes : donnons plutôt un exemple avec ce programme qui gère deux capteurs tactiles, un par tâche :

/*wait.c*/

#include <dsensor.h>
#include <dlcd.h>
#include <unistd.h>
#include <conio.h>

pid_t touch1, touch2;

wakeup_t premier(wakeup_t data)

{
return(TOUCH_1) ;
}

wakeup_t deuxieme(wakeup_t data)

{
return(TOUCH_3) ;
}

int t1()

{
while(1)

{
wait_event(premier, 0);
motor_a_dir(rev) ;
motor_c_dir(rev);
sleep(1);
motor_a_dir(fwd) ;
motor_c_dir(rev);
sleep(1);
motor_a_dir(fwd) ;
motor_c_dir(fwd);
}

}

int t2()

{
while(1)

{
wait_event(deuxieme, 0);
motor_a_dir(rev) ;
motor_c_dir(rev);
sleep(1);
motor_c_dir(fwd) ;
motor_a_dir(rev);
sleep(1);
motor_a_dir(fwd) ;
motor_c_dir(fwd);
}

}

int main()

{
motor_a_speed(255);
motor_c_speed(255);
motor_a_dir(fwd);
motor_c_dir(fwd);

touch1 = execi(&t1, 0, 0, PRIO_NORMAL, DEFAULT_STACK_SIZE) ;
touch2 = execi(&t2, 0, 0, PRIO_NORMAL+1, DEFAULT_STACK_SIZE) ;

return 0;
}


On remarquera que nous avons utilisé dans cet exemple des fonctions décrites précédemment.
Il ne vous a certainement pas échappé non plus que :
- le multitâche est déclaré dans le fichier unistd.h
- les tâches simultanées sont t1 et t2, qui gèrent chacune d'elle un capteur de toucher (capteur 1 et 3)
- on aurait pu faire le même programme sans les deux tâches.

Dans la tâche principale (main), la déclaration et le lancement des taches se fait par la fonction execi(). Elle doit être déclarée en tant que pid_t. La syntaxe est la suivante : pid_t execi(). Mettre des variables intermédiaires (touch1 et touch2) permet de ne pas lancer les tâches dès le début du programme.

Explicitons maintenant la syntaxe de la fonction execi :

Dernier point : il peut être aussi intéressant de tuer les tâches : on utilise pour cela la fonction : kill().
Si par exemple on voulait tuer la tâche t2, il faudrait alors noter : kill(touch2).

Voilà pour les tâches. Suite au prochain numéro où nous verrons comment créer du son avec la brique RCX.


Tous les cours "Programmer en legOS"
Retour au sommaire général