如何使用语音指令控制串口输出

描述

简介

在上两篇文章中, 我们实现了GPIO输出, 和PWM输出(组件介绍在前文中已经介绍过 ),在本章节我们将继续进行使用语音指令控制串口输出。
 

  配置Example默认串口数据输出     


1、首先修改

/home/vc02/Downloads/uni_hb_m_solution/unione_lite_app_hb_m/user/inc/user_config.h 

中的USER_RUN_DEMO_SELECT 为 USER_DEMO_UART
 

PWM

这样默认运行的程序就是

/home/vc02/Downloads/uni_hb_m_solution/unione_lite_app_hb_m/user/src/examples/hb_uart.c

代码如下所示

 

#include "user_uart.h"
#include "user_event.h"
#include "user_player.h"
#include "user_config.h"
#define TAG "hb_uart_voice"
static uni_pthread_t g_uart_thread_id = 0;
static bool g_uart_thread_running = false;
// 串口发送线程函数
static void _uart_send_task(void *args) {
  char buf[6] = {1, 2, 3, 4, 5, 6};
  int ret;
  g_uart_thread_running = true;
  while (g_uart_thread_running) {
    LOGT(TAG, "UART send done, ret=%d", ret);
    uni_msleep(2000); // 每隔2秒发送一次
  }
}
// 创建发送线程
static Result _create_uart_thread(void) {
  if (g_uart_thread_running) {
    return E_OK;
  }
  thread_param param;
  uni_memset(¶m, 0, sizeof(param));
  param.stack_size = STACK_SMALL_SIZE;
  param.priority = OS_PRIORITY_LOW;
  uni_strncpy(param.task_name, "uart_voice", sizeof(param.task_name) - 1);
  if (0 != uni_pthread_create(&g_uart_thread_id, ¶m, _uart_send_task, NULL)) {
    return E_FAILED;
  }
  uni_pthread_detach(g_uart_thread_id);  // 自动资源回收
  return E_OK;
}
// 停止发送线程
static void _stop_uart_thread(void) {
  if (!g_uart_thread_running) return;
  g_uart_thread_running = false;
  if (g_uart_thread_id != 0) {
    uni_pthread_destroy(g_uart_thread_id);
    g_uart_thread_id = 0;
  }
}
// 语音唤醒命令回调
static void _on_wakeup_cmd_cb(USER_EVENT_TYPE event, user_event_context_t *context) {
  if (context == NULL) return;
  event_goto_awakend_t *awake = &context->goto_awakend;
  if (strcmp(awake->cmd, "wakeup_uni") == 0) {
    _create_uart_thread();  // 启动串口线程
    user_player_reply_list_random(awake->reply_files);  // 播放语音回复
  }
}
// 自定义设置命令回调
static void _custom_setting_cb(USER_EVENT_TYPE event, user_event_context_t *context) {
  if (context == NULL) return;
  event_custom_setting_t *setting = &context->custom_setting;
  if (strcmp(setting->cmd, "TurnOn") == 0) {
    _stop_uart_thread();  // 停止串口线程
    user_player_reply_list_random(setting->reply_files);  // 播放语音回复
  }
}
// 注册语音事件回调
static void _register_event_callback(void) {
  user_event_subscribe_event(USER_GOTO_AWAKENED, _on_wakeup_cmd_cb);
  user_event_subscribe_event(USER_CUSTOM_SETTING, _custom_setting_cb);
}
// 主入口
int hb_user_uart_voice_control(void) {
  if (0 != user_uart_init(NULL)) {
    LOGE(TAG, "UART init failed");
    return -1;
  }
  _register_event_callback();
  return 0;
}
 

 

其默认行为为创建线程定时发送数据, 然后使用LOG打印。但是它没办法调试。 因此我们做一点简单的修改, 当接受的数据的时候再发送出去。

 

// 串口发送线程函数
static void _uart_send_task(void *args) {
  char buf[6] = {1, 2, 3, 4, 5, 6};
  int ret;
  g_uart_thread_running = true;
  while (g_uart_thread_running) {
    LOGT(TAG, "Voice triggered UART send [1, 2, 3, 4, 5, 6]");
    ret = user_uart_send(buf, sizeof(buf));
    LOGT(TAG, "UART send done, ret=%d", ret);
    uni_msleep(2000); // 每隔2秒发送一次
  }
}

 

2、编译和烧录
 

PWM



实验现象:串口以9600的波特率持续接收到数据 01,02,03,04,05,06 和程序中的数据对应,正确无误。

PWM




