Détection de mouvement avec l'ESP32 et un capteur de mouvement PIR

Rédigé par sazaki Aucun commentaire
Classé dans : Non classé Mots clés : aucun

Ce tutoriel montre comment détecter un mouvement avec l'ESP32 à l'aide d'un capteur de mouvement PIR. Dans cet exemple, lorsqu'un mouvement est détecté (une interruption est déclenchée), l'ESP32 démarre un timer et allume une LED pendant un nombre prédéfini de secondes. Lorsque le compte à rebours est terminé, la LED s'éteint automatiquement.

Avec ce tutoriel, nous explorerons également deux concepts importants : les interruptions et les timers.

Pièces requises

Pour suivre ce tutoriel, vous avez besoin des pièces suivantes

• Mini détecteur de mouvement PIR

LED

• Résistance 330 Ohms

• Fils de liaison

Platine (breadboard)

Vous pouvez utiliser les liens précédents pour trouver toutes les pièces de vos projets au meilleur prix !

 

Introduction aux interruptions

Pour déclencher un événement avec un détecteur de mouvement PIR, vous utilisez des interruptions. Les interruptions sont utiles pour faire en sorte que les choses se produisent automatiquement dans les programmes du 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 d'une broche. Avec les interruptions, lorsqu'un changement est détecté, un événement est déclenché (une fonction est appelée).
 
Pour définir une interruption dans l'IDE Arduino, vous utilisez la fonction attachInterrupt(), qui accepte comme arguments : la broche GPIO, le nom de la fonction à exécuter et le mode :
 
attachInterrupt(digitalPinToInterrupt(GPIO), function, mode);

Interruption GPIO

Le premier argument est un numéro GPIO. Normalement, vous devez utiliser digitalPinToInterrupt(GPIO) pour définir le GPIO réel comme broche d'interruption.

 Par exemple, si vous souhaitez utiliser GPIO 27 comme interruption, utilisez :

digitalPinToInterrupt(27)

 

Avec une carte ESP32, toutes les broches mises en évidence par un rectangle rouge dans la figure suivante peuvent être configurées comme broches d'interruption. Dans cet exemple, nous utiliserons le GPIO 27 comme une interruption connectée au capteur de mouvement PIR.

Fonction à déclencher

Le deuxième argument de la fonction attachInterrupt() est le nom de la fonction qui sera appelée à chaque déclenchement de l'interruption.

Mode

Le troisième argument est le mode. Il existe 5 modes différents :

• LOW : pour déclencher l'interruption chaque fois que la broche est LOW ;

• HIGH : pour déclencher l'interruption chaque fois que la broche est HIGH ;

• CHANGE : pour déclencher l'interruption chaque fois que la broche change de valeur – par exemple de HIGH à LOW ou LOW à HIGH ;

• FALLING : lorsque la broche passe de HIGH à LOW ;

• RISING : pour se déclencher lorsque la broche passe de LOW à HIGH.

Pour cet 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.

Introduction des Timers

Dans cet exemple, nous allons également introduire des timers. 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 une fonction delay() qui bloque votre code et ne vous permet pas de faire autre chose pendant un nombre déterminé de secondes, nous devrions utiliser un timer.

La fonction delay()

Vous devez être familiarisé avec la fonction delay() car elle est largement utilisée. Cette fonction est assez simple à utiliser. Il 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(temps en millisecondes)

Lorsque vous faites delay(1000), votre programme s'arrête sur cette ligne pendant 1 seconde.

delay() 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 delay().

Pour la plupart des projets, vous devez éviter d'utiliser des retards et utiliser des timers à la place.

La fonction millis()

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 avec millis()

L'extrait de code suivant montre comment vous pouvez utiliser la fonction millis() pour créer un projet de LED clignotante. Il allume une LED pendant 1000 millisecondes, puis l'éteint.
 
// les constantes ne changeront pas. Utilisé ici pour définir un numéro de broche :
const int ledPin =  26;      // le numéro de la broche LED
 
// Les variables changeront :
int ledState = LOW;             // ledState utilisé pour régler la LED
 
// Généralement, vous devez utiliser "unsigned long" pour les variables qui contiennent du temps
// La valeur deviendra rapidement trop grande pour qu'un int puisse la stocker
unsigned long previousMillis = 0;        // enregistrera la dernière fois que la LED a été mise à jour
// Les variables changeront :
 
const long interval = 1000;           // intervalle de clignotement (milliseconds)
 
void setup() {
  // définissez la broche numérique (digital) comme sortie :
  pinMode(ledPin, OUTPUT);
}
 
void loop() {
  // c'est ici que vous placeriez le code qui doit être exécuté tout le temps.
   // vérifie s'il est temps de faire clignoter la LED ; c'est-à-dire si la
   // différence entre l'heure actuelle et la dernière fois du clignotement
   // la LED est plus grande que l'intervalle auquel vous voulez
   // fait clignoter la LED.
  unsigned long currentMillis = millis();
 
  if (currentMillis - previousMillis >= interval) {
    // save the last time you blinked the LED
    previousMillis = currentMillis;
 
    // si le voyant est éteint, allumez-le et vice-versa :
    if (ledState == LOW) {
      ledState = HIGH;
    } else {
      ledState = LOW;
    }
 
    // définissez la LED avec le ledState de la variable :
    digitalWrite(ledPin, ledState);
  }
}

Comment fonctionne le code

Examinons de plus près cette code de clignotement qui fonctionne sans fonction delay() (il utilise à la place la fonction millis()).

Ce code soustrait l'heure enregistrée précédente (previousMillis) de l'heure actuelle (currentMillis). Si le reste est supérieur à l'intervalle (dans ce cas, 1000 millisecondes), le programme met à jour la variable previousMillis à l'heure actuelle et allume ou éteint la LED.
 
