使用 AI-Thinker ESP32-Cam 製作網絡監視器

最近在下幫助朋友設定網絡監視器
發現現在的網絡監視器,為了方便使用,大部分已經不再需要設定網絡
只需註冊產品官方的帳戶,再使用產品官方的網站或應用程式登入便可以觀看到內容
亦即是使用者必須提交個人資料給產品公司

另外,網絡監視器的影像內容是由產品公司以即時串流方式提供服務
即是技術上,產品公司能夠觀看、保存使用者的影像內容,可能會有私隱泄漏風險
因此在下嘗試尋找能夠自己控制的網絡監視器的工具

預覽

AI-Thinker ESP32-Cam

AI-Thinker ESP32-Cam 是一款使用 ESP32 為微控制器並能夠連接到 小型鏡頭 的模組

ESP32 具備 WiFi 及 BLE 功能,能夠將鏡頭的影像透過 WiFi 及 BLE 方式傳送

外觀

ESP32-Cam 的正面

ESP32-Cam 具備 高亮度LED ,與 IO4 連接,高電壓時亮著,具備 8位元PWM

FPC連接器 ,可連接 扁平絲帶線 (Ribbon Cable)
ESP32-Cam 支援多種鏡頭:

  • OV2640
  • OV3660
  • OV5640
  • OV7670
  • OV7725
  • NT99141
  • GC032A
  • GC0308
  • GC2145
  • BF3005
  • BF20A6
  • SC101IOT
  • SC030IOT
  • SC031GS

ESP32-Cam 提供 Micro SD卡模組 ,方便將資料儲存

ESP32-Cam 有一支 電壓輸出引腳
預設利用 0Ω電阻器 連接並輸出 3.3V
有需要可以將 電阻器 除焊,更改輸出電壓為 5V

ESP32-Cam 的背面

重設按鈕

ESP32-Cam 使用 ESP-32S 微控制器,具備 WiFi 及 BLE 功能

除了高亮度LED,還有一粒 普通LED ,與 IO33 連接,低電壓亮著;具備 8位元PWM

ESP32-Cam 提供 電路板天線 IPEX外接天線
預設利用 0Ω電阻器 連接並使用電路板天線
有需要可以將 電阻器 除焊,更改使用 外接天線 來增強訊號

ESP32-Cam 焊接 ESP-PSRAM32 額外提供 32Mb(4MB) 的記憶體空間,能夠寫入更多資料

引腳
SD卡
左排引腳右排引腳
5V1163V3
GND215IO16
IO12314IO0
IO13413GND
IO15512VCC
IO14611RX
IO2710TX
IO489GND
編號引腳方向功能
15V5V 輸入
2GND接地
3IO12輸入輸出第12數碼引腳;SD DATA2引腳
4IO13輸入輸出第13數碼引腳;SD DATA3引腳
5IO15輸入輸出第15數碼引腳;SD CMD引腳
6IO14輸入輸出第14數碼引腳;SD SCK引腳
7IO2輸入輸出第2數碼引腳;SD DATA0引腳
8IO4輸入輸出第4數碼引腳;SD DATA1引腳;高亮度LED引腳
9GND接地
10U0T輸出第1數碼引腳, UART TX引腳
11U0R輸入第3數碼引腳, UART RX引腳
12VCC根據選擇輸出 3.3V 或 5V ,預設 3.3V
13GND接地
14IO0輸入輸出第0引腳; FPC XCLK引腳;起動時接地進入寫入模式
15IO16輸入輸出第16引腳
163V33.3V 輸入
LED1IO33輸出第33數碼引腳;LED1引腳
FPC_HREFIO23第23數碼引腳;FPC HREF引腳;不佔用引出引腳
FPC_PCLKIO22第22數碼引腳;FPC PCLK引腳;不佔用引出引腳
FPC_PWDNIO32第32數碼引腳;FPC PWDN引腳;不佔用引出引腳 (鏡頭電源)
FPC_SIOCIO27第27數碼引腳;FPC SIOC引腳;不佔用引出引腳
FPC_SIODIO26第26數碼引腳;FPC SIOD引腳;不佔用引出引腳
FPC_VSYNCIO25第25數碼引腳;FPC VSYNC引腳;不佔用引出引腳
FPC_Y2IO5第5數碼引腳;FPC Y2引腳;不佔用引出引腳
FPC_Y3IO18第18數碼引腳;FPC Y3引腳;不佔用引出引腳
FPC_Y4IO19第19數碼引腳;FPC Y4引腳;不佔用引出引腳
FPC_Y5IO21第21數碼引腳;FPC Y5引腳;不佔用引出引腳
FPC_Y6IO36第36數碼引腳;FPC Y6引腳;不佔用引出引腳
FPC_Y7IO39第39數碼引腳;FPC Y7引腳;不佔用引出引腳
FPC_Y8IO34第34數碼引腳;FPC Y8引腳;不佔用引出引腳
FPC_Y9IO35第35數碼引腳;FPC Y9引腳;不佔用引出引腳

