Vader Cam - 10

ChangeCode
转载
发布时间: 2025-06-14 15:04:27 | 阅读数 0收藏数 0评论数 0
封面
Vader Cam 是基于ESP32-CAM模块的实时视频流设备,我们可以通过一个网页应用程序访问视频流,从而查看正在发生的事情。它就像是一个保姆摄像头或监控设备,但主题是达斯·维达(Darth Vader),象征着达斯·维达在监视一切。

准备工作:

材料:

以下是构建Vader Cam所使用的材料:

- 定制PCB:从Seeed Studio定制的印刷电路板,用于集成所有组件并确保设备的稳定性和紧凑性。

- ESP32-CAM模块:这是核心组件,一个集成了摄像头和ESP32微控制器的模块,能够捕捉图像并通过Wi-Fi传输视频流。

- M7二极管(SMA封装):用于保护电路,防止反向电流对其他电子元件造成损害。

- UART编程器:用于将代码上传到ESP32-CAM模块,实现对其编程控制。

- USB Micro接口:提供电源输入和编程接口,便于连接电脑进行固件上传或供电。

- ESP32板用排针:用于将ESP32-CAM模块固定到定制PCB上,并建立电气连接。

- 电源供应:使用智能手机适配器作为外部电源,为整个装置提供必要的电力支持。

这些组件共同构成了Vader Cam的基础硬件架构,使其能够作为一个独立的、主题化的实时监控设备工作。

1

关于ESP32 CAM

ESP32 CAM是一个非常有用的开发板,它配备了一个200万像素的OV2640摄像头模块和一个在板底部的SD读卡器。

此外,它的价格约为10$,这是一个相当甜蜜的价格标签,为这样一个强大的微控制器。

在这个版本中使用的WIFI模块是ESP-32S,它有一个内置的32Mbit的Flash和512KB的内部加上外部的4M PSRAM。

它有5伏特的耐受性

这意味着我们可以为ESP电压小于5V的32Cam供电,如果你提供电压大于5V的电压,它就会被破坏。

2

安装Arduino IDE安装ESP32

为了在Arduino IDE上安装第三方开发板,我们必须复制他们的JSON URL,在我们的案例中是这样的-

https://dl.espressif.com/dl/package_esp32_index.json

复制上面的URL,并将其粘贴到Arduino IDE的偏好中的附加板管理器URL中。

(如果您在额外的板管理器中已经有了另一个开发板URL,那么您可以在两个URL之间加上一个逗号)

放置URL后,打开板管理器,在中搜索ESP32,然后下载ESP32板包。

在完成所有这些之后,您需要重新启动Arduino IDE,新的ESP32板将出现在板管理器菜单中。

3

面包板设置

在开始这个项目之前,我们首先准备一个面包板设置,它由一个ESP32 Cam与FTDI板连接。

ESP32 CAM没有一个机载编程芯片,这是一个麻烦,因此,我们必须添加一个外部USB到串行编程模块。

为此,我将使用这个USB到串行模块。该模块基于FTDI FT232芯片。您也可以使用其他串行转换器,布线将保持相同,因为我们只需要连接TX和RX与ESP32。

设置FTDI输出为5V

将FTDI的VCC(即5V)连接到5V的ESP32 CAM上

GND到GND

RX到U0T

TX到U0R

GPIO0,即IO0到GND(这将使ESP32 CAM处于闪存模式)

4

主代码

#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 = "JioFiber-nCDgC";
const char *password = "jiexaifieXai5chu";

#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 = "\r\n--" PART_BOUNDARY "\r\n";
static const char* _STREAM_PART = "Content-Type: image/jpeg\r\nContent-Length: %u\r\n\r\n";

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: %uB\n",(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);
}


5

砸碎木板的台阶

在闪烁过程之前,您需要更改示例草图中的一些内容。

进入示例>ESP32>相机,并打开

摄像头Web服务器

草图

输入您的SSID和密码

更改照相机模块,以便从

#定义CAMERA_MODEL_WROVER_KIT

#定义CAMERA_MODEL_AI_THINKER

现在,去工具,选择正确的板,在我们的例子中是AI-Thinker ESP32-CAM。

选择正确的端口,然后点击上传按钮。

现在,当ESP32开始上传过程时,你会看到带有点和破折号的连接消息。按下板底部的复位按钮,点和破折号开始。

如果您在此设置过程中遇到了一个错误,则会说

无法连接

,这意味着您的时间不好,请重试一次,当第一个点出现在调试菜单中时,长按重置按钮至少1秒钟。

几秒钟后,你的草图将被上传。

现在,从FTDI模块中插入USB,并拆下GPIO0和GND之间的跳线。

插入USB,然后打开串行显示器。

ESP32将连接到WIFI(这将需要1 min),您将看到ESP32 CAM的IP地址。

6

结果所以FAR。

我们复制ESP32 Cam的IP地址,并在web浏览器中打开它,它将显示ESP32 Cam的实时消息。接下来,我们开始为这个设置准备PCB。

7

PCB设计

在最终确定面包板设置后,我们准备了一个简单的PCB设计,其中包括一个USB微端口连接一个二极管,为ESP32 Cam供电。

为了使这个板更美观和酷,我下载了一个黑白的达斯·维达图像,并将其转换为BMP图像,这样我就可以把它添加到PCB设计中。

我把ESP32凸轮放在达斯·维德脸的一边,这样看起来就像是通过ESP32凸轮看着我们。

8

到手PCB

在完成PCB并生成其Gerber数据后,我将其发送到SEEED工作室获取样本。

订购红色多氯联苯。

我在一周内就收到了多氯联苯,考虑到价格,他们的质量也非常低。

的种子融合PCB服务

为PCB制造和PCB组装提供一站式的原型设计,因此,他们可以在7个工作日内生产出高质量的PCB和快速交钥匙PCBA。

Seed工作室融合

PCB组装服务t

我们关心整个制造过程

PCB制造,pa

他们提供采购、组装和测试服务,所以你可以确保他们得到了一个高质量的产品。

在评估市场兴趣和验证一个工作原型后,种子传播服务可以帮助您在专业的指导和强大的连接网络下将产品带向市场。

9

PCB组件

PCB组件包括两个步骤,

添加固件粘贴和二极管

添加报头引脚和USB端口

10

焊接二极管

我们首先在电路板的底部添加索焊剂膏,然后将二极管放置在它的位置上。

11

电烙铁

接下来,我们小心地举起整个PCB,并把它放在热板上。我在用我的好的老东西

DIY热板

这是我不久以前做的。

热板加热表面到焊料糊熔化温度,它慢慢熔化。几分钟后,当焊料完全融化,我们去除PCB,让它冷却一会儿。

12

THT组件

这是最后的设置,我们放置两个头销连接器使用烙铁。

13

结果

我们把ESP32放在VaderCam板上,并插入一个5V充电器。

等了几秒钟后,我们在浏览器中打开web应用程序,我们可以看到esp32摄像头看到实时消息。

这是今天的朋友,如果你需要这个项目的帮助,请留下评论。

如果你想知道更多关于ESP32 Cam和如何开始使用它,请查看我之前关于它的文章。

https://www.instructables.com/ESP32-CAM-WEB-Server-and-Getting-Started-Guide/

https://www.instructables.com/Dumb-But-Great-Point-and-Shoot-Camera-With-ESP32-C/

阅读记录0
点赞0
收藏0
禁止 本文未经作者允许授权,禁止转载
猜你喜欢
评论/提问(已发布 0 条)
评论 评论
收藏 收藏
分享 分享
pdf下载 下载