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



Yüklə 0,51 Mb.
səhifə3/4
tarix29.10.2017
ölçüsü0,51 Mb.
#19862
1   2   3   4

Comme avec la fonction PlayFileEx, le NXT n'attend pas la fin de la note pour passer à autre chose. Donc si vous utilisez plusieurs notes à la suites, vous devrez mettre de l'attente entre les deux comme dans l'exemple suivant :

#define VOL 3

task main()

{

PlayToneEx(262,400,VOL,FALSE); Wait(500);



PlayToneEx(294,400,VOL,FALSE); Wait(500);

PlayToneEx(330,400,VOL,FALSE); Wait(500);

PlayToneEx(294,400,VOL,FALSE); Wait(500);

PlayToneEx(262,1600,VOL,FALSE); Wait(2000);

}

Vous pouvez créer très facilements des morceaux de musique avec les fonctionnalités de BricxCC.



Si vous voulez jouer de la musique tout faisant avancer le robot, la meilleure façon est d'utiliser des tâches distinctes. Ici vous avez un exemple d'un programme plutôt stupide où le robot avance en avant et en arrière, en faisant de la musique.

task music()

{

while (true)



{

PlayTone(262,400); Wait(500);

PlayTone(294,400); Wait(500);

PlayTone(330,400); Wait(500);

PlayTone(294,400); Wait(500);

}

}



task movement()

{

while(true)



{

OnFwd(OUT_AC, 75); Wait(3000);

OnRev(OUT_AC, 75); Wait(3000);

}

}



task main()

{

Precedes(music, movement);



}

Conclusion

Dans ce chapitre, vous avez apprit à faire jouer de la musique au NXT. Vous avez aussi vu comment utiliser une tâche distincte pour jouer de la musique.

Plus sur les moteurs

Il y a beaucoup de fonctions qui vous permettent de contrôler les moteurs plus précisément. Dans ce chapitre, nous allons traiter de ces commandes : ResetTachoCount , Coast( Float )OnFwdRegOnRevRegOnFwdSyncOnRevSyncRotateMotorRotateMotorEx et les concepts de PID.



Arrêt en douceur

Quand on utilise la fonction Off (), le cerveau moteur s'arrête immédiatement, freinant l'arbre et tenant donc position. Il est aussi possible de stopper les moteurs d'une manière plus douce, sans utiliser le frein. Pour cela il faut utiliser Float() ou Coast(), qui coupe simplement la puissance du moteur. Voici un exemple. Le moteur commence par freiner en utilisant les freins; ensuite sans utiliser les freins. Notez la différence. Actuellement, la différence est extrêmement faible pour ce robot en particulier. Mais cela crée beaucoup de différence pour beaucoup d'autres robots.

task main()

{

OnFwd(OUT_AC, 75);



Wait(500);

Off(OUT_AC);

Wait(1000);

OnFwd(OUT_AC, 75);

Wait(500);

Float(OUT_AC);

}

Les commandes avancées

Les commandes OnFwd() et OnRev() sont de simples routines pour faire bouger les moteurs.

Les servomoteurs du NXT contiennent un encodeur intégré qui vous permet de contrôler précisément la position et la vitesse de l'arbre;

Le firmware du NXT met en oeuvre un PID ( Proportional Integrative Derivative) pour contrôler la position des moteurs et la vitesse des moteurs. Cela permet de contrôler plus précisément la vitesse des moteurs, leur position et de faire des feedback.

Si vous voulez que le robot aille parfaitement droit, vous pouvez utiliser une fonctione de synchronisation qui fait que le couple de moteurs tournent ensemble et s'attendent si l'un ralentit ou est bloqué. D'une façon simple, vous pouvez définir un couple de moteur pour qu'il soient synchronisés. Il y a aussi de nombreuses commandes pour libérer toute la puissance des cerveau-moteurs.

