Interruptions et minuteries ESP8266 utilisant l’IDE Arduino (NodeMCU)

Interruptions et minuteries ESP8266 utilisant l'IDE Arduino (NodeMCU)

Dans ce guide, vous apprendrez à utiliser les interruptions et les minuteries avec le NodeMCU ESP8266 à l’aide de l’IDE Arduino. Les interruptions vous permettent de détecter les changements dans l’état GPIO sans avoir besoin de vérifier constamment sa valeur actuelle. Avec les interruptions, lorsqu’un changement est détecté, un événement est déclenché (une fonction est appelée).

Interruptions et minuteries avec ESP8266 à l'aide de l'IDE Arduino (NodeMCU)

Par exemple, nous détecterons un mouvement à l’aide d’un capteur de mouvement PIR : lorsqu’un mouvement est détecté, l’ESP8266 démarre une minuterie et allume une LED pendant un nombre prédéfini de secondes. Lorsque le compte à rebours est terminé, la LED s’éteint automatiquement.

Pour créer une interruption, appelez attachInterrupt() et passez en arguments la broche d’interruption GPIO, l’ISR (fonction à appeler) et le mode. La fonction ISR doit avoir la ICACHE_RAM_ATTR attribut déclaré. Le mode peut être MONNAIE, EN HAUSSE ou CHUTE.

attachInterrupt(digitalPinToInterrupt(GPIO), ISR, mode);

Avant de poursuivre ce didacticiel, vous devez avoir installé le module complémentaire ESP8266 dans votre IDE Arduino. Suivez ce tutoriel pour installer ESP8266 dans l’IDE Arduino, si vous ne l’avez pas déjà fait.

Présentation des interruptions ESP8266

Les interruptions sont utiles pour faire en sorte que les choses se produisent automatiquement dans les programmes de microcontrôleur et peuvent aider à résoudre les problèmes de synchronisation.

Avec les interruptions, vous n’avez pas besoin de vérifier constamment la valeur actuelle de la broche. Lorsqu’un changement est détecté, un événement est déclenché – une fonction est appelée. Cette fonction est appelée routine de service d’interruption (ISR).

Lorsqu’une interruption se produit, le processeur arrête l’exécution du programme principal pour exécuter une tâche, puis revient au programme principal comme indiqué dans la figure ci-dessous.

Présentation des interruptions ESP8266 NodeMCU : comment cela fonctionne

Ceci est particulièrement utile pour déclencher une action à chaque détection de mouvement ou à chaque appui sur un bouton poussoir sans avoir besoin de vérifier constamment son état.

Fonction attachInterrupt()

Pour définir une interruption dans l’IDE Arduino, vous utilisez le attachInterrupt() fonction, qui accepte comme arguments : la broche d’interruption GPIO, le nom de la fonction à exécuter et le mode :

attachInterrupt(digitalPinToInterrupt(GPIO), ISR, mode);

Broche d’interruption GPIO

Le premier argument est une interruption GPIO. Tu devrais utiliser digitalPinToInterrupt(GPIO) pour définir le GPIO réel comme broche d’interruption. Par exemple, si vous souhaitez utiliser GPIO 14 comme interruption, utilisez :

digitalPinToInterrupt(14)

L’ESP8266 prend en charge les interruptions dans n’importe quel GPIO, sauf GPIO16.

ISR

Le deuxième argument du attachInterrupt() fonction est le nom de la fonction qui sera appelée chaque fois que l’interruption est déclenchée – la routine de service d’interruption (ISR).

La fonction ISR doit être aussi simple que possible, afin que le processeur revienne rapidement à l’exécution du programme principal.

La meilleure approche consiste à signaler au code principal que l’interruption s’est produite en utilisant une variable globale et dans le boucler() vérifiez et effacez cet indicateur, puis exécutez le code.

Les ISR doivent avoir ICACHE_RAM_ATTR avant la définition de la fonction pour exécuter le code d’interruption dans la RAM.

Modes d’interruption

