第10周个人作业:手势控制迷你风扇与LED
1. 项目介绍
本周个人项目的主要目标是:向你设计的微控制器板添加输出设备并编程使其工作。基于我之前的手势传感器集成和最终项目创意,我决定设计一个手势控制系统,将输入设备(APDS-9960手势传感器)与输出设备(Grove迷你风扇和板载LED)相结合,创建一个互动电子项目。在我的最终项目,迷你风扇的电机将会用来驱动灯罩旋转,所以这次的实验对我的最终项目有重要的技术验证价值。
项目具体目标包括:
- 设计并实现手势控制风扇和LED的电路连接
- 编写程序实现基于不同手势的控制功能
- 测试手势识别的可靠性和响应速度
- 探索与多个输出设备交互的方法
2. 材料与设备
硬件组件
- XIAO ESP32C3开发板(自制)
- APDS-9960手势传感器模块(XLOT品牌)
- Grove迷你风扇模块
- 连接线/杜邦线
- USB数据线
- 电源适配器(5V/2A)
软件工具
- Arduino IDE
- XLOT_APDS9960AD库(用于手势传感器)
3. 系统设计
3.1 接口挑战与解决方案
在为自制的XIAO ESP32C3扩展板添加手势传感器和风扇模块时,我面临了一个关键挑战:我设计的扩展板没有直接引出I2C接口(SDA/SCL)引脚。
我的 XIAO 开发板的 8 针引脚如下图所示。
我设计的 XIAO 开发板的引脚编号标注
XIAO ESP32C3扩展板上8针引脚连接器(J1)的功能说明:
引脚号 | 标识 | 功能 | GPIO编号 |
---|---|---|---|
1 | GND | 接地连接 | - |
2 | 3.3V | 3.3V电源输出 | - |
3 | RX/D7 | 串口接收引脚 | GPIO20 |
4 | TX/D6 | 串口发送引脚 | GPIO21 |
5 | SCK/D8 | SPI时钟信号 | GPIO8* |
6 | MISO/D9 | SPI主机输入从机输出 | GPIO9* |
7 | MOSI/D10 | SPI主机输出从机输入 | GPIO10 |
8 | RST | 复位信号或其他功能扩展 | - |
_注:带_标记的是Strapping引脚,用于ESP32C3启动模式选择。
针对这一限制,我采用了ESP32C3的软件I2C功能,通过重新映射引脚来解决问题:
- 使用RX/D7(GPIO20)作为SDA数据线
- 使用TX/D6(GPIO21)作为SCL时钟线
- 使用MOSI/D10(GPIO10)作为风扇控制引脚
此外,开发板上已有6个LED(D0-D5),我可以直接使用这些LED作为视觉反馈输出设备。
3.2 功能设计
手势控制系统将通过APDS-9960手势传感器识别四种基本手势,并控制风扇和LED:
手势方向 | 控制功能 |
---|---|
右划 | 开启风扇 |
左划 | 关闭风扇 |
上划 | 增加点亮的LED数量 |
下划 | 减少点亮的LED数量 |
这种设计使操作更加直观:
- 左右手势用于控制风扇的启停
- 上下手势用于控制LED的亮度/数量,象征性地表示风扇速度等级
3.3 硬件连接设计
电源和地线共享解决方案
由于两个设备都需要连接到电源和地线,而J1接口只有一组3.3V和GND引脚,因此我采用了Y型分线连接的方式解决此问题:
- 制作Y型分线连接器:
- 使用杜邦线制作两个简易的Y型分线器
- 一个用于3.3V供电(引脚2),另一个用于GND(引脚1)
- 每个Y型分线器将一个引脚拓展为两个接口
- 替代方案:
- 也可以直接使用XIAO ESP32C3板上的额外GND和3.3V引脚
- 或使用面包板进行电源分配
修改后的设备连接方案
APDS-9960手势传感器连接
APDS-9960引脚 | 连接到扩展板引脚 | XIAO ESP32C3引脚 | 功能 |
---|---|---|---|
VCC(红线) | J1-2 (3.3V)的Y型分线 | 3.3V | 电源正极 |
GND(黑线) | J1-1 (GND)的Y型分线 | GND | 电源地线 |
SDA(黄线) | J1-3 (RX/D7) | GPIO20 | I2C数据线(软件实现) |
SCL(绿线) | J1-4 (TX/D6) | GPIO21 | I2C时钟线(软件实现) |
Grove迷你风扇连接
Grove迷你风扇引脚 | 连接到扩展板引脚 | XIAO ESP32C3引脚 | 功能 |
---|---|---|---|
信号线 | J1-7 (MOSI/D10) | GPIO10 | 控制信号 |
VCC | J1-2 (3.3V)的Y型分线 | 3.3V | 电源正极 |
GND | J1-1 (GND)的Y型分线 | GND | 电源地线 |
LED连接
开发板上已有6个LED(D0-D5),这些LED直接通过板载电路连接到ESP32C3的对应GPIO引脚,无需额外连接。
3.4 电路连接
系统硬件连接示意图,包括手势传感器、风扇控制和LED指示。
使用Y型分线器实现两个设备共享电源和地线的连接示意图
4. 程序设计
4.1 程序结构设计
程序主要分为以下几个部分:
- 初始化:设置串口通信、I2C通信、LED引脚、风扇引脚、手势传感器等。
- 主循环:
- 读取手势传感器数据
- 根据手势更新风扇状态和LED数量
- 控制风扇和LED
4.2 核心代码实现
#include <Wire.h>
#include "XLOT_APDS9960AD.h"
// 引脚重定义 - 适应自制扩展板
#define SDA_PIN 20 // RX/D7 (GPIO20)
#define SCL_PIN 21 // TX/D6 (GPIO21)
#define FAN_PIN 10 // MOSI/D10 (GPIO10)
// LED引脚定义
const int LED_PINS[] = {D5, D4, D3, D2, D1, D0};
const int LED_COUNT = 6;
// 手势传感器
XLOT_APDS9960AD apds;
// 风扇控制变量
bool fanState = false; // 风扇状态(开/关)
unsigned long lastGestureTime = 0; // 最后手势时间戳
const int gestureDelay = 500; // 手势识别间隔(毫秒)
// LED控制变量
int ledCount = 0; // 点亮的LED数量(0-6)
void setup() {
Serial.begin(115200);
delay(3000); // 增加延迟,确保有足够时间上传新代码
Serial.println("\n系统启动...");
// 使用重定义的引脚初始化I2C
Wire.begin(SDA_PIN, SCL_PIN);
// 初始化所有LED引脚
for(int i = 0; i < LED_COUNT; i++) {
pinMode(LED_PINS[i], OUTPUT);
digitalWrite(LED_PINS[i], LOW); // 初始状态全部关闭
}
// 初始化风扇引脚
pinMode(FAN_PIN, OUTPUT);
digitalWrite(FAN_PIN, LOW); // 初始状态关闭
if(!apds.begin()){
Serial.println("手势传感器初始化失败! 请检查接线。");
// 错误指示 - 闪烁第一个LED
while(1) {
digitalWrite(LED_PINS[0], HIGH);
delay(100);
digitalWrite(LED_PINS[0], LOW);
delay(100);
}
} else {
Serial.println("手势传感器初始化成功!");
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);
// 成功指示 - 所有LED依次亮起再熄灭
for(int i = 0; i < LED_COUNT; i++) {
digitalWrite(LED_PINS[i], HIGH);
delay(200);
}
delay(500);
for(int i = 0; i < LED_COUNT; i++) {
digitalWrite(LED_PINS[i], LOW);
delay(200);
}
}
Serial.println("系统初始化完成,等待手势控制...");
}
// 更新LED显示
void updateLEDs() {
for(int i = 0; i < LED_COUNT; i++) {
// 如果i小于ledCount,点亮LED,否则熄灭
digitalWrite(LED_PINS[i], (i < ledCount) ? HIGH : LOW);
}
}
void loop() {
// 读取手势
uint8_t gesture = apds.readGesture();
// 处理手势(添加延迟以防止过快响应)
if(gesture != 0 && millis() - lastGestureTime > gestureDelay) {
lastGestureTime = millis();
switch(gesture) {
case APDS9960_RIGHT:
// 右划 - 开启风扇
if(!fanState) {
fanState = true;
digitalWrite(FAN_PIN, HIGH);
Serial.println("风扇开启");
}
break;
case APDS9960_LEFT:
// 左划 - 关闭风扇
if(fanState) {
fanState = false;
digitalWrite(FAN_PIN, LOW);
Serial.println("风扇关闭");
}
break;
case APDS9960_UP:
// 上划 - 增加LED亮灯数量
if(ledCount < LED_COUNT) {
ledCount++;
updateLEDs();
Serial.print("LED亮灯数量: ");
Serial.println(ledCount);
}
break;
case APDS9960_DOWN:
// 下划 - 减少LED亮灯数量
if(ledCount > 0) {
ledCount--;
updateLEDs();
Serial.print("LED亮灯数量: ");
Serial.println(ledCount);
}
break;
}
}
}
程序运行时会在串口监视器给出反馈,如下图所示。
程序运行时会在串口监视器给出反馈
4.3 程序功能说明
- 引脚重定义和初始化:
- 使用RX/D7(GPIO20)和TX/D6(GPIO21)作为软件I2C的SDA和SCL引脚
- 使用MOSI/D10(GPIO10)作为风扇控制引脚
- 定义并初始化6个板载LED(D0-D5)
- 所有设备初始状态为关闭
- 手势识别与处理:
- 右划手势:开启风扇
- 左划手势:关闭风扇
- 上划手势:增加点亮的LED数量
- 下划手势:减少点亮的LED数量
- LED控制功能:
updateLEDs()
函数控制LED的按序点亮/熄灭- LED亮起数量(6-0)作为系统状态的视觉反馈
- 防抖处理:
- 添加500ms的手势识别间隔,防止意外触发或重复识别
5. 硬件实现
5.1 实物连接
我按照设计方案,使用杜邦线将手势传感器和风扇模块连接到XIAO扩展板上,并用胶带固定在一个手机支架上,方便操作和展示效果,如下图所示。
实际的硬件连接,将手势传感器连接到RX/TX引脚,将风扇连接到MOSI引脚
连接过程中遇到的主要挑战是避免引脚间的短路和确保连接稳定。使用不同颜色的杜邦线有助于区分各个连接,提高操作可靠性。
5.2 组件布局
为获得最佳的手势识别效果和风扇送风效果,组件布局做了以下考虑:
- 手势传感器放置:
- 使用手机支架支撑扩展板和手势传感器,并保持传感器朝上
- 传感器表面向上,便于从上方进行手势操作
- 保持传感器前方约15cm无遮挡
- 风扇位置:
- 风扇置于传感器下方约10cm处
- 确保风扇气流不会干扰手势识别
- 固定稳固,防止运转时晃动
- 连接线管理:
- 使用胶带固定连接线,避免松动
- 连接线尽量短而直接,减少软件I2C的干扰问题
最终组件布局,优化了手势操作空间和设备放置
6. 系统测试与演示
6.1 手势响应测试
我测试了四种手势的识别和系统响应情况:
手势方向 | 控制功能 | 识别成功率 | 备注 |
---|---|---|---|
右划 | 开启风扇 | ~92% | 识别稳定 |
左划 | 关闭风扇 | ~90% | 识别较稳定 |
上划 | 增加LED亮灯数量 | ~85% | 偶有误判为下划 |
下划 | 减少LED亮灯数量 | ~85% | 偶有误判为上划 |
测试结果表明,左右手势识别率略高于上下手势,这与手势传感器的布局和光线反射特性相关。添加的500ms手势识别间隔有效防止了意外触发。
6.2 LED序列亮灯效果
LED序列亮灯展示了良好的视觉反馈效果:
- 可以通过上下手势精确控制0-6个LED的点亮数量
- LED按顺序点亮/熄灭,提供直观的状态指示
- 系统启动时的LED初始化动画提供了视觉确认
6.3 风扇控制响应
风扇控制表现出以下特性:
- 右划手势可以稳定开启风扇
- 左划手势可以稳定关闭风扇
- 风扇响应迅速,基本无延迟
- 直接使用高电平/低电平控制,操作简单可靠
6.4 系统演示视频
视频展示了完整的系统功能,包括:
- 使用右划手势开启风扇
- 使用左划手势关闭风扇
- 使用上划手势增加LED亮灯数量
- 使用下划手势减少LED亮灯数量
7. 问题与解决方案
7.1 遇到的问题
- 引脚复用挑战:
- 问题:自制扩展板未引出专用I2C引脚
- 解决方案:使用ESP32C3的软件I2C功能,将RX/TX复用为SDA/SCL
- 后果:导致使用这些引脚时无法同时使用串口通信功能,但可以上传完程序后使用
- PWM与模拟输出兼容性:
- 问题:ESP32C3的
ledcSetup
/ledcWrite
函数在编译时报错 - 解决方案:改用标准
digitalWrite
函数进行数字控制 - 影响:只能实现开关控制,无法进行速度调节,但符合我们简化的控制需求
- 问题:ESP32C3的
- 手势识别不稳定:
- 问题:初始测试中,上/下手势经常被误识别
- 原因:环境光干扰和手势角度不一致
- 解决方案:增加简易遮光罩并添加手势识别延迟(500ms)
- 电源电压挑战:
- 问题:手势传感器推荐使用5V,但扩展板只提供3.3V
- 解决方案:将传感器直接连接到3.3V,尽管可能减小检测距离
- 测试结果:在3.3V下仍能正常工作,检测距离约为标称值的70%
7.2 改进方向
- 硬件设计优化:
- 在下一版扩展板中引出专用I2C引脚
- 增加5V输出选项,提高传感器兼容性
- 考虑添加电机驱动电路,支持精确的PWM控制
- 手势识别增强:
- 优化手势识别算法,减少误识别
- 添加更多手势组合,实现更丰富功能
- 增加接近检测功能,自动开启/关闭
- 用户界面优化:
- 设计更丰富的LED显示模式,如闪烁、流水灯效果
- 添加声音反馈,提高交互体验
- 开发双手协作手势,增加控制维度
8. 结论与反思
8.1 项目成果
本项目成功克服了扩展板设计限制,实现了手势控制风扇和LED系统,完成了以下目标:
- 通过软件I2C解决了连接难题,实现了APDS-9960手势传感器与XIAO的通信
- 成功控制Grove迷你风扇,实现了简单的开/关控制
- 实现了板载LED的序列点亮控制,提供视觉反馈
- 设计了直观的手势交互系统,让控制更自然
项目证明了ESP32C3强大的I/O复用能力,展示了如何在现有硬件限制下实现创新功能。
8.2 学习收获
- 软件I2C的实现与应用:
- 学习了ESP32C3的引脚映射技术
- 了解了通信时序和电气特性对信号质量的影响
- 掌握了处理非标准硬件配置的方法
- 多设备控制技能:
- 学习了控制风扇等执行器的基本方法
- 掌握了LED序列控制技术
- 理解了人机交互中视觉反馈的重要性
- 系统集成能力:
- 成功集成输入设备(手势传感器)和多个输出设备(风扇和LED)
- 构建完整的交互系统
- 解决设备间通信和协同工作问题
- 问题解决与创新思维:
- 在硬件限制下找到软件解决方案
- 通过实验发现和解决实际操作中的问题
- 学会利用现有资源实现创新功能
8.3 与最终项目的关联
本项目是我最终项目"智幻走马灯"的重要技术验证,特别是:
- 验证了APDS-9960手势传感器在3.3V下的可靠性和适用性
- 测试了ESP32C3的软件I2C功能和GPIO控制能力
- 探索了手势交互系统的设计方法,为最终项目奠定了交互基础
- 验证了使用ESP32C3控制电机的可行性,为灯罩旋转机构提供参考
这些技术和经验将直接用于最终项目中灯带控制和交互设计,是项目成功的关键基础。通过本次实验,我更加确信在现有硬件条件下,能够实现理想的"智幻走马灯"交互控制方案。