ESP32-CAM在Web Server中拍照和显示

释放双眼,带上耳机,听听看~!

了解如何使用ESP32-CAM开发板构建Web服务器,您可以通过在浏览器可视化最新捕获的照片,并且可以发送命令进行拍照并保存在SPIFFS中。如果需要,我们还添加了旋转图像的选项。

ESP32-CAM-Take-Photo-Display-Web-Server

您可能会喜欢我们博客中的其它ESP32-CAM项目。实际上,您可以通过添加一个PIR传感器(在检测到运动时进行拍照),一个物理按钮来拍照或在另一个URL路径中包括视频流功能,来进一步推进该项目。

其它ESP32-CAM项目和教程:

ESP32-CAM AI-Thinker引脚指南:GPIO使用说明

ESP32-CAM视频流和Arduino IDE的人脸识别

ESP32-CAM 视频流web服务器

ESP32-CAM与Assistant家庭助理集成

ESP32-CAM拍照并保存到MicroSD卡

ESP32-CAM照片捕捉-PIR运动检测传感器(保存到microSD卡)

 

所需零件

要遵循此项目,您需要以下部分:

  • 带有OV2640的ESP32-CAM
  • 母对母连接线
  • FTDI编程器
  • 5V电源或移动电源

 

项目概述

下图显示了我们将在本教程中构建的Web服务器。

ESP32-CAM-Web-Server-Display-Last-Photo-Captured

当您访问Web服务器时,您将看到三个按钮:

  • 旋转(ROTATE): 根据您的ESP32-CAM方向,您可能需要旋转照片;
  • 拍摄照片(CAPTURE PHOTO):单击此按钮时,ESP32-CAM会拍摄一张新照片并将其保存在ESP32 SPIFFS中。刷新网页前请等待至少5秒钟,以确保ESP32-CAM拍摄并存储照片。
  • 刷新页面(REFRESH PAGE): 当您单击此按钮时,网页将刷新,并使用最新的照片进行更新。

注意:如前所述,最新拍摄的照片存储在ESP32 SPIFFS中,因此即使您重新启动开发板,也始终可以访问最后保存的照片。

安装ESP32附加组件

我们将使用Arduino IDE对ESP32开发板进行编程。因此,您需要安装Arduino IDE以及ESP32附加组件:

一、ESP32开发环境搭建(arduino)

安装库

要构建Web服务器,我们将使用ESPAsyncWebServer库。该库还需要AsyncTCP库才能正常工作。请按照以下步骤安装这些库。

安装ESPAsyncWebServer库

请按照以下步骤安装 ESPAsyncWebServer 库:

安装ESP32的异步TCP库

ESPAsyncWebServer库需要 AsyncTCP 库才能工作。请按照以下步骤安装该库:

ESP32-CAM拍摄并显示Photo Web Server程序

将以下代码复制到您的Arduino IDE中。此代码构建了一个Web服务器,可让您使用ESP32-CAM拍摄照片并显示最近拍摄的照片。根据您ESP32-CAM的方向,您可能需要旋转图片,因此我们也包含了该功能。


 

代码如何工作

首先,包括与相机一起使用,构建Web服务器和使用SPIFFS所需的库。

#include "WiFi.h"
#include "esp_camera.h"
#include "esp_timer.h"
#include "img_converters.h"
#include "Arduino.h"
#include "soc/soc.h"           // Disable brownout problems
#include "soc/rtc_cntl_reg.h"  // Disable brownout problems
#include "driver/rtc_io.h"
#include <ESPAsyncWebServer.h>
#include <StringArray.h>
#include <SPIFFS.h>
#include <FS.h>

接下来,在以下变量中编写您的网络凭证,以便ESP32-CAM可以连接到您的本地网络。

const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

创建一个 AsyncWebServer 80端口上的对象。

AsyncWebServer server(80);

这 takeNewPhoto 布尔变量指示何时该拍摄新照片。

boolean takeNewPhoto = false;

然后,定义要保存在SPIFFS中的照片的路径和名称。

#define FILE_PHOTO "/photo.jpg"

接下来,为ESP32-CAM 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

建立网页

接下来,我们有HTML来构建网页:

const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
 <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <style>
    body { text-align:center; }
    .vert { margin-bottom: 10%; }
    .hori{ margin-bottom: 0%; }
  </style>
