Dans ce tutoriel, vous apprendrez comment prendre des photos avec un ESP32-CAM lorsqu’un bouton est pressé et les enregistrer sur la carte SD. Nous construisons essentiellement un appareil photo numérique simple.
Pièces requises
Vous aurez besoin d’un ESP32-CAM pour tester les exemples de code. Vous pouvez obtenir un ESP32-CAM avec un Shield USB-TTL pour la programmation ou un adaptateur FTDI USB-TTL. L’adaptateur FTDI USB-TTL est un peu plus encombrant à utiliser mais laisse les broches GPIO facilement accessibles. Le Shield USB-TTL est plus simple à utiliser mais il est plus difficile de connecter les broches GPIO.
Si vous souhaitez utiliser votre PC pour visualiser les photos prises par l’ESP32-CAM et enregistrées sur la carte SD, vous aurez peut-être aussi besoin d’un lecteur de carte SD.

ESP32-CAM avec Shield USB-TTL

Adaptateur FTDI USB-TTL

Jeu de fils Dupont

Plaque d’essai (breadboard)

Lecteur de carte SD
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.
Schéma de câblage
Nous voulons prendre une photo avec l’ESP32-CAM chaque fois qu’un bouton est pressé. Dans le schéma de câblage suivant, nous connectons donc un bouton poussoir entre la broche GND et la broche GPIO13 :

Chaque fois que le bouton est pressé (fermé), GPIO13 est relié à la masse. Cela fonctionne car GPIO13 (et d’autres broches GPIO) possède une résistance de tirage interne qui maintient GPIO13 à l’état haut lorsqu’aucune connexion n’est faite. Cela signifie que la fonction du bouton est inversée (lorsqu’il est fermé GPIO13 == LOW) et vous verrez cela dans la section code.
L’image suivante montre comment vous pouvez réaliser ce circuit avec une breadboard et l’ESP32-CAM :

Comme vous pouvez le voir, j’ai utilisé le Shield USB-TTL et j’ai pu créer un petit espace entre l’ESP32-CAM et le shield pour connecter les fils du bouton sur GND et GPIO13 :

Alternativement, vous pouvez utiliser un adaptateur FTDI USB-TTL ou connecter l’ESP32-CAM au Shield USB-TTL via un jeu de câbles Dupont.
Code pour la prise de photo et l’enregistrement
Le sketch Arduino suivant prend une photo avec la caméra ESP32-CAM et l’enregistre sur la carte SD lorsque le bouton connecté à GPIO13 est pressé (fermé).
Pour ce code, vous aurez besoin de la esp32cam bibliothèque. Vous pouvez l’installer via le LIBRARY MANAGER dans l’IDE Arduino. Il suffit de chercher « esp32cam » et de cliquer sur INSTALL. L’image ci-dessous montre l’installation terminée :