燒錄方法

由於 ESP32-Cam 沒有 USB插孔,因此需要外接燒錄器才能將資料寫入到 ESP32-Cam

使用Arduino
引腳連接

先將 Arduino 燒錄成 ArduinoISP ,然後連接線路,再透過 ArduinoISP 將資料寫入到 ESP32-Cam
連接時要注意, Arduino Nano TX1引腳 連接到 ESP32-Cam U0T引腳

Arduino Nano 引腳ESP32-Cam 引腳
5V5V
GNDGND
TX1U0T
RX0U0R
RSTGND
GNDIO0
線路原型

需要留意得是 Arduino Nano 的 RST引腳 需要接駁到 GND
而 ESP32-Cam 的 IO0 必須在起動前連接到 GND 才能載入到寫入模式

實際線路

線路簡單,與線路原型大致上相同

使用USB轉TTL

另一種方法是使用 RS232 將 USB訊號 轉換成 TTL訊號 經 UART協定 將資料寫入到 ESP32-Cam

外觀

在下過去曾經使用 FTDI 的 FT232燒錄器 ,由於 FT232燒錄器 使用 Mini USB Type-B 插孔連接
但現在已經很少裝置使用 Mini USB Type-B 插孔,因此在下改用由 LaskaKit 製作的 CH9102燒錄器

CH9102燒錄器 的 背面

CH9102燒錄器 的 正面

CH9102燒錄器 同時支援 Micro USB Type-B 及 USB Type-C 兩種常見的 USB插孔

使用 WCH 的 CH9102F 是一款 USB轉TTL 晶片

CH9102燒錄器 使用 切換器 而非 引腳連接器 ,方便切換輸出電壓

再使用另一切換器作為電源開關,避免電壓設定錯誤而燒毀目標裝置

電源連接綠色LED

電源啟動綠色LED

當資料寫入時 TX LED 及 RX LED 會閃動,均為橙色

引腳
編號引腳方向功能
1VCC
2GND
3TX輸出UART TX引腳
4RX輸入UART RX引腳
5DTR輸入輸出數據終端就緒 (Data Terminal Ready) 引腳
6RTS輸入輸出發送請求 (Request To Send) 引腳
引腳連接

使用USB轉TTL燒錄時要注意,燒錄器的TX引腳 連接到 裝置的RX引腳
同樣 ESP32-Cam IO0引腳 需要連接到 GND引腳

CH9102 引腳ESP32-Cam 引腳
5V5V
GNDGND
TXU0R
RXU0T
GNDIO0
線路原型

與 ArduinoISP 的線路相似

實際線路

與 線路原型 相同

使用專用燒錄器
外觀

ESP32-Cam 專用燒錄器 (ESP32-Cam-MB) 的 正面

ESP32-Cam-MB 的 電源顯示LED

ESP32-Cam-MB 的 起動按鈕,連接到 ESP32-Cam 的 IO0引腳,當按下後會將 IO0 連接到 GND
當 ESP32-Cam 啟動前將 IO0 拉地,便會載入到 起動模式

ESP32-Cam-MB 的 重設按鈕,連接到 ESP32-Cam 的重設引腳