if (currentMillis - previousMillis >= interval) {
  // enregistrer la dernière fois que vous avez clignoté la LED
  previousMillis = currentMillis;
  (...)

Étant donné que cet extrait de code 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 fonction loop() et que votre code fera toujours clignoter la LED toutes les secondes.

Vous pouvez télécharger ce code sur votre ESP32 et assembler le diagramme schématique suivant pour le tester et modifier le nombre de millisecondes pour voir comment cela fonctionne.

ESP32 avec capteur de mouvement PIR

Après avoir compris ces concepts : les interruptions et les timers, poursuivons le projet.

Schéma

Le circuit que nous allons construire est facile à assembler, nous allons utiliser une LED avec une résistance. La LED est connectée au GPIO 26. Nous utiliserons le capteur de mouvement PIR Mini AM312 qui fonctionne à 3,3 V. Il sera connecté au GPIO 27. Suivez simplement le schéma suivant.

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.

AM312 mini pir pinout

Téléchargement du 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 la variable timeSeconds avec le nombre de secondes que vous voulez.
 
#define timeSeconds 10
// Définir les GPIO pour le capteur de mouvement LED et PIR
const int led = 26;
const int motionSensor = 27;
 
// Timer: Variables auxiliaires
unsigned long now = millis();
unsigned long lastTrigger = 0;
boolean startTimer = false;
 
// Vérifie si un mouvement a été détecté, règle la LED sur HIGH et démarre une minuterie
void IRAM_ATTR detectsMovement() {
  Serial.println("MOUVEMENT DETECTE!!!");
  digitalWrite(led, HIGH);
  startTimer = true;
  lastTrigger = millis();
}
 
void setup() {
  // Port série à des fins de débogage
  Serial.begin(115200);
  // Mode capteur de mouvement PIR INPUT_PULLUP
  pinMode(motionSensor, INPUT_PULLUP);
  // Définissez la broche motionSensor comme interruption, affectez la fonction d'interruption et définissez le mode RISING
  attachInterrupt(digitalPinToInterrupt(motionSensor), detectsMovement, RISING);
 
  // Réglez la LED sur LOW
  pinMode(led, OUTPUT);
  digitalWrite(led, LOW);
}
 
void loop() {
  // Current time
  now = millis();
  // Éteindre la LED après le nombre de secondes défini dans la variable timeSeconds
  if(startTimer && (now - lastTrigger > (timeSeconds*1000))) {
    Serial.println("Motion stopped...");
    digitalWrite(led, LOW);
    startTimer = false;
  }
}

 

Comment fonctionne le code

Jetons un coup d'œil au code. Commencez par attribuer deux broches GPIO aux variables led et motionSensor.
 
// Définir les GPIO pour le capteur de mouvement LED et PIR
const int led = 26;
const int motionSensor = 27;
 
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.
 
// Timer: Auxiliar variables
long now = millis();
long lastTrigger = 0;
boolean startTimer = false;

La variable "now" contient l'heure actuelle. La variable lastTrigger contient l'heure à laquelle le capteur PIR détecte un mouvement. Le startTimer est une variable booléenne qui démarre la minuterie lorsqu'un mouvement est détecté.

setup()

Dans le setup(), commencez par initialiser le port série à 115200 bauds.
 
Serial.begin(115200);
 
Définissez le capteur de mouvement PIR comme INPUT PULLUP.
 
pinMode(motionSensor, INPUT_PULLUP);
 
Pour définir la broche du capteur PIR comme une interruption, utilisez la fonction attachInterrupt() comme décrit précédemment.
 
attachInterrupt(digitalPinToInterrupt(motionSensor), detectsMovement, RISING);

La broche qui détectera le mouvement est le GPIO 27 et appellera la fonction detectsMovement() en mode RISING.

La LED est un OUTPUT dont l'état commence sur LOW.
 
pinMode(led, OUTPUT);
digitalWrite(led, LOW);

loop()

La fonction loop() s'exécute constamment encore et encore. Dans chaque boucle, la variable now est mise à jour avec l'heure actuelle.
 
now = millis();
 
Rien d'autre n'est fait dans la boucle().
Mais, lorsqu'un mouvement est détecté, la fonction detectsMovement() est appelée car nous avons précédemment défini une interruption dans setup().
La fonction detectsMovement() imprime un message dans le moniteur série, allume la LED, définit la variable booléenne startTimer sur true et met à jour la variable lastTrigger avec l'heure actuelle.
 
void IRAM_ATTR detectsMovement() {
  Serial.println("MOUVEMENT DETECTE!!!");
  digitalWrite(led, HIGH);
  startTimer = true;
  lastTrigger = millis();
}

Remarque : IRAM_ATTR est utilisé pour exécuter le code d'interruption dans la RAM, sinon le code est stocké dans la mémoire flash et il est plus lent.

Après cette étape, le code retourne à la boucle loop().
Cette fois, la variable startTimer 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("Mouvement arrêté...");
  digitalWrite(led, LOW);
  startTimer = false;
}

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

Démonstration

Téléchargez le code sur votre carte ESP32. 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.

Déplacez votre main devant le capteur PIR. La LED 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.

Résumé

les interruptions sont utilisées pour détecter un changement d'état GPIO sans qu'il soit nécessaire de lire en permanence la valeur GPIO actuelle. Avec les interruptions, lorsqu'un changement est détecté, une fonction est déclenchée. Vous avez également appris à définir une minuterie simple qui vous permet de vérifier si un nombre prédéfini de secondes s'est écoulé sans avoir à bloquer votre code.

Écrire un commentaire

Quelle est le dernier caractère du mot 3m07x ?