Voici le code complet de notre petite application de prise de photo. Jetez d’abord un œil, puis nous en discuterons en détail :
#include "FS.h"
#include "SD_MMC.h"
#include "esp32cam.h"
const byte btnPin = GPIO_NUM_13;
const auto RES = esp32cam::Resolution::find(1600, 1200);
void takePicAndSave() {
static int cnt = 0;
auto frame = esp32cam::capture();
if (frame == nullptr) {
Serial.println("Capture failed!");
return;
}
String path = "/img" + String(cnt++) + ".jpg";
File file = SD_MMC.open(path.c_str(), FILE_WRITE);
if (!file) {
Serial.println("Failed to open file!");
}
frame->writeTo(file);
Serial.printf("Wrote: %s\n", path.c_str());
file.close();
}
void enableFlash(bool enable) {
digitalWrite(GPIO_NUM_4, enable ? HIGH : LOW);
}
void initCamera() {
using namespace esp32cam;
Config cfg;
cfg.setPins(pins::AiThinker);
cfg.setResolution(RES);
cfg.setJpeg(80);
bool ok = Camera.begin(cfg);
Serial.println(ok ? "CAMERA OK" : "CAMERA FAIL");
}
void initSDCard() {
if (!SD_MMC.begin("/sdcard", true)) {
Serial.println("SD Card Mount Failed!");
} else if (SD_MMC.cardType() == CARD_NONE) {
Serial.println("No SD card inserted!");
}
Serial.println("SD card ready.");
}
void setup() {
Serial.begin(115200);
initCamera();
initSDCard();
pinMode(btnPin, INPUT);
pinMode(GPIO_NUM_4, OUTPUT);
enableFlash(false);
delay(1000);
}
void loop() {
if (!digitalRead(btnPin)) {
enableFlash(true);
takePicAndSave();
enableFlash(false);
delay(500);
}
}
Bibliothèques
Au début du code, trois bibliothèques sont incluses :
#include "FS.h" #include "SD_MMC.h" #include "esp32cam.h"
Ces bibliothèques sont essentielles pour le projet ESP32-CAM. La FS.h bibliothèque fournit des opérations sur le système de fichiers, SD_MMC.h permet à l’ESP32 d’interfacer avec les cartes SD via le bus MMC (MultiMediaCard), et esp32cam.h est une bibliothèque de haut niveau qui simplifie la configuration de la caméra et la capture d’images sur le module ESP32-CAM.
Constantes
Ensuite, une constante pour la broche du bouton et un réglage de résolution de la caméra sont définis :
const byte btnPin = GPIO_NUM_13; const auto RES = esp32cam::Resolution::find(1600, 1200);
Ici, btnPin est assigné à GPIO 13, où le bouton est connecté. Vous pouvez aussi utiliser GPIO 12 mais dans les deux cas, vous devez faire fonctionner l’interface de la carte SD en mode 1-bit ! Pour plus de détails, voir le tutoriel More GPIO pins for ESP32-CAM.
L’objet RES définit la résolution de l’image, ici 1600×1200 pixels (UXGA), qui sera utilisée plus tard pour configurer la caméra. Voici une liste des résolutions possibles, bien que selon la caméra, toutes ne fonctionnent pas forcément :
- 96×96
- 160×120
- 128×128
- 176×144
- 240×176
- 240×240
- 320×240
- 320×320
- 400×296
- 480×320
- 640×480
- 800×600
- 1024×768
- 1280×720
- 1280×1024
- 1600×1200
takePicAndSave
La fonction takePicAndSave() est la fonction principale qui capture une image et l’écrit sur la carte SD :
void takePicAndSave() {
static int cnt = 0;
La variable cnt est déclarée static, ce qui signifie qu’elle conserve sa valeur entre les appels de fonction. Nous l’utilisons pour générer des noms de fichiers uniques pour chaque photo.
auto frame = esp32cam::capture();
if (frame == nullptr) {
Serial.println("Capture failed!");
return;
}
La fonction appelle esp32cam::capture() pour capturer une image depuis la caméra. Si la capture échoue (c’est-à-dire si frame est nullptr), un message d’erreur est affiché et la fonction quitte prématurément.
String path = "/img" + String(cnt++) + ".jpg"; File file = SD_MMC.open(path.c_str(), FILE_WRITE);
Le code construit un nom de fichier en concaténant « img » avec la valeur incrémentée de cnt et en ajoutant « .jpg ». Le fichier est ensuite ouvert sur la carte SD en écriture.
if (!file) {
Serial.println("Failed to open file!");
}
Si le fichier ne peut pas être ouvert (par exemple, carte SD absente, erreur système de fichiers), un message d’erreur est affiché.
frame->writeTo(file);
Serial.printf("Wrote: %s\n", path.c_str());
file.close();
}
Si le fichier s’ouvre correctement, l’image capturée est écrite dans le fichier, un message de confirmation est affiché dans le moniteur série avec le nom du fichier sauvegardé, et enfin, le fichier est fermé pour garantir l’intégrité des données.
enableFlash
La fonction enableFlash(bool enable) contrôle la LED flash intégrée de l’ESP32-CAM :
void enableFlash(bool enable) {
digitalWrite(GPIO_NUM_4, enable ? HIGH : LOW);
}
Cette fonction règle le niveau de tension sur GPIO 4. Quand enable est vrai, elle met GPIO 4 à HIGH, allumant la LED flash ; sinon, elle la met à LOW, éteignant la LED.
Pour plus d’informations sur le contrôle de la LED flash, voir le tutoriel Control ESP32-CAM Flash LED.
initCamera
La fonction initCamera() initialise le module caméra :
void initCamera() {
using namespace esp32cam;
Config cfg;
cfg.setPins(pins::AiThinker);
cfg.setResolution(RES);
cfg.setJpeg(80);
Dans initCamera(), elle importe d’abord l’espace de noms esp32cam en local. Puis, elle crée un objet Config, cfg, et le configure pour utiliser les broches prédéfinies pour une carte Ai-Thinker, qui est le type de carte typique des modules ESP32-CAM. Elle règle la résolution de la caméra à RES (1600×1200) et la qualité de compression JPEG à 80 (100 étant la meilleure qualité, des valeurs plus basses signifient plus de compression et une qualité moindre).
bool ok = Camera.begin(cfg);
Serial.println(ok ? "CAMERA OK" : "CAMERA FAIL");
}
La fonction Camera.begin(cfg) essaie de démarrer la caméra avec les réglages spécifiés. Elle affiche « CAMERA OK » si réussi, ou « CAMERA FAIL » sinon.
initSDCard
La fonction initSDCard() monte la carte SD :
void initSDCard() {
if (!SD_MMC.begin("/sdcard", true)) {
Serial.println("SD Card Mount Failed!");
} else if (SD_MMC.cardType() == CARD_NONE) {
Serial.println("No SD card inserted!");
}
Serial.println("SD card ready.");
}
Ici, SD_MMC.begin() initialise le bus SD_MMC et tente de monter le système de fichiers sous le chemin /sdcard. Le second argument true active le mode 1 ligne, qui simplifie le câblage au prix d’une vitesse réduite. Si le montage échoue, elle affiche « SD Card Mount Failed ! ». Si la carte est montée mais qu’aucune carte n’est insérée physiquement, elle affiche « No SD card inserted ! ». Sinon, elle suppose que tout est correct et affiche « SD card ready. »
setup
La fonction setup() prépare tout au démarrage :
void setup() {
Serial.begin(115200);
initCamera();
initSDCard();
pinMode(btnPin, INPUT);
pinMode(GPIO_NUM_4, OUTPUT);
enableFlash(false);
delay(1000);
}
Dans setup(), le port série est lancé à 115200 bauds pour le débogage. La caméra et la carte SD sont initialisées en appelant les fonctions initCamera() et initSDCard(). Ensuite, la broche du bouton (btnPin) est configurée en entrée, et la broche de contrôle du flash (GPIO 4) en sortie. enableFlash(false) assure que la LED flash est éteinte au départ. Un délai d’une seconde (1000 millisecondes) est ajouté à la fin pour laisser le système se stabiliser avant de commencer la boucle principale.
loop
Enfin, la fonction loop() vérifie constamment si le bouton est pressé :
void loop() {
if (!digitalRead(btnPin)) {
enableFlash(true);
takePicAndSave();
enableFlash(false);
delay(500);
}
}
Dans loop(), elle lit l’état de btnPin. Si le bouton est pressé, digitalRead(btnPin) retourne LOW car la broche est reliée à la masse quand le bouton est pressé. Lorsqu’un appui est détecté, le flash est allumé en appelant enableFlash(true), puis une photo est prise et enregistrée en appelant takePicAndSave(), et enfin, le flash est éteint avec enableFlash(false). Un délai de 500 millisecondes suit pour éviter de prendre plusieurs photos lors d’un seul appui.
Conclusions
Dans ce tutoriel, vous avez appris à construire un petit appareil photo numérique avec l’ESP32-CAM. L’exemple de code configure un ESP32-CAM pour surveiller un bouton. Quand le bouton est pressé, il allume le flash, capture une photo en 1600×1200, l’enregistre sur la carte SD sous un nom de fichier séquentiel comme /img0.jpg, /img1.jpg, etc., éteint le flash, puis attend brièvement avant de recommencer à écouter.
Si vous souhaitez mettre l’ESP32 en deep-sleep entre les prises de photos, consultez le tutoriel Motion Activated ESP32-CAM et pour le streaming vidéo, voir l’article Stream Video with ESP32-CAM.
De plus, si vous voulez être notifié à chaque détection de mouvement, regardez notre tutoriel ESP32 send Telegram Message, qui vous apprend à envoyer des messages à l’application Telegram sur votre téléphone.
Et si vous avez des questions, n’hésitez pas à les poser dans la section commentaires.
Bon bricolage 😉

