https://cipcgw.insa-lyon.fr/~rmoreau/Mecatro_Pratique/Cours_Mecatro_NXT.pdf
Dans ce premier chapitre, nous vous montrerons comment écrire un programme extrêmement simple. Nous allons programmer un robot qui avancera pendant 4 secondes, puis reculera pendant 4 secondes, puis s'arrêtera. Pas très compliqué mais cela introduira les idées de base de la programmation. Et cela vous montrera à quel point c'est facile. Mais avant de commencer à programmer, nous avons besoin d'un robot.
Construction du robot
Le robot que nous allons utiliser tout au long de ce tutoriel est Tribot, le premier robot que vous avez construit lors de l'obtention de la boite du Lego Mindstorm. Ici, la seule différence est que vous devez brancher le moteur droit au port A, le moteur gauche au port C et le dernier moteur au port B.
Assurez-vous d'avoir correctement installé les pilotes Mindstorms NXT fournis avec votre appareil.
Utilisation d'un éditeur
Nous allons utiliser le logiciel libre Gedit afin d'écrire nos programmes. Si vous êtes sous Debian ( ou debian-like ) et qu'il n'est pas installé, il suffit de l'installer via cette commande :
sudo apt-get install gedit
Vous obtiendrez ceci lorsque vous ferez un HelloWorld :
Fichier:Capture-helloWorld.nxc (~-Dropbox-NXC-NXC) - gedit.png
Vous remarquerez en bas à gauche que j'ai sélectionné "C" comme langage de programmation car le NXC n'est pas assez rependu pour pouvoir s'offrir une coloration syntaxique sur ce logiciel. Le NXC est cependant proche du C, vous disposerez donc d'une coloration syntaxique assez propre.
Ecriture du programme
Maintenant, recopiez le programme suivant dans votre éditeur préféré :
task main()
{
OnFwd(OUT_A, 75);
OnFwd(OUT_C, 75);
Wait(4000);
OnRev(OUT_AC, 75);
Wait(4000);
Off(OUT_AC);
}
Au premier coup d'œil, ça a l'air compliqué mais nous allons l'analyser ensemble.
Un programme NXC est composé de tâches. Notre programme n'a qu'une tâche, nommée main. Chaque programme doit avoir une tâche nommée main. Cette tache sera celle exécutée par le robot. Vous en apprendrez plus sur les tâches dans un prochain paragraphe. Une tâche se compose d'un certain nombre de commandes, aussi appelé déclarations. Il y a des accolades autour de ces déclarations pour montrer qu'elles appartiennent bien à la tache main. Chaque déclaration se termine par un point virgule. De cette façon, on voit clairement où finit une déclaration et où en débute une autre. En outre, une tache est généralement définie comme ceci :
task main()
{
declaration1 ;
declaration2 ;
...
}
Notre programme contient six déclarations. Regardons les une par une.
OnFwd ( OUT_A , 75 );
Cette déclaration demande au robot de démarrer le moteur de la sortie A, qui est le moteur connecté sur le port identifié A sur la brique A, vers l'avant.
OnFwd ( OUT_C , 75 );
Même déclaration que la précédente, pour démarrer le moteur C. Après ces deux déclarations, les deux moteurs sont en fonctionnement et le robot avance.
Wait ( 4000 );
Maintenant il est temps d'attendre un certain temps. Cette déclaration nous dit d'attendre pendant 4 secondes. L'argument, qui est, le nombre ( entre parenthèses ) de millisecondes : vous pouvez donc très précisément indiquer au programme le temps d'attente.Le robot a maintenant assez avancé, on peut le faire se déplacer en sens inverse. Notez que nous pouvons modifier les deux moteurs à la fois en utilisant comme argument OUT_AC. Nous pourrions aussi avoir combiné les deux premiers états de cette façon.
Wait ( 4000 );
Encore, nous attendons 4 secondes.
Off ( OUT_AC );
Et finalement, on éteint les deux moteurs.
C'est la fin du programme. Il avance 4 secondes, recule 4 secondes et éteint les moteurs.
Vous avez probablement remarqué que les couleurs apparaissent automatiquement lors de la saisie dans le programme. Les couleurs et les styles utilisés par l'éditeur quand il effectue la coloration syntaxique sont personnalisables.
Compiler et transférer votre programme
Une fois que vous avez écrit un programme, il doit être compilé (qui est, transformé en code binaire que le robot peut comprendre et exécuter) et envoyé au robot en utilisant le câble USB ou dongle BT (appelé "downloading" du programme).
Sous linux
Après avoir installé le compilateur et le programme de transfert USB, il vous faut compiler le programme.
nbc votre_code.nbc -O=votre_executable.rxe
Puis connectez la brique et transférez le programme.
t2n votre_executable.rxe
Avec Bricx Command Center sous Windows
Comme vous pouvez le voir sur l'image ci-dessous (dans l'encadré rouge) il y a les boutons qui permettent (de gauche a droite) de compiler, de compiler et de télécharger, d'exécuter le programme et de stopper le programme.
Fichier:Compiler.png
Pressez le second bouton, assurez-vous de ne pas avoir fait d'erreurs en tapant votre programme, votre programme sera correctement compilé et téléchargé sur le robot (si vous avez une erreur de compilation, voir la rubrique sur les erreurs).
Maintenant vous pouvez exécuter votre programme. Pour cela, sur le robot, aller dans My Files, Software files et choisissez le nom de votre programme et faite run.
Vous pouvez aussi exécuter le programme avec le raccourci Ctrl+F5, ou après téléchargement du programme vous pouvez cliquer sur le bouton vert (exécuter).
Les erreurs dans vos programmes
Sous linux
Après avoir compilé votre programme, il se peut que le compilateur vous envoi quelques messages dont l'amabilité sera douteuse... Ne vous inquiétez pas, il s'agit surement d'un message d'erreur. Voici un exemple. Prenez le code suivant et compilez le :
task main () {
OnRev ( OUT_A , 75 );
OfF ( OUT_A , 75 );
}
Voici la commande pour compiler :
nbc erreur.nxc -O=erreur.rxe
Ensuite, le compilateur vous sortira tout un tas de ligne que l'on expliquera pas ici, puis il vous dira :
# Error: Undefined Identifier OfF
File "/home/NXC/.nxc" ; line 3
# OfF (
#----------------------------------------------------------
# Error: ';' expected
File "/home/NXC/.nxc" ; line 3
# OfF ( 0
#----------------------------------------------------------
# Status: NXC compilation failed.
La première erreur vous dit ( clairement ) qu'il ne connait pas l'identifiant ( ici la fonction ) OfF. L'erreur est simple puisqu'il s'agit en réalité de la fonction Off. La deuxième erreur découle simplement de la première. Les erreurs ne sont pas aussi explicite que sous windows ( comme vous le verrez juste après ) mais cela suffit à trouver vos erreurs
Avec Bricx Command Center sous Windows
Lors de la saisie dans les programmes il y a une chance raisonnable que vous aillez fait des erreurs. Le compilateur va vous indiquer les erreurs et les reportes dans le bas de la fenêtre, comme vous pouvez le voir ci-dessous.
Fichier:Erreur.png
Il sélectionne automatiquement la première erreur. Quand il y a plus d'erreurs, vous pouvez cliquez sur les messages d'erreur afin d'aller vers eux. Notez que souvent des erreurs au début du programme cause d'autres erreurs à d'autres endroits. Il vaudrait donc mieux corriger les premières erreurs, puis compiler le programme à nouveau. A noter également que la coloration syntaxique aide beaucoup à éviter les erreurs. Par exemple, sur la dernière ligne nous avons tapé Of au lieu de Off. Comme il s'agit d'une commande inconnue, il n'est pas mis en évidence.
Il y a aussi des erreurs qui ne sont pas trouvées par le compilateur. Si vous actionnoez le mauvais moteur votre robot présentera un comportement inattendu, il est le plus probable que vous aillez fait une erreur dans votre programme.
Changer la vitesse
Comme vous avez remarqué, le robot avance plutôt rapidement. Pour modifier la vitesse il suffit de modifier le deuxième paramètre à l'intérieur des parenthèses. La puissance est un nombre entre 0 et 100. 100 est le plus rapide, 0 pour arrêter (servo-moteurs NXT tiendra position). Voici une nouvelle version de notre programme dans lequel le robot se déplace lentement:
task main()
{
OnFwd(OUT_AC, 30);
Wait(4000);
OnRev(OUT_AC, 30);
Wait(4000);
Off(OUT_AC);
}
Conclusion
Dans ce chapitre, vous avez écrit votre premier programme en NXC, en utilisant ou non BricxCC. Vous devriez maintenant savoir comment écrire un programme, comment le télécharger dans le robot et comment faire exécuter le programme par le robot. BricxCC peut faire beaucoup plus de choses. Pour en savoir plus sur eux, lisez la documentation qui l'accompagne. Ce tutoriel portera principalement sur le langage NXC et ne mentionnent que les caractéristiques de BricxCC dont vous avez vraiment besoin.
Un programme plus intéressant
Notre premier programme n'était pas si extraordinaire. Essayons donc de le rendre plus intéressant. Nous allons dans un certain nombre d'étapes, introduire de nombreuses caractéristiques importantes de notre langage de programmation NXC.
Faire tourner
Vous pouvez faire tourner votre robot en arrêtant ou en inversant le sens de l'un des deux moteurs. Voici un exemple. Compilez-le, télécharger-le sur votre robot et faites-le fonctionner. Il doit avancer un peu et puis tourner à droite à 90 degrés.
task main()
{
OnFwd(OUT_AC, 75);
Wait(800);
OnRev(OUT_C, 75);
Wait(360);
Off(OUT_AC);
}
Vous pourriez avoir à essayer des valeurs légèrement différentes de 500 dans la seconde commande Wait () pour faire un virage à 90 degrés. Cela dépend du type de surface sur laquelle le robot avance. Plutôt que de changer cela dans le programme, il est plus facile de créer une constante pour cette valeur. En NXC vous pouvez définir des valeurs constantes comme le montre le programme suivant.
#define MOVE_TIME 1000
#define TURN_TIME 360
task main()
{
OnFwd ( OUT_AC , 75 );
Wait ( MOVE_TIME );
OnRev ( OUT_C , 75 );
Wait ( TURN_TIME );
Off ( OUT_AC );
}
Les deux premières lignes définissent deux constantes. Celles-ci peuvent maintenant être utilisées dans le programme. Définir des constantes est bon pour deux raisons: il rend le programme plus lisible, et il est plus facile de changer les valeurs.
Les commandes répétitives
Essayons maintenant d'écrire un programme qui fait avancer le robot dans un carré. Avancer dans une carré signifie : marche avant, tournant à 90 degrés, en avançant de nouveau, tournant à 90 degrés, etc Nous pourrions répéter la partie de code du dessus à quatre reprises, mais cela peut être fait beaucoup plus facilement avec l'instruction repeat.
#define MOVE_TIME 500
#define TURN_TIME 500
task main()
{
repeat(4)
{
OnFwd(OUT_AC, 75);
Wait(MOVE_TIME);
OnRev(OUT_C, 75);
Wait(TURN_TIME);
}
Off(OUT_AC);
}
Le nombre entre parenthèses de l'instruction repeat indique combien de fois le code à l'intérieur des accolades doit être répété. Notez que, dans le programme ci-dessus, nous avons également des déclarations indentées. Ce n'est pas nécessaire, mais il rend le programme plus lisible.
Comme dernier exemple, faisons faire 10 fois le tour au robot.
#define MOVE_TIME 500
#define TURN_TIME 500
task main()
{
repeat(10)
{
repeat(4)
{
OnFwd(OUT_AC, 75);
Wait(MOVE_TIME);
OnRev(OUT_C, 75);
Wait(TURN_TIME);
}
}
Off(OUT_AC);
}
Il ya maintenant une déclaration repeat dans l'autre repeat. Nous appelons cela une déclaration repeat "imbriquée". Vous pouvez imbriquer des déclarations repeat autant de fois que vous le souhaitez. Gardez un regard attentif sur les accolades et l'indentation du programme. La tâche commence à la première accolade et se termine à la dernière. La déclaration du premier repeat commence à la deuxième accolade et se termine à la cinquième. L'instruction repeat imbriquée commence à la troisième accolade et se termine à la quatrième. Comme vous le voyez les accolades viennent toujours par paires et le code entre les accolades est indenté.
Pour que votre programme soit encore plus lisible, il est bon d'y ajouter quelques commentaires. Chaque fois que vous mettez // sur une ligne, le reste de cette ligne est ignoré et peut être utilisé pour les commentaires. Un long commentaire peut être mis entre / * et * /. Les commentaires sont colorés syntaxiquement dans BricxCC. Le programme complet peut se présenter comme suit:
/* 10 SQUARES
Ce programme fait faire 10 carrés au robot
*/
#define MOVE_TIME 500 // Temps pour avancer
#define TURN_TIME 360 // Temps pour tourner à 90 degrés
task main()
{
repeat(10) // Fait 10 carrés
{
repeat(4)
{
OnFwd(OUT_AC, 75);
Wait(MOVE_TIME);
OnRev(OUT_C, 75);
Wait(TURN_TIME);
}
}
Off(OUT_AC); // Éteint les moteurs
}
Conclusion
Dans ce chapitre, vous avez appris l'utilisation de la déclaration repeat et l'utilisation des commentaires. Aussi vous avez vu l'utilisation des accolades imbriquées et l'indentation. Avec tout ce que vous savez, vous pouvez faire bouger le robot le long de toutes sortes de chemins. C'est un bon exercice d'essayer d'écrire des variantes des programmes de ce chapitre avant de poursuivre avec le prochain chapitre.
Maintenant que vous êtes à la fin de ce chapitre, vous avez toutes les compétences dont vous avez besoin pour faire faire à votre robot des choses compliquées. Les autres chapitres de ce tutoriel vous apprendront des choses qui ne sont importantes que dans certaines applications.
Utilisation des variables
Les variables forment un aspect très important de tout langage de programmation. Les variables sont des emplacements de mémoire dans lesquels on peut stocker des valeurs. Nous pouvons utiliser ces valeurs à différents endroits et nous pouvons les changer. Nous allons décrire l'utilisation des variables en utilisant un exemple.
#define TURN_TIME 360
int move_time; // définition d'une variable
task main()
{
move_time = 200;
repeat(50)
{
OnFwd(OUT_AC, 75);
Wait(move_time);
OnRev(OUT_C, 75);
Wait(TURN_TIME);
move_time += 200;
}
Off(OUT_AC);
}
Les lignes intéressantes sont indiquées avec des commentaires. Nous avons d'abord définit une variable en tapant la mot-clé int suivi d'un nom que nous choisissons. (Normalement, nous utilisons des lettres minuscules pour les noms de variables et les lettres majuscules pour constantes.) Le nom doit commencer par une lettre, mais peut contenir des chiffres et des traits de soulignement. Aucun autre symbole n'est autorisé. (de même pour les constantes, les noms des tâches, etc) Le mot int désigne un entier. Seuls les nombres entiers peuvent être stockés. Dans la deuxième ligne on assigne la valeur 200 à la variable. À partir de ce moment, lorsque vous utilisez la variable, sa valeur sera de 200. Suit maintenant la boucle dans laquelle nous utilisons la variable pour indiquer la temps à attendre et, à la fin de la boucle nous augmentons la valeur de la variable de 200. Donc la première fois le robot attend 200 ms, la deuxième fois 400 ms, pour la troisième fois 600 ms, et ainsi de suite.
Avancer dans un cercle
Outre l'ajout de valeurs à une variable, nous pouvons aussi multiplier une variable avec un numéro à l'aide *=, soustraire à l'aide -= et diviser en utilisant /=. (Notez que pour la division le résultat est arrondi à l'entier le plus proche.) Vous pouvez également ajouter une variable à l'autre, et écrire des expressions plus complexes. L'exemple suivant n'a pas d'effet sur le robot, car nous ne savons pas comment utiliser l'écran du NXT encore!
int aaa;
int bbb,ccc;
int values[];
task main()
{
aaa = 10;
bbb = 20 * 5;
ccc = bbb;
ccc /= aaa;
ccc -= 5;
aaa = 10 * (ccc + 3); // aaa vaut maintenant 80
ArrayInit(values, 0, 10); // on alloue 10 éléments = 0
values[0] = aaa;
values[1] = bbb;
values[2] = aaa*bbb;
values[3] = ccc;
}
Notez sur les deux premières lignes que nous pouvons définir plusieurs variables en une seule ligne. Nous pourrions aussi avoir réuni les trois variables sur une seule ligne. La variable nommée values est un tableau, c'est une variable qui contient plus d'un nombre: un tableau peut être indexé avec un certain nombre entre les crochets. En NXC, les tableaux d'entiers sont déclarés ainsi:
int name[];
Ensuite, cette ligne alloue 10 éléments qui sont initialisés à 0.
ArrayInit(values, 0, 10);
Nombres aléatoires
Dans tous les programmes ci-dessus nous avons défini exactement ce que le robot était censé faire. Mais les choses deviennent beaucoup plus intéressantes quand le robot va faire des choses que nous ne savons pas. Nous voulons un peu de hasard dans les mouvements. En NXC vous pouvez créer des nombres aléatoires. Le programme suivant utilise cette technique pour faire tourner robot d'une manière aléatoire. Il avance constamment vers l'avant pour un temps aléatoire, puis tourne au hasard.
int move_time, turn_time;
task main()
{
while(true)
{
move_time = Random(600);
turn_time = Random(400);
OnFwd(OUT_AC, 75);
Wait(move_time);
OnRev(OUT_A, 75);
Wait(turn_time);
}
}
Le programme définit deux variables, puis assigne des nombres aléatoires pour eux. Random (600) renvoi un nombre aléatoire compris entre 0 et 600 (la valeur maximale est pas exclue). Chaque fois que vous l'appelez, les numéros choisis au hasard seront différents.
Notez que nous pourrions éviter l'utilisation des variables en écrivant par exemple :
Wait (Random (600)).
Vous voyez également un nouveau type de boucle ici. Plutôt que l'utilisation de l'instruction repeat, nous avons écrit while (true). L'instruction while répète les déclarations en-dessous aussi longtemps que les conditions entre parenthèses sont vraies. Le mot spécial true est toujours vrai, alors les états entre les accolades sont répétés pour toujours (ou du moins jusqu'à ce que vous appuyez sur le bouton gris foncé du NXT). Vous en apprendrez plus sur les déclarations plus tard.
Conclusion
Dans ce chapitre, vous avez appris l'utilisation des variables et des tableaux. Vous pouvez déclarer d'autres types de données qu'un int: short, long, byte, bool et string. Vous avez également appris à créer des nombres aléatoires, de sorte que vous pouvez donner au robot un comportement imprévisible. Enfin nous avons vu les utilisations de l'instruction while pour faire une boucle infinie.
Les structures de contrôle
Dans les chapitres précédents nous avons vu les déclarations repeat et while. Ces déclarations contrôlent la façon dont les autres déclarations sont exécutées. Ils sont appelés "structures de contrôle". Dans ce chapitre, nous allons voir quelques autres structures de contrôle.
La déclaration if
Parfois, vous voulez qu'une partie de votre programme soit exécutée uniquement dans certaines situations. Dans ce cas, l'instruction if est utilisée. Permettez-moi de vous donner un exemple. Nous allons à nouveau changer le programme avec lequel nous travaillons depuis le début, mais avec une nouvelle tournure. Nous voulons que le robot avance le long d'une ligne droite et tourne, soit à gauche ou à droite. Pour ce faire nous aurons encore besoin de nombres aléatoires. Nous choisissons un nombre aléatoire qui est soit positif, soit négatif. Si le nombre est négatif, le virage sera vers la droite, sinon vers la gauche. Voici le programme:
#define MOVE_TIME 500
#define TURN_TIME 360
task main()
{
while(true)
{
OnFwd(OUT_AC, 75);
Wait(MOVE_TIME);
if (Random() >= 0)
{
OnRev(OUT_C, 75);
}
else
{
OnRev(OUT_A, 75);
}
Wait(TURN_TIME);
}
}
L'instruction if ressemble un peu à l'instruction while. Si la condition entre parenthèses est vraie alors la partie entre accolades est exécutée. Sinon, la partie entre accolades après le motelse est exécutée. Regardons de plus prêt la condition que nous utilisons. On a Random() >= 0. Cela signifie que Random () doit être plus grand ou égal à 0 pour que la condition soit vraie. Vous pouvez comparer les valeurs de différentes manières. Voici les plus importantes:
== // Égal
< // Plus petit que
<= // Plus petit ou égal
> // Plus grand que
>= // plus grand ou égal
!= // Différent
Il est possible de combiner les conditions avec && pour et ou || pour ou. Voici quelques exemples :
true // Toujours vrai
false // Toujours faux
t != 3 // t différent de 3
t > 5 && t < 10 // t compris entre 5 et 10
Notez que l'instruction if a deux parties. La partie immédiatement après la condition, est exécutée lorsque la condition est vraie, et la partie après le else, qui est exécutée lorsque la condition est fausse. Le mot-clé else et la partie qui suit sont facultatives. Donc vous pouvez les omettre si il n'y a rien à faire quand la condition est fausse.
La déclaration do
Il existe une autre structure de contrôle : l'instruction do. Elle a la forme suivante :
do
{
statements;
}
while (condition);
Les instructions entre accolades après l'instruction do sont exécutées tant que la condition entre parenthèses est vraie. La condition a la même forme que dans l'instruction if décrite ci-dessus. Voici un exemple de programme. Le robot se promène au hasard pendant 20 secondes puis s'arrête.
int move_time, turn_time, total_time;
task main()
{
total_time = 0;
do
{
move_time = Random(1000);
turn_time = Random(1000);
OnFwd(OUT_AC, 75);
Wait(move_time);
OnRev(OUT_C, 75);
Wait(turn_time);
total_time += move_time;
total_time += turn_time;
}
while (total_time < 20000);
Off(OUT_AC);
}
Notez également que l'instruction do est presque la même que l'instruction while. Mais dans avec l'instruction while la condition est testée avant l'exécution des déclarations, alors qu'avec l'instruction do la condition est testée à la fin. Pour l'instruction while, les déclarations pourraient ne jamais être exécuté, mais pour l'instruction do elles sont exécutées au moins une fois.
Dostları ilə paylaş: |