Skip to Content

ESP32-CAM activé par détection de mouvement

ESP32-CAM activé par détection de mouvement

Dans ce tutoriel, vous apprendrez à construire un ESP32-CAM (AI-Thinker) alimenté par batterie et déclenché par le mouvement, qui prend des photos dès qu’un capteur PIR détecte un mouvement. Nous aborderons les différents types de capteurs PIR, les options d’alimentation par batterie et les pièges à éviter.

Ce projet est parfait pour la surveillance, la sécurité ou même l’observation de la faune. Si vous souhaitez enregistrer des vidéos au lieu de prendre des photos, consultez notre Surveillance Camera with ESP32-CAM tutoriel.

Overview

Pièces nécessaires

Vous trouverez ci-dessous la liste des composants nécessaires pour réaliser ce projet. Certains éléments comme le câble USB, la carte micro SD ou le lecteur de carte SD sont peut-être déjà en votre possession. Inutile de les acheter, aucun de ces éléments n’est spécifique à ce projet. Cependant, la carte SD ne doit pas dépasser 16 Go ; des cartes plus petites (4 Go ou 8 Go) fonctionnent très bien.

Vous avez besoin soit du USB-TTL Shield, soit de l’adaptateur FTDI USB-TTL, mais pas des deux. Bien que le module ESP32-CAM soit livré avec le USB-TTL Shield, l’adaptateur FTDI USB-TTL est plus pratique pour la programmation.

J’ai listé deux types de capteurs de mouvement différents. Si vous cherchez un format compact, choisissez le AM312. Mais si vous souhaitez activer la caméra uniquement la nuit, optez pour le HC-SR501, car il peut facilement être équipé d’un capteur de luminosité.

ESP32-CAM avec USB-TTL Shield

Adaptateur FTDI USB-TTL

Dupont wire set

Jeu de fils Dupont

Capteur de mouvement PIR AM312

Capteur de mouvement PIR HC-SR501

Carte MicroSD 16 Go

Lecteur de carte SD

USB data cable

Câble de données USB

Makerguides is a participant in affiliate advertising programs designed to provide a means for sites to earn advertising fees by linking to Amazon, AliExpress, Elecrow, and other sites. As an Affiliate we may earn from qualifying purchases.

Bases des capteurs de mouvement PIR

Il existe de nombreuses méthodes et capteurs pour détecter des objets en mouvement, mais les plus courants sont les capteurs de mouvement PIR (Passive InfraRed) qui détectent le déplacement d’objets chauds. Un capteur PIR typique se compose de deux éléments pyroelectriques et d’une lentille de Fresnel.

PIR Motion Sensor Working Principle
Principe de fonctionnement d’un capteur de mouvement PIR

Élément pyroelectrique

Les éléments pyroelectriques détectent la chaleur et sont disposés et câblés de façon à ce qu’un objet passant devant provoque un signal de sortie positif ou négatif. Si l’objet ne bouge pas, les signaux des deux éléments pyroelectriques s’annulent.

Lentille de Fresnel

La lentille de Fresnel (capuchon blanc) concentre la faible radiation thermique d’un corps humain et rend le capteur plus sensible. Vous pouvez utiliser un capteur PIR sans lentille de Fresnel, mais il sera moins sensible et risque de déclencher de fausses alertes plus souvent.

Fresnel Lens for PIR Sensor
Lentille de Fresnel pour capteur PIR

Notez que les éléments PIR ne fonctionnent pas derrière une vitre (fenêtre) et ne peuvent pas détecter les objets ayant la même température que la pièce où ils se trouvent. Veillez également à monter le capteur à l’horizontale pour une sensibilité maximale. Pour plus d’informations, consultez here .

Temps de calibration

Les capteurs PIR ont généralement un temps de calibration pendant lequel ils s’ajustent à la température ambiante. Cela peut prendre jusqu’à 15 secondes et, durant cette période, vous pouvez avoir de fausses détections. Évitez tout mouvement pendant la calibration pour laisser le capteur s’adapter.

Temps de blocage et de délai

De plus, les capteurs PIR ont un temps de blocage et un temps de délai. Le temps de blocage (ou de verrouillage) est la période pendant laquelle le capteur ignore tout mouvement détecté après un déclenchement initial. Cela évite que le capteur ne soit activé en continu par des mouvements répétés, lui permettant de se réinitialiser et d’éviter les fausses alertes. Par exemple, si le temps de blocage est réglé à 30 secondes, le capteur ne détectera aucun mouvement pendant cette période, même s’il y a du mouvement dans sa zone de détection.

Le temps de délai, quant à lui, est l’intervalle que le capteur attend avant de déclencher une action après avoir détecté un mouvement. Ce délai peut être utile si vous souhaitez éviter une réaction immédiate, par exemple allumer une lumière seulement après quelques secondes de mouvement continu. Par exemple, si le temps de délai est réglé à 10 secondes, le capteur attendra cette durée avant d’activer un appareil ou d’envoyer un signal.

Certains modules de capteurs PIR permettent d’ajuster le temps de blocage et de délai, tandis que d’autres ont des temps fixes. Il existe de nombreux modules de capteurs PIR, mais la plupart sont basés sur le capteur PIR AS312, que nous allons aborder dans la section suivante.

Capteur PIR AS312

L’image ci-dessous montre un capteur PIR AS312 et une vue de dessus avec l’emplacement des deux éléments pyroelectriques indiqués. La lentille de Fresnel a été retirée.

AS312 PIR Sensor
Capteur PIR AS312

Le AS312 fonctionne entre 2,7 et 3,3 V et consomme très peu de courant (15 μA). Il a un temps de blocage et de délai de 2,3 secondes.

Le AS312 intègre déjà beaucoup d’électronique (voir Datasheet ), mais il vous faudra une tension d’alimentation stable (régulateur de tension) et quelques autres composants pour l’utiliser dans un circuit. C’est pourquoi il existe différents modules de capteurs PIR qui ajoutent ces éléments nécessaires et offrent des fonctionnalités supplémentaires comme des temps de délai supérieurs à 2,3 secondes et un réglage de la sensibilité.

Nous allons examiner trois modules de capteurs PIR courants dans la prochaine section et je vous donnerai quelques recommandations sur ceux à utiliser avec l’ESP32-CAM.

Module PIR AM312

Le module PIR AM312 est le plus simple et le plus compact des trois modules présentés ici. Il a un temps de blocage et de délai fixe d’environ 2 secondes et ne permet pas de régler la sensibilité.

Pinout of AM312 PIR Module
Brochage du module PIR AM312

Il se compose simplement du capteur PIR AS312, d’un HT7530 régulateur de tension et d’une résistance de sortie (20K). Voir le schéma interne ci-dessous. Notez qu’il n’y a pas de protection contre l’inversion de polarité et qu’il est facile de détruire le capteur en le câblant à l’envers.

AM312 PIR Module Schematics
Schéma du module PIR AM312

Le module possède trois broches : alimentation positive (VIN), masse (GND) et sortie (OUT). La tension d’alimentation va de 2,7 à 12 V et la sortie est de 3,3 V (TTL) lorsqu’un mouvement est détecté. La portée de détection est de 3 à 5 m et l’angle de détection d’environ 100°.

C’est le capteur que je recommande pour l’ESP32-CAM à détection de mouvement. Il a un temps de blocage et de délai court (2 s), ce qui permet de prendre des photos toutes les 4 secondes environ. Il peut être connecté directement à une broche GPIO de l’ESP32-CAM et a fonctionné de façon fiable lors de mes tests.

Cependant, si vous avez besoin d’une plus grande portée de détection et d’une activation uniquement la nuit, je recommande le HC-SR501, que nous verrons dans la section suivante.

Module PIR HC-SR501

Le HC-SR501 est le capteur de mouvement que l’on retrouve le plus souvent dans les applications domestiques, comme les veilleuses à détection de mouvement. Il est facilement reconnaissable à sa grande lentille de Fresnel. Voir la photo ci-dessous.

HC-SR501 PIR Module
Module PIR HC-SR501

Schéma du HC-SR501

Le schéma du module HC-SR501 est bien plus complexe que celui du AM312, car il offre un réglage de la sensibilité (portée) et du temps de délai. Il utilise aussi le RE200B PIR Sensor à la place du capteur PIR AS312. Voir le schéma ci-dessous.

HC-SR501 PIR Module Schematics
Schéma du module PIR HC-SR501

Le temps de délai peut être réglé d’environ 0,3 seconde à 300 secondes. Il y aura toujours un temps de blocage d’environ 2,5 secondes. Cependant, le HC-SR501 vous permettra de prendre des photos un peu plus fréquemment que le AS312 (3 secondes contre 4 secondes).

Réglage du délai minimum

Comme nous allons gérer le temps de délai via le logiciel, nous voulons régler le délai matériel au minimum. Pour cela, tournez le potentiomètre de gauche dans le sens antihoraire jusqu’à la position indiquée ci-dessous. Vous obtiendrez ainsi le délai minimum d’environ 0,3 seconde.

Setting minimum delay time for HC-SR501
Réglage du délai minimum pour le HC-SR501

Il est préférable de tester cela sans les complications d’un ESP32-CAM au début. Consultez notre tutoriel How to use HC-SR501 PIR Motion Sensor . Il propose un circuit d’exemple simple qui montre comment allumer une LED lorsque le capteur détecte un mouvement.

L’autre potentiomètre du module HC-SR501 permet de régler la portée de détection (sensibilité) d’environ 2 m à un maximum d’environ 7 m. Le HC-SR501 possède aussi un cavalier pour changer le mode de déclenchement. Pour plus de détails, consultez notre tutoriel How to use HC-SR501 PIR Motion Sensor ou la DHC-SR501 Datasheet .

Activation nocturne via LDR

Le plus grand avantage (en plus de la portée) du HC-SR501 par rapport au AM312, c’est que vous pouvez ajouter une LDR (détecteur de lumière) pour que le capteur ne soit actif que la nuit. C’est idéal pour surveiller la faune nocturne. Cette fonction est peu documentée, mais si vous retirez la lentille de Fresnel, vous verrez deux ports traversants marqués RL et RT. Voir la photo ci-dessous.

Light (RL) and Temperature (RT) ports on HC-SR501
Ports lumière (RL) et température (RT) sur le HC-SR501

Le port RT (Resistor Temperature) permet d’ajouter une thermistance, ce qui rend le HC-SR501 moins sensible aux fausses alertes dues aux variations de température ambiante. Le port RL (Resistor Light) permet d’ajouter une LDR (résistance dépendante de la lumière), ce qui garantit que la détection de mouvement n’est activée que la nuit.

La valeur précise de la résistance à utiliser pour la LDR dépendra du niveau d’obscurité souhaité pour activer le capteur. Il faudra faire des essais. Voici un lien vers un LDR kit with various resistor values que vous pouvez essayer. À titre indicatif, le diviseur de tension dans le schéma ci-dessus utilise une résistance de 1 MΩ. Vous pouvez commencer avec une LDR dans cette gamme de valeurs.

Entrées et sorties

Les entrées et sorties du HC-SR501 sont essentiellement les mêmes que celles du AM312. Il faut fournir une tension d’alimentation sur les broches VCC et GND comprise entre 4,5 V et 20 V, et la broche de sortie passe à l’état haut (3,3 V) lorsqu’un mouvement est détecté. La photo ci-dessous montre le brochage.

Pinout of HC-SR501 PIR Module
Brochage du module PIR HC-SR501

En résumé, si vous voulez un capteur PIR petit, simple et économique, choisissez le AM312. Il fonctionnera très bien. Si vous souhaitez une meilleure portée et limiter la détection de mouvement à la nuit, optez pour le HC-SR501.

Dans la section suivante, je vais rapidement aborder le HC-SR505, qui s’est avéré inadapté et que je ne recommande pas pour cette application.

Module PIR HC-SR505

Le module PIR HC-SR505 est un peu plus long que le AM312 mais utilise le même capteur PIR AS312 et a le même brochage. Voir la photo ci-dessous du HC-SR505

Pinout of HC-SR505 PIR Sensor
Brochage du capteur PIR HC-SR505

La tension d’alimentation va de 4,5 V à 20 V et la sortie est en TTL (3,3 V). La portée de détection est de 3 à 4 mètres et le temps de délai est fixé à environ 8 secondes.

En plus du temps de délai long qui vous limite à une photo toutes les 8 secondes, j’ai aussi constaté que le capteur posait problème lorsque j’utilisais une batterie externe 5 V comme alimentation. J’ai essayé plusieurs capteurs du même type (HC-SR505) mais la sortie restait toujours à l’état haut. Je soupçonne que l’ondulation haute fréquence de la batterie externe en est la cause (nous en reparlerons plus loin).

Les modules HC-SR501 et AM312 n’avaient aucun problème avec cette batterie externe, mais le module PIR HC-SR505 refusait de fonctionner correctement. De plus, même en alimentant l’ESP32-CAM avec une pile 9 V ou une paire de batteries 18650 (qui n’ont pas d’ondulation), le HC-SR505 ne fonctionnait pas et restait toujours activé. Encore une fois, je pense que des interférences haute fréquence de l’ESP32-CAM avec le HC-SR505 sont en cause.

En résumé, le module PIR HC-SR505 n’est pas adapté à la prise de photos déclenchée par mouvement avec l’ESP32-CAM. Notez cependant que j’ai utilisé le module PIR HC-SR505 dans d’autres projets sans aucun problème.

Voyons maintenant rapidement le module ESP32-CAM lui-même.

Présentation de l’ESP32-CAM AI-Thinker

La carte de développement ESP32-CAM AI-Thinker est un module compact qui combine une puce ESP32-S, une caméra, un flash intégré et un lecteur de carte microSD. La carte intègre le Wi-Fi et le Bluetooth et prend en charge une caméra OV2640 ou OV7670 jusqu’à 2 mégapixels de résolution.

Dos de l’ESP32-CAM
Front of ESP32-CAM
Face avant de l’ESP32-CAM

Vous trouverez plus de détails sur la carte ESP32-CAM et surtout sur la façon d’y téléverser du code dans notre tutoriel Programming the ESP32-CAM . Lisez-le absolument, car le téléversement de code sur la carte ESP32-CAM est délicat. Dans ce tutoriel, je me concentre sur la mise en œuvre de la détection de mouvement pour l’ESP32-CAM.

Brochage

L’image suivante montre le brochage de l’ESP32-CAM. Notez qu’en théorie, l’ESP32-CAM peut fonctionner en 3,3 V, mais des comportements instables ont été signalés. Vous pouvez utiliser de 5 V à 15 V, mais je ne dépasserais pas 12 V, car le régulateur de tension pourrait chauffer. Nous parlerons plus en détail des différentes options d’alimentation plus loin.

Pinout of the ESP32-CAM module
Brochage du module ESP32-CAM AI-Thinker ( source )

La broche P_OUT est parfois étiquetée VCC sur certaines cartes. Il s’agit d’une sortie d’alimentation qui délivre 3,3 V ou 5 V selon un solder pad . Vous ne pouvez pas utiliser cette broche pour alimenter la carte ! Utilisez la broche 5V pour cela.

Notez que la plupart des broches GPIO de l’ESP32-CAM sont déjà utilisées par la caméra et le lecteur de carte SD. De plus, il faut éviter d’utiliser GPIO1, GPIO3 et GPIO0, car elles sont nécessaires à la programmation de la carte. Par ailleurs, GPIO0 est reliée à la broche XCLK de la caméra et doit rester flottante (non connectée) lors de l’utilisation de l’ESP32.

Enfin, les broches GPIO 2, 4, 12, 13, 14 et 15 sont partiellement utilisées par le lecteur de carte SD. Si vous n’utilisez pas le lecteur de carte SD, elles sont disponibles en GPIO. Pour plus de détails, consultez notre More GPIO pins for ESP32-CAM tutoriel.

Dans la suite, nous utiliserons GPIO 13 pour la détection de mouvement. Les détails sur la connexion d’un capteur PIR à l’ESP32-CAM sont décrits dans la section suivante.

Connexion du capteur PIR à l’ESP32-CAM

Connecter le module capteur PIR AM312 à l’ESP32-CAM est très simple. Reliez une alimentation (batterie) de 5 V (jusqu’à 12 V) aux broches 5V et GND de l’ESP32-CAM comme indiqué ci-dessous (fils rouge et bleu).

Connecting AM312 PIR Sensor to ESP32-CAM
Connexion de l’AM312 à l’ESP32-CAM

Vous pouvez fournir plus de 5 V pour alimenter la carte. Pas d’inquiétude : un régulateur de tension est connecté à la broche 5V et abaissera la tension au niveau requis par la carte. Mais ne dépassez pas 12 V, sinon le régulateur risque de chauffer.

De même, connectez le module capteur PIR AM312 à l’alimentation (fils rouge et bleu). Faites attention à la polarité, car l’AM312 n’a pas de protection contre l’inversion de polarité. Ensuite, reliez la sortie S ou OUT de l’AM312 à la broche GPIO13 de l’ESP32-CAM (fil vert).

