1. 入门
任务目标
本案例将使用Edge Impulse完成一个完整的边缘AI分类任务:从加速度计采集的三轴数据中,识别三种不同的手势动作(水平晃动、垂直晃动、静止)。你将学习从数据采集、模型训练到部署验证的完整流程,最终在PC上通过串口读取传感器数据并实时分类。
硬件与软件准备
- 硬件:Arduino Nano 33 BLE Sense(板载IMU LSM9DS1)、Micro USB线
- 软件:Arduino IDE(≥1.8.13)、Edge Impulse CLI(
npm install -g edge-impulse-cli)、Google Chrome浏览器 - 账号:Edge Impulse Studio账号(免费版即可)
实现步骤
1. 连接开发板并采集数据
在Arduino IDE中安装Arduino_LSM9DS1库,然后烧录以下固件,使开发板通过串口向Edge Impulse发送IMU原始数据:
#include <Arduino_LSM9DS1.h>
const float accelerationThreshold = 2.0;
const int numSamples = 119;
int samplesRead = numSamples;
void setup() {
Serial.begin(115200);
while (!Serial);
if (!IMU.begin()) {
Serial.println("Failed to initialize IMU!");
while (1);
}
Serial.println("Started");
}
void loop() {
float x, y, z;
while (samplesRead == numSamples) {
if (IMU.accelerationAvailable()) {
IMU.readAcceleration(x, y, z);
if (abs(x) + abs(y) + abs(z) > accelerationThreshold) {
samplesRead = 0;
break;
}
}
}
while (samplesRead < numSamples) {
if (IMU.accelerationAvailable()) {
IMU.readAcceleration(x, y, z);
Serial.print(x); Serial.print('\t');
Serial.print(y); Serial.print('\t');
Serial.println(z);
samplesRead++;
if (samplesRead == numSamples) break;
}
}
}
2. 在Edge Impulse Studio中创建项目
- 打开Edge Impulse Studio并创建新项目,命名为
gesture-classifier。 - 在Devices页面点击Connect a new device,选择Arduino Nano 33 BLE Sense,按提示使用CLI连接开发板。
- 连接成功后,进入Data acquisition页面,设置采样频率为62.5Hz,样本时长2000ms(约125个样本/条)。
- 采集三类数据,每类至少采集30条样本:
- idle:开发板静止放置
- horizontal:沿水平方向快速来回晃动
- vertical:沿垂直方向快速上下晃动
- 点击Add sample保存,重复采集直至每类满足数量要求。
3. 设计Impulse并训练模型
- 进入Create impulse页面,添加Spectral Analysis处理模块和Classification学习模块。
- 在Spectral features页面,设置:
- Filter:
Low-pass,截止频率25Hz - FFT length:
32 - 其余保持默认
- Filter:
- 点击Save parameters,然后进入Generate features页面生成特征。
- 进入Classifier页面,设置训练轮数
60,学习率0.0005,点击Start training。
4. 模型验证与部署
- 训练完成后,查看Model testing页面的准确率。若测试准确率≥90%,模型合格。
- 进入Deployment页面,选择Arduino library,点击Build下载生成的ZIP库。
- 在Arduino IDE中通过Sketch → Include Library → Add .ZIP Library导入下载的库。
5. 部署到开发板进行实时推理
烧录以下推理代码,实现实时手势分类:
#include <Arduino_LSM9DS1.h>
#include <gesture-classifier_inferencing.h>
const float accelerationThreshold = 2.0;
const int numSamples = EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE;
int samplesRead = numSamples;
void setup() {
Serial.begin(115200);
while (!Serial);
if (!IMU.begin()) {
Serial.println("Failed to initialize IMU!");
while (1);
}
Serial.println("Edge Impulse inference started");
}
void loop() {
float x, y, z;
while (samplesRead == numSamples) {
if (IMU.accelerationAvailable()) {
IMU.readAcceleration(x, y, z);
if (abs(x) + abs(y) + abs(z) > accelerationThreshold) {
samplesRead = 0;
break;
}
}
}
while (samplesRead < numSamples) {
if (IMU.accelerationAvailable()) {
IMU.readAcceleration(x, y, z);
signal_t signal;
signal.total_length = EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE;
signal.get_data = [](size_t offset, size_t length, float *out_ptr) {
return 0;
};
// 实际推理使用批量读取方式
float buffer[EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE * 3];
buffer[samplesRead * 3] = x;
buffer[samplesRead * 3 + 1] = y;
buffer[samplesRead * 3 + 2] = z;
samplesRead++;
if (samplesRead == numSamples) {
signal.get_data = [&](size_t offset, size_t length, float *out_ptr) {
for (size_t i = 0; i < length; i++) {
out_ptr[i] = buffer[offset + i];
}
return 0;
};
EI_CLASSIFIER_RESULT result;
EI_CLASSIFIER_RESULT_SIZE = EI_CLASSIFIER_LABEL_COUNT;
run_classifier(&signal, &result, false);
for (int i = 0; i < EI_CLASSIFIER_LABEL_COUNT; i++) {
Serial.print(result.classification[i].label);
Serial.print(": ");
Serial.print(result.classification[i].value * 100);
Serial.print("% ");
}
Serial.println();
samplesRead = numSamples;
}
}
}
}
验证方法与判定标准
- 数据采集验证:在Edge Impulse Studio的Data acquisition页面,点击Record new data,观察实时波形是否随手势变化产生明显幅值差异。
- 训练验证:在Model testing页面,测试集准确率应≥90%。若低于此值,增加每类样本量至50条以上并重新训练。
- 实时推理验证:烧录推理代码后,打开Arduino IDE串口监视器(115200波特率),依次执行三种手势各10次,观察串口输出的分类结果。判定标准:每种手势的正确识别率≥8/10,且静止时能稳定输出
idle类别。
常见问题
- 开发板无法连接Edge Impulse:确认已安装CLI并执行
edge-impulse-daemon,且开发板通过USB线直接连接电脑(非Hub)。 - 训练准确率低:检查采集数据时是否混入了其他动作,或样本间差异不明显。重新采集时确保三种手势动作幅度足够大且可区分。
- 推理结果不稳定:确认推理代码中
EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE与训练时样本长度一致(本案例为125),且触发阈值accelerationThreshold设置合理。