2024年寒假练 - 基于Seeed XIAO-esp32s3实现宠物声音检测与实时提醒
该项目使用了Edge Impulse、arduino、C语言,实现了KWS关键词模型的设计,它的主要功能为:识别宠物狗的不同声音。 该项目使用了Homeassistant,实现了设备互联的设计,它的主要功能为:各种设备集中控制中心,实现智能家居联动效果。 该项目使用了MQTT、C语言,实现了设备互联互通的设计,它的主要功能为:Seeed XIAO-esp32s3与Homeassistant的交流。
标签
嵌入式系统
接口
Sakura
更新2024-03-28
湖南科技大学
619

一、任务要求

使用声音识别AI技术来识别和记录宠物的声音,比如叫声或吠声。当宠物发出压力信号时,系统会通过Home Assistant自动播放宠物平静的音乐,以缓解宠物焦虑。

二、功能实现

1.Seeed XIAO-esp32s3识别三种声音:狗吠声、狗撒娇声、环境音。

2.Homeassistant对Seeed XIAO-esp32s3识别的不同声音作出不同动作:识别狗撒娇声则通过智能音响提醒主人并播放音乐缓解宠物狗情绪;识别狗吠声则通过智能音响提醒主人,起到一定的报警作用。

三、实现流程

1.模型训练

采集狗吠声、环境音、狗撒娇声三种声音时长总计10mins+(越长越好),作为样本输入 edge impulse 中,自动或手动分割出一秒的声音素材,将所有类型分成80%训练集和20%测试集, 通过脉冲获取原始数据,使用信号处理来提取特征,然后使用学习块对新数据进行分类。通过 edge impulse 机器学习训练,经测试,生成模型的准确率为91.41%.

2.模型部署

将训练好的模型下载,在arduino导入下好的模型,根据下载好的模型.zip名称改动例程内.h文件名,点击编译运行,打开串口监视器,右下角对话框改为“NL 和 CR”以及115200波特率(默认),随后等待编译下载完成。若成功则串口通信监视器如下图: 

3.Homeassistant安装

此步骤根据B站教程视频:BV1KS4y1F7HM,流程可能需要科学上网和github账号。感谢UP主:我叫小纪

  • 安装Oracl VM VirtualBox,创建liunx虚拟机。(安装包来自up主视频简介分享)

  • 解压压缩包(得到.vdi文件),此文件为Homeassistant的安装文件,可能版本需要更新,若安装失败需要下载新版本的,下载地址:https://www.home-assistant.io/installation/linux

  • 创建虚拟机,点击新建

  • 最后点击启动即可等待虚拟机中的Homeassistant启动,第一次可能比较久,请耐心等待。
  • 接着在浏览器中输入:homeassistant:8123,然后回车进入,随后可能是漫长的等待,我弄的时候等了一晚上。

  • 接着就是自己注册一个用户名和密码(牢记),然后在左下角点击自己头像,开启高级模式,安装完成。

4.小米智能家居接入homeassistant

此处比较复杂,篇幅所限建议继续观看视频学习:BV1KS4y1F7HM

5.MQTT安装

  • 点击配置——点加载项——点加载项商店——搜索“MQTT”——点击“Mosquitto broker”——安装“Mosquitto broker

  • 按图设置MQTT服务器名和密码

  • 点击配置——设备与服务——添加集成——搜索“MQTT”——点击“MQTT”——输入刚刚设置的服务器名和密码
  • 然后就可以设置MQTT的主题了,下图是MQTT设置、测试界面,可以设置主题和从监听主题框内测试接收主题内容

6.自动化设置

点击配置——自动化与场景——创建自动化,接下就很简单了

四、代码解析

1.KWS关键词识别代码

bool m = microphone_inference_record(); // 录制音频
if (!m) {
ei_printf("ERR: Failed to record audio...\n"); // 打印错误信息
return;
}
  • microphone_inference_record(),这是在void loop()函数中的一段代码,定义于文末,会不断循环调用——录制音频。
