Du rythme sans delay

Comment exécuter des tâches à intervalle de temps régulier, sans bloquer le reste du programme principal ?

Pourquoi delay bloque-t-il ?

On souhaite faire clignoter une LED toutes les secondes.

Soit le programme simple suivant :

const int LED_PIN = 13; // LED intégrée
byte ETAT_LED = LOW;
const unsigned long PERIODE = 500; // ms

void setup() {
  pinMode(LED_PIN , OUTPUT);
}

void loop() {
    // On allume/éteint la LED
    digitalWrite(LED_PIN, ETAT_LED);

    // Affichage du temps écoulé (en ms) et lde l'état de la LED
    Serial.print(millis());
    Serial.print("\t");
    Serial.println(ETAT_LED);
    // On change l'état de la LED
    ETAT_LED = !ETAT_LED ;
    
    // On attend ...
    delay(PERIODE);
}

Téléverser ce programme dans l’Arduino

Ouvrir le Moniteur Série

Observer les lignes Temps-État qui s’affichent dans le moniteur série et décrire le phénomène qui se produit au bout d’une certaine durée d’exécution.

Correction

Il apparaît un décalage des événements de changement d’état. Ils devraient se produire toutes les 500 ms et au bout de 20s on a déjà un décalage de 10ms environ.

 

Comment ne pas utiliser delay ?

Pour éviter de bloquer l’exécution du programme, on utilise :

  • la fonction millis() qui donne le temps écoulé depuis le démarrage de l’Arduino au format unsigned long (entier non signé de format long),
  • une constante PERIODE, représentant l’intervalle de temps entre deux tâches à réaliser,
  • et deux variables :
    • t pour mémoriser le temps « courant » donné par millis(),
      • On fait ce relevé le plus fréquemment possible, à chaque exécution de la boucle principale loop().
    • t0 pour mémoriser le dernier instant où la LED a changé d’état :
      • On compare t0 à t pour savoir s’il est temps de réaliser la tâche,
      • On initialise cette variable (on lui affecte la valeur de t) dès que la tâche est réalisée.

Remarque : toutes les variables et constantes représentant un « temps » sont exprimées en millisecondes et doivent être de type unsigned long.

 

const int LED_PIN = 13;
byte ETAT_LED = LOW;
const unsigned long PERIODE = 500; // ms
unsigned long t0 = 0;

void setup() {
  pinMode(LED_PIN , OUTPUT);
  Serial.begin(9600);
}

void loop() {
  unsigned long t = millis();
  if (t-t0 >= PERIODE) {
    t0 = t;
    // On allume.éteint la LED
    digitalWrite(LED_PIN, ETAT_LED);

    // Affichage du temps écoulé (en ms) et lde l'état de la LED 
    Serial.print(millis()); 
    Serial.print("\t"); 
    Serial.println(ETAT_LED);
    
    // On change l'état de la LED
    ETAT_LED = !ETAT_LED ;
  }
}

 

Vous aimerez aussi...

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *