網頁最後修改時間:2021/09/17
之前在 ESP32 CAMRA 二維碼(QR Code)辨識之門鎖控制(下面簡稱 ESP32QRDoorLock) 系列的第二篇-週邊裝置的控制中,沒有談論到攝像頭的部分,主要是因為它是整個門鎖控制的主角,值得獨立寫一篇!
這一篇是 ESP32QRDoorLock 系列的第四篇:主要是說明如何使用 ESP32-CAM 辨識二維碼,比對出辨識後的二維碼,是否與預先定義的字串相符合,進而觸發相對應的處理動作。
內容有:
【(00)簡介】
本篇的目的很簡單,就是把二維碼辨識的功能,繼續加入到上一篇 x03_ESP32CamWiFiWatchdog.ino 中,並設定相對應的二維碼辨識後的狀態,做為系統工作流程的狀態轉換依據。
【(01)ESP32-CAM 二維碼辨識】
ESP32QRDoorLock 二維碼辨識的功能來自於函式庫的支援,使用者不需要深入了解二維碼辨識的方法或是撰寫相關的程式碼,只要設定好定期呼叫函式取得辨識的結果即可(這部分採用上一篇所介紹的 FreeRTOS 工作任務)。
到底要怎麼做呢?看下面的說明。
/*--*//**---/*///**---*-*////***--*/*///***----*///--*/*///**--*/*//**--**/*//
*
(01-01)函式庫下載與安裝:
函式庫的下載以及安裝教學都在下面的兩個連結中,進行下面步驟之前,請完成該函式庫的安裝。
** 函式庫下載:
** 函式庫安裝教學:
/*--*//**---/*///**---*-*////***--*/*///***----*///--*/*///**--*/*//**--**/*//
*
(01-02)生成二維碼圖示:
在網路上有很多網站提供二維碼圖示的生成服務,除了可自行尋找使用之外,要不就用我用的這個網站:QR碼產生器:免費、彩色、加LOGO (ioi.tw)。
這裡要生成的二維碼圖示,主要是開門用的,它代表的文字內容是 Qh@4#I_6+。另外,也生成了文字內容 relay0.0,1 和 relay0.0,0 兩個二維碼的圖示。這幾個圖示後續會用到,請先準備好,不知道怎麼做的,看下面的說明。
打開瀏覽器輸入連結:https://qr.ioi.tw/zh/,依序進行設定:
- QR碼內容輸入
- 選擇QR碼內容:純文字
- 原生資料:Qh@4#I_6+
- QR碼設定
- 檔案名稱:自行命名
- 按下 "下載QR碼" 按鈕下載檔案
二維碼圖示還可以加上 LOGO,例如加上一行文字:
- LOGO模式設定
- 選擇LOGO模式:文字-方塊
- 選擇LOGO模式:unlock
/*--*//**---/*///**---*-*////***--*/*///***----*///--*/*///**--*/*//**--**/*//
*
(01-03)參考範例與說明:
安裝函式庫之後,請由 Arduino IDE 選單中選擇開啟 "File/Examples/ESP32QRCodeReader/basic" 範例程式。
我對這個範例做了一些註解,並新增了 Line 10, 11 這兩行,用來輸出該工作任務所運行的核心號碼為何?
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 |
#include <Arduino.h> #include <ESP32QRCodeReader.h> //* 引數 CAMERA_MODEL_AI_THINKER,代表使用的是 ESP32-CAM 開發板 ESP32QRCodeReader reader(CAMERA_MODEL_AI_THINKER); void onQrCodeTask(void *pvParameters) { //* 輸出此工作任務執行的核心號碼 Serial.print("onQrCodeTask: Executing on core "); Serial.println(xPortGetCoreID()); //* 此結構用來儲存取得的二維碼辨識資料 struct QRCodeData qrCodeData; while (true) { //* 取回二維碼辨識之後的資料,最多等待 100ms if (reader.receiveQrCode(&qrCodeData, 100)) { Serial.println("Found QRCode"); if (qrCodeData.valid) // 如果資料有效 { Serial.print("Payload: "); Serial.println((const char *)qrCodeData.payload); } else // 如果資料無效 { Serial.print("Invalid: "); Serial.println((const char *)qrCodeData.payload); } } vTaskDelay(100 / portTICK_PERIOD_MS); } } void setup() { Serial.begin(115200); Serial.println(); //* ESP32-CAM 攝像機及其接腳初始化 reader.setup(); Serial.println("Setup QRCode Reader"); // 二維碼辨識工作任務由 Core 1 負責,優先級別 5 reader.beginOnCore(1); Serial.println("Begin on Core 1"); // 設定一工作任務,一但有資料在二維碼辨識的資料在 Queue 中,就取回並顯示出辨識結果 // 執行核心此時未知,在 onQrCodeTask 輸出執行核心號碼,優先級別 4 xTaskCreate(onQrCodeTask, "onQrCode", 4 * 1024, NULL, 4, NULL); } void loop() { delay(100); } |
這範例程式主要分為兩個部分:一個是函式庫初始化的部分,另一個是工作任務的建立。
完成範例程式的修改後,編譯、上傳後打開串口調試助手,底板開關一次後再按下 "打開串口" 按鈕(或按下 "打開串口" 按鈕,再按下 ESP32-CAM 開發板的 RST 按鈕)開始通訊。
輸出欄位中,紫色框住的文字部分是 onQrCodeTask 工作任務執行的核心號碼,往下則是進行二維碼辨識的結果。
/*--*//**---/*///**---*-*////***--*/*///***----*///--*/*///**--*/*//**--**/*//
*
(01-04)提高二維碼辨識成功率與速度:
從上一節的辨識二維碼的輸出可以得知,並不是每一次的辨識都會是成功的,雖然這是在測試時故意為之的,但實際做辨識時就是會這樣發生,而且辨識成功的機率還有可能會更低(應該會更低),原因是下面幾個因素所造成:
- 二維碼圖示使用的材質
- 二維碼圖示的清晰度
- 二維碼圖片的大小
- 攝像機與二維碼圖示的距離
二維碼圖示可以用列印的或是直接由手持裝置做顯示,基本來說用什麼材質沒關係,但它所呈現的清晰度一定要好,黑就是黑白就是白,主要就是要清楚,這不難理解吧!
屏除掉前面兩個因素的影響,後面的兩點,個人覺得是最至關重要影響辨識成功與否的關鍵因素!
攝像頭與二維碼之間的距離,取的是最小可辨識的距離,兩者之間的間距一定要大於這個值才行,使用之前請先搞清楚!
如下圖所示為影片中使用的二維碼圖示:一個材質為紙張,另一個為手機畫面。左邊圖示大小 62mm * 62mm,右邊圖示為 71mm * 71mm,攝像頭距離紙箱開口處 12.5mm。
【(02)參考程式碼】
參考(01-03)裡的範例,把二維碼辨識的程式碼加到 x03_ESP32CamWiFiWatchdog.ino 裡,裡面做了一些小修改,加入了辨識結果的狀態碼,和新增了一個工作任務。
/*--*//**---/*///**---*-*////***--*/*///***----*///--*/*///**--*/*//**--**/*//
*
(02-01)監控二維碼辨識狀態:
首先,在檔案的開頭處加入函式庫的標頭檔文件。
20 |
#include <ESP32QRCodeReader.h>
|
然後修改 Watchdog 逾時時間為 30 秒,不然還沒連線成功 ESP32 就會自己重置。
40 41 |
/*================== WATCHDOG =================*/ #define WDT_TIMEOUT 30 // 設定 Watchdog 計時器的時間 |
WATCHDOG 區域的下面,建立一個二維碼辨識的函式庫的全局實例。
43 44 |
/*================== QR CODE READER =================*/ ESP32QRCodeReader qrcodereader (CAMERA_MODEL_AI_THINKER); |
lsInterrupt 區域的上方插入下面的程式碼。
此處新增了一個二維碼辨識結果的狀態全局變數(初始狀態為 OFF),和一個控制代碼(handle)。
76 77 78 79 80 81 82 83 84 85 |
/*================== TASK: ONQRCODE =================*/ enum onqrcode_state_t { OFF, WORKING, MATCH, UNMATCH, INVALID } xOnQrCodeState = OFF; TaskHandle_t xOnQrCodeTaskHandle; |
往下,建立一個用來與二維碼辨識結果作比對的字串陣列的全局變數。現在只有第一個會用到,其他的可自發揮。
91 92 93 94 95 96 |
// 定義特定任務的 QR Code // https://qr.ioi.tw/zh/ const char *pcQrCode[] { "Qh@4#I_6+", // unlock "PfgW~!$&U" // do nothing }; |
setupOTA 函式的上方,插入下面作為工作任務的二維碼辨識資料處理的函式。
在這裡除了基本的辨識資料的輸出之外,就是設定相對應的二維碼辨識的狀態。不過,在這裡沒有使用這些狀態碼,下一篇總結的時候才會說到。
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 |
/**======================================================================== ** onQrCodeTask() *? 監測二維碼辨識資料是否成功與否的任務 *@param pvParameter void* *========================================================================**/ void onQrCodeTask (void *pvParameters) { Serial.print("onQrCodeTask: Executing on core "); Serial.println(xPortGetCoreID()); struct QRCodeData qrCodeData; while (true) { if (xOnQrCodeState == OFF) xOnQrCodeState = WORKING; if (qrcodereader.receiveQrCode(&qrCodeData, 100)) { Serial.println (F("Found QRCode")); if (qrCodeData.valid) { Serial.print (F("Payload: ")); Serial.println ((const char*)qrCodeData.payload); if (strcmp((const char*)qrCodeData.payload, pcQrCode[0]) == 0) { xOnQrCodeState = MATCH; } else { xOnQrCodeState = UNMATCH; } } else { Serial.print (F("Invalid: ")); Serial.println ((const char *)qrCodeData.payload); xOnQrCodeState = INVALID; } } vTaskDelay (pdMS_TO_TICKS(100)); } } |
/*--*//**---/*///**---*-*////***--*/*///***----*///--*/*///**--*/*//**--**/*//
*
(02-02)完整程式碼:
整合上一小節所說的部份,將這些程式碼插入到 x03_ESP32CamWiFiWatchdog.ino 中就完成 x04_ESP32CamQRCodeReader.ino 程式的撰寫。
儲存上面的檔案並上傳到 ESP32-CAM 後,開啟串口調試助手,重置或重啟 ESP32-CAM,完成開機並連線到無線網路,可得到與下面類似的輸出訊息。
接著,利用之前建立的二維碼圖示,讓 ESP32-CAM 進行辨識,可得到與下面類似的輸出訊息。
【(03)結論】
二維碼辨識是整個 ESP32QRDoorLock 中最重要的環節,因此知道怎麼去做辨識和使用函式庫就很重要。函式庫內部使用修改版的 Quire 函式庫和 MaixPy 專案的一些 OpenMV 的程式碼, 辨識的結果儲存於 FreeRTOS Queue 等待被讀出...,想深入了解的話就看看函式庫裡的程式碼吧!
下一篇,是整個系列的最後一篇,將整合這兩個工作任務執行時的輸出狀態值來做監控,轉換為整個系統工作流程中的狀態值,用來觸發相對應的處理動作
.
.
<<部落格相關文章>>
.
.
不好意思,我是高職學生,我想問一下我找不到zip檔要去哪裡找,我把檔案加進去,但它顯示沒有符合的zip檔,所以來跟你請教,我的專題製作也跟您的檔案有相關,如果能得到解惑,會很感謝您。
回覆刪除在網頁開頭裡面有需要的函式庫下載連結以及安裝的說明,詳細看網頁裡的說明。
刪除我已經照著上面做了,但在編譯的時候找不到ESP32QRCodeReader.h這個檔案,但我有把他家到程式裡,草稿碼資料夾也有,那我該怎麼辦。
刪除你安裝的函式庫沒放在預設的資料夾中,所以 Arduino IDE 執行時找不到;所謂預設的資料夾可以看"手動函式庫安裝教學":https://www.arduino.cc/en/guide/libraries 連結中步驟的說明。
刪除