在這個範例中會示範如何使用ESP32-CAM建構一照片擷取、傳送與儲存裝置,擷取照片的動作以常見的焦電型紅外線PIR移動偵測模組來觸發,此外也可以用磁簧開關、微動開關或一般的按鈕來啟動。當系統被觸發之後,會立刻將擷取到的照片傳送到使用者的Line Notify群組上,以提醒使用者有人或物進入系統的警戒範圍;此外本系統還可以將擷取到的照片同步儲存起來,此儲存裝置乃使用ESP32-CAM上內建的Micro SD讀寫模,組配合外加的Micro SD卡來實現;
◎ 功能與動作說明:
在我們的系統中將具備下面的動作與功能:
當系統測到外部的輸入觸發信號時,便會啟動ESP32-CAM拍攝照片的功能,並立刻將擷取到的照片傳送到使用者的Line Notify群組上。
此外部觸發輸入(輸入腳為GPIO16)為一高態的脈波信號,每一次的脈波輸入會啟動一次拍攝和擷取及儲存照片的動作。
當系統進入待機狀態可以開始擷取照片時,ESP32-CAM上內建的LED1(接在GPIO33)會點亮,以提醒使用者可以開始使用了。
(選用項目)本系統還可將所拍攝到的照片儲存到ESP32-CAM上內建的Micro SD讀寫模中所放置的Micro SD卡上。系統最多可拍攝及儲存的照片數目由所使用的micro SD卡容量所決定,一般在Arduino IDE中保證可用的Micro SD卡的容量為4GB,而在本範例中所設定的ESP32-CAM解析度所拍攝到的照片檔案大小約為26KB左右∘
(選用項目)所拍攝及儲存的照片名稱為”pictureXXX.jpg”,其中的”XXX”為流水號數字,每次系統開機啟動時數字會由1開始,如果Micro SD卡上之前有相同檔案名稱的照片存在將會被新的覆蓋掉。
◎電路圖:
在本範例中會使用到下列零組件:
1. 一塊ESP32-CAM模組
2. 一個編號為HC-SR501的人體紅外線移動感測器
3. 一個按鍵
4. 一個10K電阻
5. 磁簧開關(選用)
6. 微動開關(選用)
下面的電路便是本次範例的電路圖:
電路中這顆編號為HC-SR501的人體紅外線移動感測器的實體照片如下:
如下圖所示,目前在市面上所販售的這款感測器模組,在旁邊右上方處有一組3 Pin的跳線短接腳座,供使用者選擇模組的工作電壓;由於我們所使用的ESP32-CAM模組基本上是工作在3.3V的電壓,為了避免HC-SR501人體紅外線移動感測器使用5V的工作電壓時,所輸出的信號位準過高,以至於傷害到ESP32-CAM模組,建議把短接Jump接在下方的3.3V位置上。
由於這個HC-SR501的人體紅外線移動感測器主要是給一般燈光感應控制之用,所以除了可以感應有溫度的紅外線物體移動之外,還可以調整紅外線感應的靈敏度,此外也可以調整動作的時間。下圖中上方兩顆橘色的半可變電阻,便是用來調整這兩個參數之用,由於我們所需要的動作脈波越短越好,建議把右邊那顆調整延遲時間用的半可變電阻往逆時鐘的方向轉到最底,這時動作的時間約在一秒左右,這樣反應會比較快。
至於上面圖片中下方的3隻黃色排針接腳,中間的那根便是感應信號的輸出腳,當模組沒有感應到移動的物體時,輸出位準是在低態(Low),如果有偵測到移動的物體便會轉為高態(High)輸出,並會持續輸出一段時間,此時間是可依使用者需求去調整的。
為了方便測試,我們的電路中使用了一顆按鈕作為手動觸發之用,當按鈕被按下時,電源正端會透過一顆10KΩ電組連接到觸發輸入腳(GPIO16)啟動拍照的動作;如果我們把這個系統應用在家裡面大門的門鈴裝置時,這個按鈕就等同門鈴的按鈕,當有人按門鈴時,便可以同步把來訪客人的長相拍攝下來,並且馬上發送給使用者,這樣即使使用者不在家也可以從接收的相片看是誰來拜訪。
除此之外也可以把這個系統作一個延伸的應用,例如把這個按鈕改成其他零組件像磁簧開關或微動開關等機械接點的裝置,就可以構成一保全防護系統。下圖是這些零組件常見的一些外觀,如果我們在家裡的門窗上裝上這些裝置,並把相機鏡頭對準它們,當門窗被非法打開時,就可以把入侵者的容貌拍攝下來發送給使用者。
門窗用磁簧開關
微動開關一
微動開關二
在ESP32-CAM模組上有一顆內建的LED,也就是下圖標示為LED1的那顆,它是接在ESP32的GPIO33上;由於HC-SR501這塊人體紅外線移動感測器動作比較慢,不管被觸發或恢復原狀都需要一點時間,而且ESP32-CAM模組每次在拍完照要將資料處存在SD卡上時,也要花一點時間,為了讓使用者知道目前系統是否已經可以開始動作,在我們的系統中會使用這顆LED做為系統已經準備好可以開始拍照的指示燈。
◎ 程式列表與說明:
以下便是本範例所使用的完整程式表:
#include "esp_camera.h"
#include "Arduino.h"
#include "FS.h" // SD Card ESP32
#include "SD_MMC.h" // SD Card ESP32
#include "soc/soc.h" // Disable brownour problems
#include "soc/rtc_cntl_reg.h" // Disable brownour problems
#include "driver/rtc_io.h"
#include <TridentTD_LineNotify.h>
#define WIFI_SSID "Your_WiFi_SSID"
#define WIFI_PASSWORD "Your_WiFi_Password"
#define LINE_TOKEN "Your_Line_Token"
// 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
int pictureNumber = 1;
const byte shootPin = 16, picLED=33;
void setup() {
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); //disable brownout detector
Serial.begin(115200);
pinMode(shootPin,INPUT_PULLUP);
pinMode(picLED, OUTPUT);
Serial.print("連線到 Wifi SSID ");
Serial.print(WIFI_SSID);
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
bool outState = false;
while (WiFi.status() != WL_CONNECTED)
{
Serial.print(".");
outState = !outState;
if (outState)
digitalWrite(picLED, 0);
else
digitalWrite(picLED, 1);
delay(500);
}
digitalWrite(picLED, 0);
Serial.println();
Serial.print("\nWiFi 連線成功! IP address: ");
Serial.println(WiFi.localIP());
LINE.setToken(LINE_TOKEN);
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; // FRAMESIZE_ + QVGA|CIF|VGA|SVGA|XGA|SXGA|UXGA
config.jpeg_quality = 10;
config.fb_count = 2;
} else {
config.frame_size = FRAMESIZE_SVGA;
config.jpeg_quality = 12;
config.fb_count = 1;
}
// Init Camera
esp_err_t err = esp_camera_init(&config);
if (err != ESP_OK) {
Serial.printf("ESP32 照相機初始化失敗! 錯誤代碼為: 0x%x", err);
return;
}
//Serial.println("Starting SD Card");
if(!SD_MMC.begin()){
Serial.println("SD 卡掛載失敗!");
return;
}
uint8_t cardType = SD_MMC.cardType();
if(cardType == CARD_NONE){
Serial.println("找不到 SD卡!");
return;
}
Serial.println("程式開始! 先送出Line的提示訊息與貼圖...");
LINE.notify("你好,我是ESP32-CAM! ");
LINE.notifySticker("歡迎使用Line抓圖傳送系統! ",11539,52114110);
LINE.notifySticker("系統已經準備好,可以開始使用了! ",11537,52002740);
delay(1000);
}
void loop() {
digitalWrite(picLED,0);
Serial.println("可以開始抓下一張圖了....");
while(digitalRead(shootPin)==0) {delay(5);};
delay(100);
digitalWrite(picLED,1);
// Path where new picture will be saved in SD Card
String path = "/picture" + String(pictureNumber) +".jpg";
takeSavePhoto(path);
pictureNumber++;
while(digitalRead(shootPin)==1) { delay(5); };
delay(1000);
}
void takeSavePhoto(String path) {
// 使用相機抓取照片
camera_fb_t * fb=esp_camera_fb_get();
if(!fb)
{
Serial.println("相機抓取錯誤!");
return;
}
Serial.println("送出照片到Line Notify....");
LINE.notifySticker("ㄚ! 有人入侵!! ",11538,51626511);
LINE.notifyPicture( "相機抓圖已啟動!", fb->buf, fb->len);
fs::FS &fs = SD_MMC;
File file=fs.open(path.c_str(), FILE_WRITE);
if(!file)
Serial.println("使用寫入模式時開啟檔案失敗!");
else {
file.write(fb->buf,fb->len);
Serial.printf("檔案儲存至路徑 : %s\n",path.c_str());
}
file.close();
esp_camera_fb_return(fb);
}
程式名稱:ESP32_CAM_SaveSD1.ino
程式開始的1~8行是本範例程式引用到的函式庫,如果有寫過ESP32-CAM模組相關程式的朋友應該都不陌生才是,在此就不多做說明。最後一個函式庫< TridentTD_LineNotify.h >是Arduino IDE中專門供Line Notify專用的函式庫,在前一章節已經介紹過如何按裝了,如果不清楚請回到上一章去參閱。
#include "esp_camera.h"
#include "Arduino.h"
#include "FS.h" // SD Card ESP32
#include "SD_MMC.h" // SD Card ESP32
#include "soc/soc.h" // Disable brownour problems
#include "soc/rtc_cntl_reg.h" // Disable brownour problems
#include "driver/rtc_io.h"
#include <TridentTD_LineNotify.h>
下面這三行程式碼請依序修改成你自己所使用的WiFi分享器名稱(SSID)與密碼(Password),並在「LINE_TOKEN」後面填上你申請到的Line群組通訊用憑證(Token)。
#define WIFI_SSID "Your_WiFi_SSID"
#define WIFI_PASSWORD "Your_WiFi_Password"
#define LINE_TOKEN "Your_Line_Token"
接著的程式碼是在定義安可信(AI_THINKER)的ESP32-CAM模組相機的相關參數,主要是相機鏡頭所使用到的一些I/O腳位,這些接腳在初始化(setup())部分程式要用到。
// 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
下面程式的第一行是在定義照片編號用的變數,由於在標準的Arduino中整數(int)變數的資料長度只有2個byte,而且範圍是由-32,768~+32767,為了能有更多的編號,所以要定義成無正負號的整數型態才行。至於後面的”shootPin”變數,是指啟動拍照功能的觸發輸入腳(即GPIO16),接到HC-SR501人體紅外線移動感測器的輸出腳,而”picLED”則是指ESP32-CAM模組上那顆內建的LED所使用GPIO腳的編號。
unsigned int pictureNumber = 1;
const byte shootPin = 16, picLED=33;
接著的程式是屬於初始化(setup())程式區的部分,程式一開始會先設定所使用到的I/O接腳,也就是上面提到那兩隻。然後開始與WiFi分享器連線,為了讓使用者能清楚的知道目前系統連線的狀態,在此使用ESP32-CAM模組上那顆內建的LED1做為指示之用;在等待連線的過程中,除了在Arduino IDE的監控視窗中會出現”….”的符號之外,這顆LED1也會以一秒一次的速度閃爍,當連線上之後,這顆LED1便會保持在恆亮的狀態,而且Arduino IDE的監控視窗中也會顯示所分配到的本地IP位址。
Serial.print("連線到 Wifi SSID ");
Serial.print(WIFI_SSID);
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
bool outState = false;
while (WiFi.status() != WL_CONNECTED)
{
Serial.print(".");
outState = !outState;
if (outState)
digitalWrite(picLED, 0);
else
digitalWrite(picLED, 1);
delay(500);
}
digitalWrite(picLED, 0);
Serial.println();
Serial.print("\nWiFi 連線成功! IP address: ");
Serial.println(WiFi.localIP());
然後初始化Line Notify,也就是設定Line群組通訊用憑證(Token)。
LINE.setToken(LINE_TOKEN);
下面這一塊程式主要就是規劃及配置ESP32-CAM模組上相機鏡頭所使用的GPIO腳,和所抓取相片的檔案格式(在此為jpg檔):
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;
再來就是依照ESP32-CAM模組上是否有內建psram來決定攝影時圖像的框架與圖片的品質,如果有會使用「UXGA」模式,如果沒有則設定為「SVGA」模式。
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;
}
然後程式開始初始化ESP32-CAM模組上的相機,假如初始化失敗,程式會在Arduino的監控視窗上顯示提示訊息及錯誤原因的代碼,以供使用者參考。
esp_err_t err = esp_camera_init(&config);
if (err != ESP_OK) {
Serial.printf("ESP32 照相機初始化失敗! 錯誤代碼為: 0x%x", err);
return;
}
再來就是初始化ESP32-CAM模組上內建掛載的Micro SD模組板,同樣的程式會在Arduino的監控視窗上顯示是否初始化成功的提示訊息,以供使用者參考。果不想使用Micro SD卡去儲存所抓取到相片這個選項功能,只要把”return”這行註解掉就可以了。
//Serial.println("Starting SD Card");
if(!SD_MMC.begin()){
Serial.println("SD 卡掛載失敗!");
return;
}
如果初始化ESP32-CAM模組上內建掛載的Micro SD模組板成功,接下來就是檢查有沒有插上Micro SD卡﹖當然結果一樣會顯示在Arduino的監控視窗上!同樣的如果不想使用Micro SD卡去儲存所抓取到相片這個選項功能,只要把”return”這行註解掉就可以了,否則如果沒有插上Micro SD卡系統將會無法正常運作。
uint8_t cardType = SD_MMC.cardType();
if(cardType == CARD_NONE){
Serial.println("找不到 SD卡!");
return;
}
初始化(setup())程式區的最後部分除了會在Arduino的監控視窗上顯"程式開始! 先送出Line的提示訊息與貼圖..."的提示訊息除此之外,為了善用Line Notify傳送文字與圖片/照片的功能,在此也順便送出一段提示訊息(即"你好,我是ESP32-CAM! ")和兩張Line的貼圖到使用者LineNotify接收群組做為系統開機提示之用。
Serial.println("程式開始! 先送出Line的提示訊息與貼圖...");
LINE.notify("你好,我是ESP32-CAM! ");
LINE.notifySticker("歡迎使用Line抓圖傳送系統! ",11539,52114110);
LINE.notifySticker("系統已經準備好,可以開始使用了! ",11537,52002740);
如果要傳送文字訊息到Line群組,只要使用下面的程式碼就可以:
LINE.notify("message");
其中的"message"就是你要傳送的訊息內容,訊息的內容中英文都可以,簡單易用。
在< TridentTD_LineNotify.h >這個函式庫中,可傳送兩種圖片內容,一種是在Line上專用的貼圖,其指令程式碼如下:
LINE.notifySticker("message",package_ID,stick_ID);
指令中共使用了三個引數,第一個"message"就是這張貼圖的文字說明訊息,和前面的純文字訊息一樣;至於第二、三個引數”package_ID”和”stick_ID”,請先到下面這個Line的官方貼圖資源網頁上去看一下:
“https://developers.line.biz/zh-hant/docs/messaging-api/sticker-list/#specify-sticker-in-message-object”
在這個網頁中我們可以看到一些常常會被使用到Line群組對話中的貼圖,一般這些貼圖會先分類成不同的包裹(package),而這些包裹Line官方會給予不同的編號(ID),至於包裹中的所有貼圖也會被分配一個特定的號碼(即它的stick ID)。以上面這張在網頁中的說明圖示來說,如果你想要傳送月亮臉人的第一張貼圖到目標Line群組上,那麼就要設定”package_ID”🡪446和”stick_ID”🡪1988。
上面三行程式執行完之後,我們將會在LineNotify接收群組上看到下面的畫面,其中兩張貼圖上方的文字訊息就是這張貼圖的說明("message")部分。
以第一張貼圖來說,他的”package_ID”🡪11539,而”stick_ID”🡪52114110,讀者們可自行到前述的Line官方貼圖資源網頁去搜尋比,對應該就可以了解了。
由於本範例程式把抓取照片與儲存照片的部分寫成了一個副程式(也就是最後面的【void takeSavePhoto(String path)】),所以整個主迴圈程式區(loop())就變得很精簡,下面就是屬於主迴圈程式區(loop())的部分:
程式一開始先點亮ESP32-CAM模組上內建的LED,以提醒使用者可以開始使用抓取照片的功能了,同時也在Arduino的監控視窗上顯"可以開始抓下一張圖了...."的提示訊息,然後就是等待外部的觸發信號到來,也就是「shootPin」這隻接腳出現高態的輸入信號。
void loop() {
digitalWrite(picLED,0); // 內建LED點亮位準為0
Serial.println("可以開始抓下一張圖了....");
while(digitalRead(shootPin)==0) {delay(5);};
當「shootPin」這隻接腳出現高態的觸發輸入信號時,程式會先把指示用的LED熄滅,好讓使用者知道目前系統正在處理拍照與儲存的動作,無暇他顧;並在合成目前的照片檔案名稱(字串變數”path”)之後,呼叫【void takeSavePhoto(String path)】)這個副程式去處理後續的動作。這個副程式會先執行拍照的動作,並把所擷取到的照片發送到使用者的Line Notify群組上,如果需要可將所攝得的照片儲存到Micro SD卡上,最後一行程式會把照片的編號數(pictureNumber)加一。
delay(100);
digitalWrite(picLED,1);
// Path where new picture will be saved in SD Card
String path = "/picture" + String(pictureNumber) +".jpg";
takeSavePhoto(path);
pictureNumber++;
在主迴圈程式區(loop())的最後會等待觸發輸入信號位準恢復(回到Low),然後重新開始整個:觸發🡪抓取照片🡪傳送照片到使用者的Line Notify群組上🡪儲存照片至Micro SD卡的過程(選項)。
while(digitalRead(shootPin)==1) { delay(5); };
delay(1000);
}
接著讓我們來看看【void takeSavePhoto(String path)】)這個副程式,它主要分成兩個部分,如下面程式所示,首先啟動相機拍攝照片的功能,並將結果暫存在變數”fb”上;假如拍攝失敗,程式會在Arduino的監控視窗上顯"相機抓取錯誤!"的提示訊息,並且馬上結束這個副程式。
void takeSavePhoto(String path) {
// 使用相機抓取照片
camera_fb_t * fb=esp_camera_fb_get(); // 啟動相機拍攝照片的功能
if(!fb)
{
Serial.println("相機抓取錯誤!");
return;
}
如果相機拍攝成功,程式會先傳送一張提示用的貼圖(stick)到使用者的Line Notify群組上,再來則是一張剛拍攝的照片,這樣使用者由照片的內容就可以知道是甚麼人或物進入系統的警戒範圍,以致觸發感測器及相機動作了!
Serial.println("送出照片到Line Notify....");
LINE.notifySticker("ㄚ! 有人入侵!! ",11538,51626511);
LINE.notifyPicture( "相機抓圖已啟動!", fb->buf, fb->len);
在< TridentTD_LineNotify.h >這個函式庫中,使用下面這個指令程式來傳送圖片或照片:
LINE.notifyPicture();
不過這個指令功能強大,而且極富彈性,以我們這次所使用的方式來說:
LINE.notifyPicture( "相機抓圖已啟動!", fb->buf, fb->len);
在括弧中共用了三個引數,第一個是這張照片的說明文字訊息(即"相機抓圖已啟動!"),第二個則是要傳送照片所在的資料暫存區(fb->buf),第三個是這張照片的資料長度值(fb->len)。
除此之外還可以用下列的格式傳送儲存在SD卡上的圖片:
LINE.notifyPicture("Hello My Tiger", SD, "/tiger.jpg");
下列的格式可用來傳送存放在網路的圖片:
LINE.notifyPicture("https://preview.ibb.co/j6G51n/capture25610417181915334.png");
而且也可以用下列的格式來傳送儲存在網路的圖片並加上說明文字:
LINE.notifyPicture("四個玻璃杯",
"https://www.fotoaparat.cz/storage/pm/09/10/23/670915_a5351.jpg");
在< TridentTD_LineNotify.h >這個函式庫所提供的範例程式中有許多相關的應用例子,有興趣的讀者不妨自行去研究測試看看。
在這個副程式的最後會依外界傳來的檔案名稱(path)將資料寫入到Micro SD卡上,並依照寫入結果是否成功,在Arduino的監控視窗上顯相對應的提示訊息。如果讀者不想使用儲存照片的功能,以便簡化系統與程式,可以不用輸入這一段程式碼,或者是暫時把這段程式註解掉,這樣以後想要恢復使用時也比較快。
fs::FS &fs = SD_MMC;
File file=fs.open(path.c_str(), FILE_WRITE);
if(!file)
Serial.println("使用寫入模式時開啟檔案失敗!");
else {
file.write(fb->buf,fb->len);
Serial.printf("檔案儲存至路徑 : %s\n",path.c_str());
}
file.close();
◎ 執行結果:
下面的畫面是系統啟動時會在Arduino IDE的監控視窗上看到的內容,前面的部分是ESP32-CAM模組上內建的啟動輸出訊息,其中標記1的是連線WiFi分享器時的提示訊息,這時ESP32-CAM模組上內建的LED1也會跟著閃爍。至於標記2,則是連線成功後顯示本系統所分配到的本地IP位址。而標記3則是
初始化(setup())程式區的最後部分,也就是前面提到系統開機時,會送出兩張Line的貼圖到使用者LineNotify接收群組做為系統開機提示之用,同時也在Arduino IDE的監控視窗上出現的訊息。
標記4的部分是主迴圈程式區(loop())開始時,系統在待機等待外部的觸發信號到來;至於至於標記5、6則是拍照功能被觸發後,呼叫【void takeSavePhoto(String path)】這個副程式執行拍照與儲存照片完成的提示訊息。接著的標記7則是再次回到主迴圈程式區(loop())開始的部分,亦即重新開始等待外部的觸發信號到來。
下面圖片是本系統裝置被觸發時,呼叫【void takeSavePhoto(String path)】這個副程式拍照及傳送圖片到使用者Line Notify群組上的結果,在這張圖片中,上面的圖案是使用Line內建的貼圖(好像叫“CHOCO和好友[動態特別篇]”),發送給使用者以做為警示之用,而第二張則是ESP32-CAM模組被觸發時所拍到的實際畫面,看起來畫質還算清晰,如果真的有外人入侵,應該可以辨識出來是什麼人才是。
沒有留言:
張貼留言