常持正念方圆梦;不忘初心总是春。 智能桌面天气预报系统(一)
智能桌面天气预报系统(二) 智能桌面天气预报系统(三)
智能桌面天气预报系统(四)
这是关于这个智能天气预报系统的最后一篇分享啦。本系统源码下载链接见文末 本系统人机对话功能采用了两个硬件模块:(1)语音识别模块:采用LD3320语音识别芯片;(2)语音合成模块:采用SYN6288语音合成芯片。 本系统语音识别模块采用的语音芯片是LD3320。该芯片已经集成了语音识别的处理器,不需要外接其他的辅助芯片如Flash、 RAM 等,直接嵌入在现有的产品中就可以实现语音识别的功能。 语音识别的过程为: (1)先预存要识别的关键词,如: //-------------------------搜索天气----------------------------------- #define STR00 "xiao tian" // 小天 #define STR01 "sou suo fu zhou tian qi" // 搜索福州天气 #define STR02 "sou suo shang hai tian qi" // 搜索上海天气 #define STR03 "sou suo shen zhen tian qi" // 搜索深圳天气 #define STR04 "sou suo bei jing tian qi" // 搜索北京天气 #define STR05 "sou suo guang zhou tian qi" // 搜索广州天气 #define STR06 "sou suo nan ning tian qi" // 搜索南宁天气 #define STR07 "sou suo xia men tian qi" // 搜索厦门天气 #define STR08 "sou suo quan zhou tian qi" // 搜索泉州天气 #define STR09 "sou suo pu tian tian qi" // 搜索莆田天气 #define STR10 "sou suo nan ping tian qi" // 搜索南平天气 可以预存50条关键词(关键句),小编已经把关键词写死在程序里了,这显然就不能灵活的面对各种场景。其实可以通过代码编写一个学习功能,即识别之前首先进行学习一些即将要识别的关键词,然后在进行识别演示,这样就可以应对比较多的场景。 但是,这样还是不够智能,毕竟只能识别已经预存的关键词(关键句),要是没有预存就没办法识别了。所以真正的语音识别应该是在软件算法上下功夫,关于语音识别已然成为热门的一大研究专题,这属于人工智能的范畴。 (2)开始识别,如: static void Task_ASR(void) { switch(nAsrStatus) { case LD_ASR_RUNING: case LD_ASR_ERROR: break; case LD_ASR_NONE: nAsrStatus=LD_ASR_RUNING; if (RunASR()==0) // 启动一次ASR识别流程:ASR初始化,ASR添加关键词语,启动ASR运算 { nAsrStatus = LD_ASR_ERROR; } break;
case LD_ASR_FOUNDOK: nAsrRes = LD_GetResult( ); // 一次ASR识别流程结束,去取ASR识别结果 ASRSuccess_Handle(nAsrRes); nAsrStatus = LD_ASR_NONE; break; case LD_ASR_FOUNDZERO: default: nAsrStatus = LD_ASR_NONE; break; } } nAsrStatus是用来表示语音识别的状态,不是LD3320芯片内部的状态寄存器。nAsrStatus有几种情况。我们比较关注的是LD_ASR_FOUNDOK状态。LD_ASR_FOUNDOK状态为识别成功,识别成功后将调用“ASRSuccess_Handle”函数进行识别后的操作。 (3)识别成功则执行相应操作,如 void ASRSuccess_Handle(uint8 asr_code) { printf("\r\n识别码:%d\n",asr_code); if(0 == asr_code) { printf("我在,需要我的帮助吗?\n"); TTSPlay(0, "[t3][2]我在,[2]需要[2]我的[3]帮助吗"); RunFlag = TRUE; } else if(RunFlag) { RunFlag = FALSE; /* 识别码0-10为搜索天气识别码 */ if(asr_code>=0&&asr_code<=10) { switch(asr_code) { case CODE01: printf("“福州”命令识别成功\r\n"); TTSPlay(0, "[t3][2]小天正在为您搜索福州天气"); memcpy(g_city,"fujianfuzhou",sizeof(g_place)); break; case CODE02: printf("“上海”命令识别成功\r\n"); TTSPlay(0, "[t3][2]小天正在为您搜索上海天气"); memcpy(g_city,"shanghai",sizeof(g_place)); break; case CODE03: printf("“深圳”命令识别成功\r\n"); TTSPlay(0, "[t3][2]小天正在为您搜索深圳天气"); memcpy(g_city,"shenzhen",sizeof(g_place)); break; case CODE04: printf("“北京”命令识别成功\r\n"); TTSPlay(0, "[t3][2]小天正在为您搜索北京天气"); memcpy(g_city,"beijing",sizeof(g_place)); break; case CODE05: printf("“广州”命令识别成功\r\n"); TTSPlay(0, "[t3][2]小天正在为您搜索广州天气"); memcpy(g_city,"guangzhou",sizeof(g_place)); break; case CODE06: printf("“南宁”命令识别成功\r\n"); TTSPlay(0, "[t3][2]小天正在为您搜索南宁天气"); memcpy(g_city,"nanning",sizeof(g_place)); break; case CODE07: printf("“厦门”命令识别成功\r\n"); TTSPlay(0, "[t3][2]小天正在为您搜索厦门天气"); memcpy(g_city,"xiamen",sizeof(g_place)); break; case CODE08: printf("“泉州”命令识别成功\r\n"); TTSPlay(0, "[t3][2]小天正在为您搜索泉州天气"); memcpy(g_city,"quanzhou",sizeof(g_place)); break; case CODE09: printf("“莆田”命令识别成功\r\n"); TTSPlay(0, "[t3][2]小天正在为您搜索莆田天气"); memcpy(g_city,"putian",sizeof(g_place)); break; case CODE10: printf("“南平”命令识别成功\r\n"); TTSPlay(0, "[t3][2]小天正在为您搜索南平天气"); memcpy(g_city,"nanping",sizeof(g_place)); break; } memset(&weather_data, 0, sizeof(weather_data)); GET_NowWeather(); GET_DailyWeather(); GetWeatherTimer = TIMER1_HOUR; DisplayWeather(weather_data); DisplayWeatherIcon(weather_data); } else { switch(asr_code) { case CODE11: printf("“语音播报天气”命令识别成功\r\n"); printf("%s\n",g_WeatherText); // TTSPlay(0, (uint8_t*)g_WeatherText); break; case CODE12: printf("“今天的气温是多少”命令识别成功\r\n"); break; default: TTSPlay(0, "语音识别失败,请对准麦克风说话!"); break; } } } } 设计识别码0为一级指令码,当一级指令码识别成功后,才能进行二级指令地识别。语音识别成功后,会调用“TTSPlay”函数播报所设定的语音,这样每一次地识别与播报就可以达到了一种人机互动的效果。 本系统的语音合成模块采用SYN6288语音合成芯片,支持文本直接转化为语音。其与单片机的通信方式为串口通信。向该模块发送以下格式的数据包: 5字节帧头+文本+1字节校验,文本字节数小于等于200字节
即可合成语音。代码如: void TTSPlay(uint8_t Music,uint8_t *Text) { /****************需要发送的文本**********************************/ uint8_t DataPacket[50]; // uint8_t Text_Len; uint8_t ecc = 0; //定义校验字节 uint8_t i=0; Text_Len =strlen((const char*)Text); //需要发送文本的长度
/*****************帧固定配置信息**************************************/ DataPacket[0] = 0xFD ; //构造帧头FD DataPacket[1] = 0x00 ; //构造数据区长度的高字节 DataPacket[2] = Text_Len + 3; //构造数据区长度的低字节 DataPacket[3] = 0x01 ; //构造命令字:合成播放命令 DataPacket[4] = 0x01 | Music<<4 ; //构造命令参数:背景音乐设定
/*******************校验码计算***************************************/ for(i = 0; i<5; i++) //依次发送构造好的5个帧头字节 { ecc=ecc^(DataPacket[i]); //对发送的字节进行异或校验 }
for(i= 0; i<Text_Len; i++) //依次发送待合成的文本数据 { ecc=ecc^(Text[i]); //对发送的字节进行异或校验 } /*******************发送帧信息***************************************/ memcpy(&DataPacket[5], Text, Text_Len); DataPacket[5+Text_Len]=ecc; UART4_SendStr((char*)DataPacket,5+Text_Len+1); } 调用方式如: TTSPlay(0, "[t3][2]小天正在为您搜索福州天气");
|