使用Arduino 33 BLE Sense和Edge Impulse构建的咳嗽检测系统

在本教程中,我们将使用 arduino 33 ble sense 和 edge impulse studio 构建咳嗽检测系统。它可以区分正常的背景噪音和实时音频中的咳嗽。我们使用 edge impulse studio 训练咳嗽和背景噪声样本数据集,并构建高度优化的 tinyml 模型,该模型可以实时检测咳嗽声音。
所需组件
硬件
arduino 33 ble 感知
引领
跳线
软件
边缘脉冲工作室
arduino ide
电路原理图
下面给出了使用 arduino 33 ble sense进行咳嗽检测的电路图。arduino 33 ble 的 fritzing 部件不可用,所以我使用了 arduino nano,因为它们具有相同的引脚。
led 的正极引线连接到 arduino 33 ble sense 的数字引脚 4,负极引线连接到 arduino 的 gnd 引脚。
为咳嗽检测机创建数据集
如前所述,我们正在使用 edge impulse studio 来训练我们的咳嗽检测模型。为此,我们必须收集一个数据集,其中包含我们希望能够在 arduino 上识别的数据样本。由于目标是检测咳嗽,因此您需要收集其中的一些样本和其他一些噪声样本,以便区分咳嗽和其他噪声。
我们将创建一个包含“咳嗽”和“噪音”两个类别的数据集。要创建数据集,请创建一个edge impulse帐户,验证您的帐户,然后开始一个新项目。您可以使用手机、arduino 板加载样本,也可以将数据集导入边缘脉冲帐户。将样本加载到您的帐户中的最简单方法是使用您的手机。为此,您必须将您的手机与 edge impulse 连接。
要连接您的手机,请单击“设备”,然后单击“连接新设备”。
现在在下一个窗口中,单击“使用您的手机”,将出现一个二维码。使用 google lens 或其他 qr 码扫描仪应用程序使用您的手机扫描 qr 码。
这会将您的手机与 edge impulse studio 连接起来。
将手机与 edge impulse studio 连接后,您现在可以加载样本。要加载样本,请单击“数据采集”。现在在数据采集页面上,输入标签名称,选择麦克风作为传感器,然后输入样本长度。单击“开始采样”,开始采样 40 秒样本。您可以使用不同长度的在线咳嗽样本,而不是强迫自己咳嗽。共记录 10 到 12 个不同长度的咳嗽样本。
上传咳嗽样本后,现在将标签设置为“噪声”并再收集 10 到 12 个噪声样本。
这些样本用于训练模块,在接下来的步骤中,我们将收集测试数据。测试数据至少应该是训练数据的 30%,所以收集 3 个样本的“噪音”和 4 到 5 个样本的“咳嗽”。
您可以使用 edge impulse cli uploader 将我们的数据集导入您的 edge impulse 帐户,而不是收集您的数据。
要安装 cli uploader,首先,在您的笔记本电脑上下载并安装node.js。之后打开命令提示符并输入以下命令:
npm install -g edge-impulse-cli
现在下载数据集(数据集链接)并将文件解压缩到您的项目文件夹中。打开命令提示符并导航到数据集位置并运行以下命令:
edge-impulse-uploader --clean
edge-impulse-uploader --category training training/*.json
edge-impulse-uploader --category training training/*.cbor
edge-impulse-uploader --category testing testing/*.json
edge-impulse-uploader --category testing testing/*.cbor
训练模型并调整代码
随着数据集准备就绪,现在我们将为数据创建一个脉冲。为此,请转到“创建冲动”页面。
现在在“创建冲动”页面上,单击“添加处理块”。在下一个窗口中,选择音频 (mfcc) 块。之后单击“添加学习块”并选择神经网络(keras)块。然后点击“保存冲动”。
在下一步中,转到 mfcc 页面,然后单击“生成功能”。它将为我们所有的音频窗口生成 mfcc 块。
之后进入“ nn classifier”页面,点击“ neural network settings”右上角的三个点,选择“ switch to keras (expert) mode”。
将原始代码替换为以下代码,并将“最低置信度评级”更改为“0.70”。然后单击“开始培训”按钮。它将开始训练您的模型。
将张量流导入为 tf
从 tensorflow.keras.models 导入顺序
从 tensorflow.keras.layers 导入 dense、inputlayer、dropout、flatten、reshape、batchnormalization、conv2d、maxpooling2d、averagepooling2d
从 tensorflow.keras.optimizers 导入 adam
从 tensorflow.keras.constraints 导入 maxnorm
# 模型架构
模型=顺序()
model.add(inputlayer(input_shape=(x_train.shape[1], ), name=‘x_input’))
model.add(reshape((int(x_train.shape[1] / 13), 13, 1), input_shape=(x_train.shape[1], )))
model.add(conv2d(10, kernel_size=5, activation=‘relu’, padding=‘same’, kernel_constraint=maxnorm(3)))
model.add(averagepooling2d(pool_size=2, padding=‘same’))
model.add(conv2d(5, kernel_size=5, activation=‘relu’, padding=‘same’, kernel_constraint=maxnorm(3)))
model.add(averagepooling2d(pool_size=2, padding=‘same’))
model.add(展平())
model.add(密集(类,activation=‘softmax’,name=‘y_pred’,kernel_constraint=maxnorm(3)))
# 这控制了学习率
选择 = 亚当(lr=0.005,beta_1=0.9,beta_2=0.999)
# 训练神经网络
model.compile(loss=‘categorical_crossentropy’,优化器=opt,metrics=[‘accuracy’])
model.fit(x_train,y_train,batch_size=32,epochs=9,validation_data=(x_test,y_test),详细=2)
训练模型后,将显示训练性能。对我来说,准确率是 96.5%,损失是 0.10,这很好。
现在我们的咳嗽检测模型已经准备就绪,我们将把这个模型部署为 arduino 库。在将模型下载为库之前,您可以通过转到“实时分类”页面来测试性能。
转到“部署”页面并选择“ arduino library”。现在向下滚动并单击“构建”以开始该过程。这将为您的项目构建一个 arduino 库。
现在在您的 arduino ide 中添加库。为此,打开 arduino ide,然后单击sketch 》 include library 》 add.zip library。
然后,通过转到 文件 》 示例 》 您的项目名称 - edge impulse 》 nano_ble33_sense_microphone 来加载示例。
我们将对代码进行一些更改,以便在 arduino 检测到咳嗽时发出警报声。为此,arduino 连接了一个蜂鸣器,当它检测到咳嗽时,led 会闪烁 3 次。
这些更改是在打印噪音和咳嗽值的void loop()函数中进行的。在原始代码中,它同时打印标签及其值。
对于 (size_t ix = 0; ix 《 ei_classifier_label_count; ix++) {
ei_printf(“%s: %.5f\n”, result.classification[ix].label, result.classification[ix].value);
}
我们将把噪声值和咳嗽值保存在不同的变量中,并比较噪声值。如果噪声值低于 0.50,则表示咳嗽值大于 0.50,它会发出声音。用这个替换原来的 for loop()代码:
对于(size_t ix = 1;ix 《 ei_classifier_label_count;ix++){
serial.print(result.classification[ix].value);
浮动数据=结果。分类[ix]。值;
如果(数据 《 0.50){
serial.print(“检测到咳嗽”);
警报();
}
}
进行更改后,将代码上传到您的 arduino。以 115200 波特率打开串行监视器。
所以这就是咳嗽检测机器的构建方式,它不是找到任何 covid19 嫌疑人的非常有效的方法,但它可以在一些拥挤的区域很好地工作。
#define eidsp_quantize_filterbank 0
#include
#include
#define led 5
/** 音频缓冲区、指针和选择器 */
类型定义结构{
int16_t *缓冲区;
uint8_t buf_ready;
uint32_t buf_count;
uint32_t n_samples;
} inference_t;
静态推理_t推理;
静态布尔记录就绪=假;
静态有符号短样本缓冲区[2048];
静态 bool debug_nn = false; // 将此设置为 true 以查看例如从原始信号生成的特征
无效设置()
{
// 把你的设置代码放在这里,运行一次:
序列号.开始(115200);
pinmode(led,输出);
serial.println(边缘脉冲推理演示);
// 推理设置摘要(来自 model_metadata.h)
ei_printf(推理设置:\n);
ei_printf(\tinterval: %.2f ms.\n, (float)ei_classifier_interval_ms);
ei_printf(\t帧大小: %d\n, ei_classifier_dsp_input_frame_size);
ei_printf(\t样本长度: %d ms.\n, ei_classifier_raw_sample_count / 16);
ei_printf(\tno. of classes: %d\n, sizeof(ei_classifier_inferencing_categories) / sizeof(ei_classifier_inferencing_categories[0]));
if (microphone_inference_start(ei_classifier_raw_sample_count) == false) {
ei_printf(err: 设置音频采样失败\r\n);
返回;
}
}
无效循环()
{
ei_printf(2秒后开始推理...\n);
延迟(2000);
ei_printf(正在录制...\n);
bool m = 麦克风推理记录();
如果(!米){
ei_printf(err: 录音失败...\n);
返回;
}
ei_printf(录制完成\n);
signal_t 信号;
signal.total_length = ei_classifier_raw_sample_count;
signal.get_data = µphone_audio_signal_get_data;
ei_impulse_result_t 结果 = { 0 };
ei_impulse_error r = run_classifier(&signal, &result, debug_nn);
如果(r!= ei_impulse_ok){
ei_printf(err: 分类器运行失败(%d)\n, r);
返回;
}
// 打印预测
ei_printf(预测 (dsp: %d ms., 分类: %d ms., 异常: %d ms.): \n,
result.timing.dsp,result.timing.classification,result.timing.anomaly);
对于(size_t ix = 1;ix < ei_classifier_label_count;ix++){
serial.print(result.classification[ix].value);
浮动数据=结果.分类[ix].值;
如果(数据 1; i++) {
inference.buffer[inference.buf_count++] = samplebuffer[i];
if(inference.buf_count >= inference.n_samples) {
inference.buf_count = 0;
inference.buf_ready = 1;
}
}
}
}
静态布尔mic_inference_start(uint32_t n_samples)
{
inference.buffer = (int16_t *)malloc(n_samples * sizeof(int16_t));
如果(推理。缓冲区 == null){
返回假;
}
inference.buf_count = 0;
inference.n_samples = n_samples;
inference.buf_ready = 0;
// 配置数据接收回调
pdm.onreceive(&pdm_data_ready_inference_callback);
// 可选设置增益,默认为 20
pdm.setgain(80);
//ei_printf(扇区大小: %d nblocks: %d\r\n, ei_nano_fs_get_block_size(), n_sample_blocks);
pdm.setbuffersize(4096);
// 使用以下命令初始化 pdm:
// - 一个通道(单声道模式)
// - 16 khz 采样率
if (!pdm.begin(1, ei_classifier_frequency)) {
ei_printf(启动 pdm 失败!);
}
记录就绪=真;
返回真;
}
静态布尔麦克风推理记录(无效)
{
inference.buf_ready = 0;
inference.buf_count = 0;
而(inference.buf_ready == 0){
延迟(10);
}
返回真;
}
静态 int 麦克风_音频_信号_get_data(size_t 偏移量,size_t 长度,浮点 *out_ptr)
{
arm_q15_to_float(&inference.buffer[offset], out_ptr, length);
返回0;
}
静态无效麦克风推理结束(无效)
{
pdm.end();
免费(推理。缓冲区);
}
#if !defined(ei_classifier_sensor) || ei_classifier_sensor != ei_classifier_sensor_microphone
#error “电流传感器的型号无效。”
#万一
无效警报(){
for (size_t t = 0; t < 4; t++) {
数字写入(领导,高);
延迟(1000);
数字写入(领导,低);
延迟(1000);
// digitalwrite(led, high);
// 延迟(1000);
// digitalwrite(led, low);
}
}

5G智慧医疗提高我国诊断与治疗水平
七进制计数器电路
在TD-SCDMA手机设计中利用MAX2392满足T3R4的
因疫情隔离多名工人,台积电预计近5000人受到影响
python语言之参数args与kwargs介绍
使用Arduino 33 BLE Sense和Edge Impulse构建的咳嗽检测系统
无线吸尘器哪个牌子好?德国大牌产品清洁效果更胜一凑
塑造政府资产管理的物联网技术有哪几种
区块链技术为什么和币有千丝万缕的关系
NextChip选择Rambus安全IP为Apache6汽车处理器保驾护航
世界最小VR座椅与今年八月上市
松下大容量导电性聚合物混合铝电解电容器8月开始量产
游戏不上分 你的鼠标急需这套按键优化方案
突发!SpaceX星舰飞船首次试飞被叫停
索尼发布用于车载摄像头的CMOS图像传感器IMX735
存储新世纪,中国的主控短板谁来补?
PCB上的DC-DC转换器封装的散热方式介绍
AD7147 ―新型电容器数码转换器,用于触控屏幕侦测功能
莫大康:准备迎接更艰难的时刻到来
iQOO7 确认搭载 4K 级动力泵液冷散热系统