La fonction OnFwdReg(port,speed,regmode) fait avancer le moteur spécifié par port à la vitesse speed en appliquant le mode de régulation regmode spécifié. regmode peut êtreOUT_REGMODE_IDLEOUT_REGMODE_SPEED ou OUT_REGMODE_SYNC. Si IDLE est sélectionné, il n'y aura pas de régulation PID d'appliqué. Si SPEED est sélectionné, le NXT va réguler LE moteur pour qu'il ai une vitesse constante, même si la charge moteur varie. Pour finir, si SYNC est sélectionné, le couple de moteurs spécifié par port se déplacera synchronisé comme expliqué avant.

La fonction OnRevReg(port,speed,regmode) fait exactement la même chose que la commande précédente mais dans le sens inverse.

task main()

{

OnFwdReg(OUT_AC,50,OUT_REGMODE_IDLE);



Wait(2000);

Off(OUT_AC);

PlayTone(4000,50);

Wait(1000);

ResetTachoCount(OUT_AC);

OnFwdReg(OUT_AC,50,OUT_REGMODE_SPEED);

Wait(2000);

Off(OUT_AC);

PlayTone(4000,50);

Wait(1000);

OnFwdReg(OUT_AC,50,OUT_REGMODE_SYNC);

Wait(2000);

Off(OUT_AC);

}

Ce programme montre très bien les différentes régulation si vous essayez de stopper les roues avec votre main. Pour le premier ( le mode IDLE ), si vous stopper une roue, cela de fera rien sur l'autre. Pour le second ( le mode SPEED ), essayer de ralentir la roue, vous verrez que le NXT augmentera la puissance de son moteur pour contrecarrer votre freinage afin de garder la vitesse constante. Enfin (pour le mode SYNC), arrêter une roue fera arrêter l'autre jusqu'à ce que la première soit débloquée.



La fonction OnFwdSync(port,speed,turnpct) est la même que la fonction OnFwdReg() avec le mode SYNC, mais maintenant vous pouvez spécifier un pourcentage de synchronisation.

La fonction OnRevSync(port,speed,turnpct) est la même que la précédente, mais dans l'autre direction. Le programme suivant fait une démonstration des fonctions : essayez de changer les valeurs pour voir ce qu'il se passe.

task main()

{

PlayTone(5000,30);



OnFwdSync(OUT_AC,50,0);

Wait(1000);

PlayTone(5000,30);

OnFwdSync(OUT_AC,50,20);

Wait(1000);

PlayTone(5000,30);

OnFwdSync(OUT_AC,50,-40);

Wait(1000);

PlayTone(5000,30);

OnRevSync(OUT_AC,50,90);

Wait(1000);

Off(OUT_AC);

}

