esp32CAM远程监控
sonder 超大杯

ESP32-CAM 远程监控的实现

1. ESP32-CAM 通过 websocket 发送图片流数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
//  先连接WIFI,然后连接websocket,连接之后不断的将帧数据发送出去
// 参考代码如下
#include "WiFi.h"
#include "esp_camera.h"
//#include "base64.h"

#include <ArduinoJson.h>
#include <WebSocketsClient_Generic.h>
// #include <WebSocketsClient.h>
//#include <SocketIOclient.h>

// Pin definition for 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


#if USE_SSL
// Deprecated echo.websocket.org to be replaced
#define WS_SERVER "ws://xx.xx.xx.xx"
#define WS_PORT x
#else
// To run a local WebSocket Server
//#define WS_SERVER "x.x.x.x"
#define WS_SERVER "xx.xx.xx.xx"
//#define WS_SERVER "x.x.x.x"
#define WS_PORT x
#endif

// Replace with your network credentials
const char* hostname = "ESP32CAM";
const char* ssid = "SONDER";
const char* password = "sonderswifi";
WebSocketsClient webSocket;

void webSocketEvent(WStype_t type, uint8_t * payload, size_t length) {

switch(type) {
case WStype_DISCONNECTED:
Serial.printf("[WSc] Disconnected!\n");
break;
case WStype_CONNECTED: {
Serial.printf("[WSc] Connected to url: %s\n", payload);
webSocket.sendTXT("camlogin");
}
break;
case WStype_TEXT:
Serial.printf("[WSc] get text: %s\n", payload);
break;
case WStype_BIN:
// Serial.printf("[WSc] get binary length: %u\n", length);
break;
case WStype_PING:
// pong will be send automatically
Serial.printf("[WSc] get ping\n");
break;
case WStype_PONG:
// answer to a ping we send
Serial.printf("[WSc] get pong\n");
break;
}

}

void setupCamera()
{

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; //;
//PIXFORMAT_JPEG;

config.frame_size = FRAMESIZE_QVGA; // FRAMESIZE_VGA; // FRAMESIZE_ + QVGA|CIF|VGA|SVGA|XGA|SXGA|UXGA
config.jpeg_quality = 6;
config.fb_count = 1;

// Init Camera
esp_err_t err = esp_camera_init(&config);
if (err != ESP_OK) {
Serial.printf("Camera init failed with error 0x%x", err);
return;
}


}

void setup(){
Serial.begin(115200);

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

// Print ESP32 Local IP Address
Serial.println(WiFi.localIP());

setupCamera();

// server address, port and URL
// webSocket.begin("127.0.0.1",xx);
#if USE_SSL
webSocket.beginSSL("xx.x.xx.xx", xx);
#else
webSocket.begin("xx.xx.xx.xx", xx, "/");
#endif
webSocket.onEvent(webSocketEvent);
webSocket.setReconnectInterval(5000);
webSocket.enableHeartbeat(15000, 3000, 2);

}


unsigned long messageTimestamp = 0;
void loop() {
webSocket.loop();
uint64_t now = millis();

if(now - messageTimestamp > 10) {
messageTimestamp = now;

camera_fb_t * fb = NULL;

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

webSocket.sendBIN(fb->buf,fb->len);
Serial.println("Image sent");
esp_camera_fb_return(fb);
}
}
2. websocket 服务端接收图片流,并传输给客户端
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
// 我是用Node来实现的  参考代码如下
// websocket.js
const ws = require("nodejs-websocket");
// const fs = require('fs')
let connectionsList = []; // 保存所有连接对象
const createServer = () => {
let server = ws.createServer((connection) => {
connectionsList.push(connection); // 将每个连接对象保存到数组中
connection.on("text", function (result) {
console.log("发送消息", result);
});
connection.on("binary", (inStream) => {
console.log("连接的客户端数量", server.connections.length);
if (server.connections.length == 1) return;
const client = server.connections[server.connections.length - 1];
// client.send(`Server received: ddd`);
// let bufferArr = [];
inStream.on("readable", () => {
let chunk;
while (null !== (chunk = inStream.read())) {
// bufferArr.push(chunk);
client.send(chunk, { binary: true }); // 发送流图片数据
}
});

inStream.on("end", () => {
// let buffer = Buffer.concat(bufferArr);
// console.log("接收到的Buffer长度: " + buffer.length); // 输出接收到的Buffer长度
// 在这里对接收到的buffer进行处理
// 将buffer转换成base64编码
// const base64 = buffer.toString("base64");
// 构造html,为了方便演示这里把图片数据写在html文件里
// const html = `<img src="data:image/jpeg;base64,${base64}">`;
// console.log("html", html);
// 发送html给客户端
// client.sendText(bufferArr);
});
});

connection.on("connect", function (code) {
console.log("开启连接", code);
});
connection.on("close", function (code) {
console.log("关闭连接", code);
});
connection.on("error", function (code) {
console.log("异常关闭", code);
});
});
return server;
};

