Funpack第二季第一期 使用Syntiant TinyML语音控制RGB灯
基于Syntiant TinyML进行简单的机器学习项目,控制内建RGB灯
标签
嵌入式系统
MPU
测试
显示
老孙头
更新2022-07-04
548

一、个人简介

    大家好,我是老孙头,是arduino届的一只草履虫。本视频的内容是使用Syntiant TinyMl开发板,完成一个简单的声控彩灯项目。这个项目只使用一块Syntiant TinyMl开发板来完成根据不同语音命令点亮板载不同颜色LED灯的功能。虽然说是声控灯听起来很low,可实际他可是基于机器学习并利用并未联网的板卡来完成。

   

二、项目描述

    本项目的硬件是一块Syntiant TinyMl开发板,这是一块只有邮票大小的小型开发板,上面包含了。神经决策处理器NDP101芯片。两个传感器:BMI160 6轴运动传感器和SPH0641LM4H麦克风。主机处理器为:SAMD21 Cortex-M0+ 32位低功耗48MHz ARM MCU,内置256KB FLASH和32KB SRAM。板载5个数字I/O,与Arduino MKR系列板兼容,其中包含1路UART接口和1路I2C接口。2MB板载串行闪存,一个用户定义的RGB LED。uSD卡插槽。还有小型锂电接口。

FkEY3BXArSpMfoed0yHky_mU4Lxt

   关于项目的设计思路,草履虫大家懂的,主要是借鉴官方例程、电子森林的视频教程和B站上几位大神的视频教程。使用板载麦克风接收数据,通过板载NDP101芯片进行机器学习处理和识别,通过samd主控和自定义RGB led显示出来对应不同语音命令下的不同LED灯状态。简要步骤如下:

   第一步是在edge-impulse   网站上找到整个开发的指南,网址为 Syntiant Tiny ML Board - Edge Impulse Documentation  先要把开发指南学明白,一定要一步步按照指南来做。注意是一步步严格按照指南走,别联想,别多做,别少做。否则就会出错,而且像我这种出错了还往往找不到原因。很凄惨。

FuXxuyt6gVeCh1HKZssbkP79Kfon

     

    第二步是完成语音模型的训练。根据指南,在edge-impulse网站的一个开发界面,网址如下,https://studio.edgeimpulse.com/studio/select-project录入我们要使用的语音命令。每一个命令要用不同的语调,最好是可以用不同的人,录入100次以上。本次我使用的语音命令是“红灯停、绿灯行、黄灯看”。然后经过各种处理,上面会进行很多运算,并生成模型文件。再最后把相关文件下载备用。一个是lib文件,一个是固件文件。两个要分别下载下来。这时候我们的模型文件就弄完了。我的这个训练是开源的,大家可以点击并参照官方项目内容修改弄成自己的。我的训练项目(可以复制)

  第三步是构建我们自己的控制程序,简单的说,就是通过训练模型,板卡已经可以识别3种不同的语音命令,那么识别语音命令以后如何完成内建LED灯的不同颜色或闪烁变化。就需要控制程序完成。首先要去根据第一步的指南,找到github网站上的官方例程,并且下载下来。这时候,初始的程序就有了。然后根据里面的.md文件。构建系统环境。先是在arduino IDE中,安装开发板的支持文件,和各种库文件。需要注意的是,库文件的版本号,一定要和他们官方的版本号相同才可以,版本高了会编译失败。本人水平太菜,只看到报错,不知道为啥。但是用了推荐的库的版本号就能编译的过去了。在arduino IDE里操作以后。就运行例程里的一个bat文件。这个bat文件是自动下载缺失的库的。最后再把USBCore.cpp拷贝进去src文件夹。把从edge-impulse下载的模型生成的那个库文件。里面有个叫“dsp_blocks.h” 和“model_metadata.h” 拷贝到咱们下载的这个例程文件的\src\model-parameters文件夹替换掉原有文件。把“model_variables.h”里面go和stop啥啥那几个关键字,换成我们训练模型时使用的关键字。 编程环境就算搭建完毕了。

    第四步,下面环节就是编程了。需要打开firmware-syntiant-tinyml.ino这个文件。然后进行编程。编程这件事,对于我,草履虫来说非常简单。就是抄,然后稍微改改,比如亮红灯给改成亮绿灯,改关键字等等诸如此类。这一步的话只要修改里面“void on_classification_changed(const char *event, float confidence, float anomaly_score)“这个函数就行了。

 

三、代码及说明

   以下是全部代码,可以先整体看个大概

