目錄
- 項目介紹
- 硬件介紹
- 項目設計
- 開發環境及工程參考
- 總體流程圖
- 硬件基本配置
- 光照傳感器讀取
- 定時器
- 檢測邏輯
- 功能展示
- 項目總結
👉 【Funpack3-2】基于EV54Y39A PIC-IOT WA的手指數量檢測功能開發
👉 Github: EmbeddedCamerata/PIC-IOT_finger_recognition
項目介紹
基于 Microchip 的 EV54Y39A PIC-IOT WA 開發板,通過板卡上集成的光照傳感器,將板卡平放后,每秒對揮動的手指數量進行檢測。在較強光源下,可準確識別揮動的手指數量。
👉 MPLAB X IDE
硬件介紹
PIC-IoT WA硬件概述:
- 控制器包含兩個主要組件:PIC微控制器(PIC24FJ128GA705)和Wi-Fi模塊(WINC1510)。PIC24F是一款低功耗的16位微控制器,時鐘頻率為32MHz,具有集成的12位ADC。Wi-Fi模塊采用Microchip的ATWINC1510,是低功耗認證的IoT網絡控制器。
- 板載ATECC608的密碼協處理器。用于生成私鑰和公鑰,私鑰用于加密發送的每條消息,而公鑰可與服務提供商(如Google IoT cloud或AWS)共享。
- 板載傳感器包括TEMT6000X01光傳感器和MCP9808溫度傳感器。光傳感器連接到PIC控制器的10位ADC,溫度傳感器通過I2C接口測量-20℃至100℃之間的溫度,典型精度為0.25℃。
- PIC IoT WA開發板可通過微型USB端口或4.2V鋰電池供電,同時具有板上編程仿真器和調試器(PKOB)支持一路串口和一個IO的邏輯分析功能。
項目設計
開發環境及工程參考
本項目使用 Microchip 官方的 MPLAB X IDE 開發。項目所用到的工具鏈、庫或 packs 如下:
- 編譯器:xc16 v1.50,這個版本的編譯器確保編譯通過
- Packs: PIC24F-GA-GB_DFP 1.9.336、PKOB nano 1.13.715
- MCC Content Libraries:
1. MCC core 5.7.1
2. PIC24 / dsPIC33 MCUs 1.171.4
3. Board Support Library 1.12.0
總體流程圖
進行系統初始化以后,先啟動周期為1s的定時器,該定時器自動重載,在其回調函數中打印識別的手指數目 count
,之后清零并進入 STATE_IDLE。工程主體為一個 while(1)
循環的 FSM,用一個全局變量記錄系統狀態:
- 每次都會先讀取光照傳感器的數據,并根據此次與上次讀數的差值,進入其他的狀態
- 在 STATE_IDLE 中,當差值小于一個負閾值時,進入 STATE_NEGA,此時識別到光照降低,這說明有手指遮擋。其余情況沒有手指遮擋,狀態不轉移。當定時器觸發時,打印出此時的識別數目并將
count
清零,系統重新進入 STATE_IDLE。 - 在 STATE_NEGA,當差值大于一個正閾值時,進入 STATE_POS,此時識別到光照增加,這說明手指移開了,
count++
。在 STATE_NEGA,若保持光照讀數相對穩定,這說明該手指還未完全經過傳感器,狀態不轉移。當定時器觸發時,打印出此時的識別數目并將count
清零,系統重新進入 STATE_IDLE。 - 在 STATE_POS 中,只有當差值又一次小于負閾值時,進入 STATE_NEGA,此時識別到光照降低,這說明又有手指遮擋。若保持光照讀數相對穩定或增加,這說明并沒有新的手指遮擋。當定時器觸發時,打印出此時的識別數目并將
count
清零,系統重新進入 STATE_IDLE。
由于測量周期是1s,即便測量狀態沒有變化,定時器回調也會將狀態、變量全部重置。在 FSM 中,只需要處理有效的測量的統計邏輯即可。
硬件基本配置
根據手冊可知,板載光照傳感器與ADC AN8(RB12)相連。檢測的周期設計為1秒,如此,需要一個定時器 TMR1。其次,還需要串口以供調試與結果顯示。在MCC中,IO口設置如下圖所示:
RB10/11供調試使用。串口設置為9600 8N1,RC8 UITX 需要勾選“Start High”,勾選“Redirect printf to UART”。
光照傳感器讀取
需要修改一下默認的 ADC1 配置。根據下方提示,修改“Conversion Clock”為2即可。
根據生成的ADC示例,可以修改實現光照傳感器數據的讀取。
uint16_t get_light_sensor(void)
{int i;uint16_t conversion;ADC1_Enable();ADC1_ChannelSelect(LIGHT_SENSOR);ADC1_SoftwareTriggerEnable();//Provide Delayfor(i = 0; i < 1000; i++){}ADC1_SoftwareTriggerDisable();while(!ADC1_IsConversionComplete(LIGHT_SENSOR));conversion = ADC1_ConversionResultGet(LIGHT_SENSOR);ADC1_Disable();return conversion;
}
定時器
如下圖所示配置,設置 TMR1 為1s周期定時器。
在定時器的回調函數 periodic_handler
中,打印 count
手指數目,而后清零并將狀態設置為 APP_STATE_IDLE
。在主循環之前創建定時器,定時器超時設置為 0xF423
,在主循環內需要調用 timeout_callNextCallback()
以檢查回調。
static uint32_t periodic_handler(void)
{printf("Finger count: %d\n", count);appState = APP_STATE_IDLE;count = 0;return 0xF423;
}int main(void)
{// initialize the deviceSYSTEM_Initialize();timerStruct_t periodic_timer = {periodic_handler, NULL};timeout_create(&periodic_timer, 0xF423);while (1){timeout_callNextCallback();main_app();}return 1;
}
檢測邏輯
當手指遮擋時,光照減小,前后兩次讀數的差值為負數,反之為正數。因此,設置一個合適的閾值 LIGHT_TRIGGER_THRES
,用于判斷是否發生了這兩種變化,同時也可以過濾掉讀數不穩定的影響。該值需要根據實際環境進行調整。
#define LIGHT_TRIGGER_THRES (50)
系統分為三個狀態,用全局變量 appState
記錄。同時,需要幾個參數記錄傳感器的數值以及手指數目。
typedef enum {APP_STATE_IDLE,APP_STATE_DETECTED_NEGA,APP_STATE_DETECTED_POS
} appStates_e;static appStates_e appState = APP_STATE_IDLE;
static uint16_t light1 = 0;
static uint16_t light2 = 0;
static float light_prev1 = 0.;
static int count = 0;
反復讀取光照傳感器數據,讀取最近的兩次數據取平均值作為此次測量的結果,并與上次讀數作差。根據該差值進行狀態跳轉:
- 處于
APP_STATE_IDLE
時,當差值delta
小于負閾值LIGHT_TRIGGER_THRES
時,進入APP_STATE_DETECTED_NEGA
,此時檢測到有手指遮擋,光照降低。其余情況下,均不會有手指遮擋,狀態不轉移。 - 處于
APP_STATE_DETECTED_NEGA
時,當delta
大于正閾值LIGHT_TRIGGER_THRES
時,進入APP_STATE_DETECTED_POS
,此時說明手指移開了,計數+1。其余情況下,手指還未完全經過傳感器,因此差值不夠大(可以過濾毛刺情況)或者為負,狀態均不轉移。 - 處于
APP_STATE_DETECTED_POS
時,當delta
又一次小于負閾值LIGHT_TRIGGER_THRES
時,進入APP_STATE_DETECTED_NEGA
,此時又有手指遮擋。其余情況下,說明光照無較大變化或者光照變強,這說明沒有手指遮擋或手指逐漸遠離,狀態均不跳轉。 - 測量周期為1s,定時器超時后,將打印出計數結果
count
并清零,同時狀態轉移至APP_STATE_IDLE
,進行下一次測量。
void main_app(void)
{float delta;float light;light1 = get_light_sensor();light2 = get_light_sensor();light = (light1 + light2) / 2;delta = light - light_prev1;light_prev1 = light;switch(appState) {case APP_STATE_IDLE:{if (delta < -LIGHT_TRIGGER_THRES) {appState = APP_STATE_DETECTED_NEGA;}break;}case APP_STATE_DETECTED_NEGA:{if (delta > LIGHT_TRIGGER_THRES) {count++;appState = APP_STATE_DETECTED_POS;}break;}case APP_STATE_DETECTED_POS:{if (delta < -LIGHT_TRIGGER_THRES) {appState = APP_STATE_DETECTED_NEGA;}break;}}
}
功能展示
下載程序后將板卡平放,注意需要保證環境光照較強,需要根據實際情況調整閾值 LIGHT_TRIGGER_THRES
。本測試在室內,并用手機手電筒照射光照傳感器的環境下進行。測試需要揮動手指,結果輸出有延遲,測試效果參見視頻更直觀。
👉 詳細展示參見:B站:基于EV54Y39A PIC-IOT WA的手指數量檢測功能開發
項目總結
本次項目通過光照傳感器、定時器與狀態機,可在一定場景下準確識別揮動的手指數量,可以根據實際場景調整參數,以達到最佳效果。MPLAB IDE 一言難盡,打開 MCC 沒個半天是不可能的,這個板卡的有些配置還有坑,例如,編譯器需要選擇 v1.50 而不能是最新版的。