static bool microphone_inference_record(void)
{
bool ret = true;

while (inference.buf_ready == 0) {
delay(10);
}

inference.buf_ready = 0;
return ret;
}
  • 该函数是一个静态函数,用于等待新的数据。当inference.buf_ready为0时,函数会进入一个循环,每次循环延迟10毫秒。当inference.buf_ready不为0时,函数会将inference.buf_ready设置为0,并返回True。inference.buf_ready就是一个能否进行录音采样的标志位。

/***************************************************************************************************************************************************************************/

   signal_t signal;
signal.total_length = EI_CLASSIFIER_RAW_SAMPLE_COUNT;//信号数据的总长度
signal.get_data = &microphone_audio_signal_get_data;//获取音频信号数据
ei_impulse_result_t result = { 0 };
  • 创建了一个 signal_t 结构体变量 signal
  • 设置 signal 结构体中的 total_length 字段为 EI_CLASSIFIER_RAW_SAMPLE_COUNT,表示信号数据的总长度。
  • get_data 字段设置为指向函数 microphone_audio_signal_get_data 的指针,该函数负责获取音频信号数据。
  • 此代码段在loop()中,上一段录音函数之后,循环进行着对录音样本进行分类器的运行。
    //使用 signal 结构、result 变量和可能的 debug_nn 参数调用了 run_classifier 函数。判断提供的信号数据上运行分类器是否有错误。
EI_IMPULSE_ERROR r = run_classifier(&signal, &result, debug_nn); // 运行分类器

if (r != EI_IMPULSE_OK) {
ei_printf("ERR: Failed to run classifier (%d)\n", r); // 打印错误信息
return;
}
  • 这段代码片段的目的是在录制音频后,使用分类器对获取的音频信号数据进行推理,然后检查推理是否成功。
    int pred_index = 0;     // 初始化预测索引
float pred_value = 0; // 初始化预测值

// 打印预测结果
ei_printf("Predictions ");
ei_printf("(DSP: %d ms., Classification: %d ms., Anomaly: %d ms.)",
result.timing.dsp, result.timing.classification, result.timing.anomaly);
ei_printf(": \n");

// 遍历分类结果
for (size_t ix = 0; ix < EI_CLASSIFIER_LABEL_COUNT; ix++) {
ei_printf(" %s: ", result.classification[ix].label); // 打印类别标签
ei_printf_float(result.classification[ix].value); // 打印预测值
ei_printf("\n");

// 更新最大预测值和对应的索引
if (result.classification[ix].value > pred_value){
pred_index = ix;
pred_value = result.classification[ix].value;
}
}
  • 紧跟上一段代码,这段代码就是对分类器预测结果的处理和打印。
static int microphone_audio_signal_get_data(size_t offset, size_t length, float *out_ptr)
{
numpy::int16_to_float(&inference.buffer[offset], out_ptr, length);

return 0;
}
  • 该函数用于获取原始音频信号数据。
  • 通过调用 numpy::int16_to_float 函数将从音频缓冲区中提取的 16 位整数转换为浮点数,并将结果存储在提供的输出指针 out_ptr 中。

KWS关键词识别的代码是官方例程中提供的,我基本没做什么改动,主要是理解每段代码的作用并为其注释。


2.MQTT消息发送代码

#include <WiFi.h>
#include <PubSubClient.h>
// WiFi连接信息 改为自己的 热点也可以 用2.5G
const char* ssid = "XXX";
const char* password = "*******";
// MQTT服务器信息
const char* mqttServer = "192.168.230.250";
const int mqttPort = 1883;
const char* mqttUsername = "admin";
const char* mqttPassword = "hlj20020511";
// 创建WiFi客户端和MQTT客户端实例
WiFiClient wifiClient;
PubSubClient mqttClient(wifiClient);
  • 这是MQTT在arduino内代码的基础设置,主要引用了WiFi、PubSubClient库,分别为连接WiFi和MQT服务器做准备。接着就是设定连接所需的信息。然后创建创建WiFi客户端和MQTT客户端实例。
