用Arduino Nano 33 BLE Sense实现手势识别的全流程实战
当Arduino Nano 33 BLE Sense开发板遇上Edge Impulse平台,内置的IMU传感器突然拥有了理解手势的能力。本文将带你完整实现从原始传感器数据采集到嵌入式AI模型部署的全过程,让一块普通开发板学会识别"上下晃动"、"左右摇晃"等动作。
1. 硬件准备与开发环境搭建
Arduino Nano 33 BLE Sense这块开发板之所以适合手势识别项目,关键在于它集成了9轴IMU(LSM9DS1传感器),包含三轴加速度计、三轴陀螺仪和三轴磁力计。我们主要利用前两种传感器数据:
- 加速度计:测量xyz三个方向的线性加速度(单位:g)
- 陀螺仪:测量绕xyz三个轴的旋转角速度(单位:dps)
提示:开发板需要通过USB连接电脑,并确保安装了最新版Arduino IDE(1.8.x或更高版本)
需要安装的库文件:
#include <Arduino_LSM9DS1.h> #include <ArduinoBLE.h>安装步骤:
- 打开Arduino IDE,导航至"工具"→"开发板"→"开发板管理器"
- 搜索并安装"Arduino nRF528x Boards"
- 在库管理器中搜索安装"Arduino_LSM9DS1"
验证传感器是否正常工作:
void setup() { Serial.begin(9600); while (!Serial); if (!IMU.begin()) { Serial.println("IMU初始化失败!"); while (1); } Serial.println("IMU初始化成功"); } void loop() { float ax, ay, az; if (IMU.accelerationAvailable()) { IMU.readAcceleration(ax, ay, az); Serial.print(ax); Serial.print(','); Serial.print(ay); Serial.print(','); Serial.println(az); } delay(50); }2. 数据采集与格式化处理
高质量的数据采集是模型成功的关键。我们需要为每种手势采集足够多的样本数据,建议每种手势至少采集3分钟(约3600个样本)。
典型手势分类:
- 上下晃动:快速上下移动开发板
- 左右摇晃:左右摆动开发板
- 画圈:在空中画圆圈
- 静止:保持开发板不动
数据采集脚本示例:
void loop() { static unsigned long timestamp = 0; float aX, aY, aZ, gX, gY, gZ; if (IMU.accelerationAvailable() && IMU.gyroscopeAvailable()) { IMU.readAcceleration(aX, aY, aZ); IMU.readGyroscope(gX, gY, gZ); Serial.print(timestamp); Serial.print(','); Serial.print(aX,4); Serial.print(','); Serial.print(aY,4); Serial.print(','); Serial.print(aZ,4); Serial.print(','); Serial.print(gX,4); Serial.print(','); Serial.print(gY,4); Serial.print(','); Serial.println(gZ,4); timestamp += 10; // 假设采样间隔10ms } delay(10); }数据格式要求:
| 列名 | 说明 | 单位 |
|---|---|---|
| timestamp | 时间戳 | ms |
| aX,aY,aZ | 三轴加速度 | g |
| gX,gY,gZ | 三轴角速度 | dps |
注意:采集数据时保持开发板朝向一致,建议用马克笔在板上标注正面方向
3. Edge Impulse项目配置
登录Edge Impulse Studio后,按以下步骤创建项目:
新建项目:命名为"GestureRecognition"
上传数据:
- 将串口监视器输出的数据保存为CSV
- 每种手势单独一个文件,命名如"up_down_1.csv"
- 上传时正确标注类别标签
创建Impulse:
- 设置窗口大小为1000ms(约100个样本)
- 添加"Processing Block"选择"Spectral Analysis"
- 添加"Learning Block"选择"Classification"
特征生成:
- 点击"Generate features"自动提取频域特征
- 检查特征可视化是否显示不同手势有可区分性
关键参数配置表:
| 参数项 | 推荐值 | 说明 |
|---|---|---|
| 采样频率 | 100Hz | 与采集设置一致 |
| 窗口大小 | 1000ms | 覆盖完整手势周期 |
| 窗口增量 | 500ms | 50%重叠增加样本量 |
| FFT长度 | 64点 | 平衡时频分辨率 |
4. 模型训练与优化
Edge Impulse提供了几种适合嵌入式设备的轻量级模型架构。对于IMU数据,推荐以下配置:
神经网络结构示例:
# 这是Edge Impulse后台实际使用的Keras模型架构 model = Sequential([ Reshape((int(input_length / 3), 3)), # 时域信号重组 Conv1D(8, kernel_size=3, activation='relu'), MaxPooling1D(pool_size=2), Flatten(), Dense(classes, activation='softmax') ])训练技巧:
- 数据增强:启用"Add synthetic noise"增加数据多样性
- 学习率:初始设为0.001,观察loss曲线调整
- epochs:从30开始,防止过拟合
- 验证集比例:保留20%数据用于验证
模型性能指标参考:
| 指标 | 优秀值 | 可接受值 |
|---|---|---|
| 准确率 | >95% | >85% |
| 推理时间 | <15ms | <30ms |
| RAM占用 | <32KB | <64KB |
| Flash占用 | <128KB | <256KB |
提示:如果准确率不理想,尝试增加更多训练数据或调整窗口大小
5. 模型部署与实时测试
训练满意后,转到"Deployment"页面,选择"Arduino library"格式导出。将生成的zip库文件导入Arduino IDE:
- 在Arduino IDE中选择"项目"→"加载库"→"添加.ZIP库"
- 选择下载的模型库文件
- 打开示例代码:文件→示例→[你的项目名称]_inferencing
关键部署代码片段:
void loop() { static float features[6 * 100]; // 100个时间点的6轴数据 // 采集数据填充features数组 if (/* 缓冲区满 */) { ei_impulse_result_t result; run_classifier(features, &result); Serial.print("预测结果: "); Serial.println(result.classification[0].label); // 重置缓冲区 } }性能优化技巧:
- 降低采样率到最小可接受值
- 使用
#define EI_CLASSIFIER_LOAD_ALL_FEATURES 0减少内存占用 - 关闭调试输出提升速度
6. 实际应用与扩展思路
成功部署后,可以进一步扩展项目功能:
应用场景示例:
- 智能家居控制(通过手势开关灯)
- 可穿戴设备交互
- 工业设备远程操控
进阶改进方向:
- 增加更多手势类别
- 结合BLE实现无线手势控制
- 添加离线学习功能
- 优化功耗实现电池供电
手势识别只是IMU应用的冰山一角。同样的技术栈稍加调整,就能实现跌倒检测、运动计数等丰富应用。关键在于理解从原始数据到特征提取,再到模型部署的完整链条。