Ne connectez pas l’AM312 à la broche 3,3 V pour l’alimentation. En théorie, cela devrait fonctionner, mais en pratique, j’ai eu des problèmes de détection en alimentant l’AM312 en 3,3 V. Si vous utilisez le module capteur PIR HC-SR501 à la place de l’AM312, connectez-le de la même façon (GND à GND, VCC à 5V-12V).

Les modules AM312 et HC-SR501 supportent une tension d’alimentation de 5 V à 12 V. Vous pouvez donc alimenter l’ESP32-CAM et le capteur PIR avec la même alimentation (batterie) et la même tension.

Circuit à transistor

Notez que de nombreux tutoriels proposent un circuit à transistor pour connecter un capteur PIR à l’ESP32-CAM. Ce n’est PAS nécessaire ! La sortie du capteur PIR (même celle, faible, de l’AM312) peut facilement piloter l’entrée GPIO. Connecter le capteur PIR directement à l’ESP32-CAM fonctionne très bien et c’est bien plus simple.

Téléversement du code

Si vous utilisez un adaptateur FTDI USB-TTL, vous pouvez laisser le capteur PIR connecté pendant le téléversement et les tests du code. Si vous utilisez le USB-TTL Shield, il faudra déconnecter et reconnecter le capteur PIR à chaque téléversement ou exécution d’un nouveau code, ce qui est assez pénible.

Je recommande donc vivement d’utiliser un adaptateur FTDI USB-TTL. La photo ci-dessous montre le montage. Vous n’avez même pas besoin de breadboard, juste de quelques fils Dupont.

FTDI Adapter and PIR Sensor connected to ESP32-CAM
Adaptateur FTDI et capteur PIR connectés à l’ESP32-CAM

Les détails sur la connexion de l’adaptateur FTDI USB-TTL et le téléversement du code se trouvent dans notre tutoriel Programming the ESP32-CAM . Dans la section suivante, je vous montre le code pour l’ESP32-CAM à détection de mouvement.

Code pour l’ESP32-CAM à détection de mouvement

Le code suivant est une implémentation complète pour une ESP32-CAM déclenchée par mouvement. Jetez-y un coup d’œil rapide pour avoir une vue d’ensemble avant d’entrer dans les détails.

Ce code met l’ESP32-CAM en deep sleep et attend un signal sur GPIO13, indiquant que le capteur PIR a détecté un mouvement. Si un mouvement est détecté, l’ESP32-CAM se réveille, prend une photo, la stocke avec un numéro incrémental sur la carte SD, puis retourne en veille profonde.

// Motion activated ES32-CAM
// Makerguides.com

#include "esp_camera.h"
#include "soc/rtc_cntl_reg.h"
#include "driver/rtc_io.h"
#include "SD_MMC.h"
#include "EEPROM.h"

// CAMERA_MODEL_AI_THINKER
#define PWDN_GPIO_NUM 32
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 0
#define SIOD_GPIO_NUM 26
#define SIOC_GPIO_NUM 27
#define Y9_GPIO_NUM 35
#define Y8_GPIO_NUM 34
#define Y7_GPIO_NUM 39
#define Y6_GPIO_NUM 36
#define Y5_GPIO_NUM 21
#define Y4_GPIO_NUM 19
#define Y3_GPIO_NUM 18
#define Y2_GPIO_NUM 5
#define VSYNC_GPIO_NUM 25
#define HREF_GPIO_NUM 23
#define PCLK_GPIO_NUM 22

void configCamera() {
  camera_config_t config;

  config.ledc_channel = LEDC_CHANNEL_0;
  config.ledc_timer = LEDC_TIMER_0;
  config.pin_d0 = Y2_GPIO_NUM;
  config.pin_d1 = Y3_GPIO_NUM;
  config.pin_d2 = Y4_GPIO_NUM;
  config.pin_d3 = Y5_GPIO_NUM;
  config.pin_d4 = Y6_GPIO_NUM;
  config.pin_d5 = Y7_GPIO_NUM;
  config.pin_d6 = Y8_GPIO_NUM;
  config.pin_d7 = Y9_GPIO_NUM;
  config.pin_xclk = XCLK_GPIO_NUM;
  config.pin_pclk = PCLK_GPIO_NUM;
  config.pin_vsync = VSYNC_GPIO_NUM;
  config.pin_href = HREF_GPIO_NUM;
  config.pin_sscb_sda = SIOD_GPIO_NUM;
  config.pin_sscb_scl = SIOC_GPIO_NUM;
  config.pin_pwdn = PWDN_GPIO_NUM;
  config.pin_reset = RESET_GPIO_NUM;
  config.xclk_freq_hz = 20000000;
  config.pixel_format = PIXFORMAT_JPEG;
  config.frame_size = FRAMESIZE_UXGA;
  config.jpeg_quality = 10;
  config.fb_count = 2;
  esp_err_t err = esp_camera_init(&config);

  sensor_t* s = esp_camera_sensor_get();
  s->set_brightness(s, 0);
  s->set_contrast(s, 0);
  s->set_saturation(s, 0);
  s->set_special_effect(s, 0);
  s->set_whitebal(s, 1);
  s->set_awb_gain(s, 1);
  s->set_wb_mode(s, 0);
  s->set_exposure_ctrl(s, 1);
  s->set_aec2(s, 0);
  s->set_ae_level(s, 0);
  s->set_aec_value(s, 300);
  s->set_gain_ctrl(s, 1);
  s->set_agc_gain(s, 0);
  s->set_gainceiling(s, (gainceiling_t)0);
  s->set_bpc(s, 0);
  s->set_wpc(s, 1);
  s->set_raw_gma(s, 1);
  s->set_lenc(s, 1);
  s->set_hmirror(s, 0);
  s->set_vflip(s, 0);
  s->set_dcw(s, 1);
  s->set_colorbar(s, 0);
}