Pour finir, les moteurs peuvent être configurés pour tourner un nombre défini de degrés ( en se rappelant qu'un tour complet fait 360° ).



Pour chacune des fonctions suivantes, vous pouvez agir sur la direction des moteurs en changeant le signe de la vitesse ou de l'angle. Donc si la vitesse et l'angle on le même signe, le moteur avancera, sinon il reculera.

La fonction RotateMotor(port,speed,degrees) fait tourner le moteur spécifié par port de degrees degrés à une vitesse de speed ( allant de 0 à 100 ).

task main()

{

RotateMotor(OUT_AC, 50,360);



RotateMotor(OUT_C, 50,-360);

}

La fonction RotateMotorEx(port,speed,degrees,turnpct,sync,stop) est une extension de la fonction précédente, ce qui vous permet de synchroniser deux moteurs, de spécifier un facteur turnpct et un booleen pour sync. Cela vous permet aussi de spécifier si le moteur doit freiner apres la rotation de l'angle spécifié en utilisant un dernier booleen.



task main()

{

RotateMotorEx(OUT_AC,50,360,0,true,true);



RotateMotorEx(OUT_AC,50,360,40,true,true);

RotateMotorEx(OUT_AC,50,360,-40,true,true);

RotateMotorEx(OUT_AC,50,360,100,true,true);

}

Les PID de contrôle

Le firmware du NXT intègre un contrôleur digital de PID ( Proportional Integrative Derivative ) pour réguler la position et la vitesse des cervau-moteurs avec précision. Ce type de contrôleur est l'un des plus simples et des plus efficaces dans l'automatisme, et est souvent utilisé.

En termes bruts, il fonctionne comme cela :

Votre programme donne au contrôleur un point fixe R(t) à atteindre, celui-ci démarre le moteur avec une commande U(t), mesure sa position Y(t) grâce au calculateur intégré et calcule une erreur E(t) = R(t) - Y(t): voici pourquoi il est appelé "contrôleur en boucle fermée", parce que la position de sortie Y(t) est ramené à l'entrée du contrôleur pour le calcul de l'erreur. Le contrôleur transforme l'erreur E(t) dans la commande U(t) ainsi:

U(t) = P(t) + I(t) + D(t)

Avec :

P(t) = K_P*E(t)



I(t) = K_I*( I(t-1) + E(t) )

D(t) = K_D*( E(t) - E(t-1) )

Cela peut sembler compliqué pour un novice, mais je vais essayer d'expliquer le mécanisme du mieux que je peux.

La fonction est la somme de trois parties : la partie proportionnelle P(t), la partie intégrative I(t) et la partie dérivative D(t).

P(t) rend le contrôleur plus rapide dans le temps mais il n'assure pas qu'il n'y ai aucune erreur d'équilibrage.

I(t) donne de la "mémoire" au contrôleur, dans un sens il accumules les traces d'erreurs et les compense, avec un zéro erreur de moyenne garantie.

D(t) donnes les "prédiction futures" au contrôleur ( comme la dérivée en maths ), ce qui accélère la réponse.

Je comprend que ça peut rester confus. Mais on peut maintenant le tester ensemble pour mieux comprendre. Le programme simple qui suit va nous y aider.

#define P 50

#define I 50

#define D 50

task main(){

RotateMotorPID(OUT_A, 100, 180, P, I, D);

Wait(3000);

}

La fonction RotateMotorPID ( port , speed , Pgain , Igain , Dgain ) vous permet de régler les valeurs des différents gains autrement que celles par défaut. Essayer de définir les valeur suivantes :



- ( 50 , 0 , 0 ) : le moteur ne tourne pas exactement à 180°, car il reste une erreur non compensée

- ( 0 , x , x ) : sans partie proportionnelle, l'erreur est énorme.

- ( 40 , 40 , 0 ) : il ya un dépassement, cela signifie que les mouvements de l'arbre du moteur vont au-delà du point voulu, il va donc faire demi-tour.

- ( 40 , 40 , 90 ) : bonne précision et rapide ( pour le temps à atteindre le point voulu )

- ( 40 , 40 , 200 ) : l'arbre moteur oscille car le gain de dérivée est trop élevé.

Essayez d'autres valeur pour comprendre comment ces gains influences les performances du moteur.



Conclusion

Dans ce chapitre avez appris des choses à propos des commandes avancées des moteurs : Float() , Coast() qui stoppent les moteurs doucement; OnXxxReg() et OnXxxSync() qui permettent de contrôler le retour des moteurs, la vitesse et la synchronisation; RotateMotor() et [[[RotateMotorEx]]]() qui sont utilisés pour tourné l'arbre du moteur d'un nombre précis de degrés. Vous avez aussi appris quelque chose à propos du contrôle PID. il n'a peut-être pas eu d'explications exhaustives, mais peut-être cela à créé un peu de curiosité en vous: recherchez sur le web !

Plus sur les capteurs

Nous avons déjà utilisé les capteurs dans un chapitre précédent. Mais vous pouvez faire beaucoup plus de choses avec les capteurs. Dans ce chapitre, nous allons voir les différences entre les différents modes et les différents types des capteurs, on va aussi voir comment utiliser les vieux capteurs compatible RCX en le connectant au NXT via un câble convertisseur.



Modes et types des capteurs

La fonction SetSensor() que nous avons vu avant fait actuellement deux choses : il défini le type de capteurs et défini le mode dans lequel le capteur opère. En configurant le mode et le type du capteur séparément, on peut contrôler le comportement du capteur avec plus de précision, ce qui est très pratique pour certaines applications.

Le type du capteur est défini grâce à la fonction SetSensorType(). Il y a beaucoup de types différents, mais on va voir les principaux : SENSOR_TYPE_TOUCH, le capteur tactile,SENSOR_TYPE_LIGHT_ACTIVE, le capteur de couleur ( avec les DELs allumées ), SENSOR_TYPE_SOUND_DB, le capteur sonore et SENSOR_TYPE_LOWSPEED_9V, le capteur à ultrasons. Définir le type de capteur est particulièrement important pour indiquer si le capteur à besoin d'énergie ( pour allumer les DELs du capteur de couleur par exemple ), ou pour indiquer au NXT que le capteur est digital et à besoin d'être lu via le protocole IC en série. C'est possible d'utiliser les vieux capteur RCX avec le NXT : SENSOR_TYPE_TEMPERATURE, pour le capteur de température, SENSOR_TYPE_LIGHT pour le vieux capteur de couleur, SENSOR_TYPE_ROTATION pour le capteur RCX de rotation ( on en parlera plus tard ).

Le mode du capteur est défini grâce à la fonction SetSensorMode(). Il y a huit différents modes. Le plus important est SENSOR_MODE_RAW. Dans ce mode, la valeur que vous recevez du capteur est un nombre entre 0 et 1023. C'est la valeur brut produite par le capteur. La signification dépend du capteur. Par exemple, pour un capteur tactile, quand le capteur n'est pas enfoncé, la valeur est proche de 1023. Quand il est complètement enfoncé, la valeur est proche de 50. Quand il est partiellement enfoncé, la valeur est entre 50 et 1000. Donc si vous définissez le mode RAW, vous pouvez savoir s'il est partiellement enfoncé. Avec le capteur de couleur, la valeur varie entre 300 ( beaucoup de lumière ) et 800 ( très sombre ). Cela donne une valeur plus précise que d'utiliser la fonction SetSensor(). Pour plus de détail, regardez le guide de programmation NXC.

Le deuxième mode est SENSOR_MODE_BOOL. Avec ce mode, la valeur retournée est 0 ou 1. Quand la valeur du mode RAW est en dessous de 562 la valeur est 0, sinon la valeur est 1.SENSOR_MODE_BOOL est la valeur par défaut du capteur tactile, mais il peut être utilisé pour d'autres capteurs qui renvoient des valeurs analogiques. Les modesSENSOR_MODE_CELCIUS et SENSOR_MODE_FAHRENHEIT ne sont utiles qu'avec les capteurs de températures. SENSOR_MODE_PERCENT convertit la valeur brut en une valeur comprise entre 0 et 100. SENSOR_MODE_PERCENT est le mode par défaut du capteur de couleur. SENSOR_MODE_ROTATION n'est utilisé qu'avec le capteur de rotation.

Il y a deux autres modes intéressants : SENSOR_MODE_EDGE et SENSOR_MODE_PULSE. Ils comptent le nombre de transitions entre une valeur faible et une valeur élevée ou opposée. Par exemple, quand on touche un capteur tactile, cela cause une transition d'une valeur haute à une valeur basse. Quand on le relâche, cela crée une autre transition. Quand vous définissez le mode à SENSOR_MODE_PULSE, seules les transition de faibles à élevées sont comptées. Donc chaque pression et relâchement comptent pour une seule fois. Quand vous définissez le mode à SENSOR_MODE_EDGE, chaque transitions sont comptées. Donc chaque pression et relâchement comptent pour deux fois. Quand vous comptez les pressions ou impulsions, vous devez reinitialiser les compteurs à 0. Vous pouvez le faire grâce à la fonction ClearSensor(), vous réinitialisez le compteur indiqué à 0.

Regardons un exemple. Le programme suivant utilise le capteur tactile pour diriger le robot. Connectez le capteur tactile avec un long câble à l'entrée une. Si vous pressez deux fois, le robot recule. Si vous le pressez une fois, il s'arrête de bouger.

task main()

{

SetSensorType(IN_1, SENSOR_TYPE_TOUCH);



SetSensorMode(IN_1, SENSOR_MODE_PULSE);

while(true)

{

ClearSensor(IN_1);



until (SENSOR_1 > 0);

Wait(500);

if (SENSOR_1 == 1) {Off(OUT_AC);}

if (SENSOR_1 == 2) {OnFwd(OUT_AC, 75);}

}

}

Notez que nous commençons par définir le type et ensuite le mode. C'est essentiel car changer le type affecte le mode.



Capteur de rotation

Le capteur de rotation est un type de capteur très utile. Le capteur de rotation possède un trou dans lequel vous pouvez passer un axe. Ce qui permettra de mesurer la position angulaire relative. Une rotation complète de l'axe compte 16 étapes ( ou -16 si la rotation se fait dans l'autre sens ), ce qui fait 22,5° l'étape... Loin du respect à 1° près des servomoteurs. L'avantage du vieux capteur est qu'il est très facile à faire tourner alors que les nouveaux nécessitent un couple important.

