Dans ce projet, nous allons construire une caméra de surveillance IP avec la carte ESP32-CAM. La caméra ESP32 va héberger un serveur Web de streaming vidéo auquel vous pouvez accéder avec n’importe quel appareil de votre réseau.
Vous pouvez intégrer ce serveur Web de streaming vidéo avec des plates-formes domotiques populaires telles que Assistante à domicile ou Noeud-ROUGE. Dans ce tutoriel, nous allons vous montrer comment l’intégrer à Home Assistant et Node-RED.
Regardez le didacticiel vidéo
Vous pouvez regarder le didacticiel vidéo ou continuer à lire cette page pour les instructions écrites.
Pièces requises
Pour suivre ce tutoriel, vous avez besoin des composants suivants :
Vous pouvez utiliser les liens précédents ou aller directement sur MakerAdvisor.com/tools pour trouver toutes les pièces pour vos projets au meilleur prix !
Présentation de l’ESP32-CAM
le ESP32-CAM est un très petit module de caméra avec la puce ESP32-S qui coûte moins de 10 $. Vous pouvez lire notre guide de démarrage pour l’ESP32-CAM et apprendre à utiliser l’exemple de streaming vidéo et de reconnaissance faciale.
Serveur de diffusion vidéo
Suivez les étapes suivantes pour créer un serveur Web de streaming vidéo avec l’ESP32-CAM auquel vous pouvez accéder sur votre réseau local.
1. Installez le module complémentaire ESP32
Dans cet exemple, nous utilisons Arduino IDE pour programmer la carte ESP32-CAM. Donc, vous devez avoir installé Arduino IDE ainsi que le module complémentaire ESP32. Suivez l’un des prochains tutoriels pour installer le module complémentaire ESP32, si vous ne l’avez pas déjà fait :
2. Code de serveur Web de streaming vidéo
Après cela, copiez le code ci-dessous dans votre IDE Arduino.
/*********
Rui Santos
Complete project details at https://Raspberryme.com/esp32-cam-video-streaming-web-server-camera-home-assistant/
IMPORTANT!!!
- Select Board "AI Thinker ESP32-CAM"
- GPIO 0 must be connected to GND to upload a sketch
- After connecting GPIO 0 to GND, press the ESP32-CAM on-board RESET button to put your board in flashing mode
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
*********/
#include "esp_camera.h"
#include <WiFi.h>
#include "esp_timer.h"
#include "img_converters.h"
#include "Arduino.h"
#include "fb_gfx.h"
#include "soc/soc.h" //disable brownout problems
#include "soc/rtc_cntl_reg.h" //disable brownout problems
#include "esp_http_server.h"
//Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
#define PART_BOUNDARY "123456789000000000000987654321"
// This project was tested with the AI Thinker Model, M5STACK PSRAM Model and M5STACK WITHOUT PSRAM
#define CAMERA_MODEL_AI_THINKER
//#define CAMERA_MODEL_M5STACK_PSRAM
//#define CAMERA_MODEL_M5STACK_WITHOUT_PSRAM
// Not tested with this model
//#define CAMERA_MODEL_WROVER_KIT
#if defined(CAMERA_MODEL_WROVER_KIT)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 21
#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 19
#define Y4_GPIO_NUM 18
#define Y3_GPIO_NUM 5
#define Y2_GPIO_NUM 4
#define VSYNC_GPIO_NUM 25
#define HREF_GPIO_NUM 23
#define PCLK_GPIO_NUM 22
#elif defined(CAMERA_MODEL_M5STACK_PSRAM)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM 15
#define XCLK_GPIO_NUM 27
#define SIOD_GPIO_NUM 25
#define SIOC_GPIO_NUM 23
#define Y9_GPIO_NUM 19
#define Y8_GPIO_NUM 36
#define Y7_GPIO_NUM 18
#define Y6_GPIO_NUM 39
#define Y5_GPIO_NUM 5
#define Y4_GPIO_NUM 34
#define Y3_GPIO_NUM 35
#define Y2_GPIO_NUM 32
#define VSYNC_GPIO_NUM 22
#define HREF_GPIO_NUM 26
#define PCLK_GPIO_NUM 21
#elif defined(CAMERA_MODEL_M5STACK_WITHOUT_PSRAM)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM 15
#define XCLK_GPIO_NUM 27
#define SIOD_GPIO_NUM 25
#define SIOC_GPIO_NUM 23
#define Y9_GPIO_NUM 19
#define Y8_GPIO_NUM 36
#define Y7_GPIO_NUM 18
#define Y6_GPIO_NUM 39
#define Y5_GPIO_NUM 5
#define Y4_GPIO_NUM 34
#define Y3_GPIO_NUM 35
#define Y2_GPIO_NUM 17
#define VSYNC_GPIO_NUM 22
#define HREF_GPIO_NUM 26
#define PCLK_GPIO_NUM 21
#elif defined(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
#else
#error "Camera model not selected"
#endif
static const char* _STREAM_CONTENT_TYPE = "multipart/x-mixed-replace;boundary=" PART_BOUNDARY;
static const char* _STREAM_BOUNDARY = "rn--" PART_BOUNDARY "rn";
static const char* _STREAM_PART = "Content-Type: image/jpegrnContent-Length: %urnrn";
httpd_handle_t stream_httpd = NULL;
static esp_err_t stream_handler(httpd_req_t *req){
camera_fb_t * fb = NULL;
esp_err_t res = ESP_OK;
size_t _jpg_buf_len = 0;
uint8_t * _jpg_buf = NULL;
char * part_buf[64];
res = httpd_resp_set_type(req, _STREAM_CONTENT_TYPE);
if(res != ESP_OK){
return res;
}
while(true){
fb = esp_camera_fb_get();
if (!fb) {
Serial.println("Camera capture failed");
res = ESP_FAIL;
} else {
if(fb->width > 400){
if(fb->format != PIXFORMAT_JPEG){
bool jpeg_converted = frame2jpg(fb, 80, &_jpg_buf, &_jpg_buf_len);
esp_camera_fb_return(fb);
fb = NULL;
if(!jpeg_converted){
Serial.println("JPEG compression failed");
res = ESP_FAIL;
}
} else {
_jpg_buf_len = fb->len;
_jpg_buf = fb->buf;
}
}
}
if(res == ESP_OK){
size_t hlen = snprintf((char *)part_buf, 64, _STREAM_PART, _jpg_buf_len);
res = httpd_resp_send_chunk(req, (const char *)part_buf, hlen);
}
if(res == ESP_OK){
res = httpd_resp_send_chunk(req, (const char *)_jpg_buf, _jpg_buf_len);
}
if(res == ESP_OK){
res = httpd_resp_send_chunk(req, _STREAM_BOUNDARY, strlen(_STREAM_BOUNDARY));
}
if(fb){
esp_camera_fb_return(fb);
fb = NULL;
_jpg_buf = NULL;
} else if(_jpg_buf){
free(_jpg_buf);
_jpg_buf = NULL;
}
if(res != ESP_OK){
break;
}
//Serial.printf("MJPG: %uBn",(uint32_t)(_jpg_buf_len));
}
return res;
}
void startCameraServer(){
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
config.server_port = 80;
httpd_uri_t index_uri = {
.uri = "/",
.method = HTTP_GET,
.handler = stream_handler,
.user_ctx = NULL
};
//Serial.printf("Starting web server on port: '%d'n", config.server_port);
if (httpd_start(&stream_httpd, &config) == ESP_OK) {
httpd_register_uri_handler(stream_httpd, &index_uri);
}
}
void setup() {
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); //disable brownout detector
Serial.begin(115200);
Serial.setDebugOutput(false);
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;
if(psramFound()){
config.frame_size = FRAMESIZE_UXGA;
config.jpeg_quality = 10;
config.fb_count = 2;
} else {
config.frame_size = FRAMESIZE_SVGA;
config.jpeg_quality = 12;
config.fb_count = 1;
}
// Camera init
esp_err_t err = esp_camera_init(&config);
if (err != ESP_OK) {
Serial.printf("Camera init failed with error 0x%x", err);
return;
}
// Wi-Fi connection
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.print("Camera Stream Ready! Go to: http://");
Serial.print(WiFi.localIP());
// Start streaming web server
startCameraServer();
}
void loop() {
delay(1);
}
Avant de télécharger le code, vous devez insérer vos identifiants réseau dans les variables suivantes :
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
Ensuite, assurez-vous de sélectionner le bon module de caméra. Dans ce cas, nous utilisons le modèle AI-THINKER.
Si vous utilisez le même module de caméra, vous n’avez pas besoin de modifier quoi que ce soit sur le code.
#define CAMERA_MODEL_AI_THINKER
Maintenant, vous pouvez télécharger le code sur votre carte ESP32-CAM.
3. Téléchargement du code
Connectez la carte ESP32-CAM à votre ordinateur à l’aide d’un programmeur FTDI. Suivez le schéma suivant :
De nombreux programmeurs FTDI ont un cavalier qui vous permet de sélectionner 3,3 V ou 5 V. Assurez-vous que le cavalier est au bon endroit pour sélectionner 5V.
Important: GPIO 0 doit être connecté à GND afin que vous puissiez télécharger du code.
ESP32-CAM | Programmeur FTDI |
GND | GND |
5V | VCC (5V) |
U0R | Émission |
U0T | Réception |
GPIO 0 | GND |
Pour télécharger le code, suivez les étapes suivantes :
1) Aller à Outils > Conseil et sélectionnez AI-penseur ESP32-CAM.
2) Aller à Outils > Port et sélectionnez le port COM auquel l’ESP32 est connecté.
3) Ensuite, cliquez sur le bouton de téléchargement pour télécharger le code.
4) Lorsque vous commencez à voir ces points sur la fenêtre de débogage comme indiqué ci-dessous, appuyez sur le bouton RST intégré de l’ESP32-CAM.
Après quelques secondes, le code devrait être téléchargé avec succès sur votre tableau.
Obtenir l’adresse IP
Après avoir téléchargé le code, déconnectez-vous GPIO 0 à partir de GND. Ouvrez le moniteur série à un débit en bauds de 115 200. Appuyez sur le bouton de réinitialisation intégré de l’ESP32-CAM.
L’adresse IP ESP32 doit être imprimée dans le moniteur série.
Accéder au serveur de streaming vidéo
Maintenant, vous pouvez accéder à votre serveur de streaming de caméra sur votre réseau local. Ouvrez un navigateur et saisissez l’adresse IP ESP32-CAM. Une page avec le streaming vidéo actuel devrait se charger.
Intégration de l’assistant à domicile
Faire fonctionner uniquement l’ESP32-CAM via IP peut être utile pour la plupart des gens, mais vous pouvez intégrer ce projet avec Home Assistant (ou avec d’autres plates-formes domotiques). Continuez à lire pour savoir comment intégrer Home Assistant.
Conditions préalables
Ajout d’ESP32-CAM à Home Assistant
Ouvrez votre tableau de bord Home Assistant et accédez à la suite Réglages menu.
Ouvert Configurer l’interface utilisateur:
Ajoutez une nouvelle carte à votre tableau de bord :
Choisissez une carte du type Image.
Dans le Champ URL de l’image, entrez votre adresse IP ESP32-CAM. Ensuite, cliquez sur le « SAUVER” et revenir au tableau de bord principal.
Si vous utilisez le fichier de configuration, c’est ce que vous devez ajouter.
Après cela, Home Assistant peut afficher le streaming vidéo ESP32-CAM.
Aller plus loin
Pour aller plus loin dans ce projet, vous pouvez utiliser un fausse caméra factice et placez l’ESP32-CAM à l’intérieur.
La carte ESP32-CAM s’intègre parfaitement dans le boîtier de la caméra factice.
Vous pouvez l’alimenter à l’aide d’un adaptateur secteur 5V via l’ESP32-CAM GND et 5V épingles.
Placez la caméra de surveillance dans un endroit approprié.
Après cela, accédez à l’adresse IP de la caméra ou à votre tableau de bord Home Assistant et voyez en temps réel ce qui se passe. L’image suivante nous montre tester la caméra de streaming vidéo. Sara prend une capture d’écran pendant que je filme la caméra.
C’est impressionnant ce que ce petit $9 Module caméra ESP32 peut faire et cela fonctionne de manière fiable. Maintenant, nous pouvons utiliser la caméra de surveillance pour voir en temps réel ce qui se passe dans ma porte d’entrée.
Astuce : Intégration de Node-RED
Le serveur Web de streaming vidéo s’intègre également avec Node-RED et Node-RED Dashboard. Il vous suffit de créer un nœud de modèle et d’ajouter les éléments suivants :
<div style="margin-bottom: 10px;">
<img src="https://YOUR-ESP32-CAM-IP-ADDRESS" width="650px">
</div>
Dans le src attribut, vous devez saisir votre adresse IP ESP32-CAM :
<div style="margin-bottom: 10px;">
<img src="https://192.168.1.91" width="650px">
</div>
Dépannage
Si vous obtenez l’une des erreurs suivantes, lisez notre Guide de dépannage ESP32-CAM : problèmes les plus courants résolus
- Échec de la connexion à ESP32 : attente de l’en-tête du paquet dépassée
- L’initialisation de la caméra a échoué avec l’erreur 0x20001 ou similaire
- Détecteur de baisse de tension ou erreur de méditation du gourou
- Esquisse trop grosse erreur – Mauvais schéma de partition sélectionné
- La carte à COMX n’est pas disponible – Port COM non sélectionné
- Erreur psram : le service GPIO isr n’est pas installé
- Signal Wi-Fi faible
- Pas d’adresse IP dans le moniteur série Arduino IDE
- Impossible d’ouvrir le serveur Web
- L’image est en retard/montre beaucoup de latence
Emballer
Dans ce didacticiel, nous vous avons montré comment créer un serveur Web de streaming vidéo simple avec la carte ESP32-CAM pour créer une caméra IP. Le serveur Web que nous avons construit peut être facilement intégré à votre plate-forme domotique comme Node-RED ou Home Assistant.
Nous espérons que ce tutoriel vous sera utile. Si vous n’avez pas encore d’ESP32-CAM, vous pouvez attrape-le ici.
Si vous aimez ce projet, vous aimerez peut-être aussi d’autres projets avec l’ESP32-CAM :
Merci d’avoir lu!