#include "src/syntiant.h"
#include <NDP.h>
#include <NDP_utils.h>
#include <Arduino.h>


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

    static int8_t count =0;
    
    if (strcmp(event, "hong") == 0) 
        // Toggle LED
      {
        if(count != 1){
          digitalWrite(LED_RED, LOW);
          digitalWrite(LED_GREEN, LOW);
          digitalWrite(LED_BLUE, LOW);
         }
        digitalWrite(LED_BLUE, HIGH);
        count = 1;
        Serial.println("hong, hongDengTing,BLUE led ");
        delay (6000);
       }


        if (strcmp(event, "lv") == 0) 
        // Toggle LED
      {
        if(count != 2){
          digitalWrite(LED_RED, LOW);
          digitalWrite(LED_GREEN, LOW);
          digitalWrite(LED_BLUE, LOW);
         }
        digitalWrite(LED_GREEN, HIGH);
        count = 2;
        Serial.println("lv, lvDengXing,GREEN led ");
        delay (6000);
       }

         if (strcmp(event, "huang") == 0) 
        // Toggle LED
      {
        if(count != 3){
          digitalWrite(LED_RED, LOW);
          digitalWrite(LED_GREEN, LOW);
          digitalWrite(LED_BLUE, LOW);
         }
           digitalWrite(LED_BLUE, HIGH);
            delay (1000);
             digitalWrite(LED_BLUE, LOW);
          digitalWrite(LED_GREEN, HIGH);
           delay (1000);
           digitalWrite(LED_GREEN, LOW);
          digitalWrite(LED_BLUE, HIGH);
          
            delay (1000);
             digitalWrite(LED_BLUE, LOW);
          digitalWrite(LED_GREEN, HIGH);
           delay (1000);
           digitalWrite(LED_GREEN, LOW);
            digitalWrite(LED_BLUE, HIGH);
            
            delay (1000);
             digitalWrite(LED_BLUE, LOW);
          digitalWrite(LED_GREEN, HIGH);
           delay (1000);
        
        count = 3;
        Serial.println("huang, huangDengKan,BLUE/G led ");
        
       }
  
     }    
    

void setup(void)
{
    syntiant_setup();
}

void loop(void)
{
    syntiant_loop();
}

    根据电子森林老师的教学,你要是水平比较高的话,还可以修改syntiant_loop.cpp这个文件,里面有更多的内容,可以实现呼吸灯等等之类的效果,或是更牛的效果。编程完毕之后要编译一下,但是别上传。然后去到temp目录(.md文件写的很明白了)下找到一个叫firmware-syntiant-tinyml.ino.bin的文件。“.ino.bin”前面那一坨其实对应的是你这个运行程序的名字。把这个名字改成firmware.ino.bin。然后复制到,我们第二步训练模型后下载出来的固件文件夹里去替换同名文件。然后开发板连上电脑再运行固件文件夹里的.bat文件。就能完成全部的操作了。这个bat文件,会通过命令行,把我们编译好的文件上传到开发板里去。中间开发板会重启1-3次,然后所有的工作就办完了。

    这时候,打开串口调试工具,然后再对着开发板说我们之前训练过的语音命令,串口就会显示出来开发板辨识的结果。开发板上的RGB灯也会按照我们在第四步编程时的设置红红绿绿的闪起来了。

 

   各部分程序如下:

    红灯闪烁,语音命令为“下雨了”。就是先把所有的灯都关掉,然后红灯用1s亮1s黑的方式持续5秒钟。

if (strcmp(event, "rb") == 0) //慢速闪烁模式,颜色后期可以改,红色闪烁,下雨了
        // Toggle LED
      {
          digitalWrite(LED_RED, LOW);
          digitalWrite(LED_GREEN, LOW);
          digitalWrite(LED_BLUE, LOW);
         
        digitalWrite(LED_RED, HIGH);
        
        Serial.print("hong, hongShanShuo ,RED led blink=5,");
        delay (1000); 
        digitalWrite(LED_RED, LOW);
        Serial.print("4,");
        delay (1000);
        digitalWrite(LED_RED, HIGH);
        Serial.print("3,");
        delay (1000);
        digitalWrite(LED_RED, LOW);
        Serial.print("2,");
        delay (1000);
        digitalWrite(LED_RED, HIGH);
        Serial.print("1,");
        delay (1000);
        digitalWrite(LED_RED, LOW);
        Serial.println("0.");
        delay (1000);        
       }     

 

    绿灯闪烁,语音命令为“菜青虫”。就是先把所有的灯都关掉,然后把绿灯用1s亮1s黑的方式持续5秒钟。

 if (strcmp(event, "gb") == 0) //慢速闪烁模式,颜色后期可以改,绿色闪烁,菜青虫
        // Toggle LED
     {
          digitalWrite(LED_RED, LOW);
          digitalWrite(LED_GREEN, LOW);
          digitalWrite(LED_BLUE, LOW);
       
        digitalWrite(LED_GREEN, HIGH);
      
        Serial.print("lv, lvShanShuo ,GREEN led blink=5,");
        delay (1000); 
        digitalWrite(LED_GREEN, LOW);
        Serial.print("4,");
        delay (1000);
        digitalWrite(LED_GREEN, HIGH);
        Serial.print("3,");
        delay (1000);
        digitalWrite(LED_GREEN, LOW);
        Serial.print("2,");
        delay (1000);
        digitalWrite(LED_GREEN, HIGH);
        Serial.print("1,");
        delay (1000);
        digitalWrite(LED_GREEN, LOW);
        Serial.println("0.");
        delay (1000);        
       }             

 

    红灯常亮,语音命令为“玫瑰花”。就是先把所有的灯都关掉,然后红灯点亮持续5秒钟。

    if (strcmp(event, "rc") == 0) //常亮模式,颜色后期可以改,rc 红色常亮 
        // Toggle LED
      {
        
          digitalWrite(LED_RED, LOW);
          digitalWrite(LED_GREEN, LOW);
          digitalWrite(LED_BLUE, LOW);
        
        digitalWrite(LED_RED, HIGH);
     
        Serial.print("hong, hongChangLiang,RED led =5,");
        delay (1000);
        Serial.print("4,");
        delay (1000);
        Serial.print("3,");
        delay (1000);
        Serial.print("2,");
        delay (1000);
        Serial.print("1,");
        delay (1000);
        Serial.println("0.");
        digitalWrite(LED_RED, LOW);
        delay (1000);        
       }

    其他程序部分本项目中并没有修改,就是简简单单的调用其他库文件