unsigned int incCounter() {
  unsigned int cnt = 0;
  EEPROM.get(0, cnt);
  EEPROM.put(0, cnt + 1);
  EEPROM.commit();
  return cnt;
}

void enableFlash(bool enable) {
  if (enable) {
    rtc_gpio_hold_dis(GPIO_NUM_4);
  } else {
    pinMode(GPIO_NUM_4, OUTPUT);
    digitalWrite(GPIO_NUM_4, LOW);
    rtc_gpio_hold_en(GPIO_NUM_4);
  }
}

void skipPictures(int n) {
  for(int i=0; i<n; i++) {
    camera_fb_t* fb = esp_camera_fb_get();
    esp_camera_fb_return(fb);
  }
}

void takePicture() {
  camera_fb_t* fb = esp_camera_fb_get();
  unsigned int cnt = incCounter();
  String path = "/img" + String(cnt) + ".jpg";
  File file = SD_MMC.open(path.c_str(), FILE_WRITE);
  file.write(fb->buf, fb->len);
  file.close();
  esp_camera_fb_return(fb);
}

void deepSleep(int atleast) {
  esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
  rtc_gpio_pulldown_en(GPIO_NUM_13);
  rtc_gpio_pullup_dis(GPIO_NUM_13);
  esp_sleep_enable_ext0_wakeup(GPIO_NUM_13, 1);
  delay(atleast);
  esp_deep_sleep_start();
}

void setup() {
  WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);
  enableFlash(true);
  EEPROM.begin(8);
  SD_MMC.begin();
  configCamera();
  skipPictures(10);
  takePicture();
  enableFlash(false);
  deepSleep(5000);
}

void loop() {
}

Décortiquons le code étape par étape pour comprendre comment fonctionne la configuration de la caméra et la capture d’image.

Inclus

Dans la première partie, nous incluons les bibliothèques nécessaires pour contrôler la caméra, la carte SD et l’EEPROM. Nous avons aussi besoin de quelques fonctions liées à l’horloge temps réel (rtc) pendant la veille profonde.

#include "esp_camera.h"
#include "soc/rtc_cntl_reg.h"
#include "driver/rtc_io.h"
#include "SD_MMC.h"
#include "EEPROM.h"

Constantes

Il existe différents modèles de cartes ESP32-CAM. Ce code est spécifique au modèle AI-Thinker mais fonctionnera aussi avec la plupart des autres cartes caméra à base d’ESP32, à condition qu’elles aient de la PSRAM (voir model definitions ).

Dans la section de code ci-dessous, nous définissons les broches spécifiques au modèle AI-Thinker. Si vous avez une autre carte ESP32-CAM, il faudra probablement modifier ces constantes. Vous trouverez ici le pin definitions pour les autres modèles pris en charge.

// CAMERA_MODEL_AI_THINKER
#define PWDN_GPIO_NUM 32
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 0
#define SIOD_GPIO_NUM 26
#define SIOC_GPIO_NUM 27
#define Y9_GPIO_NUM 35
#define Y8_GPIO_NUM 34
#define Y7_GPIO_NUM 39
#define Y6_GPIO_NUM 36
#define Y5_GPIO_NUM 21
#define Y4_GPIO_NUM 19
#define Y3_GPIO_NUM 18
#define Y2_GPIO_NUM 5
#define VSYNC_GPIO_NUM 25
#define HREF_GPIO_NUM 23
#define PCLK_GPIO_NUM 22

Configuration de la caméra

La fonction configCamera() configure la caméra avec des paramètres spécifiques comme le canal LEDC, les broches pour les lignes de données, les signaux d’horloge et les réglages d’image (format, taille, qualité). Si la qualité d’image de l’ESP32-CAM ne vous satisfait pas, essayez de modifier ces paramètres.

void configCamera() {
  sensor_t* s = esp_camera_sensor_get();
  s->set_brightness(s, 0);
  s->set_contrast(s, 0);
  ...
  s->set_colorbar(s, 0);
}

Incrémentation du compteur

La fonction incCounter() lit et incrémente un compteur stocké dans la mémoire EEPROM. Ce compteur sert à nommer les images capturées de façon séquentielle. À chaque appel, il incrémente le compteur. Le compteur doit être stocké dans EEPROM pour ne pas être perdu pendant la veille profonde.

unsigned int incCounter() {
  unsigned int cnt = 0;
  EEPROM.get(0, cnt);
  EEPROM.put(0, cnt + 1);
  EEPROM.commit();
  return cnt;
}

Le code est très simple. On récupère d’abord la valeur actuelle du compteur via EEPROM.get(0, cnt) , puis on stocke le compteur incrémenté via EEPROM.put(0, cnt + 1 ) et on valide la modification avec EEPROM.commit() . Enfin, on retourne la valeur actuelle du compteur. Lors du prochain appel, la fonction retournera le compteur incrémenté et l’incrémentera à nouveau.

Notez qu’il faut réserver de la mémoire pour le compteur dans l’EEPROM. Cela se fait plus loin, en appelant EEPROM.begin(8) dans la fonction setup(). Le compteur est un entier non signé de 4 octets. Mais par sécurité, je réserve 8 octets de mémoire – au cas où.

Un compteur entier non signé de 4 octets peut compter jusqu’à 4 294 967 295 avant de déborder. C’est largement suffisant pour numéroter toutes les images que l’on souhaite stocker sur la carte SD.

Contrôle du flash

La fonction enableFlash() active ou désactive le flash selon le paramètre enable . C’est un point délicat. Le problème avec l’ESP32-CAM, c’est qu’écrire sur la carte SD allume la LED du flash, et qu’en passant ensuite en veille profonde, la LED reste allumée.