Si vous avez besoin d'une résolution plus fine que 16 pas par tour, vous pouvez toujours utiliser une démultiplication pour augmenter le nombre de pas par tour.

Une application standard est d'avoir deux capteurs de rotations relié aux deux roues du robot que vous contrôlez avec les deux moteurs. Pour un mouvement rectiligne vous voulez que les deux roues tournent à la même vitesse. Malheureusement, les moteurs ne fonctionnent pas toujours à la même vitesse. En utilisant les capteurs de rotation, vous pouvez voir qu'une roue tourne plus vite. Vous pouvez alors arrêter temporairement un moteur ( en utilisant float ()) jusqu'à ce que les capteurs soient de nouveau à la même vitesse. Le programme qui suit fait cela. Il permet tout simplement au robot d'avancer en ligne droite. Pour l'utiliser, modifier votre robot en reliant les deux capteurs de rotation pour les deux roues. Branchez les capteurs à l'entrée 1 et 3.

task main()

{

SetSensor(IN_1, SENSOR_ROTATION);



ClearSensor(IN_1);

SetSensor(IN_3, SENSOR_ROTATION);

ClearSensor(IN_3);

while (true)

{

if (SENSOR_1 < SENSOR_3) {



OnFwd(OUT_A, 75);

Float(OUT_C);

}

else if (SENSOR_1 > SENSOR_3) {



OnFwd(OUT_C, 75);

Float(OUT_A);

}

else


OnFwd(OUT_AC, 75);

}

}



