【Funpack3-2】基于EV54Y39A PIC-IOT WA的手指数量检测功能开发
该项目使用了EV54Y39A PIC-IOT WA,实现了手指数量检测的设计,它的主要功能为:通过板卡上集成的光照传感器,将板卡平放后,在较强光源下,可准确识别挥动的手指数量。
标签
嵌入式系统
Funpack活动
ADC
Microchip
MPLAB X IDE
PIC-IOT WA
葉SiR
更新2024-06-04
北京大学
78

项目介绍

基于 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 如下:

  1. 编译器:xc16 v1.50,这个版本的编译器确保编译通过
  2. Packs: PIC24F-GA-GB_DFP 1.9.336、PKOB nano 1.13.715
  3. 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++。在 NEGA 态中,若保持光照读数相对稳定,这说明该手指还未完全经过传感器,状态不转移。当定时器触发时,打印出此时的识别数目并将 count 清零,系统重新进入 STATE_IDLE。
  • 在 STATE_POS 中,只有当差值又一次小于负阈值时,进入 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 Delay
for(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 device
SYSTEM_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;

反复读取光照传感器数据,读取最近的两次数据取平均值作为此次测量的结果,并与上次读数作差。根据该差值进行状态跳转:

  1. 处于 APP_STATE_IDLE 时,当差值 delta 小于负阈值 LIGHT_TRIGGER_THRES 时,进入 APP_STATE_DETECTED_NEGA,此时检测到有手指遮挡,光照降低。其余情况下,均不会有手指遮挡,状态不转移。
  2. 处于 APP_STATE_DETECTED_NEGA 时,当 delta 大于正阈值 LIGHT_TRIGGER_THRES 时,进入 APP_STATE_DETECTED_POS,此时说明手指移开了,计数+1。其余情况下,手指还未完全经过传感器,因此差值不够大(可以过滤毛刺情况)或者为负,状态均不转移。
  3. 处于 APP_STATE_DETECTED_POS 时,当 delta 又一次小于负阈值 LIGHT_TRIGGER_THRES 时,进入 APP_STATE_DETECTED_NEGA,此时又有手指遮挡。其余情况下,说明光照无较大变化或者光照变强,这说明没有手指遮挡或手指逐渐远离,状态均不跳转。
  4. 测量周期为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 而不能是最新版的。

附件下载
FingerCountRecog.zip
工程源代码
团队介绍
北京大学 软件与微电子学院 集成电路工程专业就读
团队成员
葉SiR
二次元の开发者;👉 GitHub: https://github.com/KafCoppelia
评论
0 / 100
查看更多
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号