Le troisième argument est le mode et il existe 3 modes différents :

  • MONNAIE: pour déclencher l’interruption chaque fois que la broche change de valeur – par exemple de HIGH à LOW ou LOW à HIGH ;
  • CHUTE: pour quand la broche passe de HIGH à LOW ;
  • EN HAUSSE: se déclencher lorsque la broche passe de LOW à HIGH.

Pour notre exemple, nous utiliserons le mode RISING, car lorsque le capteur de mouvement PIR détecte un mouvement, le GPIO auquel il est connecté passe de LOW à HIGH.

Présentation des minuteries ESP8266

Présentation des minuteurs ESP8266 NodeMCU : comment cela fonctionne

Pour ce didacticiel, nous utiliserons des minuteries. Nous voulons que la LED reste allumée pendant un nombre prédéterminé de secondes après la détection d’un mouvement. Au lieu d’utiliser un retard() fonction qui bloque votre code et ne vous permet pas de faire quoi que ce soit d’autre pendant un nombre déterminé de secondes, nous utiliserons une minuterie.

retard () contre millis ()

le retard() La fonction accepte un seul nombre int comme argument. Ce nombre représente le temps en millisecondes que le programme doit attendre avant de passer à la ligne de code suivante.

delay(time in milliseconds);

Quand vous appelez retard (1000) votre programme s’arrête sur cette ligne pendant 1 seconde. retard() est une fonction bloquante. Les fonctions de blocage empêchent un programme de faire quoi que ce soit d’autre jusqu’à ce que cette tâche particulière soit terminée. Si vous avez besoin que plusieurs tâches se produisent en même temps, vous ne pouvez pas utiliser retard(). Pour la plupart des projets, vous devez éviter d’utiliser des retards et utiliser des minuteries à la place.

En utilisant une fonction appelée millis() vous pouvez renvoyer le nombre de millisecondes qui se sont écoulées depuis le premier démarrage du programme.

millis();

Pourquoi cette fonction est-elle utile ? Parce qu’en utilisant des calculs, vous pouvez facilement vérifier combien de temps s’est écoulé sans bloquer votre code.

Clignotement d’une LED à l’aide de millis() (sans délai)

Si vous n’êtes pas familier avec millis() fonction, nous vous recommandons de lire cette section. Si vous êtes déjà familiarisé avec les minuteries, vous pouvez passer au projet de capteur de mouvement PIR.

L’extrait de code suivant montre comment vous pouvez utiliser le millis() fonction pour créer un projet clignotant. Il allume une LED pendant 1000 millisecondes, puis l’éteint.

/*********
  Rui Santos
  Complete project details at https://www.raspberryme.com  
*********/

// constants won't change. Used here to set a pin number :
const int ledPin =  26;      // the number of the LED pin

// Variables will change :
int ledState = LOW;             // ledState used to set the LED

// Generally, you should use "unsigned long" for variables that hold time
// The value will quickly become too large for an int to store
unsigned long previousMillis = 0;        // will store last time LED was updated

// constants won't change :
const long interval = 1000;           // interval at which to blink (milliseconds)

void setup() {
  // set the digital pin as output:
  pinMode(ledPin, OUTPUT);
}

void loop() {
  // here is where you'd put code that needs to be running all the time.

  // check to see if it's time to blink the LED; that is, if the
  // difference between the current time and last time you blinked
  // the LED is bigger than the interval at which you want to
  // blink the LED.
  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis >= interval) {
    // save the last time you blinked the LED
    previousMillis = currentMillis;

    // if the LED is off turn it on and vice-versa:
    if (ledState == LOW) {
      ledState = HIGH;
    } else {
      ledState = LOW;
    }

    // set the LED with the ledState of the variable:
    digitalWrite(ledPin, ledState);
  }
}

Afficher le code brut

Comment fonctionne le code

Examinons de plus près ce croquis clignotant qui fonctionne sans le retard() fonction (elle utilise la fonction millis() fonction à la place).

