Changes between Initial Version and Version 1 of SujetTP6-2017


Ignore:
Timestamp:
Mar 24, 2017, 7:10:49 AM (8 years ago)
Author:
franck
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • SujetTP6-2017

    v1 v1  
     1= Programmation Arduino =
     2
     3== Préambule ==
     4
     5Vous devez utiliser la version d'arduino qui se trouve :
     6{{{#!bash
     7> /opt/arduino-1.6.8/arduino
     8}}}
     9
     10Les documents nécessaires se trouvent :
     11- [https://github.com/adafruit/Adafruit_SSD1306 Repository API Ecran OLED]
     12- [https://github.com/adafruit/Adafruit-GFX-Library Repository API Graphique]
     13- [http://www.mon-club-elec.fr/pmwiki_reference_arduino/pmwiki.php?n=Main.ReferenceMaxi Langage Arduino]
     14
     15== Objectif ==
     16
     17Le but de cette séance est de faire de la programmation sur Arduino en utilisant 3 entrées-sorties :
     18- La LED présente sur le module.
     19- L'écran OLED
     20- Le port série qui relie le module et le PC.
     21
     22Nous 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().
     23
     24== Exécution ''multi-tâches'' ==
     25
     26Nous allons docnc voir comment il est possible de programmer des applications multi-tâches coopératives dans l'environnement Arduino sans pour autant alors les services d'un OS. Le code a été volontairement simplifié à l'extrême afin de bien comprendre le principe.
     27
     28Commençons par exprimer les besoins. Dans une applications pour micro-contrôleur, il est nécessaire :
     29- d'exécuter des tâches périodiquement ;
     30- d'exécuter des tâches lorsque des événements surviennent ;
     31- de mesurer le temps séparant deux événements ;
     32- de synchroniser l'exécution de deux tâches (une tâche T1 s'exécute et produit des données qui sont récupérées par une tache T2) ;
     33- etc.
     34
     35Chaque tâche est représentée par une fonction qui code son comportement.
     36Dans l'environnement Arduino, la fonction loop() s'exécute en boucle, c'est elle qui va séquencer l'exécution des tâches.
     37La fonction loop() demande donc l'exécution des tâches à tour de rôle.
     38Les tâches n'ont pas le droit de conserver le processeur sinon celà crée un blocage du système.
     39La structure générale d'une tâche est la suivante :
     40
     41{{{#!c
     42void tache(arguments) {
     43   // test de la condition d'exécution
     44   if (evement_attendu_absent) return;
     45   // code de la tache
     46   ....
     47}
     48}}}
     49
     50Pour 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érioodiques). Le second est une période en microsecondes.
     51
     52`wairFor()` peut être appelée aussi souvent que nécessaire, elle rend 1 une seule fois par période (second paramètre).
     53Si elle n'est pas appelée pendant longtemps alors elle rend le nombre de périodes qui se sont écoulées.
     54
     55Dans l'application suivante nous avons deux tâches périodiques `Led()` et `Mess()`.
     56La première fait clignoter une led dont le numéro est passé en paramètre à 5Hz.
     57La seconde affiche bonjour à une fois par seconde.
     58{{{#!c
     59// --------------------------------------------------------------------------------------------------------------------
     60// Multi-tâches cooperatives : solution basique
     61// --------------------------------------------------------------------------------------------------------------------
     62
     63// unsigned int waitFor(timer, period)
     64// Timer pour taches périodique
     65// arguments :
     66//  - timer  : numéro de timer entre 0 et MAX_WAIT_FOR_TIMER-1
     67//  - period : période souhaitée
     68// retour :
     69//  - nombre de période écoulée depuis le dernier appel
     70//
     71#define MAX_WAIT_FOR_TIMER 16
     72unsigned int waitFor(int timer, unsigned long period){
     73  static unsigned long waitForTimer[MAX_WAIT_FOR_TIMER];
     74  unsigned long newTime = micros() / period;              // numéro de la période modulo 2^32
     75  int delta = newTime - waitForTimer[timer];              // delta entre la période courante et celle enregistrée
     76  if ( delta < 0 ) delta += 1 + (0xFFFFFFFF / period);    // en cas de dépassement du nombre de périodes possibles sur 2^32
     77  if ( delta ) waitForTimer[timer] = newTime;             // enregistrement du nouveau numéro de période
     78  return delta;
     79}
     80
     81void Led(int timer, long period, byte led) {
     82  static byte val = 0;                                    // valeur à mettre sur la led
     83  if (!waitFor(timer,period)) return;                     // sort s'il y a moins d'une période écoulée
     84  digitalWrite(led,val);                                  // ecriture
     85  val = 1 - val;                                          // changement d'état
     86}
     87
     88void Mess(int timer, long period, const char * mess) {
     89  if (!(waitFor(timer,period))) return;                   // sort s'il y a moins d'une période écoulée
     90  Serial.println(mess);                                   // affichage du message
     91}
     92
     93void setup() {
     94  pinMode(13,OUTPUT);                                     // initialisation de la direction de la broche
     95  Serial.begin(115200);                                   // initialisation du débit de la liaison série
     96}
     97
     98void loop() {
     99  Led (0,100000,13);                                      // Led est exécutée toutes les 100ms
     100  Mess(1,1000000,"bonjour");                              // Mess est exécutée toutes les secondes
     101}
     102}}}
     103
     104== Utilisation de l'écran ==
     105
     106Nous allons utiliser un écran OLED connecté en I2C, 128x32 **ssd1306**
     107- La bibliothèque de l'écran se trouve en tapant la requête `ssd1306 arduino`[[BR]] à l'adresse   
     108  [https://github.com/adafruit/Adafruit_SSD1306].
     109  Vous devrez prendre également la bibliothèque GFX à l'adresse [https://github.com/adafruit/Adafruit-GFX-Library]
     110  qui est la bibliothèque graphique.   
     111- Vous pouvez exécuter l'exemple proposé dans la bibliothèque. Cette bibliothèque fonctionne pour plusieurs
     112  types modèles. Vous allez choisir le bon exemple : 128x32 I2C.
     113
     114**Questions** :
     115- Quel est le numéro de l'abonné I2C de l'écran ?
     116- Modifier le programme initial pour afficher "bonjour" sur l'Oled toutes les 2 secondes sans changer le comportement de existant.
     117
     118
     119