Il ne suffit pas d’écrire LOW sur GPIO4 , où la LED du flash est connectée. Pendant la veille profonde, ce niveau de sortie est perdu. Pour garder GPIO4 à l’état bas pendant la veille profonde, il faut appeler rtc_gpio_hold_en(GPIO_NUM_4) , ce qui indique à l’ESP32 de préserver l’état de GPIO4 pendant la veille profonde.

Mais GPIO4 fait aussi partie de l’interface de la carte SD, donc on ne peut pas la figer à ce niveau. Ainsi, au réveil de l’ESP32-CAM, on désactive le maintien de GPIO4 via rtc_gpio_hold_dis(GPIO_NUM_4) et on laisse l’ESP32-CAM la contrôler pour prendre une photo et écrire sur la carte SD.

Avant de mettre l’ESP32-CAM en veille profonde, on appelle enableFlash(false) , ce qui éteint la LED du flash et préserve cet état pendant la veille profonde.

void enableFlash(bool enable) {
  if (enable) {
    rtc_gpio_hold_dis(GPIO_NUM_4);
  } else {
    pinMode(GPIO_NUM_4, OUTPUT);
    digitalWrite(GPIO_NUM_4, LOW);
    rtc_gpio_hold_en(GPIO_NUM_4);
  }
}

Sauter des images

La fonction SkipPictures(n) capture n images et les jette. Voici pourquoi : la caméra intègre plusieurs fonctions automatiques, comme la balance des blancs, qui nécessitent un certain temps et plusieurs images pour s’ajuster à l’environnement. Après un redémarrage depuis la veille profonde, il faut donc laisser à la caméra le temps de s’adapter.

void skipPictures(int n) {
  for(int i=0; i<n; i++) {
    camera_fb_t* fb = esp_camera_fb_get();
    esp_camera_fb_return(fb);
  }
}

Si vous prenez la première image après un redémarrage, elle sera de très mauvaise qualité, souvent avec une forte dominante bleue, ou trop sombre ou trop claire. En sautant les premières images, vous obtenez généralement (mais pas toujours) des photos de bonne qualité.

Vous pouvez aussi essayer de désactiver la balance des blancs automatique et d’autres fonctions automatiques dans les réglages de la caméra, mais il faudra alors un environnement très stable pour ajuster les autres paramètres. Sinon, il sera difficile d’obtenir de bonnes photos.

Prendre une photo

La fonction takePicture() capture une image avec la caméra et l’enregistre sur la carte SD avec un nom de fichier unique basé sur la valeur du compteur. On crée d’abord un frame buffer fb en appelant esp_camera_fb_get() . Ensuite, on crée un nom de fichier unique pour la photo et on enregistre le frame buffer en tant que fichier JPG (img{cnt}.jpg) sur la carte SD. Enfin, on libère la mémoire utilisée par le frame buffer en appelant esp_camera_fb_return .

void takePicture() {
  camera_fb_t* fb = esp_camera_fb_get();
  unsigned int cnt = incCounter();
  String path = "/img" + String(cnt) + ".jpg";
  File file = SD_MMC.open(path.c_str(), FILE_WRITE);
  file.write(fb->buf, fb->len);
  file.close();
  esp_camera_fb_return(fb);
}

Veille profonde

La fonction deepSleep() met l’ESP32 en mode veille profonde pour une durée spécifiée après la capture de l’image. Cela permet d’économiser l’énergie lorsque l’appareil ne prend pas de photos.

Les trois premières lignes ( esp_sleep_pd_config, rtc_gpio_pulldown_en, rtc_gpio_pullup_dis ) activent la résistance de pull-down interne sur GPIO13 , où le capteur PIR est connecté. Le code/ESP32-CAM fonctionne sans utiliser la résistance de pull-down interne, mais j’ai préféré jouer la sécurité ici.

Ensuite, on spécifie la source de réveil via esp_sleep_enable_ext0_wakeup(GPIO_NUM_13, 1) . Cela signifie que si GPIO13 passe à l’état haut (1 = le capteur PIR a détecté un mouvement), on réveille l’ESP32-CAM de la veille profonde.

Avant de passer en veille profonde, on delay pendant quelques secondes ( atleast ) pour éviter de prendre des photos trop fréquemment. J’ai utilisé 5 secondes et il est difficile d’aller plus vite à cause des temps de blocage et de délai du capteur PIR lui-même. Mais vous pouvez augmenter ce temps, par exemple à 10 ou 60 secondes, si vous souhaitez réduire le nombre de photos prises.

void deepSleep(int atleast) {
  esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
  rtc_gpio_pulldown_en(GPIO_NUM_13);
  rtc_gpio_pullup_dis(GPIO_NUM_13);
  esp_sleep_enable_ext0_wakeup(GPIO_NUM_13, 1);
  delay(atleast);
  esp_deep_sleep_start();
}

Fonction setup

La fonction setup() est celle où tout s’assemble. On commence par appeler WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0) pour désactiver la détection de brownout . Si l’alimentation est instable ou si l’ESP32-CAM consomme trop de courant au démarrage du WiFi ou lors de l’écriture sur la carte SD, cela évite un redémarrage automatique. Pour plus de détails, voir cet article de blog Disabling the ESP32 Brownout detector .

Je n’ai pas eu de problème de brownout et vous pouvez probablement désactiver cette ligne. L’avantage de la détection de brownout est de réduire le risque de corruption de la carte SD. L’inconvénient, c’est que cela peut provoquer des redémarrages accidentels. Cela dépendra de votre alimentation, à vous de voir ce qui est préférable.

Après avoir géré le brownout, on active la LED du flash via enableFlash(true) . Ensuite, on réserve 8 octets de mémoire dans l’EEPROM pour stocker le compteur de fichiers, on initialise la carte SD avec SD_MMC.begin() et on configure la caméra.

