Les boucles d'attente : comment les rendre utiles
Nous avons souvent fait des boucles d'attente pour faire patienter, laisser le temps pour lire un message, séquencer des opérations, etc.
Mais si on fait tout simplement avec delay(), notre programme se trouve bloqué pendant le duré de l'attente. Comme ici :
/*
Delai 'normale' Glenn Smith 2014
*/
#define LED 13
unsigned long maintenant = 0;
unsigned long plus_tard = 0;
void setup() {
Serial.begin(9600); // Utiliser la liaison série
pinMode(LED, OUTPUT); // Définir port13 comme SORTIE
maintenant = millis(); // Noter l'heure de début
Serial.print("Debut : millis() = ");
Serial.println(maintenant);
digitalWrite(LED, HIGH); // Allumer la LED
delay(5000); // Attendre 5s
plus_tard = millis(); // Noter l'heure de fin
digitalWrite(LED, LOW); // Eteindre la LED
Serial.print("Fin : millis() = ");
Serial.println(plus_tard);
Serial.print("Temps ecoule = ");
Serial.print(plus_tard - maintenant);
Serial.println(" mS");
// Terminé
}
void loop() {
// loop() est appelé sans cesse, c'est une boucle sans fin
}
Si on voulait, par exemple, tester une valeur analogique ou faire clignoter une LED - ou tout simplement lire une entrée numérique (appui sur un bouton) - c'est raté.
Un technique est de faire une boucle constitué de plusieurs attentes de périodes plus courtes. Mais on perd rapidement notre latin (surtout moi), dans un truc pareil.
Voici un autre façon de faire :
/*
Delai 'utile' Glenn Smith 2014
*/
#define LED 13
unsigned long debut = 0;
unsigned long plus_tard = 0;
void setup() {
Serial.begin(9600); // Utiliser la liaison série
pinMode(LED, OUTPUT); // Définir port13 comme SORTIE
debut = millis(); // Noter l'heure de début
Serial.print("Debut : millis() = ");
Serial.println(debut);
plus_tard = debut + 5000UL;
digitalWrite(LED, HIGH); // Allumer la LED
do{ } while ( plus_tard > millis() );
digitalWrite(LED, LOW); // Eteindre la LED
Serial.print("Fin : millis() = ");
Serial.println(plus_tard);
Serial.print("Temps ecoule = ");
Serial.print(plus_tard - debut);
Serial.println(" mS");
// Terminé
}
void loop() {
// loop() est appelé sans cesse, c'est une boucle sans fin
}
Et alors ? Je vous entends dire. Oui, c'est vrai : cette exemple n'a rien changé coté fonctionnalité. Mais regarder d'un peu plus près. Nous avons un boucle do..while() dans lequel il est possible de faire autre choses. Comme ici - on peut faire clignoter la LED :
/*
Delai 'plus utile' Glenn Smith 2014
*/
#define LED 13
#define vrai true
#define faux false // Un peu de Français dans ce monde de ...
const unsigned long mille = 1000UL;
unsigned long debut = 0;
unsigned long maintenant = 0;
unsigned long plus_tard = 0;
boolean est_allume = vrai;
void setup() {
Serial.begin(9600); // Utiliser la liaison série
pinMode(LED, OUTPUT); // Définir port13 comme SORTIE
debut = millis(); // Noter l'heure de début
Serial.print("Debut : millis() = ");
Serial.println(debut);
plus_tard = debut + 5000UL; // 5s plus tard !
digitalWrite(LED, est_allume); // Allumer la LED
do{
maintenant = millis();
if ( ( maintenant % mille ) < 10 ) {
// % c'est pour voir le restant aprés division
est_allume = !est_allume; // inverser le valeur vrai/faux
}
digitalWrite(LED, est_allume); // Allumer la LED.. ou pas ?
delay(50);
} while ( plus_tard > maintenant );
digitalWrite(LED, LOW); // Eteindre la LED
Serial.print("Fin : millis() = ");
Serial.println(plus_tard);
Serial.print("Temps ecoule = ");
Serial.print(plus_tard - debut);
Serial.println(" mS");
// Terminé
}
void loop() {
}
Ce n'est pas tout. Le boucle do..while() nous permet plusieurs tests et calculs pendant le temps 'mort'. Ici on fait clignoter la LED -ET- on test une entrée numérique pour arrêter l'attente si un bouton est appuyé.
/*
Delai 'tres tres utile' Glenn Smith 2014
*/
#define LED 13
#define BOUTON 12
#define vrai true
#define faux false
#define SORTIE OUTPUT
#define ENTREE INPUT
#define ENTREE_TIRE_HAUT INPUT_PULLUP // Un peu de Français dans ce monde de ...
const unsigned long mille = 1000UL;
unsigned long debut = 0;
unsigned long maintenant = 0;
unsigned long plus_tard = 0;
boolean est_allume = vrai;
void setup() {
Serial.begin(9600); // Utiliser la liaison série
pinMode(LED, SORTIE); // Définir port13 comme SORTIE
pinMode(BOUTON, ENTREE_TIRE_HAUT); // port12 comme entrée
debut = millis(); // Noter l'heure de début
Serial.print("Debut : millis() = ");
Serial.println(debut);
plus_tard = debut + 10000UL; // 10s plus tard !
digitalWrite(LED, est_allume); // Allumer la LED
do{
maintenant = millis();
if ( ( maintenant % mille ) < 10 ) {
est_allume = !est_allume; // inverser le valeur vrai/faux
digitalWrite(LED, est_allume); // Allumer la LED.. ou pas ?
}
if ( !(digitalRead(BOUTON)) ) break; // Bouton appuyé ?
delay(50);
} while ( plus_tard > maintenant );
digitalWrite(LED, LOW); // Eteindre la LED
Serial.print("Fin : millis() = ");
Serial.println(maintenant);
Serial.print("Temps ecoule = ");
Serial.print(maintenant - debut);
Serial.println(" mS");
// Terminé
}
void loop() {
}
La, ça commence à être utile, non?