• 基于Syntiant TinyML Board与Edge Impulse的LED语音控制(Arduino/C++)


    项目介绍

    本项目基于Syntiant TinyML Board,通过Edge Impulse平台,在web端收集数据、训练、部署神经网络模型固件至NDP101内,实现了三种中文指令控制LED灯,闪烁、开灯、关灯(这个效果不明显)。

    硬件介绍

    Syntiant的TinyML Board,配备超低功耗Syntiant NDP101神经决策处理器,可以通过Edge Impulse平台,在Web端收集数据、训练、部署神经网络模型,通过USB连接通过Edge Impulse轻松下载经过训练的模型,而无需任何专用硬件。

    👉 更多介绍:

    1. Syntiant TinyML
    2. Funpack第二季第一期
      硬件结构图
      Syntiant TinyML Board实物图

    主要特点

    • 神经决策处理器使用NDP101,连接了两个传感器:
      • BMI160 6轴运动传感器
      • SPH0641LM4H麦克风
    • 主机处理器:SAMD21 Cortex-M0+ 32位低功耗48MHz ARM MCU
      • 内置256KB FLASH和32KB SRAM
      • 5个数字I/O,与Arduino MKR系列板兼容
      • 其中包含1路UART接口和1路I2C接口(包括在数字I/O引脚中)
      • 2MB板载串行闪存
      • 一个用户定义的RGB LED
      • uSD卡插槽
    • 电路板可使用5V micro-USB或3.7V LiPo电池供电

    神经网络模型

    👉 Syntiant Tiny ML Board

    由于该开发板完全支持Edge Impulse,因此可根据官网引导:

    数据采集

    该部分完全在Web端通过电脑的麦克风录制中文音频,”闪烁“、“开灯”、“关灯”,三者各120+30段左右(训练集:测试集=4:1),每段1秒钟长度。录制时可先连续录制10s,后手动裁剪。

    ⚠️ 检查录音是否完整、清晰

    前面说可以克隆它提供的Go & Stop示例工程,其中有一类别是“z_openset”,语音大多是一些"Hello world"之类的语句,可以将他们也纳入你的训练集。但实际部署 测试效果很差:这一类别目的是作为“其他”类,即当没有下达指令或受噪声干扰时分为此类,但实际测试中也很难判断到此类别,失去意义。

    以下是训练集、测试集样本数量和比例,“z_openset”一类给disable了,后续没有用到。

    Training Set
    Test Set

    网络训练

    Impulse Design这一步骤请严格参照上述给出的官方指导即可:Syntiant Tiny ML Board

    ⚠️ 我感觉网络训练的学习率、cycles、dropout等一些超参数可能需要结合实际训练效果微调,loss小一点更好,不要过分看重验证集正确率。

    训练后的模型验证集正确率能90%+,loss<0.2就算凑合。可以发现“开灯”和“关灯”容易误判。

    训练后

    模型部署

    这一步,首先选择"Create libray"下的"Syntiant NDP101 library",然后选择下方“Find posterior parameters”(寻找先验参数)。

    ⚠️ 注意不要选到“Build firmware”上,它生成的是Go & Stop示例工程的固件,除非你是按照示例工程演示
    Deployment
    后续勾选你实际要判断的类别与No calibration。测试了有10分钟English radio的校准,感觉也没啥效果。
    FInd posterior parameters
    找到先验参数后,build完会下载一个压缩包,解压后如图所示:

    build package

    • model_parameters内是网络的一些信息,替换其示例工程下./src/model_parameters
    • 后面两个就是网络模型的固件,通过Audio firmware中的flash_linux.sh(Win端类似)可同时下载Arduino程序与NN固件;
    • 因此一个工程需要由两部分组成:NN固件以及业务逻辑程序(Arduino),在其中实现LED的控制。

    业务逻辑程序

    直接修改示例工程的firmware.ino部分代码,主要是函数on_classification_changed

    typedef enum {
        _BLINK,
        _TURN_ON,
        _TURN_OFF,
        //_Z_OPENSET = 0U
    } Led_Status;
    
    Led_Status last_state = _TURN_OFF;	// 这个变量最后没用上
    
    void on_classification_changed(const char *event, float confidence, float anomaly_score) {
        // here you can write application code, e.g. to toggle LEDs based on keywords
        if (strcmp(event, "blink") == 0) {
            blink_cb();
        }
    
        else if (strcmp(event, "turn_off") == 0) {
            turn_off_cb();
        }
    
        else if (strcmp(event, "turn_on") == 0) {
            turn_on_cb();
        }
    }
    
    // 这个函数没有用到,期望是在判断到非三种模式时保持之前的业务逻辑操作
    void on_classification_unmatched() {
        if (last_state == _BLINK)
            blink_cb();
        else if (last_state == _TURN_ON)
            turn_on_cb();
        else if (last_state == _TURN_OFF)
            turn_off_cb();
    }
    
    void turn_on_cb() {
        last_state = _TURN_ON;
        digitalWrite(LED_GREEN, HIGH);
    }
    
    void turn_off_cb() {
        last_state = _TURN_OFF;
        digitalWrite(LED_GREEN, LOW);
    }
    
    void blink_cb() {
        last_state = _BLINK;
        digitalWrite(LED_BLUE, HIGH);
        delay(200);
        digitalWrite(LED_BLUE, LOW);
        delay(200);
        digitalWrite(LED_BLUE, HIGH);
        delay(200);
        digitalWrite(LED_BLUE, LOW);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54

    比较简单,但效果也不太明显:此次判断为“开灯”,接着绿灯亮起,但过一会绿灯也会灭,恢复初始态。因此“关灯”的展示效果不行(需要开灯完迅速关灯)。

    由于我的PC是linux,因此直接使用arduino_build.sh -- build编译Arduino工程,并将firmware.ino.bin(如果改了工程名称最后改回这个即可)与上述网络模型的固件一起,通过flash_linux.sh下载至开发板。

    ⚠️ 若下载出错,请查阅官网示例教程,内有提示

    Arduino工程build
    Flash
    上述通过flash_linux.sh同时将两部分的固件下载至开发板。

    功能展示

    简单拍了一些效果图,还是看视频效果更直观,正确率有些感人,预测的结果从串口打印。每次说话时得凑近开发板麦克风说话。

    👉 项目演示视频参见B站:基于Syntiant TinyML Board与Edge Impulse的LED语音控制

    1. 开灯:绿灯亮

    Turn on
    2. 关灯:绿灯灭,要在开灯后迅速关灯

    Turn off
    3. 闪烁:蓝灯闪烁一会最后灭,图片看不出动效,但看串口为blink没问题

    Blink

    总结

    此次项目使用Syntiant TinyML Board,在Edge Impulse平台上实现了三种中文词汇的检测,“开灯”、“关灯”以及“闪烁”,效果较好,正确率实际能有个八成吧,前提是你离麦克风够近。

    Syntiant TinyML Board确实小巧精悍,有麦克风与IMU,背后还有SD卡槽,虽然预留的IO口不多,但是主打功耗的NN推理的不要奢求太多,能做到这么小也是本事。它的判断速度很快,但是说话时最好凑近开发板,录制训练集时用它的麦克风很难顶,会出现录制不全、声音小等各种现象。

    Edge Impulse这种在网页端完成整个NN流程的模式,对于这种嵌入式轻度应用的开发很友善、方便,但我感觉能训练的模型只有简单几层FC这是否……但是能克隆别人的项目顺带把数据集也克隆了,后续也能搞个数据集共享就更好。

    👉 【Funpack第二季第一期】
    👉 CSDN:工程源代码下载(包括固件)
    👉 Syntiant工程
    👉 Github工程

  • 相关阅读:
    nacos-高可用seata之TC搭建(02)
    【网络篇】第八篇——多进程版的TCP网络程序
    Mybatis从零开始创建
    05目标检测-区域推荐(Anchor机制详解)
    Open3D 点云分割之区域生长
    js 设计模式(灵活的语言 JavaScript)
    《 Python List 列表全实例详解系列(七)》__索引和切片
    css主题切换
    pandas学习(五)merge
    Axure RP仿QQ音乐app高保真原型图交互模板源文件
  • 原文地址:https://blog.csdn.net/weixin_46422143/article/details/125528750