ESP32-Cam-MB 使用 Micro USB Type-B 插孔

ESP32-Cam 安裝到 ESP32-Cam-MB
ESP32-Cam-MB 最大好處就是不需要使用跳線便可以將資料寫入

寫入資料

線路連接後,可以使用 Arduino IDE 寫入資料

到 Additional Boards Manager URLs: 加入

https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_dev_index.json

並尋找及安裝 ESP32

安裝後,燒錄前,建議使用以下設定值:

  • Board: "AI Thinker ESP32-CAM"
  • CPU Frequency: "240MHz (WiFi/BT)"
  • Flash Frequency: "80MHz"
  • Flash Mode: "DIO"
  • Partition Scheme: "Huge APP (3MB No OTA/1MB SPIFFS)"
  • Core Debug Level: "None"
  • Erase All Flash Before Sketch Upload: "Disabled"

設定正確後可以編寫程式及上載

測試

測試普通LED (IO33),連接電源時亮著

測試高亮度LED (IO4),接地時亮著

普通LED 及 高亮度LED 都支援 PWM

OV2640 攝影鏡頭

OV2640 是一種輕量、低功耗攝影鏡頭,只需要 1.7V 至 3.3V 便能夠運作

外觀

OV2640 使用 軟性印刷電路板 (Flexible Printed Circuit (FPC))
比較輕、電路板可以有一定程度彎曲(摺疊會損壞電路)

OV2640 的正面

OV2640 的背面

OV2640 共有 24支引腳

引腳
編號引腳方向功能
1STROBE輸入輸出控制閃光燈(高亮度LED)
2AGND類比數碼轉換器(Analog/Digital Converter (ADC))接地
3SIOD輸入輸出序列鏡頭控制總線(Serial Camera Control BUS (SCCB)) 資料訊號
4AVDD2.8V 類比數碼轉換器(Analog/Digital Converter (ADC))電源
5SIOC輸入序列鏡頭控制總線(Serial Camera Control BUS (SCCB)) 時脈訊號
6RESETB輸入晶片選擇,低電壓啟動
7VSYNC輸出垂直同步輸出
8PWDN輸入電源啟動,高電壓啟動
9HREF輸出水平參考輸出
10DVDD1.3V 數碼電路電源
11DOVDD2.8V 數碼影像輸出電源
12DATA9輸出第9位元數碼影像輸出
13XCLK1輸入石英晶體振盪器時脈輸入
14DATA8輸出第8位元數碼影像輸出
15DGND數碼影像接地
16DATA7輸出第7位元數碼影像輸出
17PCLK輸出像素時脈輸出
18DATA6輸出第6位元數碼影像輸出
19DATA2輸出第2位元數碼影像輸出
20DATA5輸出第5位元數碼影像輸出
21DATA3輸出第3位元數碼影像輸出
22DATA4輸出第4位元數碼影像輸出
23DATA1輸出第1位元數碼影像輸出
24DATA0輸出第0位元數碼影像輸出
安裝

雖然 OV2640 的引腳又多又密,但只要使用 ESP32-Cam ,便可以簡單地透過 FPC連接器 連接

將 FPC連接器 的固定鎖向上拉開 (需要輕微用力)

將 OV2640 的引腳向下安置到 FPC連接器 ,並推至最入

將 FPC連接器 的固定鎖向下推回 (需要輕微用力) ,固定並壓著 OV2640 的引腳

測試

選擇 Example > ESP32 > Camera > CameraWebServer

示範中提供大量不同型號的鏡頭設定,將不適用的資料更改為注釋

將適用的資料取消注釋,例如 AI-Thinker ESP32-Cam 使用 CAMERA_MODEL_AI_THINKER 設定

設定連接到無線網絡的 SSID 及 密碼

如果不打算連接到無線網絡,亦可以將 ESP32 設定為 存取點(Access Point) ,讓其他裝置連接

將原本的

