基于VIT获取天气信息的RT语音识别系统

2024-06-21 07:28

本文主要是介绍基于VIT获取天气信息的RT语音识别系统,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

基于VIT获取天气信息的RT语音识别系统

  • 一, 文档简介
  • 二, 相关准备
    • 2.1 天气API平台
    • 2.2 postman测试天气API
    • 2.3 VIT自定义命令
  • 三, 代码讲解
    • 3.1 LWIP socket 客户端代码获取天气API
    • 3.2 VIT识别自定义代码添加
    • 3.3 语音识别天气信息
  • 四, 测试结果
  • 五, 问题总结
    • 5.1 LWIP获取天气失败
    • 5.2 VIT LWIP融合内存不足
    • 5.3 中文打印

一, 文档简介

NXP EdgeReady解决方案可以使用RT106/5 S/L/A/F实现语音语音识别,但是相关配套软件库对于RT4位系列仅仅局限于S/L/A/F系列, 如果想使用普通的RT芯片是否可以同样实现语音识别功能呢?NXP官方推出VIT软件包,可以支持RT1060,RT1160,RT1170,RT600,RT500实现基于SDK的语音识别功能。
对于天气信息的获取,通常可以对接第三方平台或者云端的天气API,使用http客户端形式直接获取,目前支持天气API的平台很多,可以直接注册后实现调用,所以可以利用RT SDK的lwip socket 客户端形式调用对应的天气API,实现实时具体地理位置的天气预报数据。
本文将使用MIMXRT1060-EVK基于SDK VIT实现客户自定义唤醒词和识别词的识别,以及LWIP socket客户端实现上海实时天气的信息获取,并且打印到终端,暂时未添加播报,因为还需要实现实时TTS功能。
本文系统结构框图如下:

在这里插入图片描述

图1 系统框图
本系统VIT自定义唤醒词为“小恩小恩”,唤醒之后可以识别如下识别词之一:”开灯”,“关灯”,”今天天气”,“明天天气”,“后天天气”。开灯关灯即开关板上外接LED红灯。“今天天气”获取当日天气预报,格式如下:

                "date": "2022-05-27","week": "5","dayweather": "阴","nightweather": "阴","daytemp": "28","nighttemp": "21","daywind": "东南","nightwind": "东南","daypower": "≤3","nightpower": "≤3"

“明天天气”,“后天天气”也是同样格式,只是相对当日日期退后1-2天。获取天气,MIMXRT1060-EVK板子需要联网,实现高德地图天气API的获取。

二, 相关准备

2.1 天气API平台

目前网上能够获取天气的第三方平台很多,比如:百度智能云,百度地图API,华为云平台,聚合天气,高德地图API等等。本文试了几个,测试结果发现:百度智能云,日免费调用次数少,需要实时合成AK,SK,调用繁琐;百度地图API需要上传身份证信息;其他几个也有类似情况。最终,选择了注册方便,日调用次数多,反馈天气数据信息相对全的高德地图API。
下面主要讲关于高德地图API的情况,进入链接:

https://lbs.amap.com/api/webservice/guide/api/weatherinfo
根据链接申请账号以及API key,然后添加相关参数可以实现天气API的调用。
申请API Key 情况如下:
在这里插入图片描述

图2 高德地图API key
下图是调用量情况:
在这里插入图片描述

图3 高德地图API调用量
下图是具体调用API情况:
在这里插入图片描述

图4 天气API调用参数
所以,一个调用高德地图API的完整链接情况如下:

https://restapi.amap.com/v3/weather/weatherInfo?key=xxxxxxx&city=xxx&extensions=all&output=JSON

如果需要测试上海天气,city代码为310000。

2.2 postman测试天气API

Postman是一个接口测试工具,在做接口测试的时候,Postman相当于一个客户端,它可以模拟用户发起的各类HTTP请求,将请求数据发送至服务端,获取对应的响应结果, 从而验证响应中的结果数据是否和预期值相匹配. Postman下载链接:https://www.postman.com/   

找到合适的天气API平台与调用链接之后,首先先用postman做一个http的get去获取试试看,根据图4,填入相关参数到postman:
在这里插入图片描述

图5 postman调用天气API

发送之后,可以在7位置看到获取的天气信息,一个完整的all信息如下:

{"status": "1","count": "1","info": "OK","infocode": "10000","forecasts": [{"city": "上海市","adcode": "310000","province": "上海","reporttime": "2022-05-27 17:34:12","casts": [{"date": "2022-05-27","week": "5","dayweather": "阴","nightweather": "阴","daytemp": "28","nighttemp": "21","daywind": "东南","nightwind": "东南","daypower": "≤3","nightpower": "≤3"},{"date": "2022-05-28","week": "6","dayweather": "小雨","nightweather": "中雨","daytemp": "24","nighttemp": "20","daywind": "东南","nightwind": "东南","daypower": "≤3","nightpower": "≤3"},{"date": "2022-05-29","week": "7","dayweather": "大雨","nightweather": "小雨","daytemp": "23","nighttemp": "20","daywind": "南","nightwind": "南","daypower": "≤3","nightpower": "≤3"},{"date": "2022-05-30","week": "1","dayweather": "小雨","nightweather": "晴","daytemp": "27","nighttemp": "20","daywind": "北","nightwind": "北","daypower": "≤3","nightpower": "≤3"}]}]
}

这里可以看到,可以连续或许从GET命令开始的4天时间,所以有这个数据,我们就很容易的得到了天气信息。
从postman,还可以查看具体的代码情况,如下:
在这里插入图片描述

图6 postman调用API HTTP代码
现在有API,而且经过测试,可以完整获取天气信息,这里就可以考虑把对应的http客户端API添加到MIMXRT1060-EVK的代码中去。

2.3 VIT自定义命令

从RT1060 SDK的maestro代码中,我们可以知道SDK已经支持了VIT库,何为VIT?
VIT全名为:Voice Intelligent Technology,该库提供语音识别服务,旨在唤醒和识别具体命令,控制IOT以及智能家居。

在这里插入图片描述

图7 VIT系统框图
在我们SDK代码中,已经提供了生成好的唤醒词和命令词,并放在了VIT_Model.h文件中,那么如果在客户的项目中,如何自定义唤醒词和命令词呢?通过NXP的努力,我们已经做成了网页的形式,可以供客户自行选择,然后生成对应的VIT_Model.h文件,供代码调用。VIT命令词生成网页:
https://vit.nxp.com/#/home
登录官方账号之后,可以自行选择RT芯片,唤醒词,命令词。这里需要注意,目前仅支持如下RT芯片:
支持RT1060,RT1160,RT1170,RT600,RT500
关于生成唤醒词和命令词,相关情况如下:
在这里插入图片描述

图8 自定义VIT配置

在这里插入图片描述

图9 生成结果
下载生成的模型,可以得到VIT_Model_cn.h,打开可以看到命令词信息以及相关的模型数据存放在const PL_MEM_ALIGN(PL_UINT8 VIT_Model_cn[], VIT_MODEL_ALIGN_BYTES) 数组中,命令词信息如下:

WakeWord supported : " 小恩 小恩 " Voice Commands supported
Cmd_Id : Cmd_Name
0 : UNKNOWN
1 : 开灯
2 : 关灯
3 : 今天 天气
4 : 明天 天气
5 : 后天 天气

使用maestro_record代码出部测试自定义命令结果:
在这里插入图片描述

图10 自定义唤醒词命令词测试
从测试结果可以看到,唤醒词和命令词均可以成功识别。

三, 代码讲解

3.1 LWIP socket 客户端代码获取天气API

从2.2章节,我们已经能够得到获取天气API并且通过测试,能够成功实现天气的获取,所以就需要结合自身系统的需求添加相关的命令。 对于天气API的获取,基于RT1060 SDK的lwip代码,采用socket client的形式。相关代码如下:

#define PORT            80
#define IP_ADDR        "59.82.9.133"
uint8_t get_weather[]= "GET /v3/weather/weatherInfo?key=xxx&city=310000&extensions=all&output=JSON HTTP/1.1\r\nHost: restapi.amap.com\r\n\r\n\r\n\r\n";if (sys_thread_new("weather_main", weathermain_thread, NULL, HTTPD_STACKSIZE, HTTPD_PRIORITY) == NULL)LWIP_ASSERT("main(): Task creation failed.", 0);
static void weathermain_thread(void *arg)
{static struct netif netif;ip4_addr_t netif_ipaddr, netif_netmask, netif_gw;ethernetif_config_t enet_config = {.phyHandle  = &phyHandle,.macAddress = configMAC_ADDR,};LWIP_UNUSED_ARG(arg);mdioHandle.resource.csrClock_Hz = EXAMPLE_CLOCK_FREQ;IP4_ADDR(&netif_ipaddr, configIP_ADDR0, configIP_ADDR1, configIP_ADDR2, configIP_ADDR3);IP4_ADDR(&netif_netmask, configNET_MASK0, configNET_MASK1, configNET_MASK2, configNET_MASK3);IP4_ADDR(&netif_gw, configGW_ADDR0, configGW_ADDR1, configGW_ADDR2, configGW_ADDR3);tcpip_init(NULL, NULL);netifapi_netif_add(&netif, &netif_ipaddr, &netif_netmask, &netif_gw, &enet_config, EXAMPLE_NETIF_INIT_FN,tcpip_input);netifapi_netif_set_default(&netif);netifapi_netif_set_up(&netif);PRINTF("\r\n************************************************\r\n");PRINTF(" TCP client example\r\n");PRINTF("************************************************\r\n");PRINTF(" IPv4 Address     : %u.%u.%u.%u\r\n", ((u8_t *)&netif_ipaddr)[0], ((u8_t *)&netif_ipaddr)[1],((u8_t *)&netif_ipaddr)[2], ((u8_t *)&netif_ipaddr)[3]);PRINTF(" IPv4 Subnet mask : %u.%u.%u.%u\r\n", ((u8_t *)&netif_netmask)[0], ((u8_t *)&netif_netmask)[1],((u8_t *)&netif_netmask)[2], ((u8_t *)&netif_netmask)[3]);PRINTF(" IPv4 Gateway     : %u.%u.%u.%u\r\n", ((u8_t *)&netif_gw)[0], ((u8_t *)&netif_gw)[1],((u8_t *)&netif_gw)[2], ((u8_t *)&netif_gw)[3]);PRINTF("************************************************\r\n");sys_thread_new("weather", weather_thread, NULL, DEFAULT_THREAD_STACKSIZE, DEFAULT_THREAD_PRIO);vTaskDelete(NULL);
}
static void weather_thread(void *arg)
{int sock = -1,rece;struct sockaddr_in client_addr;char* host_ip;ip4_addr_t dns_ip;err_t err;uint32_t *pSDRAM= pvPortMalloc(BUF_LEN);//host_ip = HOST_NAME;PRINTF("host name : %s , host_ip : %s\r\n",HOST_NAME,host_ip);while(1){sock = socket(AF_INET, SOCK_STREAM, 0);if (sock < 0){PRINTF("Socket error\n");vTaskDelay(10);continue;}client_addr.sin_family = AF_INET;client_addr.sin_port = htons(PORT);client_addr.sin_addr.s_addr = inet_addr(host_ip);memset(&(client_addr.sin_zero), 0, sizeof(client_addr.sin_zero));if (connect(sock, (struct sockaddr *)&client_addr,  sizeof(struct sockaddr)) == -1){PRINTF("Connect failed!\n");closesocket(sock);vTaskDelay(10);continue;}PRINTF("Connect to server successful!\r\n");write(sock,get_weather,sizeof(get_weather));while (1){rece = recv(sock, (uint8_t*)pSDRAM, BUF_LEN, 0);//BUF_LENif (rece <= 0)break;memcpy(weather_data.weather_info, pSDRAM,1500);//max 1457}Weather_process();memset(pSDRAM,0,BUF_LEN);closesocket(sock);vTaskDelay(10000);}
}

3.2 VIT识别自定义代码添加

将之前生成的VIT_Model_cn.h,替换到maestro_record工程的文件夹路径:vit\RT1060_CortexM7\Lib
具体唤醒词和识别词相关代码,可以从代码vit_pro.c中查看,主要涉及函数为
int VIT_Execute(void *arg, void *inputBuffer, int size)
代码修改如下,主要是记录唤醒以及唤醒词号,用于具体的功能控制,这里直接控制的命令是本地“开灯“,”关灯“命令,至于天气命令需要调用socket client API,所以在主程序lwip调用区域结合命令词识别号予以调用:

if (VIT_DetectionResults == VIT_WW_DETECTED){PRINTF(" - WakeWord detected \r\n");weather_data.ww_flag =  1; //kerry}else if (VIT_DetectionResults == VIT_VC_DETECTED){// Retrieve id of the Voice Command detected// String of the Command can also be retrieved (when WW and CMDs strings are integrated in Model)VIT_Status = VIT_GetVoiceCommandFound(VITHandle, &VoiceCommand);if (VIT_Status != VIT_SUCCESS){PRINTF("VIT_GetVoiceCommandFound error: %d\r\n", VIT_Status);return VIT_Status; // will stop processing VIT and go directly to MEM free}else{PRINTF(" - Voice Command detected %d", VoiceCommand.Cmd_Id);weather_data.vc_index = VoiceCommand.Cmd_Id;//kerry 1:ledon 2:ledoff 3:today weather 4:tomorrow weather 5:aftertomorrow weatherif(weather_data.vc_index == 1)//1{GPIO_PinWrite(GPIO1, 3, 1U); //pull highPRINTF(" led on!\r\n");}else if(weather_data.vc_index == 2)//2{GPIO_PinWrite(GPIO1, 3, 0U); //pull lowPRINTF(" led off!\r\n");}// Retrieve CMD Name: OPTIONAL// Check first if CMD string is presentif (VoiceCommand.pCmd_Name != PL_NULL){PRINTF(" %s\r\n", VoiceCommand.pCmd_Name);}else{PRINTF("\r\n");}}}

3.3 语音识别天气信息

这里代码在weather_thread的while循环中,判断唤醒词与识别词,只有满足条件才建立socket连接,并且写API以及获取数据:
代码如下:

while(1)
{//add the command request, only cmd == weather flag, then call it.if((weather_data.ww_flag ==  1)){if(weather_data.vc_index >= 3){// create connection//write API and read APIWeather_process();}memset(weather_data.weather_info, 0, sizeof(weather_data.weather_info));weather_data.ww_flag = 0;weather_data.vc_index = 0;}vTaskDelay(10000);
}
void Weather_process(void)
{char * datap, *datap1;datap = strstr((char*)weather_data.weather_info,"date");if(datap != NULL){memcpy(today_weather, datap,184);//max 1457if(weather_data.vc_index == 3){PRINTF("\r\n*******************today weather***********************************\n\r");PRINTF("%s\r\n",today_weather);return;}}elsereturn;datap1 = strstr(datap+4,"date");if(datap1 != NULL){memcpy(tomorr_weather, datap1,184);//max 1457if(weather_data.vc_index == 4){PRINTF("\r\n*******************tomorrow weather*******************************\n\r");PRINTF("%s\r\n",tomorr_weather);return;}}elsereturn;datap = strstr(datap1+4,"date");if(datap != NULL){memcpy(aftertom_weather, datap,184);//max 1457if(weather_data.vc_index == 5){PRINTF("\r\n*******************after tomorrow weather**************************\n\r");PRINTF("%s\r\n",aftertom_weather);}}elsereturn;
}

其中Weather_process函数是根据语音识别的天气索引号,去提取对应的日期数据,并且打印出来。

四, 测试结果

测情况视频:

record

打印log结果如图11,经过测试,可以看到唤醒和识别词均能成功识别,在识别词序号为3,4,5也就是天气获取的时候,可以成功调用lwip socket client API,成功获取天气信息并且打印。
在这里插入图片描述

图11 系统测试打印结果

五, 问题总结

5.1 LWIP获取天气失败

在构建代码的时候,开始调用postman提供的http代码:

GET /v3/weather/weatherInfo?key=8f777fc7d867908eebbad7f96a13af10&amp; city=310000&amp; extensions=all&amp; output=JSON HTTP/1.1
Host: restapi.amap.com

添加到socket API函数中:

uint8_t get_weather[]= "GET /v3/weather/weatherInfo?key=xxx&amp;city=310000&amp;extensions=all&amp;output=JSON HTTP/1.1\r\nHost: restapi.amap.com\r\n\r\n\r\n\r\n";

调用结果总是出现下图:
在这里插入图片描述

图12 初测socket 天气API返回问题
可以看到,sever也连接了,http数据也返回了,就是出现参数错误的情况,最后检查下来,采用了postman C代码情况,构建数组如下:
uint8_t get_weather[]= "GET /v3/weather/weatherInfo?key=xxx&city=310000&extensions=all&output=JSON HTTP/1.1\r\nHost: restapi.amap.com\r\n\r\n\r\n\r\n";
然后能够成功获取天气数据,和postman一致。

5.2 VIT LWIP融合内存不足

在融合maestro_record和lwip socket代码之后,编译出现DTCM内存溢出问题。

在这里插入图片描述

图13 融合代码内存溢出
经过各种精简,还是会导致DTCM超出一点,最后选择重新配置flexRAM:
OCRAM 192K, DTCM 256K, ITCM 64K
再次编译,内存问题解决:
在这里插入图片描述

图14 flexRAM重配

5.3 中文打印

直接使用teraterm,当天气API返回有中文的时候,打印中文出乱码,后经过如下配置,实现中文的打印:
Setup -> Terminal
Locale : american->chinese
Codepage : 65001 ->936
在这里插入图片描述

图15 Tera Term中文打印
综上,经过各种资料收集,问题解决,最后在MIMXRT1060-EVK上结合官方SDK,完成了自定义VIT语音命令获取实时天气与本地控制的功能。说明,就算是普通的RT非S/L/A/F系列,也可以利用VIT实现语音识别功能。
代码包请到这个链接下载:
https://community.nxp.com/t5/i-MX-RT-Knowledge-Base/The-RT-speech-recognition-system-based-on-VIT-to-obtain-weather/ta-p/1513203

这篇关于基于VIT获取天气信息的RT语音识别系统的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1080572

相关文章

阿里开源语音识别SenseVoiceWindows环境部署

SenseVoice介绍 SenseVoice 专注于高精度多语言语音识别、情感辨识和音频事件检测多语言识别: 采用超过 40 万小时数据训练,支持超过 50 种语言,识别效果上优于 Whisper 模型。富文本识别:具备优秀的情感识别,能够在测试数据上达到和超过目前最佳情感识别模型的效果。支持声音事件检测能力,支持音乐、掌声、笑声、哭声、咳嗽、喷嚏等多种常见人机交互事件进行检测。高效推

让树莓派智能语音助手实现定时提醒功能

最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束对话,这样一来,chatbot定时提醒的触发就不会被语音助手获悉。那怎么让语音助手也具有定时提醒功能呢? 我最后选择的方法是用threading.Time

业务中14个需要进行A/B测试的时刻[信息图]

在本指南中,我们将全面了解有关 A/B测试 的所有内容。 我们将介绍不同类型的A/B测试,如何有效地规划和启动测试,如何评估测试是否成功,您应该关注哪些指标,多年来我们发现的常见错误等等。 什么是A/B测试? A/B测试(有时称为“分割测试”)是一种实验类型,其中您创建两种或多种内容变体——如登录页面、电子邮件或广告——并将它们显示给不同的受众群体,以查看哪一种效果最好。 本质上,A/B测

【北交大信息所AI-Max2】使用方法

BJTU信息所集群AI_MAX2使用方法 使用的前提是预约到相应的算力卡,拥有登录权限的账号密码,一般为导师组共用一个。 有浏览器、ssh工具就可以。 1.新建集群Terminal 浏览器登陆10.126.62.75 (如果是1集群把75改成66) 交互式开发 执行器选Terminal 密码随便设一个(需记住) 工作空间:私有数据、全部文件 加速器选GeForce_RTX_2080_Ti

AI(文生语音)-TTS 技术线路探索学习:从拼接式参数化方法到Tacotron端到端输出

AI(文生语音)-TTS 技术线路探索学习:从拼接式参数化方法到Tacotron端到端输出 在数字化时代,文本到语音(Text-to-Speech, TTS)技术已成为人机交互的关键桥梁,无论是为视障人士提供辅助阅读,还是为智能助手注入声音的灵魂,TTS 技术都扮演着至关重要的角色。从最初的拼接式方法到参数化技术,再到现今的深度学习解决方案,TTS 技术经历了一段长足的进步。这篇文章将带您穿越时

Android Environment 获取的路径问题

1. 以获取 /System 路径为例 /*** Return root of the "system" partition holding the core Android OS.* Always present and mounted read-only.*/public static @NonNull File getRootDirectory() {return DIR_ANDR

基于人工智能的智能家居语音控制系统

目录 引言项目背景环境准备 硬件要求软件安装与配置系统设计 系统架构关键技术代码示例 数据预处理模型训练模型预测应用场景结论 1. 引言 随着物联网(IoT)和人工智能技术的发展,智能家居语音控制系统已经成为现代家庭的一部分。通过语音控制设备,用户可以轻松实现对灯光、空调、门锁等家电的控制,提升生活的便捷性和舒适性。本文将介绍如何构建一个基于人工智能的智能家居语音控制系统,包括环境准备

JS和jQuery获取节点的兄弟,父级,子级元素

原文转自http://blog.csdn.net/duanshuyong/article/details/7562423 先说一下JS的获取方法,其要比JQUERY的方法麻烦很多,后面以JQUERY的方法作对比。 JS的方法会比JQUERY麻烦很多,主要则是因为FF浏览器,FF浏览器会把你的换行也当最DOM元素。 <div id="test"><div></div><div></div

Linux命令(11):系统信息查看命令

系统 # uname -a # 查看内核/操作系统/CPU信息# head -n 1 /etc/issue # 查看操作系统版本# cat /proc/cpuinfo # 查看CPU信息# hostname # 查看计算机名# lspci -tv # 列出所有PCI设备# lsusb -tv

vcpkg子包路径批量获取

获取vcpkg 子包的路径,并拼接为set(CMAKE_PREFIX_PATH “拼接路径” ) import osdef find_directories_with_subdirs(root_dir):# 构建根目录下的 "packages" 文件夹路径root_packages_dir = os.path.join(root_dir, "packages")# 如果 "packages"