发送测试:之后尝试向其发送数据, 查看VC-02是否能正常转发回来(关闭HEX显示, 发送的数据和接受的一致)。

PWM



 

  使用语音命令控制串口发送数据     


1、创建文件

hb_user_uart_testing.c 在 /home/vc02/Downloads/uni_hb_m_solution/unione_lite_app_hb_m/user/src/examples 下

 

#include "user_uart.h"
#include "user_event.h"
#include "user_player.h"
#include "user_config.h"
#define TAG "hb_uart_voice"
static uni_pthread_t g_uart_thread_id = 0;
static bool g_uart_thread_running = false;
// 串口发送线程函数
static void _uart_send_task(void *args) {
  char buf[6] = {1, 2, 3, 4, 5, 6};
  int ret;
  g_uart_thread_running = true;
  while (g_uart_thread_running) {
    LOGT(TAG, "Voice triggered UART send [1, 2, 3, 4, 5, 6]");
    ret = user_uart_send(buf, sizeof(buf));
    LOGT(TAG, "UART send done, ret=%d", ret);
    uni_msleep(2000); // 每隔2秒发送一次
  }
}
// 创建发送线程
static Result _create_uart_thread(void) {
  if (g_uart_thread_running) {
    return E_OK;
  }
  thread_param param;
  uni_memset(¶m, 0, sizeof(param));
  param.stack_size = STACK_SMALL_SIZE;
  param.priority = OS_PRIORITY_LOW;
  uni_strncpy(param.task_name, "uart_voice", sizeof(param.task_name) - 1);
  if (0 != uni_pthread_create(&g_uart_thread_id, ¶m, _uart_send_task, NULL)) {
    return E_FAILED;
  }
  uni_pthread_detach(g_uart_thread_id);  // 自动资源回收
  return E_OK;
}
// 停止发送线程
static void _stop_uart_thread(void) {
  if (!g_uart_thread_running) return;
  g_uart_thread_running = false;
  if (g_uart_thread_id != 0) {
    uni_pthread_destroy(g_uart_thread_id);
    g_uart_thread_id = 0;
  }
}
// 语音唤醒命令回调
static void _on_wakeup_cmd_cb(USER_EVENT_TYPE event, user_event_context_t *context) {
  if (context == NULL) return;
  event_goto_awakend_t *awake = &context->goto_awakend;
  if (strcmp(awake->cmd, "wakeup_uni") == 0) {
    _create_uart_thread();  // 启动串口线程
    user_player_reply_list_random(awake->reply_files);  // 播放语音回复
  }
}
// 自定义设置命令回调
static void _custom_setting_cb(USER_EVENT_TYPE event, user_event_context_t *context) {
  if (context == NULL) return;
  event_custom_setting_t *setting = &context->custom_setting;
  if (strcmp(setting->cmd, "TurnOn") == 0) {
    _stop_uart_thread();  // 停止串口线程
    user_player_reply_list_random(setting->reply_files);  // 播放语音回复
  }
}
// 注册语音事件回调
static void _register_event_callback(void) {
  user_event_subscribe_event(USER_GOTO_AWAKENED, _on_wakeup_cmd_cb);
  user_event_subscribe_event(USER_CUSTOM_SETTING, _custom_setting_cb);
}
// 主入口
int hb_user_uart_voice_control(void) {
  if (0 != user_uart_init(NULL)) {
    LOGE(TAG, "UART init failed");
    return -1;
  }
  _register_event_callback();
  return 0;
}

 

输入上述代码, 其主要的业务逻辑就是通过唤醒命令来触发串口的定时输出,然后通过TrunOn的命令来关闭串口输出的线程。

2、添加编译支持在 

/home/vc02/Downloads/uni_hb_m_solution/unione_lite_app_hb_m/build/user/src/examples下的subdir.mk添加对当前编译文件的引用。

PWM



3、修改

/home/vc02/Downloads/uni_hb_m_solution/unione_lite_app_hb_m/user/inc/user_config.h 文件, 增加对应的demo宏支持。

PWM



4、修改

/home/vc02/Downloads/uni_hb_m_solution/unione_lite_app_hb_m/user/src/user_main.c ,增加对上述自定义宏的支持。

PWM



5-、编译并且烧录固件。

PWM



 

实验现象 

烧录完成之后, 串口默认不输出任何数据。
 

PWM



当识别到语音命令“你好小美” 之后将开始打印01 02 03 04 05。
 

PWM



当识别到语音命令“打开灯光” 的时候将删除串口发送进程, 串口停止输出。
 

PWM



如上图所示, 此时的串口处于打开状态,但是没有输出数据。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分