Skip to content

第10周个人作业:手势控制迷你风扇与LED

1. 项目介绍

本周个人项目的主要目标是:向你设计的微控制器板添加输出设备并编程使其工作。基于我之前的手势传感器集成最终项目创意,我决定设计一个手势控制系统,将输入设备(APDS-9960手势传感器)与输出设备(Grove迷你风扇和板载LED)相结合,创建一个互动电子项目。在我的最终项目,迷你风扇的电机将会用来驱动灯罩旋转,所以这次的实验对我的最终项目有重要的技术验证价值。

项目具体目标包括:

  1. 设计并实现手势控制风扇和LED的电路连接
  2. 编写程序实现基于不同手势的控制功能
  3. 测试手势识别的可靠性和响应速度
  4. 探索与多个输出设备交互的方法

2. 材料与设备

硬件组件

  1. XIAO ESP32C3开发板(自制)
  2. APDS-9960手势传感器模块(XLOT品牌)
  3. Grove迷你风扇模块
  4. 连接线/杜邦线
  5. USB数据线
  6. 电源适配器(5V/2A)

软件工具

  1. Arduino IDE
  2. XLOT_APDS9960AD库(用于手势传感器)

3. 系统设计

3.1 接口挑战与解决方案

在为自制的XIAO ESP32C3扩展板添加手势传感器和风扇模块时,我面临了一个关键挑战:我设计的扩展板没有直接引出I2C接口(SDA/SCL)引脚。

我的 XIAO 开发板的 8 针引脚如下图所示。

我设计的 XIAO 开发板的引脚编号标注

XIAO ESP32C3扩展板上8针引脚连接器(J1)的功能说明:

引脚号标识功能GPIO编号
1GND接地连接-
23.3V3.3V电源输出-
3RX/D7串口接收引脚GPIO20
4TX/D6串口发送引脚GPIO21
5SCK/D8SPI时钟信号GPIO8*
6MISO/D9SPI主机输入从机输出GPIO9*
7MOSI/D10SPI主机输出从机输入GPIO10
8RST复位信号或其他功能扩展-

_注:带_标记的是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型分线连接的方式解决此问题:

  1. 制作Y型分线连接器
    • 使用杜邦线制作两个简易的Y型分线器
    • 一个用于3.3V供电(引脚2),另一个用于GND(引脚1)
    • 每个Y型分线器将一个引脚拓展为两个接口
  2. 替代方案
    • 也可以直接使用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)GPIO20I2C数据线(软件实现)
SCL(绿线)J1-4 (TX/D6)GPIO21I2C时钟线(软件实现)
Grove迷你风扇连接
Grove迷你风扇引脚连接到扩展板引脚XIAO ESP32C3引脚功能
信号线J1-7 (MOSI/D10)GPIO10控制信号
VCCJ1-2 (3.3V)的Y型分线3.3V电源正极
GNDJ1-1 (GND)的Y型分线GND电源地线
LED连接

开发板上已有6个LED(D0-D5),这些LED直接通过板载电路连接到ESP32C3的对应GPIO引脚,无需额外连接。

3.4 电路连接

系统硬件连接示意图,包括手势传感器、风扇控制和LED指示。

使用Y型分线器实现两个设备共享电源和地线的连接示意图

4. 程序设计

4.1 程序结构设计

程序主要分为以下几个部分:

  1. 初始化:设置串口通信、I2C通信、LED引脚、风扇引脚、手势传感器等。
  2. 主循环
    • 读取手势传感器数据
    • 根据手势更新风扇状态和LED数量
    • 控制风扇和LED

4.2 核心代码实现

cpp
#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 程序功能说明

  1. 引脚重定义和初始化
    • 使用RX/D7(GPIO20)和TX/D6(GPIO21)作为软件I2C的SDA和SCL引脚
    • 使用MOSI/D10(GPIO10)作为风扇控制引脚
    • 定义并初始化6个板载LED(D0-D5)
    • 所有设备初始状态为关闭
  2. 手势识别与处理
    • 右划手势:开启风扇
    • 左划手势:关闭风扇
    • 上划手势:增加点亮的LED数量
    • 下划手势:减少点亮的LED数量
  3. LED控制功能
    • updateLEDs() 函数控制LED的按序点亮/熄灭
    • LED亮起数量(6-0)作为系统状态的视觉反馈
  4. 防抖处理
    • 添加500ms的手势识别间隔,防止意外触发或重复识别

5. 硬件实现

5.1 实物连接

我按照设计方案,使用杜邦线将手势传感器和风扇模块连接到XIAO扩展板上,并用胶带固定在一个手机支架上,方便操作和展示效果,如下图所示。

实际的硬件连接,将手势传感器连接到RX/TX引脚,将风扇连接到MOSI引脚

连接过程中遇到的主要挑战是避免引脚间的短路和确保连接稳定。使用不同颜色的杜邦线有助于区分各个连接,提高操作可靠性。

5.2 组件布局

为获得最佳的手势识别效果和风扇送风效果,组件布局做了以下考虑:

  1. 手势传感器放置
    • 使用手机支架支撑扩展板和手势传感器,并保持传感器朝上
    • 传感器表面向上,便于从上方进行手势操作
    • 保持传感器前方约15cm无遮挡
  2. 风扇位置
    • 风扇置于传感器下方约10cm处
    • 确保风扇气流不会干扰手势识别
    • 固定稳固,防止运转时晃动
  3. 连接线管理
    • 使用胶带固定连接线,避免松动
    • 连接线尽量短而直接,减少软件I2C的干扰问题