Enfin, on prend réellement la photo en appelant notre fonction takePicture() . Après cela, on désactive la LED du flash et on met l’ESP32-CAM en veille profonde (pour au moins 5 secondes).

void setup() {
  WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);
  enableFlash(true);
  EEPROM.begin(8);
  SD_MMC.begin();
  configCamera();
  takePicture();
  enableFlash(false);
  deepSleep(5000);
}

Fonction loop

La fonction loop() est vide dans ce code, car la logique principale est dans la fonction setup. L’ESP32 exécute la fonction setup, passe en veille profonde, se réveille lorsqu’un mouvement est détecté, puis relance la fonction setup. La fonction loop n’est jamais exécutée.

void loop() {
  // Empty loop
}

Et voilà, vous avez le code complet pour une ESP32-CAM déclenchée par mouvement.

Lorsque vous exécutez le code, vous remarquerez peut-être que le compteur de fichiers commence à un nombre arbitraire et non à zéro. Vous pouvez réinitialiser le compteur de fichiers en exécutant le code suivant.

Réinitialiser le compteur de fichiers

Téléverser et exécuter le code ci-dessous réinitialisera le compteur de fichiers stocké à l’adresse 0 à zéro. Ensuite, il faudra téléverser à nouveau le code principal de prise de photos.

#include "EEPROM.h"
  
void setup() {
  EEPROM.begin(512);
  unsigned int cnt = 0;
  EEPROM.put(0, cnt);
  EEPROM.commit();
}

void loop() {
}

Nous avons le code, nous avons le câblage, parlons maintenant de l’alimentation du projet.

ESP32-CAM alimentée par batterie

Souvent, on souhaite faire fonctionner une ESP32-CAM à détection de mouvement sur batterie, par exemple pour l’observation de la faune. Trouver la bonne source d’alimentation s’avère assez compliqué. Je vais vous présenter ci-dessous quatre options que j’ai testées.

Batterie externe USB 1

La première option consiste à utiliser une batterie externe USB classique. Tout le monde en a une pour recharger son téléphone en cas d’urgence. J’ai essayé d’utiliser la batterie externe ci-dessous.

USB Power Bank with automatic Shutdown
Batterie externe USB avec arrêt automatique

C’est une batterie externe de 30 000 mAh qui pourrait faire fonctionner l’ESP32-CAM très longtemps. Cependant, cette batterie dispose d’un arrêt automatique. Si la charge sur la sortie est très faible (<80 mA), ce qui arrive lorsque l’ESP32-CAM passe en veille profonde (6 mA), la batterie s’éteint.

