第9周个人作业 2:为 XIAO 扩展板添加手势传感器
项目介绍
本周个人项目的主要目标是:向你设计的微控制器板添加传感器并读取数据。因为我最终项目"智幻走马灯"的创意,需要用到手势控制,如下图所示。
在我的最终项目"智幻走马灯"中,手势控制系统将作为主要的用户交互界面,实现以下控制功能:
- 左右手势: 控制走马灯的旋转方向(顺时针/逆时针)
- 上下手势: 调节灯光亮度(增加/减少)
所以我在淘宝搜索了一些手势传感器,找到一个觉得可以尝试的传感器:超mini手势传感器感应运动方向RGB颜色识别模块Arduino树莓派。
淘宝新地科技的店铺提供一个超 mini 的手势传感器,价格是 29.9 元RMB
于是我购买了 3 只回来,一方面作为第 9 周个人作业的一部分,一方面也想尝试看看是否可以用于我的最终项目。
所以本周作业我先列出了几个具体目标包括:
- 理解手势传感器的工作原理
- 设计传感器电路并与XIAO ESP32C3进行连接
- 编写程序测试手势识别功能
- 记录整个设计、制造和测试过程
- 展示输入设备的工作原理及其在最终项目中的应用场景
理解手势传感器的工作原理
我购买的"超mini手势传感器"产品,新地科技(或XLOT品牌)将 APDS-9960 芯片进行了适当的模块化,便于与各种微控制器(如 XIAO 开发版)进行简单的集成。下图左侧是购得的传感器,店家还送了各种连接线材,右侧是我目前做好的开发板。
XLOT APDS-9960 模块(左侧)与我的 XIAO 开发板对比
下面将重点研究 APDS-9960 手势传感器,这是一款由 Broadcom 设计和制造的多功能集成传感器。该传感器被新地科技(XLOT)采用并封装为便于DIY电子爱好者使用的模块。
淘宝的供应商的文档比较简陋,只有图片的简单说明
APDS-9960 简介
模块上的 APDS-9960 传感器
APDS-9960 是一款集手势检测、接近感应、环境光传感和RGB颜色传感于一体的多功能传感器。我在其官方网站找到了 APDS-9960 传感器的 Data Sheet:其特点包括:
- 手势检测:可识别上下左右四个方向的手势
- 接近检测:能测量物体与传感器的距离
- 环境光和RGB颜色传感:能测量环境光强度和RGB颜色成分
- I2C通信接口:标准I2C接口,兼容3.3V和5V逻辑电平
- 集成IR LED:内置红外LED光源,用于手势和接近检测
物理结构
APDS-9960传感器具有紧凑的封装尺寸(约3.94mm×2.36mm×1.35mm),包含以下核心组件:
- 红外LED发光源:发射940nm波长的红外光
- 四个方向光电二极管:分别探测上、下、左、右四个方向反射的红外光
- 滤光片:包含紫外线和红外线过滤器,提高色彩感应的准确性
- 集成LED驱动电路:控制IR LED的脉冲宽度和电流强度
APDS-9960 传感器的 Data Sheet 中的功能框图
工作原理
手势检测原理
APDS-9960的手势检测功能基于光反射原理,工作流程如下:
- IR光发射:内置的红外LED发射脉冲IR光
- 手势反射:当用户手在传感器上方做出手势时,IR光被反射
- 方向性光电二极管接收:四个方向的光电二极管接收反射光并转换为电信号
- 信号处理:传感器内部处理器分析四个光电二极管的信号强度变化
- 手势识别:根据不同方向光电二极管信号的时序和强度变化,识别出手势方向
手势识别原理基于运动探测:
- 从左到右手势:首先激活左侧光电二极管,然后是右侧
- 从右到左手势:首先激活右侧光电二极管,然后是左侧
- 从上到下手势:首先激活上侧光电二极管,然后是下侧
- 从下到上手势:首先激活下侧光电二极管,然后是上侧
通过分析这些信号随时间的变化,传感器能识别基本的方向性手势。理论上,通过复杂的算法处理,还可以识别更复杂的手势模式。
APDS-9960 传感器的 Data Sheet 中的方向定位原理图
接近检测原理
接近检测利用相同的IR LED和光电二极管,但使用不同的信号处理方式:
- IR LED发射红外光
- 物体反射红外光
- 光电二极管检测反射光强度
- 反射光强度与距离成反比,通过测量反射光强度估算物体距离
APDS-9960传感器能够测量约10厘米范围内的物体距离,分辨率为8位(0-255)。
环境光和颜色检测原理
环境光和颜色感应使用专门的光电二极管阵列:
- 光电二极管上方有不同颜色的滤光片(红、绿、蓝和清晰)
- 四个通道并行收集特定波长范围的光强度
- 内置16位ADC将光电二极管信号转换为数字值
- 可以通过这些值计算出环境光强度和颜色成分
APDS-9960传感器的关键特性
根据数据手册,APDS-9960具有以下技术特性:
参数 | 规格 |
---|---|
工作电压 | 2.4V-3.6V |
通信协议 | I²C (最高400kHz) |
集成LED波长 | 950nm |
手势检测距离 | 约10-15cm |
接近检测范围 | 0-255 (8位分辨率) |
颜色检测分辨率 | 16位 (每通道) |
集成FIFO缓冲区 | 32×4字节 (用于手势数据) |
工作温度 | -30°C至85°C |
传感器状态机工作流程
APDS-9960内部实现了一个状态机来控制各个功能单元的工作流程:
工作流程简述:
- 初始化:上电后传感器进入低功耗睡眠状态
- 唤醒:通过I2C指令激活内部振荡器
- 功能启用:可单独启用手势、接近、颜色/环境光功能
- 数据采集:根据启用的功能,按特定顺序采集数据
- 中断生成:数据超过阈值或手势被识别时生成中断
- 数据读取:主控制器通过I2C读取数据寄存器
- 返回空闲或睡眠:完成数据处理后返回空闲状态或睡眠状态
APDS-9960 传感器的 Data Sheet 中的 状态机简化状态示意图
APDS-9960 传感器的 Data Sheet 中的详细状态图
手势引擎数据流
手势检测的数据流如下:
- 手势入口条件:当接近值超过设定阈值,进入手势状态机
- 数据采集:连续测量四个方向的信号强度
- FIFO存储:将四个方向(UDLR)的信号数据存入32×4字节的FIFO缓冲区
- 中断生成:当FIFO数据量达到阈值,生成中断
- 手势识别:主控制器读取FIFO数据,进行手势算法处理
- 手势退出:当所有方向的信号强度降至阈值以下,退出手势状态
这种设计允许连续监测手势,同时最小化对主控制器的干扰。
APDS-9960 传感器的 Data Sheet 中的详细手势操作流程图
与微控制器的接口方式
APDS-9960 通过I2C接口与微控制器通信:
- 固定I2C地址:0x39
- 通信速率:最高支持400kHz快速模式
- 中断引脚:提供一个专用中断输出引脚,可触发微控制器的外部中断
- 寄存器映射:通过寄存器配置传感器参数和读取数据
XLOT设计的模块在APDS-9960基础上增加了电平转换电路,使其能同时兼容3.3V和5V的逻辑电平,方便与各种微控制器连接。
设计传感器电路并与XIAO ESP32C3进行连接
硬件连接方案
APDS-9960 手势传感器采用 I2C 通信协议,与 XIAO ESP32C3 的连接非常简单直接。该传感器只需要四个引脚连接,包括电源、地线和I2C通信的两根数据线。
我给手势传感器插上了有 4 色线的接头,并向供应商询问了四条颜色线对应的引脚,红黑黄绿分别代表 VCC、GND、SDA 和 SCL。
XLOT APDS-9960 模块插上购买附送的 4 色线接头,另一端的引脚母头可以直接插入 XIAO 的引脚排针
由于我之前设计的开发板,没有引出 D4 和 D5,所以,我先直接通过引脚连接,以测试代码和性能。
连接方案详情
APDS-9960引脚 | XIAO ESP32C3引脚 | 功能 |
---|---|---|
VCC | 5V | 电源正极 |
GND | GND | 电源地线 |
SDA | D4/GPIO6 | I2C数据线 |
SCL | D5/GPIO7 | I2C时钟线 |
接线图
XIAO ESP32C3 与 XLOT APDS-9960 模块的接线图
硬件连接注意事项
- 电源选择:和淘宝卖家沟通,被告知传感器模块可在 3V-5V电压范围内工作,所以我接在了5V引脚上。
- I2C总线配置:默认情况下,XIAO ESP32C3的I2C总线使用D4(SDA)和D5(SCL)引脚。无需上拉电阻,因为XIAO ESP32C3 内部已经有上拉电阻。
- 传感器放置:手势传感器的放置位置非常重要,应确保:
- 传感器上方5-10cm范围内没有遮挡物
- 传感器面向用户,便于进行手势操作
- 固定牢固,避免晃动导致误读
- 连接线长度:使用尽可能短的连接线,特别是I2C信号线,以减少信号干扰。推荐连接线长度不超过20cm。
实际连接实现
由于项目处于原型阶段,我使用杜邦线进行了临时连接,将XLOT APDS-9960模块与之前设计的XIAO ESP32C3扩展板相连。完成连接后的实物如下图所示:
XIAO ESP32C3 与 XLOT APDS-9960 模块的连接效果图
在最终项目中,将考虑使用更可靠的连接方式,如焊接或使用牢固的接插件,以确保系统长期稳定工作。
传感器放置设计
为了获得最佳的手势识别效果,传感器的放置非常关键。经过几次次测试,我确定了以下放置方案:
- 纸盒安装方式:我采用了简单但实用的方法,将手势传感器用胶带固定在纸盒上盖的内壁,这种方式有几个明显优势:
- 便于传感器保持直立姿态
- 可以随时调整传感器角度
- 提供了轻量且稳定的支撑结构
XLOT APDS-9960 模块使用胶带固定在纸盒上盖的内壁
- 高度定位:传感器表面距离底座约3cm,便于用户在设备上方5-10cm处进行手势操作。
- 角度调整:传感器略微向上倾斜约15度,使其更容易捕捉用户手部动作。这种倾斜角度是通过胶带固定在纸盒上盖内壁的方式轻松实现的。
- 遮光设计:纸盒本身就提供了一定的遮光效果,我在纸盒上方只保留了足够的开口供手势操作。这种简易的遮光设计大大提高了在强光环境下的识别准确率。
- 位置标识:在纸盒外部添加了简单的标记,指示用户进行手势操作的最佳位置。
这种使用纸盒作为支架的方法不仅成本低廉,而且组装拆卸方便,非常适合原型开发阶段的快速测试和调整。
编程测试手势识别功能
开发环境搭建
开发环境基于Arduino IDE进行搭建,主要包括以下步骤:
- 安装 XIAO ESP32C3 开发板支持:
- 在 Arduino IDE 中添加 Seeed Studio XIAO 开发板支持
- 选择"XIAO_ESP32C3"作为目标开发板
- 安装XLOT_APDS9960库:
- 将下载的XLOT_Gesture_Sensor库复制到Arduino库文件夹
- 测试环境准备:
- 设置串口监视器波特率为115200
- 准备测试环境,确保有稳定的光照条件
3.2 测试程序代码
店家首先提供了一个 I2C 的测试程序,以便能检测到 0x39 的传感器设备。
#include <Wire.h>
void setup() {
Wire.begin(6,7); // 初始化I2C总线//17,16 21 22
Serial.begin(115200); // 初始化串口
while (!Serial); // 等待串口打开
}
void loop() {
byte error, address;
int devices = 0;
Serial.println("Scanning...");
for (address = 1; address < 127; address++ ) {
Wire.beginTransmission(address);
error = Wire.endTransmission();
if (error == 0) {
Serial.print("I2C device found at address 0x");
if (address<16) {
Serial.print("0");
}
Serial.print(address,HEX);
Serial.println(" !");
devices++;
}
else if (error==4) {
Serial.print("Unknown error at address 0x");
if (address<16) {
Serial.print("0");
}
Serial.println(address,HEX);
}
}
if (devices == 0) {
Serial.println("No I2C devices found\n");
}
else {
Serial.println("done\n");
}
// delay(5000); // 每5秒执行一次I2C扫描
}
运行测试程序,如果接线正确,会看到下面的画面。
扫描提示在 0x39 发现 I2C 设备
Scanning...
I2C device found at address 0x39 !
done
然后运行淘宝店家提供的手势识别测试程序,它能够识别APDS-9960传感器捕获的上、下、左、右四个方向的手势,并通过LED和串口输出提供反馈:
#include <Wire.h>
#include "XLOT_APDS9960AD.h"
XLOT_APDS9960AD apds;
// the setup function runs once when you press reset or power the board
void setup() {
Serial.begin(115200);
Wire.begin(6, 7);
if(!apds.begin()){
Serial.println("failed to initialize device! Please check your wiring.");
}
else Serial.println("Device initialized!");
//gesture mode will be entered once proximity mode senses something close
apds.enableProximity(true);
apds.enableGesture(true);
apds.setProxGain(APDS9960_PGAIN_8X);
apds.setGestureGain(APDS9960_PGAIN_8X);
apds.setGestureGain(APDS9960_AGAIN_64X);
apds.setGestureGain(APDS9960_GGAIN_8);
}
// the loop function runs over and over again forever
void loop() {
//read a gesture from the device
uint8_t gesture = apds.readGesture();
if(gesture == APDS9960_DOWN) Serial.println("v");
if(gesture == APDS9960_UP) Serial.println("^");
if(gesture == APDS9960_LEFT) Serial.println("<");
if(gesture == APDS9960_RIGHT) Serial.println(">");
}
运行程序,可以在串口监视器看到输出的手势方向指示,如下图所示。
在串口监视器看到输出的手势方向指示
实际操作的效果视频如下所示。