Fondamentalement, ce code soustrait le temps enregistré précédent (précédentMillis) à partir de l’heure actuelle (courantMillis). Si le reste est supérieur à l’intervalle (dans ce cas, 1000 millisecondes), le programme met à jour le précédentMillis variable à l’heure actuelle, et allume ou éteint la LED.

if (currentMillis - previousMillis >= interval) {
  // save the last time you blinked the LED
  previousMillis = currentMillis;
  (...)

Étant donné que cet extrait n’est pas bloquant, tout code situé en dehors de cette première instruction if devrait fonctionner normalement.

Vous devriez maintenant être en mesure de comprendre que vous pouvez ajouter d’autres tâches à votre boucler() fonction et votre code continuera à faire clignoter la LED toutes les secondes.

Vous pouvez télécharger ce code sur votre ESP8266 pour le tester. La LED intégrée doit clignoter toutes les secondes.

LED ESP8266 clignotante intégrée (attachée au GPIO 2) à l'aide de Millis

ESP8266 NodeMCU avec capteur de mouvement PIR

Dans cette section, vous apprendrez à détecter un mouvement avec un capteur de mouvement PIR en utilisant des interruptions et des minuteries dans votre code.

Pièces requises

Voici une liste des pièces nécessaires pour terminer ce didacticiel :

Vous pouvez utiliser les liens précédents ou accéder directement à MakerAdvisor.com/tools pour trouver toutes les pièces pour vos projets au meilleur prix !

1643663528 164 Interruptions et minuteries ESP8266 utilisant lIDE Arduino NodeMCU

Diagramme schématique

Assemblez le capteur de mouvement PIR et une LED à votre ESP8266. Nous connecterons la LED à GPIO 12 (D6) et la broche de données du capteur de mouvement PIR à GPIO 14 (D5).

Interruptions et minuteries ESP8266 NodeMCU avec schéma de circuit du capteur de mouvement PIR

Lecture recommandée: Guide de référence de brochage ESP8266

Important: le capteur de mouvement PIR Mini AM312 utilisé dans ce projet fonctionne à 3,3 V. Cependant, si vous utilisez un autre capteur de mouvement PIR comme le HC-SR501, il fonctionne à 5V. Vous pouvez soit le modifier pour qu’il fonctionne à 3,3 V, soit simplement l’alimenter à l’aide de la broche Vin.

La figure suivante montre le brochage du capteur de mouvement AM312 PIR.

Brochage du capteur de mouvement AM312 PIR : GND, données, 3,3 V

Code

Après avoir câblé le circuit comme indiqué dans le schéma, copiez le code fourni dans votre IDE Arduino.

Vous pouvez télécharger le code tel quel ou vous pouvez modifier le nombre de secondes pendant lesquelles la LED est allumée après la détection d’un mouvement. Changez simplement le tempsSecondes variable avec le nombre de secondes que vous voulez.

/*********
  Rui Santos
  Complete project details at https://www.raspberryme.com  
*********/

#define timeSeconds 10

// Set GPIOs for LED and PIR Motion Sensor
const int led = 12;
const int motionSensor = 14;

// Timer: Auxiliary variables
unsigned long now = millis();
unsigned long lastTrigger = 0;
boolean startTimer = false;

// Checks if motion was detected, sets LED HIGH and starts a timer
ICACHE_RAM_ATTR void detectsMovement() {
  Serial.println("MOTION DETECTED!!!");
  digitalWrite(led, HIGH);
  startTimer = true;
  lastTrigger = millis();
}

void setup() {
  // Serial port for debugging purposes
  Serial.begin(115200);
  
  // PIR Motion Sensor mode INPUT_PULLUP
  pinMode(motionSensor, INPUT_PULLUP);
  // Set motionSensor pin as interrupt, assign interrupt function and set RISING mode
  attachInterrupt(digitalPinToInterrupt(motionSensor), detectsMovement, RISING);

  // Set LED to LOW
  pinMode(led, OUTPUT);
  digitalWrite(led, LOW);
}

void loop() {
  // Current time
  now = millis();
  // Turn off the LED after the number of seconds defined in the timeSeconds variable
  if(startTimer && (now - lastTrigger > (timeSeconds*1000))) {
    Serial.println("Motion stopped...");
    digitalWrite(led, LOW);
    startTimer = false;
  }
}

Afficher le code brut

Comment fonctionne le code

Jetons un coup d’œil au code.

Commencez par attribuer deux broches GPIO au LED et capteur de mouvement variables.

const int led = 12;
const int motionSensor = 14;

Ensuite, créez des variables qui vous permettront de définir une minuterie pour éteindre la LED après la détection d’un mouvement.

unsigned long now = millis();
unsigned long lastTrigger = 0;
boolean startTimer = false;

le à présent variable contient l’heure actuelle. le dernierTrigger variable contient l’heure à laquelle le capteur PIR détecte un mouvement. le startTimer est une variable booléenne qui démarre le temporisateur lorsqu’un mouvement est détecté.

mettre en place()

Dans le mettre en place()commencez par initialiser le port série à 115200 bauds.

Serial.begin(115200);

Réglez le capteur de mouvement PIR comme INPUT_PULLUP.

pinMode(motionSensor, INPUT_PULLUP);

Pour définir la broche du capteur PIR comme une interruption, utilisez le attachInterrupt() fonctionner comme décrit précédemment.

attachInterrupt(digitalPinToInterrupt(motionSensor), detectsMovement, RISING);

La broche qui détectera le mouvement est GPIO 14 et il appellera la fonction détecteMouvement() au EN HAUSSE mode.

La LED est un SORTIR dont l’état commence à MEUGLER.

pinMode(led, OUTPUT);
digitalWrite(led, LOW);

boucler()

le boucler() fonction tourne constamment encore et encore. Dans chaque boucle, le à présent variable est mise à jour avec l’heure actuelle.

now = millis();

Rien d’autre n’est fait dans le boucler(). Mais, lorsqu’un mouvement est détecté, le détecteMouvement() La fonction est appelée car nous avons précédemment défini une interruption dans le mettre en place().

le détecteMouvement() fonction imprime un message dans le moniteur série, allume la LED, définit le startTimer variable booléenne à true et met à jour la dernierTrigger variable avec l’heure actuelle.

ICACHE_RAM_ATTR void detectsMovement() {
  Serial.println("MOTION DETECTED!!!");
  digitalWrite(led, HIGH);
  startTimer = true;
  lastTrigger = millis();
}

Après cette étape, le code retourne au boucler(). Cette fois, le startTimer variable est vraie. Ainsi, lorsque le temps défini en secondes s’est écoulé (depuis la détection du mouvement), l’instruction if suivante sera vraie.

if(startTimer && (now - lastTrigger > (timeSeconds*1000))) {
  Serial.println("Motion stopped…");
  digitalWrite(led, LOW);
  startTimer = false;
}

Le message « Mouvement arrêté… » sera imprimé dans le moniteur série, la LED s’éteindra et le startTimer variable est définie sur faux.

Manifestation

Téléchargez le code sur votre ESP8266. Assurez-vous d’avoir sélectionné la bonne carte et le bon port COM.

Ouvrez le moniteur série à un débit en bauds de 115 200.

Moniteur série ouvert Arduino IDE au débit en bauds 115200

Déplacez votre main devant le capteur PIR. Le voyant doit s’allumer et un message est imprimé dans le moniteur série indiquant « MOUVEMENT DETECTE!!!”. Après 10 secondes, la LED doit s’éteindre.

Interruptions et minuteries avec ESP8266 NodeMCU utilisant la démonstration de l'IDE Arduino

Conclusion

En résumé, les interruptions sont utiles pour détecter un changement d’état GPIO et déclencher instantanément une fonction. Vous avez également appris que vous devez utiliser des minuteries pour écrire du code non bloquant.

Nous espérons que vous avez trouvé ce tutoriel utile. Nous avons d’autres tutoriels sur la façon de gérer les interruptions en utilisant MicroPython et en utilisant ESP32 :

Apprenez-en plus sur la carte ESP8266 avec nos ressources :

Merci d’avoir lu.