L’ESP32-CAM fonctionnait environ 10 à 15 secondes, prenait quelques photos puis ne se réveillait plus jamais. J’ai mis du temps à comprendre, pensant que mon code ou mon câblage était en cause : (

Leçon retenue : n’utilisez pas de batterie externe avec arrêt automatique pour ce projet.

Batterie externe USB 2

J’avais une deuxième batterie externe, ci-dessous, d’une capacité de 10 000 mAh.

USB Power Bank without automatic Shutdown
Batterie externe USB sans arrêt automatique

Cette batterie ne s’éteint pas automatiquement, mais en l’utilisant avec le module PIR HC-SR505, je n’ai pas réussi à faire fonctionner correctement le capteur. La sortie du capteur restait toujours à l’état haut, même en utilisant le module seul (sans l’ESP32-CAM), juste avec l’alimentation et une LED.

Un coup d’œil à l’oscilloscope a révélé que cette batterie externe présente une ondulation visible sur sa sortie 5 V, avec une fréquence d’environ 160 Hz et une amplitude de 88 mV. Je pense que cela a causé les problèmes avec le module PIR HC-SR505, car ce capteur fonctionnait bien avec une pile 9 V, par exemple.

Ondulation de la tension de sortie 5 V de la batterie externe USB

L’ESP32-CAM avec un capteur PIR HC-SR501 ou AM312 fonctionnait bien avec cette batterie externe lors de mes tests, mais j’avais quelques doutes sur la fiabilité à long terme. Ce montage serait-il fiable sur plusieurs jours ou semaines ?

Motion-activated ESP32-CAM powered by USB Power Bank
ESP32-CAM à détection de mouvement alimentée par batterie externe USB

Je pense qu’il vaut mieux utiliser une batterie rechargeable classique, qui n’a pas le circuit d’élévation de tension interne d’une batterie externe USB, responsable de ces ondulations sur la tension de sortie.

Batterie rechargeable 9 V

Pour alimenter l’ESP32-CAM et le capteur PIR, vous pouvez simplement utiliser une pile 9 V. Ici, j’ai utilisé une pile rechargeable 9 V de 1000 mAh, connectée directement à la broche 5V de la carte ESP32-CAM et à la broche VCC du capteur PIR.

Motion-activated ESP32-CAM powered by 9V battery

Ce montage fonctionne bien, mais l’autonomie n’est pas exceptionnelle. L’ESP32-CAM consomme seulement 6 mA en veille profonde, mais jusqu’à 240 mA lorsqu’elle est active. En veille profonde, on pourrait tenir 1000 mAh / 6 mA = 166,67 heures = 6,9 jours, ce qui n’est pas mal. Mais si on prend souvent des photos, l’autonomie sera bien plus courte.

La courte vidéo ci-dessous montre que l’ESP32-CAM avec un module PIR AM312 peut fonctionner sur une pile 9 V.

Motion-activated ESP32-CAM powered by 9V battery in Action
ESP32-CAM à détection de mouvement alimentée par pile 9 V en action

Dans la section suivante, nous verrons des batteries de plus grande capacité pour augmenter l’autonomie.

Pack de batteries rechargeables 18650

Prenons donc une batterie plus grosse. Une batterie lithium-ion 18650 a une tension nominale de 3,6 V et une capacité de 1800 à 2800 mAh. Deux en série donnent 7,2 V en sortie, ce qui est parfait pour l’ESP32-CAM et permet aussi une certaine marge de chute de tension.

Motion-activated ESP32-CAM powered by two 18650 batteries
ESP32-CAM à détection de mouvement alimentée par deux batteries 18650

Avec une capacité de 2800 mAh, on peut presque tripler l’autonomie (par rapport à la batterie de 1000 mAh). Et si besoin, il suffit d’ajouter une deuxième paire de 18650 pour doubler encore l’autonomie.

Mais attention à la polarité lors du branchement des batteries. Les 18650 peuvent fournir de forts courants et j’ai grillé un de mes capteurs PIR en faisant cette erreur.

Dans la section suivante, j’essaie d’estimer plus précisément l’autonomie.

Autonomie

J’ai mesuré la consommation en veille profonde de l’ESP32-CAM avec le capteur PIR AM312 connecté : 3,6 mA en deep-sleep. Lorsqu’elle est active et prend une photo, la consommation monte à environ 120 mA.

Si on utilise les deux batteries lithium-ion 18650 en série avec une capacité totale de 2800 mAh, on obtient 2800 mAh / 3,6 mA = 777,7 heures = 32 jours d’autonomie en veille profonde. Soit un mois d’autonomie, mais sans prendre de photos.

Supposons que l’on prenne 100 photos sur toute la période. L’ESP32-CAM reste éveillée 5 secondes à chaque photo, soit 100 * 120 mA * 5 sec / 60 = 1000 mAh.

Si on soustrait ces 1000 mAh à notre capacité de batterie de 2800 mAh, il reste 1800 mAh / 3,6 mA = 500 heures = 20 jours. Presque trois semaines ; c’est correct. Bien sûr, des températures basses ou un plus grand nombre de photos réduiront l’autonomie. À l’inverse, ajouter une deuxième paire de batteries 18650 est facile et double l’autonomie.

Conclusions

Dans ce tutoriel, nous avons construit avec succès une ESP32-CAM à détection de mouvement à l’aide d’un capteur PIR. Nous avons vu les bases des capteurs de mouvement PIR et comment les connecter à l’ESP32-CAM AI-Thinker. En implémentant le code fourni, notre ESP32-CAM peut maintenant capturer des images dès qu’un mouvement est détecté.

Si vous souhaitez être notifié à chaque détection de mouvement, consultez notre ESP32 send Telegram Message tutoriel, qui vous explique comment envoyer des messages à l’application Telegram sur votre téléphone.

Nous avons également exploré la possibilité d’alimenter l’ESP32-CAM sur batterie pour une solution plus portable. Ce projet ouvre de nombreuses possibilités pour créer des systèmes de surveillance, des pièges photographiques ou toute application nécessitant détection de mouvement et capture d’images.

La leçon la plus importante est qu’il faut bien choisir son capteur PIR et sa solution d’alimentation. Faire fonctionner l’ESP32-CAM n’est pas simple, mais le résultat en vaut la peine.

Bon bricolage !

Foire aux questions

Voici quelques questions fréquentes et solutions pour vous aider à dépanner :

Q : Y a-t-il des capteurs PIR spécifiques qui fonctionnent mieux avec l’ESP32-CAM ?

R : Oui, utilisez le HC-SR501 ou l’AM312. N’utilisez pas le HC-SR505, car son temps de délai est trop long et il pose des problèmes avec l’ESP32-AM.

Q : Comment puis-je régler la sensibilité du capteur PIR ?

R : Certains capteurs PIR (dont le HC-SR501) sont équipés d’un potentiomètre permettant de régler la sensibilité. En tournant le potentiomètre, vous pouvez ajuster la portée de détection du capteur.

Q : Puis-je alimenter l’ESP32-CAM avec une batterie ?

R : Oui, vous pouvez alimenter l’ESP32-CAM avec une batterie pour un montage portable. Si vous utilisez une batterie externe USB, assurez-vous qu’elle n’a pas d’arrêt automatique. L’idéal est d’utiliser une paire de batteries 18650 ou toute autre solution fournissant une tension stable entre 5 V et 12 V.

Q : Dois-je modifier le code pour différents capteurs PIR ?

R : Le code fourni dans ce tutoriel est générique et devrait fonctionner avec la plupart des capteurs PIR.

Q : Quelle est la portée d’un capteur PIR pour détecter un mouvement ?

R : Cela dépend du capteur et des conditions, mais en général autour de 5 mètres. Notez que vous ne pouvez pas placer le détecteur derrière une vitre et qu’il ne détectera pas les objets à la même température que l’environnement.

Q : Existe-t-il d’autres capteurs de mouvement utilisables avec l’ESP32-CAM ?

R : Oui, il existe d’autres capteurs de mouvement comme les capteurs ultrasoniques, les barrières photoélectriques ou les capteurs à micro-ondes qui peuvent aussi être utilisés avec l’ESP32-CAM.

Q : Comment puis-je augmenter l’autonomie de l’ESP32-CAM ?

R : Pour augmenter l’autonomie de l’ESP32-CAM, vous pouvez rallonger le temps de délai. Utiliser une batterie de plus grande capacité prolongera aussi l’autonomie.

Q : Pourquoi les images prises par l’ESP32-CAM ont-elles une teinte bleue après un redémarrage ?

R : La caméra dispose de fonctions automatiques, comme la balance des blancs, qui mettent un certain temps à s’ajuster à l’environnement. Sans cela, vous obtiendrez des images bleutées ou très sombres/claires. Pour éviter cela, il suffit de prendre plusieurs photos après un redémarrage et de les ignorer. Voir la fonction skipPictures() du tutoriel qui fait exactement cela.