Répéter des instructions : les boucles

. Par : Jean-Luc. URL : http://www.locoduino.org/spip.php?article65

Nous allons ajouter une nouvelle corde à notre arc avec les boucles. Une boucle permet d’exécuter de manière répétitive une ou plusieurs instructions. Un premier usage auquel nous pouvons penser est de lire plusieurs capteurs de même nature pour effectuer en conséquence plusieurs actions de même nature. Par exemple supposons que vous vouliez gérer 5 ou 6 ILS avec un Arduino, il est plus concis et plus clair de le faire avec une boucle que de répliquer les instructions pour chacun des ILS.

Le langage permettant de programmer l’Arduino offre 3 types de boucles qui ont chacune un usage.

La boucle while ( ... ) { ... }

La boucle permet de répéter des instructions tant qu’une condition est vraie. Si vous ne savez pas ce qu’est une condition dans le langage de l’Arduino, faites un tour dans l’article « Instructions conditionnelles : le if … else », vous y trouverez toutes les explications nécessaires.

La syntaxe de la boucle while est la suivante :

  1. while (condition) {
  2. // à remplacer par les instructions qui seront
  3. // exécutées tant que la condition est vraie
  4. }

La boucle suivante est celle utilisée pour mettre en œuvre des boucle infinies, celles qui répètent les instructions sans jamais s’arrêter :

  1. while (true) {
  2. // instructions exécutées à l'infini
  3. }

Si la boucle n’est pas infinie, la condition est soit issue de l’extérieur de l’Arduino, soit remise à jour par les instructions que la boucle répète. Sinon elle ne peut pas changer. Ainsi si l’on veut compter combien de temps, en dizaines de millisecondes, la broche 4, configurée en entrée numérique, de l’Arduino est HIGH [1], on pourra écrire :

  1. void loop() {
  2. unsigned long dureePression = 0; // variable pour compter la durée
  3.  
  4. while (digitalRead(4) == HIGH) {
  5. dureePression++;
  6. delay(10);
  7. }
  8.  
  9. Serial.println(dureePression);
  10. }

Si le signal sur la broche 4 n’est pas HIGH Au moment du digitalRead, les deux instructions qui sont dans la boucle ne seront pas exécutées et dureePression restera à 0. Si le signal est HIGH au moment de l’exécution du digitalRead, dureePression sera incrémenté puis après 10ms le signal sera de nouveau testé et ainsi de suite. On voit également que la durée sera comptée de manière optimiste. Pour une durée inférieure à 10ms on retrouvera 1 dans dureePression, pour une durée comprise entre 10ms et 20ms, on retrouvera 2, etc.

Incrémenter consiste à ajouter quelque chose à une variable, généralement 1. Décrémenter est l’action inverse. Pour incrémenter dans le langage Arduino, on peut écrire dureePression = dureePression + 1; ou dureePression++;. -- est l’opérateur de décrémentation.

La boucle do { ... } while (condition);

On a vu dans la boucle while (...) { ... } que si la condition était fausse, les instructions de la boucle ne sont pas exécutées. Parfois, il est nécessaire de faire des calculs pour déterminer la condition. Avec la boucle while (...) { ... } que nous venons de voir, il faudrait calculer une première fois la condition avant la boucle puis une seconde fois, répétitivement, dans la condition de la boucle. Pour éviter la duplication du code de calcul de la condition, il existe un autre type de boucle.

Dans la boucle do { ... } while ( ... ); la condition est testée à la fin de la boucle au lieu d’être testée au début. Les instructions de la boucle sont donc exécutées au moins une fois. La syntaxe est la suivante :

  1. do {
  2. // instructions de la boucle
  3. } while (condition);

Notez le point-virgule obligatoire à la fin du while

La boucle for ( ... ; ... ; ... ) { ... }

La boucle for ( ... ; ... ; ... ) { ... } permet de répéter une séquence d’instructions avec une séquence d’initialisation exécutée avant la boucle, une condition de continuation et une séquence exécutée à la fin des instructions de la boucle.

La syntaxe est la suivante :

  1. for ( initialisation ; condition ; incrementation ) {
  2. // instructions de la boucle
  3. }

Habituellement, l’initialisation consiste à mettre une variable, que l’on appelle compteur de boucle à 0 ; la condition consiste à tester cette variable par rapport à une valeur où la boucle doit s’arrêter ; l’incrémentation consiste à incrémenter cette variable. On trouve donc le plus souvent cette boucle sous cette forme par exemple :

  1. for ( int i = 0 ; i < 10 ; i++ ) {
  2. Serial.println(i);
  3. }

Dans l’ordre d’exécution,, la variable i est déclarée et initialisée à 0. Puis, de manière répétitive, i est comparé à 10 et si il est strictement inférieur, Serial.println(i); est exécuté puis i est incrémenté. Si i est supérieur ou égal à 10, l’exécution du programme continue après la boucle.

La condition étant évaluée avant l’exécution les instructions de la boucle, ces dernières ne sont jamais exécutées si la condition est fausse dès la première évaluation de la condition.

Vous rencontrerez parfois des boucles for où l’initialisation, la condition et l’incrémentation sont vides, comme ceci :

  1. for (;;) {
  2. // instructions de la boucle
  3. }

Cette syntaxe particulière permet, comme le while (true) { ... } que nous avons vu plus haut de mettre en œuvre des boucles infinies.

C’est très exactement de cette manière que le logiciel de base de l’Arduino appelle la fonction loop() répétitivement.

[1Il peut s’agir d’un capteur de présence et cette durée peut renseigner sur la vitesse d’un train par exemple