发帖
1 0 0

安信可离线语音模组 VC-01、VC-02 系列教程 【二次开发篇】事件和GPIO控制

WangChong
论坛元老

79

主题

861

回帖

1万

积分

论坛元老

积分
11749
VC系列 54 1 18 小时前
本帖最后由 WangChong 于 2025-5-22 02:53 编辑

简介


在上一篇文章中,我们已经成功的搭建好了VC系列的Linux开发环境,并且使用VScode进行了远程连接。成功的进入到了下载后的SDK固件源码中。并且进行了编译等操作。 那么在本章我将对SDK中常见的模块进行解析,并且带着大家编译一个通过安信可语音平台生成固件中的语音唤醒或者控制事件在源码中进行自定义的操作(这里的意思指的是, 在安信可语音平台生成语音唤醒词和控制命令的时候并不指定控制行为, 通过在SDK里指定控制行为




准备工作


首先我给大家看一下我默认生成的固件配置信息(来自安信可语音平台

Snipaste_2025-05-22_01-30-28.png


下图为配置的控制行为

Snipaste_2025-05-22_01-37-11.png

可以从上面的两个图中看到, 我们仅仅是配置了默认的唤醒, 和一个控制行为。 但是这个控制行为也并没有对应的命令(无法点亮LED灯或者关闭LED灯。)
之后我们生成对应的SDK并且把SDK下载到虚拟机中(替换上一个帖子中下载的SDK,在文末我会附加上这次我生成的SDK文件,达到教程和代码一致)。


Snipaste_2025-05-22_01-41-43.png


SDK重要组件介绍

1- 首先在~/Downloads/uni_hb_m_solution/unione_lite_app_hb_m/tools/scripts下的tones 目录和 wav_tones 目录


Snipaste_2025-05-22_01-49-35.png

这两个目录其主要保存的为安信可语音平台生成的音频文件。 即所有的音频输出(唤醒词,回复词等)。 在程序编译后,其音频文件会被编译成PCM文件,然后由VC01/ VC02进行播放。


2- 开发板PIN初始化配置信息 /home/vc02/Downloads/uni_hb_m_solution/unione_lite_app_hb_m/tools/scripts/custom_config.json


360截图20250522015259.png

当前的文件主要记录了在安信可语音平台中配置的PIN的初始化信息。 如下图所示(不建议在代码中配置, 推荐使用安信可语音平台)

Snipaste_2025-05-22_01-53-49.png


3- cmd_reply_data.json 文件,位于/home/vc02/Downloads/uni_hb_m_solution/unione_lite_app_hb_m/tools/scripts/


360截图20250522015645.png

拿唤醒词你好小美 举例子, 这里主要的JSON key 有pcm, cmd。 PCM决定当前的命令词触发的时候将会播放哪些音乐, 而CMD则是做为对应唤醒事件的KEY(稍后会解释这个是什么意思)。




4- 二次开发集成的example配置文件user_config.h 文件, 位于 ~/Downloads/uni_hb_m_solution/unione_lite_app_hb_m/user/inc

360截图20250522020154.png

在默认的SDK中,其开启的Macro 为 USER_DEMO_AUTO_GPIO 。 所以用户的自定义功能将会使用example下的hb_auto_gpio.c 文件作为额外自定义功能, 以此类推,如果开启的是USER_DEMO_BUZZER 宏, 那么开启的Demo则为 /home/vc02/Downloads/uni_hb_m_solution/unione_lite_app_hb_m/user/src/examples 下的hb_timer_buzzer.c

Snipaste_2025-05-22_02-07-14.png

而当前的开发板所有支持的二次开发的库函数的定义则都在 /home/vc02/Downloads/uni_hb_m_solution/unione_lite_app_hb_m/user/inc 目录下

360截图20250522020939.png

这里所有库函数对应的例程都可以从example下找到。

5 - 非常非常重要的一个文件 user_event.h 位于inc 目录下, 此文件记录了所有开发板中可以触发的事件。 比如说识别到你好小美 或者是识别到 对应的命令

Snipaste_2025-05-22_02-13-34.png

  1. typedef enum {
  2.   USER_INVALID_EVENT = 0, ///< 错误的事件类型
  3.   USER_AUDIO_PLAY_START,  ///< 音频开始播放时发送
  4.   USER_AUDIO_PLAY_END,    ///< 音频播放完毕或被停止时发送
  5.   USER_CUSTOM_SETTING,    ///< 识别到客户自定义的识别词时发送
  6.   USER_VOLUME_SETTING,    ///< 识别到音量调节指令时发送
  7.   USER_GOTO_SLEEPING,     ///< 进入待唤醒状态时发送
  8.   USER_GOTO_AWAKENED,     ///< 进入识别状态(已唤醒)时发送
  9.   USER_EVENT_MAX
  10. }USER_EVENT_TYPE;
复制代码


上述枚举为所有可以被用户订阅的事件, 当对应的事件触发的时候将会触发事件的callback function进行处理。


  1. /** @brief 事件内容,共用体,根据事件类型具体处理*/
  2. typedef union {
  3.     event_audio_play_t      audio_play;     ///< 对应USER_AUDIO_PLAY_START事件
  4.     event_audio_end_t       audio_end;      ///< 对应USER_AUDIO_PLAY_END事件
  5.     event_custom_setting_t  custom_setting; ///< 对应USER_CUSTOM_SETTING事件
  6.     event_volume_setting_t  voluem_setting; ///< 对应USER_VOLUME_SETTING事件
  7.     event_goto_sleeping_t   goto_sleeping;  ///< 对应USER_GOTO_SLEEPING事件
  8.     event_goto_awakend_t    goto_awakend;   ///< 对应USER_GOTO_AWAKENED事件
  9. }user_event_context_t;
复制代码


针对于上述事件的每一个事件, 其具备对应的事件内容。 比如说用户订阅了USER_GOTO_AWAKENED 事件, 那么便可以从user_event_context_tgoto_awakend 捕获到对应的事件内容。而对应事件的内容信息则被下述的结构体定义.  只举例唤醒事件(其他的同样的道理)

  1. typedef struct {
  2.     EVENT_TRIGGER   trigger;      ///< 触发来源
  3.     char            *cmd;         ///< 命令词意图,对应UDP平台上用户定义脚本中的action
  4.     char            *word_str;    ///< 识别到的命令词
  5.     char            *reply_files; ///< 回复语列表[1, 2, 3],对应UDP平台上用户定义脚本中的回复语列表,在pcm_map.txt中可以找到对应关系
  6. }event_goto_awakend_t;
复制代码


这样的话,我们便可以通过cmd来获取到对应的命令! 这里就可以解释在 3- cmd_reply_data.json 文件中所说明的JSON KEY对应Value的作用。即用户可以根据对应的事件, 判断对应的cmd来自定义行为。 其支持的行为为所有Inc文件夹下包含的库函数。




GPIO控制(通过使用唤醒词:你好小美。关闭LED,使用命令词:打开台灯。打开LED)

明白原理之后, 我们便可以开始着手来开发我们的GPIO功能, 即通过使用唤醒词:你好小美。关闭LED,使用命令词:打开台灯。打开LED。需要注意的是: "你好小美" 是属于唤醒事件, 而打开台灯是属于命令事件。 打开台灯必须在你好小美之后触发. 明白原理之后我们就可以很轻松的在example下的hb_auto_gpio.c 进行修改 (默认启用,上文有介绍)


首先在原本的_register_event_callback 方法中额外注册一个用户唤醒事件的回调
  1. user_event_subscribe_event(USER_GOTO_AWAKENED, _custom_setting_cb2);
复制代码
如下图所示

360截图20250522022617.png

之后拷贝原本的 _custom_setting_cb 方法 改名为 _custom_setting_cb2 (我这里不规范, 不要学习我这样的随意命名, 可以改成_custom_setting_wakeup_cb)
  1. static void _custom_setting_cb2(USER_EVENT_TYPE event,
复制代码


代码解析,由于我们订阅的是USER_GOTO_AWAKENED 事件, 所以其联合体中goto_awakend 才会具有数据,因此需要根据上下文中的context 来获取到对应的goto_awakend 从而来获取到对应的cmd命令 "wakeup_uni"  (被cmd_reply_data.json 定义, 上文有介绍)。这样的话就可以实现, 当识别到“你好小美” 的时候关闭LED灯。


同上,我们可以实现,对控制命令的LED灯打开。 代码如下所示。


  1. static void _custom_setting_cb(USER_EVENT_TYPE event,
复制代码


这样的话, 当识别到 “你好小美”的时候便会关闭LED, 当识别到 “打开台灯”等命令词的时候便会打开LED。从而实现用户的自定义控制!



编译烧录和测试

接下来,我们便可以在SDK的根目录来编译自己的固件了。 执行命令
  1. ./build.sh update
复制代码
360截图20250522023617.png


此时我们便可以打开output 文件夹,然后把uni_app_release_update.bin 下载到本地电脑。 然后使用 UniOneUpdateTool.exe 进行烧录。

360截图20250522023747.png


下图为烧录成功界面

360截图20250522023808.png


实验现象


使用 “你好小美” 唤醒VC02, 然后 “打开台灯” LED 灯被点亮

微信图片_20250522024030.jpg


使用 “你好小美” 唤醒VC02LED灯被熄灭


微信图片_20250522024200.jpg


附件:固件和SDK

https://www.123865.com/s/UNArVv-k4UKd


──── 0人觉得很赞 ────

使用道具 举报

赞~
您需要登录后才可以回帖 立即登录
高级模式
返回
统计信息
  • 会员数: 28790 个
  • 话题数: 41081 篇