Le programme indique d'abord que les deux capteurs sont des capteurs de rotation, et les remet à zéro. Ensuite, il commence une boucle infinie. Dans la boucle, nous vérifions que les deux valeurs du capteur sont égales. Si elles le sont, le robot se déplace tout droit. Si l'une est plus grande, le moteur s'arrête jusqu'à ce que les deux valeurs soient à nouveau égales.

Clairement, ce programme est très simple. Vous pouvez étendre ceci pour que le robot fasse une distance très précise.



Mettre plusieurs capteurs sur une entrée

En raison de la nouvelle structure des capteurs NXT et des câbles 6-fils, il n'est pas facile de faire comme avant (comme cela a été fait pour le RCX) pour connecter plusieurs capteurs sur le même port. À mon humble avis, la seule solution fiable serait de construire un capteur tactile multiplexeur analogique à utiliser en combinaison avec un câble convertisseur. L'alternative est un multiplexeur numérique complexe qui permet de gérer la communication I2C avec NXT, mais ce n'est pas vraiment une solution abordable pour les débutants.

Le NXT possède quatre entrées pour connecter des capteurs. Si vous voulez faire des robots plus complexes (et vous avez acheté des capteurs supplémentaires) cela pourrait ne pas être suffisant pour vous. Heureusement, avec quelques astuces, vous pouvez connecter deux (voir plus) capteurs sur une entrée.

Le plus simple est de brancher deux capteurs de contact à une entrée. Si l'un d'eux (ou les deux) est touché la valeur est 1, sinon il est égale à 0. Vous ne pouvez pas distinguer les deux, mais parfois ce n'est pas nécessaire. Par exemple, lorsque vous mettez un capteur tactile à l'avant et un à l'arrière du robot, vous savez que l'on est touché et vous modifiez l'orientation du robot. Mais vous pouvez aussi changer le mode de l'entrée à RAW ce qui vous permet d'obtenir beaucoup plus d'informations. Si vous êtes chanceux, la valeur lorsqu'un capteur sera pressé ne sera pas la même pour les deux capteurs. Si tel est le cas, vous pouvez effectivement faire la distinction entre les deux capteurs. Et quand les deux sont pressés vous obtenez une valeur beaucoup plus faible (environ 30) de sorte que vous pouvez également le détecter.

