T5+2M-ASR-PRO 定制命令词
项目介绍
由于 T5 默认支持的唤醒词有限,例如:
- TuyaOS 支持三种默认唤醒词:“你好涂鸦”、“小智同学”、“Hey, Tuya”(英文)
- TuyaOpen 支持四种默认唤醒词:“你好涂鸦“、“小智同学”、“小智管家”、“你好小智”
因此,如果您想要自定义唤醒词,有三种方案:
- 增加语音识别模组
- 替换唤醒词算法
- 定制唤醒词(如需定制,请联系涂鸦商务人员)
本教程为您介绍第一种方案:增加语音识别模组,该方案具有以下几点优势:
- 技术门槛低,不需要了解音频算法。
- 配合涂鸦智能体多角色可以实现多唤醒词。不同的唤醒词对应不同的角色,避免角色和唤醒词不匹配的尴尬场景。
- 支持离线语音识别。ASR PRO 模组支持离线神经网络计算,无需依赖网络即可实现语音识别。这一特性使其即便在无网络连接或网络信号不稳定的环境中,仍能保持正常工作状态。
- 高识别率。ASR PRO 模组具备强劲的回声消除和环境噪声抑制能力,即使在嘈杂环境中也能保持较高的语音识别准确性。其识别率可达 98 %以上,响应时间小于 0.15 秒。
所需材料
硬件 | 功能参数 |
---|---|
T5 开发板 | 提供 AI 对话功能核心功能 |
ASR PRO 模组 | 支持自定义唤醒词和离线语音识别 |
串口板或 ASR-LINK 自动下载器 | 普通的 CH340 串口板即可,用于给 ASR PRO 下载程序。如果有条件可以自行购买 ASR-LINK 自动下载器 |
麦克风 | 用于给 ASR RPO 模组拾音 |
2M ASR PRO 语音识别模组(核心板)
芯片规格书:点击查看
外观图:

硬件接线说明
首先需要对 ASR PRO 进行编程和固件烧录,然后将 ASR PRO 模组连接到 T5 开发板,因此接线分成两部分:
ASR PRO 烧录接线
ASR PRO 模组 | 串口板 |
---|---|
GND | GND |
5V | 5V |
PB5(UART0 TX) | RX |
PB6(UART0 RX) | TX |
MIC + | 咪头 + |
MIC - | 咪头 - |
T5 开发板与 ASR PRO 模组连接
T5 开发板 | ASR PRO 模组 |
---|---|
GND | GND |
5V | 5V |
P10(UART0 TX) | PB5(RX) |
P11(UART0 RX) | PB6(TX) |
P12(唤醒脚) | PA4(演示使用,可自定义)。注意:如果使用串口程序唤醒,可以不接 P12 唤醒引脚 |
运行效果
ASR PRO 程序制作
Tuya AI 智能体支持多角色,ASR PRO 模组支持最多 5 个唤醒词,每个唤醒词有单独的识别标识 ID,因此可以考虑设计一个程序为每个角色设计一个专有唤醒词。在制作 ASR PRO 程序时可以用识别标识 ID 来区分唤醒词,比如识别到不同的标识 ID 控制不同的 IO 引脚拉低,或者也可以通过串口将数据发送到需要连接的主控芯片 T5 上。
通常使用 天问 Block 开发 ASR PRO 模组,其图形化编程对新手非常友好。您可以点击前往 天问 51 官网 下载。
示例程序
系统配置三个唤醒词,分别为 “你好哪吒”、“你好猪八戒”、“你好柯南”。当 ASR PRO 模组识别到上述任一唤醒词时,需通过 IO 接口触发唤醒功能,同时通过串口输出数据:
- ASR PRO 识别到唤醒词后,会控制 PA4 输出低电平 100 ms 然后拉高。
- 通过串口(PB5 PB6)引脚输出十六进制。
唤醒词 | 串口输出 |
---|---|
你好哪吒 | A0 01 00 |
你好猪八戒 | A0 01 01 |
你好柯南 | A0 01 02 |
资料下载
固件烧录
关于固件烧录的方法,请参考 视频教程。
参考图:

T5 程序制作
IO 唤醒
IO 唤醒相对易操作,只需要将 ASR PRO 设置的唤醒脚连接到 T5 唤醒脚(默认 P12)即可。
串口唤醒
串口唤醒只需要在串口接收程序中判断识别到唤醒指令并调用 audio_recorder_start();
接口即可,下面是一个串口例程:
#include "tal_uart.h"
#include "tal_system.h"
#include "tal_log.h"
#include "base_event.h"
#include "tuya_cloud_types.h"
#include <stdio.h>
#include "audio_recorder.h"
#ifdef ENABLE_WIFI_SERVICE
#include "tuya_iot_wifi_api.h"
#else
#include "tuya_iot_base_api.h"
#endif
#define UART_BOUND 9600
STATIC THREAD_HANDLE my_uart_thread = NULL;
/***********************************************************
***********************typedef define***********************
***********************************************************/
#define ROLE_API "thing.ai.agent.switch.role"
#define API_VERSION "1.0"
typedef struct {
char *commandInfo;
char *description;
} TY_AI_ROLE_T;
/*
*commandInfo\": 是角色 ID,可以在涂鸦开发者平台获取
*/
const TY_AI_ROLE_T POST_CONTENTS[] = {
{"{\"commandInfo\": \"DIY_XEM_EPAXATC0U0W0\"}","小恶魔"},
{"{\"commandInfo\": \"DIY_XTS_EPAXBE3SFRB4\"}","小天使"},
{"{\"commandInfo\": \"DIY_SWK_EPAA4V9THGQO\"}","孙悟空"},
{"{\"commandInfo\": \"DIY_ZBJ_EPA9XXFY2WOW\"}","猪八戒"},
{"{\"commandInfo\": \"DIY_CE_EPA9SDZAXOG0\"}","嫦娥"},
{"{\"commandInfo\": \"DIY_TZ_EPA9NAVSDKAO\"}","唐僧" },
{"{\"commandInfo\": \"DIY_ND_EPAW3QRNEDQ8\"}","牛顿"},
{"{\"commandInfo\": \"DIY_HTL_EPAWROAK5TDS\"}","灰太狼"},
{"{\"commandInfo\": \"DIY_HLBT_EPAWXZXJJG8W\"}","哈利波特"},
{"{\"commandInfo\": \"DIY_KN_EPAX5IQQQOE8\"}","柯南"},
{"{\"commandInfo\": \"SYS_GJXY_EKGXPAQA11J4\"}","杠精小丫"},
};
int g_role_max = sizeof(POST_CONTENTS) / sizeof(POST_CONTENTS[0]);;
/***********************************************************
***********************variable define**********************
***********************************************************/
/**
* @brief http task
* 功能:切换角色
* @param[in] param:Task parameters
* @return none
*/
VOID switch_iot_role(char *role_name)
{
OPERATE_RET rt = OPRT_OK;
ty_cJSON* result = NULL;
CHAR_T *print_data = NULL;
const CHAR_T post_count = sizeof(POST_CONTENTS) / sizeof(POST_CONTENTS[0]);
CHAR_T i;
for(i=0; i<post_count; i++)
{
if(strstr(POST_CONTENTS[i].description,role_name) != NULL) {
break;
}
}
// 检查索引是否有效
if(i >= post_count) {
TAL_PR_ERR("Role not found: %s", role_name);
return;
}
TAL_PR_DEBUG("Processing POST_CONTENT[%u]: %s", i, POST_CONTENTS[i].commandInfo);
// 调用 HTTP POST 函数,传递指定的数组元素
rt = iot_httpc_common_post_simple(ROLE_API, API_VERSION, POST_CONTENTS[i].commandInfo, NULL, &result);
if (NULL == result) {
TAL_PR_DEBUG("result is NULL");
return;
}
print_data = ty_cJSON_PrintUnformatted(result);
if (NULL != print_data) {
TAL_PR_NOTICE("%s", print_data);
ty_cJSON_FreeBuffer(print_data);
print_data = NULL;
}
ty_cJSON_Delete(result);
result = NULL;
return;
}
STATIC VOID __uart0_rev_task(VOID *arg)
{
UINT8_T rx_data[256];
INT_T ret_len=0;
OPERATE_RET rt = OPRT_OK;
int uart_num=TUYA_UART_NUM_0;
while ((1))
{
int cnt=0;
//判断读取超时时间
while(tal_uart_get_rx_data_size(uart_num)<1){
cnt++;
if(cnt>5){
break;
}
tal_system_sleep(10);
}
if(cnt>5) continue;
ret_len = tal_uart_read(uart_num,rx_data,sizeof(rx_data));
char STR[128]= {0};
if(ret_len != 0)
{
TAL_PR_HEXDUMP_DEBUG("UART_RX:",rx_data,ret_len);
if(rx_data[0] == 0xA0 && rx_data[1] == 0x01) {
switch (rx_data[2]) // Assuming rx_data[2] contains the command type
{
case 0x00:
{ /* 哪吒唤醒词 */
sprintf(STR, "哪吒");
break;
}
case 0x01:
/* 猪八戒唤醒词 */
{
sprintf(STR, "猪八戒");
break;
}
case 0x02:
/* 柯南唤醒词 */
{
sprintf(STR, "柯南");
break;
}
default:
break;
}
switch_iot_role(STR);
audio_recorder_start();
// tuya_voice_proto_get_tts_text(STR);//文本对话,将 STR 内容发送到 Agent
TAL_PR_DEBUG("-------------->唤醒词: %s", STR);
}
}
}
tal_thread_delete(my_uart_thread);
my_uart_thread = NULL;
}
OPERATE_RET my_asr_uart_thread(VOID)
{
OPERATE_RET rt = OPRT_OK;
TAL_UART_CFG_T cfg = {0};
cfg.base_cfg.baudrate = UART_BOUND;
cfg.base_cfg.databits = TUYA_UART_DATA_LEN_8BIT;
cfg.base_cfg.stopbits = TUYA_UART_STOP_LEN_1BIT;
cfg.base_cfg.parity = TUYA_UART_PARITY_TYPE_NONE;
cfg.rx_buffer_size = 256;
cfg.open_mode = O_BLOCK;
tal_uart_deinit(TUYA_UART_NUM_0);
TUYA_CALL_ERR_RETURN(tal_uart_init(TUYA_UART_NUM_0,&cfg));//usrt 0 init
THREAD_CFG_T param;
param.priority = THREAD_PRIO_3;
param.stackDepth = 1024*4;
param.thrdname = "my_uart_asr_thread";
TUYA_CALL_ERR_RETURN( tal_thread_create_and_start(&my_uart_thread, NULL, NULL,__uart0_rev_task ,NULL , ¶m));
TAL_PR_DEBUG("======_asr_uart_ task success==============");
return rt;
}