30 | | |
31 | | Nous voulons aussi expérimenter la programmation "multi-tâches". Les guillemets expriment le fait qu'il s'agit plus d'une structure du programme que d'une vraie programmation multi-tâches dans la mesure où il n'y a pas de système d'exploitation. Toutefois, les "tâches" seront programmées de sorte à être indépendantes de leur contexte d'utilisation et elles seront "ordonnancées" par la fonction loop(). |
| 30 | - Le port SPI qui relie le module au NRF |
| 31 | |
| 32 | == Démarrage |
| 33 | |
| 34 | La première chose est d'exécuter l'exemple `blink`` |
| 35 | - Brancher le module Arduino avec le câble USB |
| 36 | - lancer : `/opt/arduino-1.6.8/arduino &` |
| 37 | - Sélectionner : `Tools -> Boards -> Arduino Nano` |
| 38 | - Sélectionner : `Tools -> Processor -> ATmega328` |
| 39 | - Sélectionner : `Tools -> Ports -> /dev/ttyUSB0 ou /dev/ttyUSB1` |
| 40 | - Charger le programme Blink : `File -> Exemples -> 0.1 Basics -> Blink` |
| 41 | - Cliquer sur l'icône en forme de V pour Compiler |
| 42 | - Cliquer sur l'icône en forme de -> pour uploader |
| 43 | - En bas de la fenêtre un message vous indique la réussite de la compilation et de l'upload. |
| 44 | - La led doit clignoter sur le module |
| 45 | |
| 46 | Changer la fréquence et tester. |
35 | | Nous allons donc voir comment il est possible de programmer des applications multi-tâches coopératives dans l'environnement Arduino sans pour autant disposee des services d'un OS. Le code a été volontairement simplifié à l'extrême afin de bien comprendre le principe. ICI, toute l'application sera dans un seul fichier et nous n'allons pas utiliser la programmation objet pour ne pas complexifier (mais nous le ferons plus tard). |
36 | | |
37 | | Chaque tâche est représentée par une fonction qui code son comportement. |
38 | | Dans l'environnement Arduino, la fonction loop() s'exécute en boucle, c'est elle qui va séquencer l'exécution des tâches. |
39 | | La fonction loop() demande donc l'exécution des tâches à tour de rôle. |
| 50 | Il est possible de programmer des applications multi-tâches coopératives dans l'environnement Arduino sans pour autant dispose des services d'un OS. Le code a été volontairement simplifié à l'extrême afin de bien comprendre le principe. ICI, toute l'application sera dans un seul fichier et nous n'allons pas utiliser la programmation objet pour ne pas complexifier. |
| 51 | |
| 52 | Chaque tâche est représentée par une fonction `loop_Tache()` qui code son comportement. |
| 53 | Dans l'environnement Arduino, la fonction `loop()` s'exécute en boucle, c'est elle qui va séquencer l'exécution des fonction `loop_Tache()`. |
| 54 | La fonction `loop()` demande donc l'exécution des fonction `loop_Tache()` à tour de rôle. |
52 | | Pour les tâches périodiques, nous pouvons écrire une fonction qui exploite un timer interne du processeur qui s'incrémente chaque microseconde. Cette fonction nommée `waitFor(int timer, unsigned long period)` prend deux paramètres `timer` et `period`. Le premier un numéro de timer (il en faudra autant que de tâches périodiques). Le second est une période en microsecondes. |
| 68 | Dans le cas plus général, les tâches ont un contexte d'exécution représenté par une variable globale sous forme d'une structure. Cette structure est passée en argument de la tâche. Cette structure doit le plus souvent être initialisée. L'initialisation est faite par une seconde fonction `setup_Tache()`, laquelle doit être appelée par la fonction `setup()`. |
| 69 | |
| 70 | Pour les tâches périodiques (elles sont fréquentes), nous pouvons écrire une fonction qui exploite un timer interne du processeur qui s'incrémente chaque microseconde. Cette fonction nommée `waitFor(int timer, unsigned long period)` prend deux paramètres `timer` et `period`. Le premier un numéro de timer (il en faudra autant que de tâches périodiques). Le second est une période en microsecondes. |
86 | | void Led(int timer, long period, byte led) { |
87 | | static byte val = 0; // valeur à mettre sur la led |
88 | | if (!waitFor(timer,period)) return; // sort s'il y a moins d'une période écoulée |
89 | | digitalWrite(led,val); // ecriture |
90 | | val = 1 - val; // changement d'état |
91 | | } |
92 | | |
93 | | void Mess(int timer, long period, const char * mess) { |
94 | | if (!(waitFor(timer,period))) return; // sort s'il y a moins d'une période écoulée |
95 | | Serial.println(mess); // affichage du message |
96 | | } |
| 105 | //--------- définition de la tache Led |
| 106 | |
| 107 | typedef struct Led_st { |
| 108 | int timer; // numéro de timer utilisé par WaitFor |
| 109 | int period; // periode de clignotement |
| 110 | int pin; // numéro de la broche sur laquelle est la LED |
| 111 | int etat; // etat interne de la led |
| 112 | } Led_t ; |
| 113 | |
| 114 | void setup_Led( Led_t * ctx, int timer, long period, byte pin) { |
| 115 | ctx->timer = timer; |
| 116 | ctx->period = period; |
| 117 | ctx->pin = pin; |
| 118 | ctx->etat = 0; |
| 119 | pinMode(pin,OUTPUT); |
| 120 | digitalWrite(pin, ctx->etat); |
| 121 | } |
| 122 | |
| 123 | void loop_Led(Led_t * ctx) { |
| 124 | if (!waitFor(ctx->timer, ctx->period)) return; // sort s'il y a moins d'une période écoulée |
| 125 | digitalWrite(ctx->pin,ctx->etat); // ecriture |
| 126 | ctx->etat = 1 - ctx->etat; // changement d'état |
| 127 | } |
| 128 | |
| 129 | //--------- definition de la tache Mess |
| 130 | |
| 131 | typedef struct Mess_st { |
| 132 | int timer; // numéro de timer utilisé par WaitFor |
| 133 | int period; // periode d'affichage |
| 134 | char mess[20]; |
| 135 | } Mess_t ; |
| 136 | |
| 137 | void setup_Mess(Mess_t * ctx, int timer, long period, const char * mess) { |
| 138 | ctx->timer = timer; |
| 139 | ctx->period = period; |
| 140 | strcpy(ctx->mess, mess); |
| 141 | Serial.begin(9600); // initialisation du débit de la liaison série |
| 142 | } |
| 143 | |
| 144 | void loop_Mess(Mess_t *ctx) { |
| 145 | if (!(waitFor(ctx->timer,ctx->period))) return; // sort s'il y a moins d'une période écoulée |
| 146 | Serial.println(ctx->mess); // affichage du message |
| 147 | } |
| 148 | |
| 149 | //--------- Déclaration des tâches |
| 150 | |
| 151 | Led_t led1; |
| 152 | Mess_t mess1; |
| 153 | |
| 154 | //--------- Setup et Loop |
154 | | - Vous allez reprendre le programme ci-dessus qui fait clignoter la LED et afficher un message périodique sur l'écran Oled et le transformer de sorte à modifier son comportement par des commandes envoyé par l'utilisateur depuis le clavier du PC. |
155 | | |
156 | | - Le programme est en attente d'un commande pour contrôler l'état de la LED et le message affiché sur l'écran Oled. Les commandes pourraient être : |
157 | | - A : met la lED en clignotement. |
158 | | - E : éteint la LED. |
159 | | - P message : change le message affiché sur l'écran. |
160 | | |
161 | | Le langage est volontairement simple pour que l'interprétation de la commande soit simple. |
162 | | Commencez par les commandes de la LED |
163 | | |
164 | | Quand cela marche ajouter la commande de message. |
165 | | |
166 | | - Pour la tâche qui lit le clavier vous avez deux possibilités. Un tâche "normale" qui est ordonnancée par la fonction loop() ou une tâche dont l'exécution est déclenchée par l'arrivée d'un caractère. En effet, l'arrivée d'un caractère déclenche une interruption, il est possible de programmer une routine d'interruption ISR (Interrupt Service Routine). Faites une tâche "normale" et tenter de faire une tâche ISR. |
167 | | |
168 | | |
169 | | |
170 | | |
171 | | |
172 | | |
173 | | |
174 | | |
175 | | |
176 | | |
177 | | == Récupération de la bibliothèque du NRF24L01 == |
178 | | |
179 | | Si nous voulons continuer à cross compiler, il faut installer la librairie qui va permettre de contrôler le module NRF24L01. Il existe plusieurs librairies. Celle choisie à le mérite d'être disponible dans l'environnement !RaspberryPi et !Arduino. C'est-à-dire que lorsque vous aurez compris comment l'utiliser avec la !RaspberryPi, le passage sur Arduino sera facile. |
| 220 | - Ajouter une tâche qui lit toutes les 0,5 seconde le port analogique 15 (par `analogRead()`) sur lequel se |
| 221 | trouve la photo-résistance et qui sort sa valeur dans une boite à lettre. |
| 222 | - Mofifier la tâche Led pour que la fréquence de clignotement soit inversement proportionnel à la lumière reçue |
| 223 | (moins il y a de lumière plus elle clignote vite). La tâche Led devra donc se brancher sur la boite à lettre. |
| 224 | |
| 225 | ◊{{{#!protected |
| 226 | = Utilisation du module NRG24L01 |
| 227 | |
| 228 | |
| 229 | == Récupération de la bibliothèque du NRF24L01 |
| 230 | |
| 231 | Si nous voulons continuer à cross compiler, il faut installer la librairie qui va permettre de contrôler le module NRF24L01. Il existe plusieurs librairies. Celle choisie à le mérite d'être disponible dans l'environnement !RaspberryPi et Arduino. C'est-à-dire que lorsque vous aurez compris comment l'utiliser avec la !RaspberryPi, le passage sur Arduino sera facile. |