createServer().listen(1332);
3. 客户端连接 websocket 实时展示图像信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// 打开一个 web socket,设定websocket服务器地址和端口
var ws = new WebSocket("ws://xx.xx.xx.xx:xx");

//开启连接open后客户端处理方法
ws.onopen = function () {
// Web Socket 已连接上,在页面中显示消息
document.getElementById("res").innerHTML =
"当前客户端已经连接到websocket服务器";
const idMsg = {
command: "set-id",
data: {
id: "123456", // 客户端的唯一标识
},
};
ws.send(JSON.stringify(idMsg));
};

// 接收消息后客户端处理方法
ws.onmessage = function (evt) {
// console.log(evt);
const blob = new Blob([evt.data], {
type: "image/jpeg",
});
const url = URL.createObjectURL(blob);
const img = document.createElement("img");
img.src = url;
$("#img").attr("src", url);
};

// websocket关闭
ws.onclose = function () {
alert("连接已关闭...");
};

最后:

  • 将第一步中的代码通过 Arduino 烧录进开发板,然后连接 wifi,就可以在串口中监听到信息输出了。
  • 然后在服务中打印查看传输的数据,比如 buffer 的长度,注意:我这里的服务端代码仅实现了功能,还有优化的地方,我这里就懒的做了。
  • 最后在客户端打开 html,将 js 文件引入进去,一切正常应该就能看到 ESP32-CAM 的实时图像信息了。

更新:
ESP32 相机模块的引脚定义。在使用 ESP32 来连接和控制相机模块时,需要指定相应的引脚来进行通信和数据传输。
以下是每个引脚定义的含义:
PWDN_GPIO_NUM:电源使能引脚,用于控制相机模块的电源,GPIO 32。
RESET_GPIO_NUM:复位引脚,用于复位相机模块,-1 表示没有对应的引脚。
XCLK_GPIO_NUM:像素时钟引脚,用于同步像素数据传输的时钟信号,GPIO 0。
SIOD_GPIO_NUM:串行数据引脚,GPIO 26。
SIOC_GPIO_NUM:串行时钟引脚,GPIO 27。
Y9_GPIO_NUM 到 Y2_GPIO_NUM:数据引脚,用于接收图像像素数据,分别对应 GPIO 35 到 GPIO 5。
VSYNC_GPIO_NUM:垂直同步引脚,用于标识图像帧的垂直同步位置,GPIO 25。
HREF_GPIO_NUM:行同步引脚,用于标识图像帧的行同步位置,GPIO 23。
PCLK_GPIO_NUM:像素时钟引脚,用于同步像素数据传输的时钟信号,GPIO 22。
这些引脚定义可以根据具体的硬件连接和相机模块的规格进行调整。修改这些定义可以确保正确地与相机进行通信,并在 ESP32 上实现图像捕获和处理等功能。

ledc_channel 和 ledc_timer:用于配置 LEDC(LED 控制器)的通道和定时器。在相机模块中,LEDC 可以用于控制 LED 灯的亮度,这里选择了 LEDC_CHANNEL_0 和 LEDC_TIMER_0。
pin_d0 到 pin_d7:用于配置数据引脚 D0 到 D7。这些引脚与之前定义的 Y2 到 Y9 相对应。
pin_xclk、pin_pclk、pin_vsync 和 pin_href:用于配置时钟和同步引脚。分别是像素时钟引脚 XCLK、像素时钟引脚 PCLK、垂直同步引脚 VSYNC 和行同步引脚 HREF。
pin_sscb_sda 和 pin_sscb_scl:用于配置串行数据传输引脚 SDA 和 SCL。
pin_pwdn 和 pin_reset:用于配置电源使能引脚和复位引脚。
xclk_freq_hz:设置像素时钟频率,这里是 20,000,000 Hz(20 MHz)。
pixel_format:设置像素格式,这里选择的是 JPEG 格式。
frame_size:设置帧的大小,这里设置为 QVGA(320x240)。
jpeg_quality:设置 JPEG 压缩质量,范围是 0-63,这里选取了 6。
fb_count:帧缓冲区的数量,这里设置为 1。

  • 本文标题:esp32CAM远程监控
  • 本文作者:sonder
  • 创建时间:2023-06-14 17:33:43
  • 本文链接:https://sonderss.github.io/2023/06/14/esp32CAM远程监控/
 评论