WiFi.begin(ssid, password);
WiFi.setSleep(false);
while (WiFi.status() != WL_CONNECTED) {
	delay(500);
	Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
startCameraServer();
Serial.print("Camera Ready! Use 'https://");
Serial.print(WiFi.localIP());
Serial.println("' to connect");

修改為

WiFi.mode(WIFI_AP);
WiFi.softAP(ssid, password);
WiFi.setSleep(false);
startCameraServer();
Serial.print("Camera Ready! Use 'https://");
Serial.print(WiFi.softAPIP());
Serial.println("' to connect");

上載 Sketch 到 ESP32-Cam 後,序列監視器可以查看 ESP32-Cam 的 IP (預設是 192.168.4.1)
便可以經網頁連接到 ESP32-Cam

連接到 ESP32-Cam 的 存取點,並以網頁瀏覽器載入 IP
便會顯示 OV2640 的設定頁面

按 Start Stream 便會開始將 鏡頭擷取到畫面 在頁面上顯示即時的影像

啟動閃光燈功能

雖然 CameraWebServer 已經提供了視像鏡頭的基本控制,但卻無法控制閃光燈
因為光度不足,會影響影像效果,因此要想辦法亮著閃光燈

修改 CameraWebServer 的 app_httpd.cpp

加入

#include <Arduino.h>

加入

static int8_t flash_enabled = 0;

尋找 cmd_handler 並加入

 else if (!strcmp(variable, "flash")) {
	pinMode(4, OUTPUT);
	digitalWrite(4, atoi(value));
	flash_enabled = atoi(value);
}

尋找 status_handler 並加入

p += sprintf(p, "\"flash\":%u", flash_enabled);

將 CameraWebServer 的頁面的原始碼複製成 HTML檔案

在 id="face_recognize-group" 元素後加入

<div class="input-group" id="flash-group">
	<label for="flash">Flash</label>
	<div class="switch">
		<input id="flash" type="checkbox" class="default-action">
		<label class="slider" for="flash"></label>
	</div>
</div>

在 Terminal 輸入

cat "${html_file}" | gzip | hexdump -e '32/1 "0x%02X," "\n"' | sed -r 's/0x +,//g'

將 HTML檔案 轉換成 十六進制資料

在 Terminal 輸入

cat "${html_file}" | gzip | hexdump -e '32/1 "0x%02X," "\n"' | sed -r 's/0x +,//g' | tr -cd ',' | wc -c

計算 十六進制資料 的 位元組數量

將 十六進制資料 取代 index_ov2640_html_gz 及 位元組數量 取代 index_ov2640_html_gz_len 的 資料

將 CameraWebServer 編譯並上載到 ESP32-Cam

載入到 ESP32-Cam 的頁面,會顯示能夠控制 高亮度LED 的 Flash開關掣

測試開關 高亮度LED

SD卡 模組

引腳

根據規格文件,ESP32-Cam 連接到 SD卡模組 的引腳是使用 SD協定 而不是 SPI協定

ESP32-CamSD Card
IO14SCK
IO15CMD
IO2DATA0
IO4DATA1
IO12DATA2
IO13DATA3

不過在下參考了網上很多只需要複製、貼上便能夠做到效果的資料在下都無法成功
因此在下暫時停止儲存到 SD卡 的操作

補充資料

簡化開發板選擇

ESP32 Arduino 分類,總共有 198個項目(截至本文章)
而 AI Thinker ESP32-CAM 是第130個項目(截至本文章),每次尋找都會很麻煩
(如果使用 Arduino IDE 2.X 可以搜尋並選擇)
可以修改 ${HOME}/.arduino15/packages/esp32/hardware/esp32/2.0.11/boards.txt 改變次序方便選擇

將原本的的 esp32cam.name=AI Thinkder ESP32-CAM 更改為註釋(不建議刪除)

將 esp32cam.name=AI Thinkder ESP32-CAM 編寫在第1項目

重新開啟 Arduino IDE , AI Thinkder ESP32-CAM 便會在第1項目
有需要亦可以調整其他開發板的次序,同樣只需要將 .name 整行內容複製並注釋,再到其他位置貼上即可

總結

可能由於專案比較久遠,需要修改部分原始碼才能完善地運作

參考資料