</head>
<body>
  <div id="container">
    <h2>ESP32-CAM Last Photo</h2>
    <p>It might take more than 5 seconds to capture a photo.</p>
    <p>
      <button onclick="rotatePhoto();">ROTATE</button>
      <button onclick="capturePhoto()">CAPTURE PHOTO</button>
      <button onclick="location.reload();">REFRESH PAGE</button>
    </p>
  </div>
  <div><img src="saved-photo" id="photo" width="70%"></div>
</body>
<script>
  var deg = 0;
  function capturePhoto() {
    var xhr = new XMLHttpRequest();
    xhr.open('GET', "/capture", true);
    xhr.send();
  }
  function rotatePhoto() {
    var img = document.getElementById("photo");
    deg += 90;
    if(isOdd(deg/90)){ document.getElementById("container").className = "vert"; }
    else{ document.getElementById("container").className = "hori"; }
    img.style.transform = "rotate(" + deg + "deg)";
  }
  function isOdd(n) { return Math.abs(n % 2) == 1; }
</script>
</html>)rawliteral";

我们不会详细介绍此HTML的工作方式。我们只是简要介绍一下。

网页中的英文如果改成中文注意,需要在head标签加入这条代码,不然英文会乱码:

<meta charset="UTF-8">

基本上,创建三个按钮: 旋转; 拍摄照片 和 刷新页面。每张照片调用不同的JavaScript函数:rotationPhoto(), capturePhoto() 和 reload():

<button onclick="rotatePhoto();">ROTATE</button>
<button onclick="capturePhoto()">CAPTURE PHOTO</button>
<button onclick="location.reload();">REFRESH PAGE</button>

capturePhoto() 函数在上发送请求 /捕获 ESP32的URL,因此需要拍摄一张新照片。

function capturePhoto() {
  var xhr = new XMLHttpRequest();
  xhr.open('GET', "/capture", true);
  xhr.send();
}

rotationPhoto() 功能旋转照片。

function rotatePhoto() {
  var img = document.getElementById("photo");
  deg += 90;
  if(isOdd(deg/90)){ document.getElementById("container").className = "vert"; }
  else{ document.getElementById("container").className = "hori"; }
  img.style.transform = "rotate(" + deg + "deg)";
}
function isOdd(n) { return Math.abs(n % 2) == 1; }

我们不确定使用JavaScript旋转照片的“最佳”方法是什么。该方法可以很好地工作,但是可能有更好的方法可以做到这一点。如果您有任何建议,请与我们分享。

最后,以下部分显示了照片。

<div><img src="saved-photo" id="photo" width="70%"></div>

当您单击 刷新 按钮,它将加载最新图像。

setup()

在 setup()  里面  ,初始化串行通讯:

Serial.begin(115200);

将ESP32-CAM连接到您的局域网:

WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
  delay(1000);
  Serial.println("Connecting to WiFi...");
}

初始化SPIFFS:

if (!SPIFFS.begin(true)) {
  Serial.println("An Error has occurred while mounting SPIFFS");
  ESP.restart();
}
else {
  delay(500);
  Serial.println("SPIFFS mounted successfully");
}

打印ESP32-CAM的本地IP地址:

Serial.print("IP Address: http://");
Serial.println(WiFi.localIP());

接下来的几行将使用正确的设置对摄像机进行配置和初始化。

处理Web服务器

接下来,我们需要处理ESP32-CAM在URL上收到请求时发生的情况。

当ESP32-CAM在根目录/ URL上收到请求时,我们发送HTML文本来构建网页。

server.on("/", HTTP_GET, [](AsyncWebServerRequest * request) {
  request->send_P(200, "text/html", index_html);
});

当我们按“捕获Web服务器上的“”按钮,我们向ESP32 / capture URL发送一个请求。发生这种情况时,我们将takeNewPhoto 可变为 真的,以便我们知道该拍摄新照片了。

server.on("/capture", HTTP_GET, [](AsyncWebServerRequest * request) {
  takeNewPhoto = true;
  request->send_P(200, "text/plain", "Taking Photo");
});

如果/ saved-photo URL上有请求,请将保存在SPIFFS中的照片发送到连接的客户端:

server.on("/saved-photo", HTTP_GET, [](AsyncWebServerRequest * request) {
  request->send(SPIFFS, FILE_PHOTO, "image/jpg", false);
});

最后,启动Web服务器。

server.begin();

loop()

在 loop()  里面 ,如果 takeNewPhoto 变量为True,我们称 capturePhotoSaveSpiffs()拍摄新照片并将其保存到SPIFFS。然后,将takeNewPhoto 可变为 错误的。

void loop() {
  if (takeNewPhoto) {
    capturePhotoSaveSpiffs();
    takeNewPhoto = false;
  }
  delay(1);
}

拍张照片

程序中还有两个其它功能: checkPhoto() 和 capturePhotoSaveSpiffs()。

checkPhoto() 功能检查照片是否已成功保存到SPIFFS。

bool checkPhoto( fs::FS &fs ) {
  File f_pic = fs.open( FILE_PHOTO );
  unsigned int pic_sz = f_pic.size();
  return ( pic_sz > 100 );
}

capturePhotoSaveSpiffs() 功能拍摄照片并将其保存到SPIFFS。

void capturePhotoSaveSpiffs( void ) {
  camera_fb_t * fb = NULL; // pointer
  bool ok = 0; // Boolean indicating if the picture has been taken correctly

  do {
    // Take a photo with the camera
    Serial.println("Taking a photo...");

    fb = esp_camera_fb_get();
    if (!fb) {
      Serial.println("Camera capture failed");
      return;
    }

    // Photo file name
    Serial.printf("Picture file name: %sn", FILE_PHOTO);
    File file = SPIFFS.open(FILE_PHOTO, FILE_WRITE);

    // Insert the data in the photo file
    if (!file) {
      Serial.println("Failed to open file in writing mode");
    }
    else {
      file.write(fb->buf, fb->len); // payload (image), payload length
      Serial.print("The picture has been saved in ");
      Serial.print(FILE_PHOTO);
      Serial.print(" - Size: ");
      Serial.print(file.size());
      Serial.println(" bytes");
    }
    // Close the file
    file.close();
    esp_camera_fb_return(fb);

    // check if file has been correctly saved in SPIFFS
    ok = checkPhoto(SPIFFS);
  } while ( !ok );
}

该功能基于dualvim的程序

ESP32-CAM上传代码

要将代码上传到ESP32-CAM开发板,请使用FTDI编程器将其连接到您的计算机 。请遵循以下原理图:

ESP32-CAM-FTDI-programmer-5V-supply

重要提示: GPIO 0需要连接到GND,以便能够上传代码。

许多FTDI编程器都有一个连接线,可让您选择3.3V或5V。确保连接线在正确的位置以选择5V。

ESP32-CAM FTDI编程器
GND GND
5V VCC(5V)
U0R TX
U0T 接收
GPIO 0 GND

要上传代码,请按照以下步骤操作:

1)转到工具>主板,然后选择AI-Thinker ESP32-CAM。

2)进入工具>端口,选择ESP32连接的COM端口。

3)然后,点击上传按钮上传代码。

upload-button-arduino-ide

4)当您开始在调试窗口中看到这些点时,如下所示,请按ESP32-CAM板载RST按钮。

dots-uploading-code

几秒钟后,该代码应成功上传到您的电路板上。

示范

打开浏览器,输入ESP32-CAM IP地址。然后,单击“捕获照片”以拍摄新照片,并等待几秒钟以将照片保存到SPIFFS中。

然后,如果您按下“刷新页面”按钮,页面将使用最新保存的照片进行更新。如果需要调整图像方向,可以始终使用“ ROTATE ”按钮进行调整。

ESP32-CAM-Web-Server-Display-Last-Photo-Captured-Demonstration

在您的Arduino IDE串行监视器窗口中,您应该看到类似的消息:

ESP32-CAM-Take-Photo-Display-Web-Server-Arduino-IDE-Serial-Monitor

给TA买糖
共{{data.count}}人
人已赞赏
ESP32-CAM免费项目

ESP32-CAM照片捕捉-PIR运动检测传感器(保存到microSD卡)

2021-5-25 9:35:33

ESP32-CAM免费项目

ESP32-CAM:使用SMTP服务器通过电子邮件发送拍摄的照片

2021-5-28 10:07:18

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索