// 设置MQTT连接函数
void setupMQTT() {
mqttClient.setServer(mqttServer, mqttPort);
}

// 重新连接MQTT服务器函数
void reconnectMQTT() {
while (!mqttClient.connected()) {
Serial.println("正在连接到MQTT...");
if (mqttClient.connect("ESP32Client", mqttUsername, mqttPassword)) {
Serial.println("连接到MQTT");
} else {
Serial.print("MQTT连接失败,rc=");
Serial.print(mqttClient.state());
Serial.println(" 5秒钟后重试...");
delay(5000);
}
}
}
  • MQTT连接函数,注释已写好,简单易懂
    if ((pred_index == 2) && (pred_value > 0.8)){
mqttClient.publish("dog bark", "环境音~");
}
else if ((pred_index == 1) && (pred_value > 0.8)){
mqttClient.publish("dog bark", "狗狗在大叫呢!!!");
}else if ((pred_index == 0) && (pred_value > 0.8)){
mqttClient.publish("dog bark", "狗狗在撒娇呢~");
}
  • pred_index 变量代表KWS识别的三个类型(0——撒娇声,1——狗吠声,2——环境音),上述代码是通过模型判别结果,用 if 语句选择相应消息(“主题”,“消息”)调用库函数mqttclient.publish发送给MQTT服务器(Homeassistant)。

五、主要问题及未来计划

1.环境配置

主要是homeassistant、esphome、hacs、xiaomi miot auto等都是第一次接触,教程不是很齐全流畅,各种安装方法很杂分布很广,网络问题,耗费了大量精力去寻找实验适合自己当前环境的方法,其实回头看并不困难,只是信息检索和适配以及网络问题需要我们很有耐心。

  • 未来计划:其实这些哭都只用吃过一遍的,但是受益还是很大的,所谓吃一堑长一智,这样能长久地获得一个智能家居控制中心,我还是很满意滴。

2.语音识别精准度、类型广度

音频样本还是比较好标注的,比图片好标注多了,edge impulse 里都支持自动标注,真的不错。但是这次我完成后发现其实识别率在现实中并不灵敏,狗叫声也不是全都一样的“汪汪”叫,也会有音色之差,会有明显错误的地方,比如说狗吠声识别成环境音、撒娇声识别成狗吠声、狗吠声持续好几秒后才有反应等等。

  • 未来计划:未来应该会增加训练样本的数量,然后可以加入更多的声音类型:根据犬种来采集叫声(同种犬种音色感觉会差不多)、猫咪声音也可以加入、最好是通过片上Mic来采集,那应该是最好的,但是很困难,我们无法控制宠物发声。

3.功耗、便捷性

在我使用的电脑上使用liunx虚拟机装homeassistant是暂时的,因为需要它一直处于开机状态,这样使用homeassistant功耗、占用资源是比较大的。

  • 未来计划:想长久使用homeassistant,查资料的时候有很多安装方式都值得尝试,安装在云服务器(腾讯、阿里云等)上、树莓派上、NAS上等等都不错。


六、资料地址

  1. 项目在Hackster平台
  2. KWS关键词识别教程(利用egde脉冲)
  3. wiki文档内的KWS关键词识别教程
  4. homeassistant安装教程(bilibili视频)
  5. 项目介绍+效果展示
  6. 纯效果展示


  • 总的来说还是学习到了很多之前想学习的物联网知识,尝试了很多未曾涉及的新领域,自己很开心这一次的项目经历,感谢丝递科技和硬禾科技给予的机会,让我们学生无需顾虑也能体验到这么棒的产品o( ̄▽ ̄)d






附件下载
esp32_microphone.zip
arduino 代码文件
llly-project-1_inferencing.zip
edge impulse 训练好的模型(可直接部署)
团队介绍
只有我
评论
0 / 100
查看更多
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号