void setup(void)
{
    syntiant_setup();
}

void loop(void)
{
    syntiant_loop();
}

    想继续修改的得去改syntiant.cpp文件。这个我就不赘述了。

    其他要修改的就是一个关键字的设置文件。在\src\model-parameters目录下model_variables.h文件里改,可别直接用网站生成的这个文件直接代替哦,会报错。

    对“model_variables.h”的修改内容如下。

FoiyKq3PLzfDVOC6_Mu8-lbCZIRW

 

四、效果展示

    最终的功能展示如下,就是我们说“菜青虫”  ,“玫瑰花”,  “下雨了”的时候,相应的灯就会亮起来,或是闪起来,实在是不会弄gif图,所以发几个视频的截图。具体效果可以看最上的视频

FjKJxtk-cH5HzmlPhR7n8LpWazlBFtMf98SHHui8iIikeWmoNbyJFNLuFqQI4yjUdte2cF1nmX5GafxNSDj_

 

五、心得体会

     最后说下心得体会,首先通过电子森林这种活动方式,让我对硬件编程有了更多学习的动力。非常感谢电子森林提供的这一次活动。其次回到本次活动的板卡本身,作为硬件草履虫,我觉得它的功能有很深的落地前景。因为貌似现在很多各种语音识别工具,比如天猫精灵这类通过语音命令操作某种功能的硬件,它们是必须要联网的,也就是生产者,还需要搭设相应的服务器。使用环境也必须有网络支持才行。这本身就是一个很大的限制。而传统的声控设备,比如声控灯,就只能实现有声音就亮,没声音就关。是提供不了很多命令控制方式的。在这两种控制方程或是语音控制方案之间的巨大市场,NDP101恰好可以填满。 还有就是运动传感器方面的机器学习功能。在不久的几年前,我记得运动手表计步还是很蠢的,人坐着,手来回摆动,它会认为你再走路。像Garmin这种大厂,他们家的算法比较好,就能识别出来。这得是他们程序员付出多少努力才得到的啊。而现在有了TinyML,我觉得这事儿就要简单多了。而且识别准确度也会有很大的提高。但是这些都是针对NDP101神经元芯片的。这块Syntiant TinyMl开发板 将近300块的售价,我觉得还是比较贵的。至少我觉得性价比要差过Seeed的WIO terminal很多。而且这块Syntiant TinyMl开发板也不是很稳定,在上传模型的时候,有很多概率失败或是飞跑。而且官方的例程,咳咳咳,对于我这种草履虫来说,觉得简单的地方太简单到没多少发挥的空间,难的地方太难到真的不敢瞎发挥。官方可能还是应该让这个例程更丰富一点吧。或是通过更多的活动让比较厉害的电子爱好者去搞,然后找个地方集中让我这种草履虫去学也好啊。真的。B站那位叫简简单单的大侠。他弄的那个官方例程,我觉得可操作性都比现在的官方例程要强的多。。。可是真是找不到过去版本官方例程的下载了。这真是有点遗憾。当然官方还是很用心的。我玩这个大概2个月时间。在github上,他们已经更新过好几次例程了。

最后再次感谢电子森林,再次感谢几位提供教程的大侠。

附件下载
最终提交文件.rar
内含全部相关文件
团队介绍
自己一个人
团队成员
老孙头
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2023 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号