最终组件布局,优化了手势操作空间和设备放置

6. 系统测试与演示

6.1 手势响应测试

我测试了四种手势的识别和系统响应情况:

手势方向控制功能识别成功率备注
右划开启风扇~92%识别稳定
左划关闭风扇~90%识别较稳定
上划增加LED亮灯数量~85%偶有误判为下划
下划减少LED亮灯数量~85%偶有误判为上划

测试结果表明,左右手势识别率略高于上下手势,这与手势传感器的布局和光线反射特性相关。添加的500ms手势识别间隔有效防止了意外触发。

6.2 LED序列亮灯效果

LED序列亮灯展示了良好的视觉反馈效果:

  • 可以通过上下手势精确控制0-6个LED的点亮数量
  • LED按顺序点亮/熄灭,提供直观的状态指示
  • 系统启动时的LED初始化动画提供了视觉确认

6.3 风扇控制响应

风扇控制表现出以下特性:

  • 右划手势可以稳定开启风扇
  • 左划手势可以稳定关闭风扇
  • 风扇响应迅速,基本无延迟
  • 直接使用高电平/低电平控制,操作简单可靠

6.4 系统演示视频

视频展示了完整的系统功能,包括:

  1. 使用右划手势开启风扇
  2. 使用左划手势关闭风扇
  3. 使用上划手势增加LED亮灯数量
  4. 使用下划手势减少LED亮灯数量

7. 问题与解决方案

7.1 遇到的问题

  1. 引脚复用挑战
    • 问题:自制扩展板未引出专用I2C引脚
    • 解决方案:使用ESP32C3的软件I2C功能,将RX/TX复用为SDA/SCL
    • 后果:导致使用这些引脚时无法同时使用串口通信功能,但可以上传完程序后使用
  2. PWM与模拟输出兼容性
    • 问题:ESP32C3的 ledcSetup/ledcWrite函数在编译时报错
    • 解决方案:改用标准 digitalWrite函数进行数字控制
    • 影响:只能实现开关控制,无法进行速度调节,但符合我们简化的控制需求
  3. 手势识别不稳定
    • 问题:初始测试中,上/下手势经常被误识别
    • 原因:环境光干扰和手势角度不一致
    • 解决方案:增加简易遮光罩并添加手势识别延迟(500ms)
  4. 电源电压挑战
    • 问题:手势传感器推荐使用5V,但扩展板只提供3.3V
    • 解决方案:将传感器直接连接到3.3V,尽管可能减小检测距离
    • 测试结果:在3.3V下仍能正常工作,检测距离约为标称值的70%

7.2 改进方向

  1. 硬件设计优化
    • 在下一版扩展板中引出专用I2C引脚
    • 增加5V输出选项,提高传感器兼容性
    • 考虑添加电机驱动电路,支持精确的PWM控制
  2. 手势识别增强
    • 优化手势识别算法,减少误识别
    • 添加更多手势组合,实现更丰富功能
    • 增加接近检测功能,自动开启/关闭
  3. 用户界面优化
    • 设计更丰富的LED显示模式,如闪烁、流水灯效果
    • 添加声音反馈,提高交互体验
    • 开发双手协作手势,增加控制维度

8. 结论与反思

8.1 项目成果

本项目成功克服了扩展板设计限制,实现了手势控制风扇和LED系统,完成了以下目标:

  1. 通过软件I2C解决了连接难题,实现了APDS-9960手势传感器与XIAO的通信
  2. 成功控制Grove迷你风扇,实现了简单的开/关控制
  3. 实现了板载LED的序列点亮控制,提供视觉反馈
  4. 设计了直观的手势交互系统,让控制更自然

项目证明了ESP32C3强大的I/O复用能力,展示了如何在现有硬件限制下实现创新功能。

8.2 学习收获

  1. 软件I2C的实现与应用
    • 学习了ESP32C3的引脚映射技术
    • 了解了通信时序和电气特性对信号质量的影响
    • 掌握了处理非标准硬件配置的方法
  2. 多设备控制技能
    • 学习了控制风扇等执行器的基本方法
    • 掌握了LED序列控制技术
    • 理解了人机交互中视觉反馈的重要性
  3. 系统集成能力
    • 成功集成输入设备(手势传感器)和多个输出设备(风扇和LED)
    • 构建完整的交互系统
    • 解决设备间通信和协同工作问题
  4. 问题解决与创新思维
    • 在硬件限制下找到软件解决方案
    • 通过实验发现和解决实际操作中的问题
    • 学会利用现有资源实现创新功能

8.3 与最终项目的关联

本项目是我最终项目"智幻走马灯"的重要技术验证,特别是:

  1. 验证了APDS-9960手势传感器在3.3V下的可靠性和适用性
  2. 测试了ESP32C3的软件I2C功能和GPIO控制能力
  3. 探索了手势交互系统的设计方法,为最终项目奠定了交互基础
  4. 验证了使用ESP32C3控制电机的可行性,为灯罩旋转机构提供参考

这些技术和经验将直接用于最终项目中灯带控制和交互设计,是项目成功的关键基础。通过本次实验,我更加确信在现有硬件条件下,能够实现理想的"智幻走马灯"交互控制方案。

9. 参考资料

  1. APDS-9960数据手册
  2. Grove迷你风扇官方Wiki
  3. ESP32 软件I2C实现
  4. ESP32 GPIO控制文档
  5. 第10周课程大纲:输出设备
  6. XIAO ESP32C3官方文档