Vous pouvez également connecter un capteur tactile et un capteur de lumière à une entrée (capteurs RCX seulement). Définissez le type de ce port comment capteur de lumière (sinon le capteur de lumière ne fonctionne pas). Sélectionnez le mode RAW. Dans ce cas, lorsque le capteur de contact est poussée vous obtenez une valeur RAW inférieure à 100. Si ce n'est pas poussé, vous obtenez la valeur du capteur de lumière, qui n'est jamais en dessous de 100. Le programme suivant utilise cette idée. Le robot doit être équipé d'un capteur de lumière orienté vers le bas, et un pare-chocs à l'avant relié à un capteur tactile. Connectez les deux capteurs à l'entrée 1. Le robot avancera au hasard dans une zone. Lorsque le capteur de lumière voit une ligne sombre ( valeur RAW > 750) il recule un peu. Lorsque le capteur tactile touche quelque chose (valeur RAW inférieure à 100), il fait la même chose. Voici le programme:

mutex moveMutex;

int ttt,tt2;

 

task moverandom()



{

while (true)

{

ttt = Random(500) + 40;



tt2 = Random();

Acquire(moveMutex);

if (tt2 > 0) {

OnRev(OUT_A, 75);

OnFwd(OUT_C, 75);

Wait(ttt);

}

else {


OnRev(OUT_C, 75);

OnFwd(OUT_A, 75);

Wait(ttt);

}

ttt = Random(1500) + 50;



OnFwd(OUT_AC, 75);

Wait(ttt);

Release(moveMutex);

}

}



 

task submain()

{

SetSensorType(IN_1, SENSOR_TYPE_LIGHT);



SetSensorMode(IN_1, SENSOR_MODE_RAW);

while (true)

{

if ((SENSOR_1 < 100) || (SENSOR_1 > 750))



{

Acquire(moveMutex);

OnRev(OUT_AC, 75); Wait(300);

Release(moveMutex);

}

}

}



 

task main()

{

Precedes(moverandom, submain);



}

J'espère que le programme est clair. Il ya deux tâches. La tâche moverandom fait bouger le robot d'une manière aléatoire. La tâche principale démarre en premier moverandom, définit le capteur, puis attend que quelque chose se passe. Si la valeur capteur est trop basse (touché) ou trop élevé (sur la zone blanche), il arrête les mouvements aléatoires, recule un peu, et recommence les mouvements aléatoires.



Conclusion

Dans ce chapitre, nous avons vu un certain nombre de solutions supplémentaires sur les capteurs. Nous avons vu comment régler séparément le type et le mode d'un capteur et comment cela pourrait être utilisé pour obtenir des informations supplémentaires. Nous avons appris à utiliser les capteurs de rotation. Et nous avons vu comment de multiples capteurs peuvent être connectés à une unique entrée du NXT. Tous ces trucs sont très utiles lors de la construction de robot plus complexes dans lesquels les capteurs jouent toujours un rôle primordial.

Les taches parallèles

Comme cela a été indiqué précédemment, les tâches sont exécutées simultanément NXC, ou en parallèle. Cela est extrêmement utile. Cela vous permet d'observer les capteurs dans une tâche tout en exécutant une autre tâche qui s'occupe du déplacement du robot. Mais les tâches parallèles peuvent aussi causer des problèmes. Une tâche peut interférer avec une autre.



Yüklə 0,51 Mb.

Dostları ilə paylaş:
1   2   3   4




Verilənlər bazası müəlliflik hüququ ilə müdafiə olunur ©muhaz.org 2024
rəhbərliyinə müraciət

gir | qeydiyyatdan keç
    Ana səhifə


yükləyin