本教程的内容可能不再有效,不再提供新的软件维护和技术支持。
使用 XIAO nRF52840 基于 Edge Impulse 的语音识别
在这个教程中,我将展示如何将 Edge Impulse 与 Seeed Studio XIAO nRF52840 的机器学习功能结合使用来实现语音识别。我们将使用 XIAO nRF52840 Sense 上已有的麦克风。
项目前置知识
XIAO nRF52840 并未得到 Edge Impulse 的官方支持,也不作为数据收集设备出现,但我将演示如何使用它通过设备麦克风运行推理。
开始使用
要跟随本教程,您需要以下硬件
Seeed Studio XIAO nRF52840-Sense |
---|
![]() |
硬件准备
我们不需要任何硬件准备。XIAO nRF52840 已经具备了这个项目所需的一切。我们只需要 PDM 麦克风。
以下是 XIAO nRF52840 Sense 的硬件引脚图
软件准备
要尝试这个项目,我们只需要三样东西:
- Google 语音命令数据集(见下文)
- Edge Impulse 账户
- Arduino IDE
数据集
- 我将使用 Google 语音命令数据集。不是完整的数据集,只是其中的一些词汇。
- 现在,下载数据集并解压。完整数据集大小为 2.3GB。
- 这个 Google 语音命令数据集 被 Google 用于他们的 TensorFlow Lite for MicroControllers 微语音示例中。
- 您可以在这里找到代码。
我们可以从上面的第一个链接下载数据集,解压后如下所示:
开始使用
现在让我们开始使用 Edge Impulse 基于数据集创建一个机器学习模型。
步骤 1 - 打开 Edge Impulse
- Edge Impulse 是一个机器学习(ML)开发平台,使开发者能够创建自定义机器学习模型并将其部署到边缘设备上,如微控制器和智能手机。
- 它提供了各种工具和资源来帮助构建和优化针对特定任务的机器学习模型,如关键词识别、异常检测和分类。
让我们创建一个新项目。给它起个名字。
创建新项目后,转到数据采集页面。
步骤 2 - 添加数据
因为我们将使用 Google 语音命令数据集,选择"添加现有数据"。 接下来,选择"上传数据"
接下来,我们需要选择数据 - 让我们从语音数据集中选择一个文件夹。
数据集有很多单词可以用来训练。让我们选择 3 个文件夹(我们的标签)进行训练,以及背景噪声。我们将得到 4 个标签。 按下"浏览"按钮。 第一个是"go"。选择文件夹 - 你可以看到所有的 .wav 文件 - 然后按"上传"。
接下来,让我们保持类别的默认选项。让 Edge Impulse 分割数据。 对于标签,自己写标签。完成所有这些后,按"上传数据"。
在右侧,你会看到文件正在上传。这可能需要一段时间,因为文件很多。
过一段时间后,上传完成并显示已上传文件的简要摘要。
之后,这是屏幕显示
要上传更多数据,按右侧文件列表上方的小上传按钮。 重复这个过程 3 次 - 再添加 2 个标签和背景噪声。 我将选择 happy、bird 和标签为"noise"的"background noise"文件夹。 最后,这些是我们拥有的所有标签
接下来,让我们创建网络来学习我们的单词。点击 Impulse design 来创建 impulse
步骤 3 - 选择训练方法
因为每个片段都是 1 秒长,16Khz,让我们保持相同的窗口大小和频率。现在,让我们添加一个处理块。
Edge Impulse 在这里也帮了我们很多。点击"添加处理块"并选择 Audio (MFCC)。
接下来,点击"添加学习块"并选择 Classification。
现在,我们的最后一列 - 输出特征 - 有我们的 4 个标签(bird、go、happy、noise)。 按"保存 Impulse"来保存我们目前的工作。
步骤 4 - 生成特征
现在,让我们看看 MFCC 参数。如果你想要,可以更改这些值。 现在,让我们保持默认值。点击"保存参数"。 保存参数后,我们会得到一个新窗口来"生成特征"。
点击后,Edge Impulse 将开始生成特征。
过一段时间后,我们生成了特征并可以将其可视化
现在我们可以使用选择的参数来训练我们的网络。点击"Classifier"。
步骤 5 - 分类器
在这里我们可以调整网络设置,比如训练周期、是否需要数据增强等等。 Edge Impulse 为关键词识别提供了一个简单但有效的神经网络架构。该架构包含以下层:
- 输入层: 输入层将 MFCC 特征作为输入。
- 隐藏层: 隐藏层学习从 MFCC 特征中提取更高级别的特征。Edge Impulse 支持多种隐藏层类型,如卷积层和循环层。
- 输出层: 输出层预测音频输入包含关键词的概率。
我们可以更改默认参数,但默认设置就足够了。点击"Start Training"。
开始训练后,在屏幕右侧我们可以观看训练进度。
我们可以将目标设备更改为 nRF52840 - 就像我们的 XIAO nRF52840 Sense - 这样我们就可以看到性能计算和优化。
训练完成后,我们得到混淆矩阵和数据浏览器
现在网络已经准备好了,让我们尝试一些样本并进行实时分类。 如果你进入实时分类,我们可以选择一个样本并查看分类结果。这里,对于一个鸟类示例,我们在结果中得到了鸟类。太棒了。模型正在工作。
现在,让我们进入模型测试。 让我们使用分割的样本来测试模型。点击"Classify all"。
我们得到了将近 90% 的准确率。
步骤 6 - 部署并获取 Arduino 库
现在,让我们进入部署来获取微控制器的文件。
部署选项
让我们选择 Arduino
接下来,让我们保持选择 Quantized(int8) 并点击"Build"来下载用于 Arduino IDE 的文件 我们可以稍微调整一下优化设置。如果你发现准确率很低,尝试关闭 EON 编译器并重试。
过一段时间后,文件将自动下载。
步骤 7 - 将库添加到 Arduino IDE
在 Arduino IDE 中,让我们添加新下载的文件。 转到 Sketch > Include Library > Add .ZIP Library
选择下载的文件。过一段时间后,输出窗口中会出现一条消息,说明库已安装。
步骤 8 - 在 XIAO nRF52840 Sense 上语音控制 RGB 灯
让我们打开一个示例 转到 Examples > <your_files_names> > nano_ble33_sense > nano_ble33_sense_microphone
为什么是 Arduino BLE 33 Sense?它们使用相同的库 - PDM(脉冲密度调制)- 来控制麦克风。Arduino Nano BLE 33 Sense 有一个 MP34DT05,而 XIAO nRF52840 Sense 有 MSM261D3526H1CPM。 打开草图后,让我们编译它并看看是否没有任何错误。
过一段时间后,草图编译完成,没有报告错误。
现在,连接 XIAO nRF52840 Sense(如果您还没有连接的话)并将代码上传到开发板。
现在,打开串口监视器(Ctrl+Shift+M)并检查推理结果(开发板已经开始录音、进行推理和预测)
尝试说出选择的单词之一。我说了"go"
如果它正确检测到单词,最可能的单词将有一个接近1.0的结果,而其他单词的值接近0.0 现在,让我们来点乐趣,稍微修改一下代码。 XIAO nRF52840 Sense有一个内置LED,有3种颜色:
- 红色 - LED_BUILTIN 或 LED_RED
- 绿色 - LED_GREEN
- 蓝色 - LED_BLUE
由于我们有3个单词,让我们为每个单词分配一种颜色,并为相应的单词点亮相应的颜色。
- 红色代表bird
- 绿色代表Go
- 蓝色代表happy
为了更简单,我检查了开发板的引脚定义,以下引脚分配给LED颜色:
- RED - 引脚11
- GREEN - 引脚13
- BLUE - 引脚12
首先,我们需要定义一个阈值。我们知道预测值从0.0到1.0。越接近1.0,我们对单词分类的确定性就越高。这个值可以稍后调整。我将其设置为0.7。
首先,定义一些变量。我在包含的库之后定义了这些:
/* threshold for predictions */
float threshold = 0.7;
/**
LABELS INDEX:
0 - bird
1 - go
2 - happy
3 - noise
*/
// LED pin (defines color) to light up
/**
PIN 11 - RED
PIN 12 - BLUE
PIN 13 - GREEN
*/
int LED = 0;
int oldLED;
int oldLED 将定义之前点亮的LED,这样当没有预测或预测改变时,我们可以将其关闭。
int LED 是我们将要点亮的当前LED。
接下来,在loop()函数中,在for循环指令内部,我们循环遍历CLASSIFIER_LABEL_COUNT(大约在第129行 - 已经包含上面的行):
for (size_t ix = 0; ix < EI_CLASSIFIER_LABEL_COUNT; ix++) {
我们使用if指令来检查分类值。如果它高于定义的阈值,我们使用switch指令检查记录了哪个单词。
完整的for循环,包含我们的添加内容,是:
for (size_t ix = 0; ix < EI_CLASSIFIER_LABEL_COUNT; ix++) {
ei_printf(" %s: %.5f\n", result.classification[ix].label, result.classification[ix].value);
//lets light up some LEDS
if (result.classification[ix].value > threshold) {
//now let's see what label were in
switch (ix) {
case 0: LED = 11; break;
case 1: LED = 13; break;
case 2: LED = 12; break;
default: LED = 0;
}
//in Sense, LOW will light up the LED
if (LED != 0) {
digitalWrite (oldLED, HIGH); //if we enter a word right next to previous - we turn off the previous LED
digitalWrite (LED, LOW);
oldLED = LED;
}
else //turn off LED
digitalWrite (oldLED, HIGH);
}
}
修改后,只需将代码上传到您的微控制器,尝试说出训练的单词,看看LED根据单词点亮。
就是这样。虽然没有直接支持,但我们现在可以使用XIAO nRF52840 Sense通过Edge Impulse运行一些ML模型
✨ 贡献者项目
技术支持与产品讨论
感谢您选择我们的产品!我们在这里为您提供不同的支持,以确保您使用我们产品的体验尽可能顺畅。我们提供多种沟通渠道,以满足不同的偏好和需求。