L’exemple CameraWebServer pour l’ESP32-CAM livré avec la librairie ESP32 est très bien pour tester et découvrir les fonctionnalités de la caméra. Le code est assez difficile à comprendre (surtout lorsqu’on débute) et surtout à modifier lorsqu’on veut développer une petite caméra de surveillance DIY. Je vous propose pour ce nouveau projet une version ultra-simplifiée du code qui intègre les principales fonctions que vous avez demandé dans les commentaires, à savoir comment attribuer une adresse IP fixe à l’ESP32-CAM, comment démarrer en mode AP (Access Point), comment re-démarrer automatiquement en cas de perte de connexion WiFi ou d’indisponibilité du réseau, comment faire une rotation de l’image de 90°
Dans le tutoriel précédent, j’avais fait une modification de l’exemple CameraWebServer afin que celui-ci diffuse une image fixe plus facile à intégrer sur un serveur domotique qu’un flux MJEG. (domoticz, home assistant, jeedom, node-red).
.IRPP_button , .IRPP_button .postImageUrl , .IRPP_button .centered-text-area { min-height: 86px; position: relative; } .IRPP_button , .IRPP_button:hover , .IRPP_button:visited , .IRPP_button:active { border:0!important; } .IRPP_button { display: block; transition: background-color 250ms; webkit-transition: background-color 250ms; width: 100%; opacity: 1; transition: opacity 250ms; webkit-transition: opacity 250ms; background-color: #eaeaea; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.17); -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.17); -o-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.17); -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.17); } .IRPP_button:active , .IRPP_button:hover { opacity: 1; transition: opacity 250ms; webkit-transition: opacity 250ms; } .IRPP_button .postImageUrl { background-position: center; background-size: cover; float: right; margin: 0; padding: 0; width: 30%; } .IRPP_button .centered-text-area { float: left; width: 70%; padding:0; margin:0; } .IRPP_button .ctaText { border-bottom: 0 solid #fff; color: #FFFFFF; font-size: 13px; font-weight: bold; letter-spacing: .125em; margin: 0; padding: 0; } .IRPP_button .postTitle { color: #141414; font-size: 16px; font-weight: 600; margin: 0; padding: 0; width: 100%; } .IRPP_button .ctaButton { background: #C0392B; color: #FFFFFF; border: none; border-radius: 3px; box-shadow: none; font-size: 14px; font-weight: bold; line-height: 26px; margin: 18px 14px 18px 14px; moz-border-radius: 3px; padding: 12px 0; text-align: center; text-decoration: none; text-shadow: none; webkit-border-radius: 3px; width: 80px; position: absolute; } .IRPP_button:hover .ctaButton { background: #E74C3C; } .IRPP_button .centered-text { display: table; height: 86px; padding:0; margin:0; padding-left: 108px!important; top: 0; } .IRPP_button .IRPP_button-content { display: table-cell; margin: 0; padding: 0; padding-right: 10px; position: relative; vertical-align: middle; width: 100%; } .IRPP_button:after { content: « »; display: block; clear: both; }
A LIRE AUSSI :
ESP32-CAM, flash du firmware officiel modifié avec capture d’image
Dans ce nouveau projet, je vous propose une version ultra-simplifiée du code et les principales fonctions demandées dans les commentaires. Vous pouvez accéder directement au paragraphe en suivant le lien
Comment attribuer (fixer) l’adresse IP de l’ESP32-CAM ?Comment démarrer l’ESP32-CAM en mode Access Point (AP) ?Comment faire un re-connexion automatique en cas de perte ou d’indisponibilité du réseau WiFi ?Code simplifié avec une interface HTMLComment stocker le code HTML de l’interface sous la forme d’une longue chaîne sur la mémoire Flash de l’ESP32Comment faire une rotation de 90° de l’image ?Code complet du projet ESP32-CAM
Le code a été développé avec une carte ESP32-CAM générique de type AI Thinker. Il devrait cependant fonctionner parfaitement à l’identique sur les cartes M5Stack et TTGO notamment.
Pour une application de vidéo surveillance, on trouve des modules OV2640 avec une optique de type fisheye pouvant atteindre jusqu’à 160° (au lieu de 78° en standard) qui est mieux adaptée.
Remarque concernant les librairies WiFiManager et esp_http_server.h
L’idéal serait de pouvoir saisir les paramètres de connexion au réseau WiFi lorsqu’on met en service la caméra ESP32-CAM.
Une version de la librairie WiFiManager est en cours de développement est disponible pour l’ESP32.
.IRPP_button , .IRPP_button .postImageUrl , .IRPP_button .centered-text-area { min-height: 86px; position: relative; } .IRPP_button , .IRPP_button:hover , .IRPP_button:visited , .IRPP_button:active { border:0!important; } .IRPP_button { display: block; transition: background-color 250ms; webkit-transition: background-color 250ms; width: 100%; opacity: 1; transition: opacity 250ms; webkit-transition: opacity 250ms; background-color: #eaeaea; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.17); -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.17); -o-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.17); -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.17); } .IRPP_button:active , .IRPP_button:hover { opacity: 1; transition: opacity 250ms; webkit-transition: opacity 250ms; } .IRPP_button .postImageUrl { background-position: center; background-size: cover; float: right; margin: 0; padding: 0; width: 30%; } .IRPP_button .centered-text-area { float: left; width: 70%; padding:0; margin:0; } .IRPP_button .ctaText { border-bottom: 0 solid #fff; color: #FFFFFF; font-size: 13px; font-weight: bold; letter-spacing: .125em; margin: 0; padding: 0; } .IRPP_button .postTitle { color: #141414; font-size: 16px; font-weight: 600; margin: 0; padding: 0; width: 100%; } .IRPP_button .ctaButton { background: #C0392B; color: #FFFFFF; border: none; border-radius: 3px; box-shadow: none; font-size: 14px; font-weight: bold; line-height: 26px; margin: 18px 14px 18px 14px; moz-border-radius: 3px; padding: 12px 0; text-align: center; text-decoration: none; text-shadow: none; webkit-border-radius: 3px; width: 80px; position: absolute; } .IRPP_button:hover .ctaButton { background: #E74C3C; } .IRPP_button .centered-text { display: table; height: 86px; padding:0; margin:0; padding-left: 108px!important; top: 0; } .IRPP_button .IRPP_button-content { display: table-cell; margin: 0; padding: 0; padding-right: 10px; position: relative; vertical-align: middle; width: 100%; } .IRPP_button:after { content: « »; display: block; clear: both; }
A LIRE AUSSI :
ESP32. Comment utiliser la librairie WiFiManager pour gérer les connexions WiFi
Malheureusement la librairie WiFiManager rentre en conflit avec la librairie esp_http_server.h du SDK ESP-IDF utilisée dans ce projet.
1. Attribuer (fixer) l’adresse IP de l’ESP32-CAM
Une adresse IP est automatiquement attribuée à l’ESP32-CAM lorsqu’il se connecte pour la première fois au réseau WiFi. La plupart des routeurs / box internet conservent cette adresse d’une part par optimisation, d’autre part pour nous faciliter la vie. En cas de panne ou de remplacement de matériel (routeur, box internet), l’adresse IP va changer, ce qui peut s’avérer être un problème pour une caméra de surveillance !
L’ESP32-CAM est avant tout une carte de développement ESP32. Le module caméra utilise plusieurs broches de l’ESP32 pour envoyer le flux vidéo. Le code est absolument identique à ce qu’on a déjà pu faire dans ce tutoriel.
.IRPP_button , .IRPP_button .postImageUrl , .IRPP_button .centered-text-area { min-height: 86px; position: relative; } .IRPP_button , .IRPP_button:hover , .IRPP_button:visited , .IRPP_button:active { border:0!important; } .IRPP_button { display: block; transition: background-color 250ms; webkit-transition: background-color 250ms; width: 100%; opacity: 1; transition: opacity 250ms; webkit-transition: opacity 250ms; background-color: #eaeaea; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.17); -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.17); -o-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.17); -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.17); } .IRPP_button:active , .IRPP_button:hover { opacity: 1; transition: opacity 250ms; webkit-transition: opacity 250ms; } .IRPP_button .postImageUrl { background-position: center; background-size: cover; float: right; margin: 0; padding: 0; width: 30%; } .IRPP_button .centered-text-area { float: left; width: 70%; padding:0; margin:0; } .IRPP_button .ctaText { border-bottom: 0 solid #fff; color: #FFFFFF; font-size: 13px; font-weight: bold; letter-spacing: .125em; margin: 0; padding: 0; } .IRPP_button .postTitle { color: #141414; font-size: 16px; font-weight: 600; margin: 0; padding: 0; width: 100%; } .IRPP_button .ctaButton { background: #C0392B; color: #FFFFFF; border: none; border-radius: 3px; box-shadow: none; font-size: 14px; font-weight: bold; line-height: 26px; margin: 18px 14px 18px 14px; moz-border-radius: 3px; padding: 12px 0; text-align: center; text-decoration: none; text-shadow: none; webkit-border-radius: 3px; width: 80px; position: absolute; } .IRPP_button:hover .ctaButton { background: #E74C3C; } .IRPP_button .centered-text { display: table; height: 86px; padding:0; margin:0; padding-left: 108px!important; top: 0; } .IRPP_button .IRPP_button-content { display: table-cell; margin: 0; padding: 0; padding-right: 10px; position: relative; vertical-align: middle; width: 100%; } .IRPP_button:after { content: « »; display: block; clear: both; }
A LIRE AUSSI :
Comment attribuer une IP fixe à un projet ESP32 ESP8266 ou ESP01
Pour attribuer l’adresse IP du module ESP32-CAM, il suffit de définir les paramètres de connexion avant d’appeler la méthode WiFi.begin(). Voici un exemple de configuration. L’ESP32-CAM aura l’adresse IP fixe 192.168.1.80 sur le réseau local. La box internet (ou le routeur est à l’adresse 192.168.1.1). Il ne vous reste qu’à adapter les paramètres à votre configuration réseau.
#define USE_FIXED_IP false// L’adresse IP que vous souhaitez attribuer à l’ESP32-CAM. Attention à ne pas utiliser une adresse existante !IPAddress local_IP(192, 168, 1, 80);// Adresse du routeur ou de la box internetIPAddress gateway(192, 168, 1, 1);IPAddress subnet(255, 255, 0, 0);IPAddress primaryDNS(8, 8, 8, 8); //optionalIPAddress secondaryDNS(8, 8, 4, 4); //optional
Pour attribuer l’adresse IP fixe, il suffira de passer à constante USE_FIXED_IP à true dans le code source du projet.
Démarrer l’ESP32-CAM en mode Access Point (AP)
Le mode AP pour Access Point permet de se connecter directement à l’ESP32-CAM. La caméra n’est pas connectée au réseau WiFi local, ni à internet. C’est un mode de fonctionnement privé en quelque sorte.
Il n’y a presque rien à faire pour activer le mode AP. Pour se connecter au réseau WiFi, on utilise la méthode WiFi.begin(). Pour démarrer l’ESP32 en mode AP, il suffit d’exécuter la méthode WiFi.softAP(ap_ssid, ap_password) à la place. Les paramètres de la méthode sont les suivants :
ap_ssid nom du réseau, 63 caractères max.ap_password mot de passe avec au minimum 8 caractères. NULL pour un accès libre. déconseillé !!!channel (optionnel) canal Wi-Fi, entre 1 et 13ssid_hidden (optionnel) 0 = diffuser le nom du réseau, 1 = cache le nom du réseau SSIDmax_connection nombre maximum de clients connectés simultanément à l’ESP32-CAM. 4 au maximum.
Pour activer le mode AP, il suffit de mettre la constante AP_MODE à true dans le code du projet
Re-connexion automatique en cas de perte ou d’indisponibilité du réseau WiFi
Problème récurrent avec l’ESP32-CAM, la re-connexion automatique en cas de perte de connexion du réseau WiFi. C’est essentiel d’avoir une fonction de re-connexion automatique surtout lorsqu’on utilise l’ESP32-CAM comme caméra de surveillance.
Plutôt que de re-démarrer l’ESP32 à l’aide de la méthode ESP.restart(), je vous conseille plutôt de plonger l’ESP32 en sommeil profond durant une certaine période. Contrairement à l’ESP8266, il n’y a rien à prévoir coté matériel pour activer le mode deep-sleep de l’ESP32. 2 lignes de codes suffisent !
void restartESP32Cam(){ esp_sleep_enable_timer_wakeup(uS_TO_S_FACTOR * TIME_TO_SLEEP); esp_deep_sleep_start();}
Vous trouverez beaucoup d’autres informations sur la mise en sommeil des modules ESP32 (et de facto l’ESP32-CAM) en lisant cet article détaillé.
.IRPP_button , .IRPP_button .postImageUrl , .IRPP_button .centered-text-area { min-height: 86px; position: relative; } .IRPP_button , .IRPP_button:hover , .IRPP_button:visited , .IRPP_button:active { border:0!important; } .IRPP_button { display: block; transition: background-color 250ms; webkit-transition: background-color 250ms; width: 100%; opacity: 1; transition: opacity 250ms; webkit-transition: opacity 250ms; background-color: #eaeaea; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.17); -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.17); -o-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.17); -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.17); } .IRPP_button:active , .IRPP_button:hover { opacity: 1; transition: opacity 250ms; webkit-transition: opacity 250ms; } .IRPP_button .postImageUrl { background-position: center; background-size: cover; float: right; margin: 0; padding: 0; width: 30%; } .IRPP_button .centered-text-area { float: left; width: 70%; padding:0; margin:0; } .IRPP_button .ctaText { border-bottom: 0 solid #fff; color: #FFFFFF; font-size: 13px; font-weight: bold; letter-spacing: .125em; margin: 0; padding: 0; } .IRPP_button .postTitle { color: #141414; font-size: 16px; font-weight: 600; margin: 0; padding: 0; width: 100%; } .IRPP_button .ctaButton { background: #C0392B; color: #FFFFFF; border: none; border-radius: 3px; box-shadow: none; font-size: 14px; font-weight: bold; line-height: 26px; margin: 18px 14px 18px 14px; moz-border-radius: 3px; padding: 12px 0; text-align: center; text-decoration: none; text-shadow: none; webkit-border-radius: 3px; width: 80px; position: absolute; } .IRPP_button:hover .ctaButton { background: #E74C3C; } .IRPP_button .centered-text { display: table; height: 86px; padding:0; margin:0; padding-left: 108px!important; top: 0; } .IRPP_button .IRPP_button-content { display: table-cell; margin: 0; padding: 0; padding-right: 10px; position: relative; vertical-align: middle; width: 100%; } .IRPP_button:after { content: « »; display: block; clear: both; }
A LIRE AUSSI :
ESP32. Code Arduino pour mise en sommeil (Deep Sleep) et réveils (Timer, Touch Pad, GPIO…)
Ensuite, il suffit compter le nombre de tentatives d’échec de connexion au démarrage et d’appeler la méthode restartESP32Cam lorsqu’on dépasse un seuil
WiFi.begin(ssid, password);while ( WiFi.status() != WL_CONNECTED) { delay(500); Serial.print(« . »); wifi_counter++; if ( wifi_counter > wifi_try ) { restartESP32Cam(); }}
Une fois démarré, il suffira de tester à chaque passage dans la boucle loop que la connexion est toujours disponible et d’appeler la mise en veille si ce n’est pas le cas.
void loop() { if ( WiFi.status() != WL_CONNECTED ) { // On vient de perdre la connexion WiFi restartESP32Cam(); } delay(10);}
Et voilà, maintenant dès l’ESP32-CAM sait se reconnecter automatiquement en cas de perte de connexion du réseau WiFi. Si votre ESP32-CAM fonctionne sur batterie, celle-ci ne sera pas drainée. Il faudra juste décider du temps durant lequel l’ESP32-CAM est mis en sommeil (deep-sleep). L’idéal serait d’avoir un système de secours basé sur LoRa afin de détecter une perte de connexion WiFi. C’est le principe utilisé notamment par Verisure qui dispose d’un canal Sigfox pour son système d’alarme en cas de coupure de courant.
Code de l’interface HTML simplifié
Vous avez certainement vu que le code de l’interface HTML de l’exemple CameraWebServer est compressé au format GZIP dans le fichier camera_index.h.
En voici un petit extrait par curiosité
//File: index_ov2640.html.gz, Size: 4316#define index_ov2640_html_gz_len 4316const uint8_t index_ov2640_html_gz[] = { 0x1F, 0x8B, 0x08, 0x08, 0x50, 0x5C, 0xAE, 0x5C, 0x00, 0x03, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x5F, 0x6F, 0x76, 0x32, 0x36, 0x34, 0x30, 0x2E, 0x68, 0x74, 0x6D, 0x6C, 0x00, 0xE5, 0x5D, 0x7B, 0x73, 0xD3, 0xC6, 0x16, 0xFF, 0x9F, 0x4F, 0x21, 0x04, 0x25, 0xF6, 0x34, 0x76, 0x6C, 0xC7, 0x84, 0xE0,….}
C’est une excellente idée car il n’est pas nécessaire de téléverser séparément l’interface HTML que l’on doit normalement placer dans le dossier data du projet Arduino.
Voici deux articles qui expliquent comment intégrer des fichiers HTML, CSS, JS à un projet ESP32 ou ESP8266 (le fonctionnement est identique).
.IRPP_button , .IRPP_button .postImageUrl , .IRPP_button .centered-text-area { min-height: 86px; position: relative; } .IRPP_button , .IRPP_button:hover , .IRPP_button:visited , .IRPP_button:active { border:0!important; } .IRPP_button { display: block; transition: background-color 250ms; webkit-transition: background-color 250ms; width: 100%; opacity: 1; transition: opacity 250ms; webkit-transition: opacity 250ms; background-color: #eaeaea; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.17); -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.17); -o-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.17); -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.17); } .IRPP_button:active , .IRPP_button:hover { opacity: 1; transition: opacity 250ms; webkit-transition: opacity 250ms; } .IRPP_button .postImageUrl { background-position: center; background-size: cover; float: right; margin: 0; padding: 0; width: 30%; } .IRPP_button .centered-text-area { float: left; width: 70%; padding:0; margin:0; } .IRPP_button .ctaText { border-bottom: 0 solid #fff; color: #FFFFFF; font-size: 13px; font-weight: bold; letter-spacing: .125em; margin: 0; padding: 0; } .IRPP_button .postTitle { color: #141414; font-size: 16px; font-weight: 600; margin: 0; padding: 0; width: 100%; } .IRPP_button .ctaButton { background: #C0392B; color: #FFFFFF; border: none; border-radius: 3px; box-shadow: none; font-size: 14px; font-weight: bold; line-height: 26px; margin: 18px 14px 18px 14px; moz-border-radius: 3px; padding: 12px 0; text-align: center; text-decoration: none; text-shadow: none; webkit-border-radius: 3px; width: 80px; position: absolute; } .IRPP_button:hover .ctaButton { background: #E74C3C; } .IRPP_button .centered-text { display: table; height: 86px; padding:0; margin:0; padding-left: 108px!important; top: 0; } .IRPP_button .IRPP_button-content { display: table-cell; margin: 0; padding: 0; padding-right: 10px; position: relative; vertical-align: middle; width: 100%; } .IRPP_button:after { content: « »; display: block; clear: both; }
A LIRE AUSSI :
ESP32 Sketch data upload pour IDE Arduino. Téléverser des fichiers SPIFFS sur la mémoire flash
.IRPP_button , .IRPP_button .postImageUrl , .IRPP_button .centered-text-area { min-height: 86px; position: relative; } .IRPP_button , .IRPP_button:hover , .IRPP_button:visited , .IRPP_button:active { border:0!important; } .IRPP_button { display: block; transition: background-color 250ms; webkit-transition: background-color 250ms; width: 100%; opacity: 1; transition: opacity 250ms; webkit-transition: opacity 250ms; background-color: #eaeaea; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.17); -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.17); -o-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.17); -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.17); } .IRPP_button:active , .IRPP_button:hover { opacity: 1; transition: opacity 250ms; webkit-transition: opacity 250ms; } .IRPP_button .postImageUrl { background-position: center; background-size: cover; float: right; margin: 0; padding: 0; width: 30%; } .IRPP_button .centered-text-area { float: left; width: 70%; padding:0; margin:0; } .IRPP_button .ctaText { border-bottom: 0 solid #fff; color: #FFFFFF; font-size: 13px; font-weight: bold; letter-spacing: .125em; margin: 0; padding: 0; } .IRPP_button .postTitle { color: #141414; font-size: 16px; font-weight: 600; margin: 0; padding: 0; width: 100%; } .IRPP_button .ctaButton { background: #C0392B; color: #FFFFFF; border: none; border-radius: 3px; box-shadow: none; font-size: 14px; font-weight: bold; line-height: 26px; margin: 18px 14px 18px 14px; moz-border-radius: 3px; padding: 12px 0; text-align: center; text-decoration: none; text-shadow: none; webkit-border-radius: 3px; width: 80px; position: absolute; } .IRPP_button:hover .ctaButton { background: #E74C3C; } .IRPP_button .centered-text { display: table; height: 86px; padding:0; margin:0; padding-left: 108px!important; top: 0; } .IRPP_button .IRPP_button-content { display: table-cell; margin: 0; padding: 0; padding-right: 10px; position: relative; vertical-align: middle; width: 100%; } .IRPP_button:after { content: « »; display: block; clear: both; }
A LIRE AUSSI :
Projet de station météo avec interface HTML sur ESP8266 (DHT22 + BMP180)
Le problème lorsqu’on débute, c’est qu’on ne peut pas modifier ce fichier, ni même s’en inspirer pour développer sa propre interface.
Voici une version ultra-simplifié que vous pouvez utiliser dans vos projets. Il diffuse le flux vidéo MJPEG de façon fluide sur n’importe quel navigateur. Vous trouverez également deux boutons qui permettent de tourner l’image vers la gauche ou la droite de 90° à chaque fois.
On serait tenter d’utiliser une chaine pour stocker le code HTML de la page mais c’est très rapidement difficile à gérer et à écrire. Regardez par exemple cet extrait de code HTML. On doit ajouter à la fin de chaque ligne le code n pour renvoyer à la ligne et mettre entre guillemets chaque ligne… des heures de mise au point !
const char http_index_hml[] = « n » »n » » n » » n » » n »…
Stocker le code HTML de l’interface dans une variable PROGMEM R”===()===”
A la place, on va utiliser l’opérateur C++ R qui permet de stocker n’importe quelle chaîne. Le R signifie “Traitez tout ce qui se trouve entre ces délimiteurs comme une chaîne brute”. Tout est expliqué en détail ici.
Le code de l’interface HTML sera donc stocker entre deux délimiteurs comme ceci.
R »delimiteur(code html de la page)delimiteur »
La chaîne entre les deux délimiteurs peut avoir n’importe quelle longueur et contenir n’importe quel caractère. Ce qui est important, c’est d’avoir le même délimiteur avant et après la chaîne.
Comme le code HTML peut être très long, il est préférable de le placer dans la mémoire flash plutôt que dans la SRAM, où il irait normalement. On peut faire cela à l’aide du mot clé PROGMEM qui est un modificateur de variable (documentation).
Voici le code source de la page HTML plus facile à manipuler. Vous pouvez même utiliser un générateur de code HTML puis le coller dans votre code pour aller encore plus vite !
const char index_html[] PROGMEM = R »=====( .row { display: flex; } .leftcol { flex: 30%; } .rightcol { flex: 70%; }
ESP32-CAM Stream Server
Rotate Image
« »
Use only HTML + CSS
)===== »;
Voici quelques articles pour vous aider à concevoir vos interfaces HTML.
.IRPP_button , .IRPP_button .postImageUrl , .IRPP_button .centered-text-area { min-height: 86px; position: relative; } .IRPP_button , .IRPP_button:hover , .IRPP_button:visited , .IRPP_button:active { border:0!important; } .IRPP_button { display: block; transition: background-color 250ms; webkit-transition: background-color 250ms; width: 100%; opacity: 1; transition: opacity 250ms; webkit-transition: opacity 250ms; background-color: #eaeaea; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.17); -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.17); -o-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.17); -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.17); } .IRPP_button:active , .IRPP_button:hover { opacity: 1; transition: opacity 250ms; webkit-transition: opacity 250ms; } .IRPP_button .postImageUrl { background-position: center; background-size: cover; float: right; margin: 0; padding: 0; width: 30%; } .IRPP_button .centered-text-area { float: left; width: 70%; padding:0; margin:0; } .IRPP_button .ctaText { border-bottom: 0 solid #fff; color: #FFFFFF; font-size: 13px; font-weight: bold; letter-spacing: .125em; margin: 0; padding: 0; } .IRPP_button .postTitle { color: #141414; font-size: 16px; font-weight: 600; margin: 0; padding: 0; width: 100%; } .IRPP_button .ctaButton { background: #C0392B; color: #FFFFFF; border: none; border-radius: 3px; box-shadow: none; font-size: 14px; font-weight: bold; line-height: 26px; margin: 18px 14px 18px 14px; moz-border-radius: 3px; padding: 12px 0; text-align: center; text-decoration: none; text-shadow: none; webkit-border-radius: 3px; width: 80px; position: absolute; } .IRPP_button:hover .ctaButton { background: #E74C3C; } .IRPP_button .centered-text { display: table; height: 86px; padding:0; margin:0; padding-left: 108px!important; top: 0; } .IRPP_button .IRPP_button-content { display: table-cell; margin: 0; padding: 0; padding-right: 10px; position: relative; vertical-align: middle; width: 100%; } .IRPP_button:after { content: « »; display: block; clear: both; }
A LIRE AUSSI :
Découverte du langage Pug (Jade) pour développer des interfaces HTML avec VSCode ou Geany
.IRPP_button , .IRPP_button .postImageUrl , .IRPP_button .centered-text-area { min-height: 86px; position: relative; } .IRPP_button , .IRPP_button:hover , .IRPP_button:visited , .IRPP_button:active { border:0!important; } .IRPP_button { display: block; transition: background-color 250ms; webkit-transition: background-color 250ms; width: 100%; opacity: 1; transition: opacity 250ms; webkit-transition: opacity 250ms; background-color: #eaeaea; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.17); -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.17); -o-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.17); -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.17); } .IRPP_button:active , .IRPP_button:hover { opacity: 1; transition: opacity 250ms; webkit-transition: opacity 250ms; } .IRPP_button .postImageUrl { background-position: center; background-size: cover; float: right; margin: 0; padding: 0; width: 30%; } .IRPP_button .centered-text-area { float: left; width: 70%; padding:0; margin:0; } .IRPP_button .ctaText { border-bottom: 0 solid #fff; color: #FFFFFF; font-size: 13px; font-weight: bold; letter-spacing: .125em; margin: 0; padding: 0; } .IRPP_button .postTitle { color: #141414; font-size: 16px; font-weight: 600; margin: 0; padding: 0; width: 100%; } .IRPP_button .ctaButton { background: #C0392B; color: #FFFFFF; border: none; border-radius: 3px; box-shadow: none; font-size: 14px; font-weight: bold; line-height: 26px; margin: 18px 14px 18px 14px; moz-border-radius: 3px; padding: 12px 0; text-align: center; text-decoration: none; text-shadow: none; webkit-border-radius: 3px; width: 80px; position: absolute; } .IRPP_button:hover .ctaButton { background: #E74C3C; } .IRPP_button .centered-text { display: table; height: 86px; padding:0; margin:0; padding-left: 108px!important; top: 0; } .IRPP_button .IRPP_button-content { display: table-cell; margin: 0; padding: 0; padding-right: 10px; position: relative; vertical-align: middle; width: 100%; } .IRPP_button:after { content: « »; display: block; clear: both; }
A LIRE AUSSI :
ESP8266. Développer et tester l’interface HTML avec Node.js et Pug (ancien Jade)
Si vous débuter en programmation C++ et les interfaces HTML, vous pouvez commencer par lire cet article plus détaillé
.IRPP_button , .IRPP_button .postImageUrl , .IRPP_button .centered-text-area { min-height: 86px; position: relative; } .IRPP_button , .IRPP_button:hover , .IRPP_button:visited , .IRPP_button:active { border:0!important; } .IRPP_button { display: block; transition: background-color 250ms; webkit-transition: background-color 250ms; width: 100%; opacity: 1; transition: opacity 250ms; webkit-transition: opacity 250ms; background-color: #eaeaea; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.17); -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.17); -o-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.17); -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.17); } .IRPP_button:active , .IRPP_button:hover { opacity: 1; transition: opacity 250ms; webkit-transition: opacity 250ms; } .IRPP_button .postImageUrl { background-position: center; background-size: cover; float: right; margin: 0; padding: 0; width: 30%; } .IRPP_button .centered-text-area { float: left; width: 70%; padding:0; margin:0; } .IRPP_button .ctaText { border-bottom: 0 solid #fff; color: #FFFFFF; font-size: 13px; font-weight: bold; letter-spacing: .125em; margin: 0; padding: 0; } .IRPP_button .postTitle { color: #141414; font-size: 16px; font-weight: 600; margin: 0; padding: 0; width: 100%; } .IRPP_button .ctaButton { background: #C0392B; color: #FFFFFF; border: none; border-radius: 3px; box-shadow: none; font-size: 14px; font-weight: bold; line-height: 26px; margin: 18px 14px 18px 14px; moz-border-radius: 3px; padding: 12px 0; text-align: center; text-decoration: none; text-shadow: none; webkit-border-radius: 3px; width: 80px; position: absolute; } .IRPP_button:hover .ctaButton { background: #E74C3C; } .IRPP_button .centered-text { display: table; height: 86px; padding:0; margin:0; padding-left: 108px!important; top: 0; } .IRPP_button .IRPP_button-content { display: table-cell; margin: 0; padding: 0; padding-right: 10px; position: relative; vertical-align: middle; width: 100%; } .IRPP_button:after { content: « »; display: block; clear: both; }
A LIRE AUSSI :
ESP8266. Comprendre le code Arduino d’un serveur web avec interface HTML
Comment faire une rotation de 90° de l’image
Il n’existe aucune fonction native permettant de faire une rotation directe de l’image. On dispose simplement des méthodes set_vflip et set_hmirror qui permettent respectivement d’inverser l’image verticalement (vflip) ou horizontalement (hmirror).
Le seul moyen de tourner l’image et donc de prévoir l’angle directement au niveau du montage ou de faire une rotation “logicielle”.
Sur un navigateur internet, c’est très facile, vous pourrez vous inspirer de la méthode sur un logiciel domotique. Il suffit en effet de faire une transformation de type rotate sur l’image. On indique simplement l’angle souhaité en degrés. Tout se passe coté navigateur, il n’y a aucune interaction avec le code Arduino du projet ESP32.
document.getElementById(« stream »).style.transform = ‘rotate(‘ + deg + ‘deg)’;
Code complet du projet
Voici le code source complet de l’exemple que vous pouvez également récupérer directement sur GitHub. Le projet peut être compilé à l’aide de l’IDE Arduino ou de PlatformIO.
Lisez cet article pour débuter votre projet ESP32-CAM et PlatformIO
.IRPP_button , .IRPP_button .postImageUrl , .IRPP_button .centered-text-area { min-height: 86px; position: relative; } .IRPP_button , .IRPP_button:hover , .IRPP_button:visited , .IRPP_button:active { border:0!important; } .IRPP_button { display: block; transition: background-color 250ms; webkit-transition: background-color 250ms; width: 100%; opacity: 1; transition: opacity 250ms; webkit-transition: opacity 250ms; background-color: #eaeaea; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.17); -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.17); -o-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.17); -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.17); } .IRPP_button:active , .IRPP_button:hover { opacity: 1; transition: opacity 250ms; webkit-transition: opacity 250ms; } .IRPP_button .postImageUrl { background-position: center; background-size: cover; float: right; margin: 0; padding: 0; width: 30%; } .IRPP_button .centered-text-area { float: left; width: 70%; padding:0; margin:0; } .IRPP_button .ctaText { border-bottom: 0 solid #fff; color: #FFFFFF; font-size: 13px; font-weight: bold; letter-spacing: .125em; margin: 0; padding: 0; } .IRPP_button .postTitle { color: #141414; font-size: 16px; font-weight: 600; margin: 0; padding: 0; width: 100%; } .IRPP_button .ctaButton { background: #C0392B; color: #FFFFFF; border: none; border-radius: 3px; box-shadow: none; font-size: 14px; font-weight: bold; line-height: 26px; margin: 18px 14px 18px 14px; moz-border-radius: 3px; padding: 12px 0; text-align: center; text-decoration: none; text-shadow: none; webkit-border-radius: 3px; width: 80px; position: absolute; } .IRPP_button:hover .ctaButton { background: #E74C3C; } .IRPP_button .centered-text { display: table; height: 86px; padding:0; margin:0; padding-left: 108px!important; top: 0; } .IRPP_button .IRPP_button-content { display: table-cell; margin: 0; padding: 0; padding-right: 10px; position: relative; vertical-align: middle; width: 100%; } .IRPP_button:after { content: « »; display: block; clear: both; }
A LIRE AUSSI :
ESP32-CAM. Migrer le projet CameraWebServer pour l’IDE Arduino vers PlatformIO
Le code source peut servir de base pour le développement de votre propre caméra de surveillance par exemple. Pour compiler avec l’IDE Arduino, renommer le fichier main.cpp en main.ino par exemple.
La base du code est identique à l’exemple CameraWebServer. Il utilise la librairie standard esp_http_server.h du SDK ESP-IDF. Deux ports sont utilisés. Le port 80 pour gérer l’interface avec l’utilisateur. Le port 81 sur lequel est envoyé le flux vidéo au format MJPEG.
.tabs-menu:not(.rh-tab-shortcode) li{ list-style:none !important;cursor:pointer; float: left; margin: 0 8px 8px 0; text-decoration: none; background: #000;transition: all 0.3s; text-align: center; padding: 8px 14px; font-weight:700; font-size: 15px; line-height:16px; color: #fff; text-transform: uppercase; outline: 0} .wpsm-tabs ul.tabs-menu { display: block; margin: 0; padding: 0; margin-bottom: -1px;z-index: 1;position: relative; } .wpsm-tabs ul.tabs-menu li { display: block; height: 40px; padding: 0; float: left; margin: 0; outline: none;} .wpsm-tabs ul.tabs-menu li span { display: block; text-decoration: none; padding: 0px 20px; line-height: 38px; border: solid 1px #ddd; border-width: 1px 1px 0 0; margin: 0; background-color: #f5f5f5; font-size: 1em; } .wpsm-tabs ul.tabs-menu li span:hover { background: #eee; } .wpsm-tabs ul.tabs-menu .current span { background: #fff; line-height: 36px; position: relative; margin: 0; border-top: 3px solid #fb7203;font-weight: bold;border-bottom: 1px solid #fff;} .wpsm-tabs ul.tabs-menu .current span:hover { background: #fff; } .wpsm-tabs ul.tabs-menu li:first-child span { margin-left: 0; border-left: 1px solid #ddd;} .wpsm-tabs .tab-content { background: #fff; padding: 20px; border: solid 1px #ddd; position: relative;z-index: 0 } .rtl .wpsm-tabs ul li{float: right;} .rtl .wpsm-tabs ul li:first-child span{border-left:none;} .rtl .wpsm-tabs ul li:last-child span{border-left: 1px solid #ddd;} @media screen and (max-width: 500px) { .wpsm-tabs ul.tabs-menu li{float:none !important}.wpsm-tabs ul.tabs-menu li span{border-left: 1px solid #ddd} }
main.cppcamera_pin.hplatformio.ini
/* Five ESP32-CAM tips. Simplified version of HTML and C ++ code Fixed IP address. AP mode. Image rotation 90 °. Automatic recovery WiFi connection. HTML code storage 5 astuces pour ESP32-CAM. Version simplifiée du code HTML et C++ Adresse IP fixe. Mode AP. Rotation image 90°. Récupération automatique connexion WiFi. stockage du code HTML Licence : see licence file */#include #include « esp_camera.h »#include #include « esp_http_server.h »// Select camera model// Dé-commentez (uniquement) votre ESP32-CAM//#define CAMERA_MODEL_WROVER_KIT//#define CAMERA_MODEL_ESP_EYE//#define CAMERA_MODEL_M5STACK_PSRAM//#define CAMERA_MODEL_M5STACK_WIDE#define CAMERA_MODEL_AI_THINKER#include « camera_pins.h »/**********************************************************************//* PARAMETRES WIFI *//**********************************************************************/const char* ssid = « enter_your_ssid »;const char* password = « enter_your_password »;// Activate AP mode AP (Access point). User need to connect directly to ESP32 wifi network to access video stream// Active le mode AP (Access point). L’ESP32-CAM n’est pas connectée au WiFi, on se connecte directement sur la caméra#define AP_MODE falseconst char* ap_ssid = « esp32-cam »;const char* ap_password = « 12345678 »; // Mini. 8 car/**********************************************************************//* USE FIXED IP *//* UTILISE UNE IP FIXE *//**********************************************************************/#define USE_FIXED_IP true// Set your Static IP address. Do not use existing IP address (other computer, TV box, printer, smartphone)// L’adresse IP que vous souhaitez attribuer à l’ESP32-CAM. Attention à ne pas utiliser une adresse existante !IPAddress local_IP(192, 168, 1, 80);// Set your Gateway IP address// Adresse du routeur ou de la box internetIPAddress gateway(192, 168, 1, 1);IPAddress subnet(255, 255, 0, 0);IPAddress primaryDNS(8, 8, 8, 8); //optionalIPAddress secondaryDNS(8, 8, 4, 4); //optional/**********************************************************************//* PARAMETRE DE REDEMARRAGE SI LE RESEAU WIFI N’EST PAS DISPONIBLE *//**********************************************************************/int wifi_counter = 0;#define wifi_try 10#define uS_TO_S_FACTOR 1000000ULL /* Conversion factor for micro seconds to seconds */#define TIME_TO_SLEEP 30 /* Time ESP32 will go to sleep (in seconds) *//**********************************************************************//* PROTOTYPES *//**********************************************************************/void restartESP32Cam();void startCameraServer();/**********************************************************************//* WEB SERVER + STREAM SERVER *//* SERVEUR WEB + SERVEUR VIDEO *//**********************************************************************/#define PART_BOUNDARY « 123456789000000000000987654321 »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;httpd_handle_t camera_httpd = NULL;// Stream sever port number// Numéro du port du server vidéoint port_number; const char index_html[] PROGMEM = R »=====( .row { display: flex; } .leftcol { flex: 30%; } .rightcol { flex: 70%; } .button { width: 60px; height: 40px; color: white; font-size: 22px; background-color: #1acc59; border-color: transparent; border-radius: 8px }
ESP32-CAM Stream Server
)===== »;/*********************************************//* GENERATE MJPEG STREAM *//* GENERE LE FLUX VIDEO MJPEG *//*********************************************/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]; static int64_t last_frame = 0; if (!last_frame) { last_frame = esp_timer_get_time(); } res = httpd_resp_set_type(req, _STREAM_CONTENT_TYPE); if (res != ESP_OK) { return res; } httpd_resp_set_hdr(req, « Access-Control-Allow-Origin », « * »); while (true) { fb = esp_camera_fb_get(); if (!fb) { // Echec de la capture de camera Serial.println(« JPEG 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) { // Echec de la compression JPEG 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; } } last_frame = 0; return res;}/*******************************************************//* HTML PAGE BUILDER *//* CONSTRUCTEUR DE LA PAGE HTML *//*******************************************************/static esp_err_t web_handler(httpd_req_t *req) { httpd_resp_set_type(req, « text/html »); httpd_resp_set_hdr(req, « Content-Encoding », « identity »); int indexhtmlsize = sizeof(index_html) + 50; char indexpage[indexhtmlsize] = « »; //strcat(indexpage, index_html); char streamip[20] = « »; if ( AP_MODE ) { // In AP Mode, IP is always 192.168.4.1 // En mode AP (connexion directe à l’ESP32-CAM), l’IP est toujours 192.168.4.1 sprintf(streamip, « 192.168.4.1:%d », port_number); } else { sprintf(streamip, « %d.%d.%d.%d:%d », WiFi.localIP()[0], WiFi.localIP()[1], WiFi.localIP()[2], WiFi.localIP()[3], port_number); } // Replace stream url inside HTML page code // Remplace l’adresse du flux vidéo dans le code de la page HTML sprintf(indexpage, index_html, streamip); int pagezize = strlen(indexpage); // Return HTML page source code // Renvoie le code source de la page HTML return httpd_resp_send(req, (const char *)indexpage, pagezize);}/***********************************************************//* START WEB SERVER AND VIDEO STREAM *//* DEMARRE LE SERVEUR WEB ET LE FLUX VIDEO *//***********************************************************/void startCameraServer() { httpd_config_t config = HTTPD_DEFAULT_CONFIG(); httpd_uri_t index_uri = { .uri = « / », .method = HTTP_GET, .handler = web_handler, .user_ctx = NULL }; httpd_uri_t stream_uri = { .uri = « /stream », .method = HTTP_GET, .handler = stream_handler, .user_ctx = NULL }; // Démarre le serveur web de l’interface HTML accessible depuis le navigateur internet Serial.printf(« Web server started on port: ‘%d’n », config.server_port); if (httpd_start(&camera_httpd, &config) == ESP_OK) { httpd_register_uri_handler(camera_httpd, &index_uri); } config.server_port += 1; config.ctrl_port += 1; // Démarre le flux vidéo Serial.printf(« Stream server started on port: ‘%d’n », config.server_port); if (httpd_start(&stream_httpd, &config) == ESP_OK) { httpd_register_uri_handler(stream_httpd, &stream_uri); } port_number = config.server_port;}void setup() { Serial.begin(115200); Serial.setDebugOutput(true); Serial.println(); // Configure camera Pins // Configure les broches de la caméra 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; // Init with high specs to pre-allocate larger buffers // Utilise toute la mémoire PSRAM disponible pour augmenter la taille du buffer vidéo /* AVAILABLE RESOLUTIONS Résolutions disponibles FRAMESIZE_QQVGA, // 160×120 FRAMESIZE_QQVGA2, // 128×160 FRAMESIZE_QCIF, // 176×144 FRAMESIZE_HQVGA, // 240×176 FRAMESIZE_QVGA, // 320×240 FRAMESIZE_CIF, // 400×296 FRAMESIZE_VGA, // 640×480 FRAMESIZE_SVGA, // 800×600 FRAMESIZE_XGA, // 1024×768 FRAMESIZE_SXGA, // 1280×1024 FRAMESIZE_UXGA, // 1600×1200 FRAMESIZE_QXGA, // 2048*1536 */ if(psramFound()){ config.frame_size = FRAMESIZE_UXGA; //FRAMESIZE_UXGA; // 1600×1200 config.jpeg_quality = 10; config.fb_count = 1; // Si > 1, active le bus I2S } else { config.frame_size = FRAMESIZE_SVGA; // 800×600 config.jpeg_quality = 12; config.fb_count = 1; }#if defined(CAMERA_MODEL_ESP_EYE) pinMode(13, INPUT_PULLUP); pinMode(14, INPUT_PULLUP);#endif // 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; } if ( AP_MODE ) { // En mode AP, on se connecte directement au réseau WiFi de l’ESP32 à l’adresse http://192.168.4.1 // En mode AP, on se connecte directement au réseau WiFi de l’ESP32 à l’adresse http://192.168.4.1 /* ACCESS POINT PARAMETERS ap_ssid (defined earlier): maximum of 63 characters ap_password (defined earlier): minimum of 8 characters; set to NULL if you want the access point to be open channel: Wi-Fi channel, number between 1 to 13 ssid_hidden: (0 = broadcast SSID, 1 = hide SSID) max_connection: maximum simultaneous connected clients, max. 4 ——– ap_ssid (déjà définit): 63 caractères max. ap_password (déjà defint): au minimum 8 caractères. NULL pour un accès libre. déconseillé !!! channel: canal Wi-Fi, nombre entre 1 et 13 ssid_hidden: 0 = diffuser le nom du résau, 1 = cache le nom du réseau SSID max_connection: nombre maximum de clients connectés simultannément à l’ESP32-CAM. 4 max. */ WiFi.softAP(ap_ssid, ap_password); } else { if ( USE_FIXED_IP ) { if(!WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS)) { Serial.println(« STA Failed to configure »); } } WiFi.begin(ssid, password); while ( WiFi.status() != WL_CONNECTED) { delay(500); Serial.print(« . »); wifi_counter++; if ( wifi_counter > wifi_try ) { restartESP32Cam(); } } Serial.println(« »); Serial.println(« WiFi connected »); } // La caméra est prête, ouvrez votre navigateur à l’adresse suivante Serial.print(« Camera Ready! Open your browser at ‘http:// »); Serial.print(WiFi.localIP()); Serial.println(« »); long logrssi = 0 ; for (size_t i = 0; i
#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_ESP_EYE)#define PWDN_GPIO_NUM -1#define RESET_GPIO_NUM -1#define XCLK_GPIO_NUM 4#define SIOD_GPIO_NUM 18#define SIOC_GPIO_NUM 23#define Y9_GPIO_NUM 36#define Y8_GPIO_NUM 37#define Y7_GPIO_NUM 38#define Y6_GPIO_NUM 39#define Y5_GPIO_NUM 35#define Y4_GPIO_NUM 14#define Y3_GPIO_NUM 13#define Y2_GPIO_NUM 34#define VSYNC_GPIO_NUM 5#define HREF_GPIO_NUM 27#define PCLK_GPIO_NUM 25#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_WIDE)#define PWDN_GPIO_NUM -1#define RESET_GPIO_NUM 15#define XCLK_GPIO_NUM 27#define SIOD_GPIO_NUM 22#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 25#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
[env:esp32cam]platform = espressif32board = esp32camframework = arduinomonitor_speed = 115200
Le code a été développé avec une carte ESP32-CAM générique de type AI Thinker. Il devrait cependant fonctionner parfaitement à l’identique sur les cartes M5Stack et TTGO notamment.
Modules ESP32-CAM génériques
TTGO T-Camera avec détecteur de mouvement PIR
TTGO T-Camera Plus avec écran TFT couleur 1,8″
TTGO T-Journal avec connecteur SMA pour antenne externe et écran OLED
Voir d’autres modules ESP32-CAM
Mises à jour
09/12/2020 Publication de l’article
English Version
ESP32-CAM. Broches et équipements ESP-EYE, AI Thinker, TTGO T-Camera, M5Stack Timer Camera…ESP32-CAM. Quel modèle choisir ? ESP-EYE, AI Thinker, TTGO T-Camera, M5Stack Timer Camera…ESP32-CAM. Souder l’antenne externe pour améliorer la portée et la stabilité du flux vidéo5 astuces pour ESP32-CAM. Adresse IP fixe. Mode AP. Rotation image 90°. Récupération automatique connexion WiFi. stockage du code HTMLESP32-CAM. Migrer le projet CameraWebServer pour l’IDE Arduino vers PlatformIO
Avez-vous aimé cet article ?