前言
前面学习了树莓派的串口通信,本节将树莓派和语音模块结合起来,二者通过串口通信实现语音识别功能。 具体就是语音模块将识别到的指令进行处理发送给树莓派,树莓派根据接收到的指令,执行不同的语句,执行不同的操作。比如控制不同的继电器,从而实现打开和关闭不同灯光的操作。
一、语音识别模块介绍
本次开发用到的语音模块是淘宝购买的,型号为:YS-LDV7 ①本模块实际原理为 1 片 STC11 单片机+1 片 LD3320 组合形成的一款语音识别模块, 语音识别部分已写好驱动程序, 用于只需要对 STC 单片机进行编程加入自己的识别语句和控制程序即可。模块内部通信为SPI接口,对外通信为串口。 ②语音识别模块可以接STM32、ARDUINO、STC单片机、树莓派吗? 答:可以,模块对外是串口通信。只要有串口的设备都可以对接。具体的串口接收程序要看你接的硬件了,需要自己写对应的串口接收程序。 ③有很多人在STC-ISP中找不到STC11L08XE,它就在STC11L60XE系列中。先找到STC11L60XE系列然后选STC11L08XE。 ④keil打开源代码的时候会报下面的错误,不用理会。
二、语音识别模块的二次开发
本次开发是在LD3320模块提供的源代码基础上进行的二次开发。在开发前,需要将源代码读一遍,理清源代码的逻辑关系,在此基础上才能进行代码的修改,进行二次开发。
源代码大概流程:
void ExtInt0Handler(void) interrupt 0
nAsrRes = LD_GetResult();
User_handle(nAsrRes);
main
Led_test();
MCU_init();
LD_Reset();
UartIni();
while(1){
RunASR();
LD_AsrStart();
LD_Init_ASR();
LD_AsrAddFixed();
LD_AsrRun();
ProcessInt0()
}
- LD_AsrAddFixed(); 向LD模块添加关键词 在LDchip.c
- 识别出结果后,把数据从语音模块发出来!void User_handle(uint8 dat) main
1. 重点代码修改部分
理顺整个源代码的执行流程之后,不难理解,可进行二次开发的地方,也就是代码修改部分: ①语音识别口令 ②识别码 ③识别结果串口输出
2. 二次开发部分
理顺整个源代码的执行流程之后,不难理解,可进行二次开发的地方,也就是代码修改部分: ①修改词条
②识别码修改 ③修改语音识别串口输出结果
三、语音模块结合继电器组控制所有灯
二次开发的过程如上所述,包含有家居各种灯的语音控制口令。比如客厅灯、卧室灯、餐厅灯和二楼灯。
1. 接线
首先是接线,前面已经介绍,语音识别模块与外部模块如51、32、树莓派等通信是采用串口通信,串口通信是全双工的,但在这里,不需要将通信的两根线都接上,因为语音识别的结果直接发送到树莓派上,树莓派根据由于该结果(也就是指令)去实现不同的动作,但是树莓派不需要向语音模块发送数据,也就是说二者只需单项数据传输。
2. 树莓派程序
结合树莓派外设开发基础—wiringPi库和树莓派外设开发基础—串口通信。我们来编写树莓派程序,实现语音识别控制各种灯,也就是语音识别控制继电器组。
#include <stdio.h>
#include <string.h>
#include <wiringPi.h>
#include <wiringSerial.h>
#include <unistd.h>
#include <stdlib.h>
#define SWITCH1 21
#define SWITCH2 22
#define SWITCH3 23
#define SWITCH4 24
int initwiringPiSetup()
{
if (wiringPiSetup() == -1)
{
printf("init error\n");
exit(-1);
}
}
void initPin()
{
pinMode(SWITCH1,OUTPUT);
pinMode(SWITCH2,OUTPUT);
pinMode(SWITCH3,OUTPUT);
pinMode(SWITCH4,OUTPUT);
digitalWrite(SWITCH1,HIGH);
digitalWrite(SWITCH2,HIGH);
digitalWrite(SWITCH3,HIGH);
digitalWrite(SWITCH4,HIGH);
}
int main()
{
int fd;
int n_read;
char cmd[128]={'\0'};
initwiringPiSetup();
initPin();
fd = serialOpen("/dev/ttyAMA0",9600);
while(1)
{
n_read = read(fd,cmd,sizeof(cmd));
if(strlen(cmd)==0)
{
printf("overtime...\n");
continue;
}
if(strstr(cmd,"KKTD") != NULL)
{
digitalWrite(SWITCH1,LOW);
printf("ke ting deng yi da kai\n");
}
if(strstr(cmd,"GKTD") != NULL)
{
digitalWrite(SWITCH1,HIGH);
printf("ke ting deng yi guan bi\n");
}
if(strstr(cmd,"KWSD") != NULL)
{
digitalWrite(SWITCH2,LOW);
}
if(strstr(cmd,"GWSD") != NULL)
{
digitalWrite(SWITCH2,HIGH);
}
if(strstr(cmd,"KCTD") != NULL)
{
digitalWrite(SWITCH3,LOW);
}
if(strstr(cmd,"GCTD") != NULL)
{
digitalWrite(SWITCH3,HIGH);
}
if(strstr(cmd,"KELD") != NULL)
{
digitalWrite(SWITCH4,LOW);
}
if(strstr(cmd,"GELD") != NULL)
{
digitalWrite(SWITCH4,HIGH);
}
if(strstr(cmd,"KQBD") != NULL)
{
digitalWrite(SWITCH1,LOW);
digitalWrite(SWITCH2,LOW);
digitalWrite(SWITCH3,LOW);
digitalWrite(SWITCH4,LOW);
}
if(strstr(cmd,"GQBD") != NULL)
{
digitalWrite(SWITCH1,HIGH);
digitalWrite(SWITCH2,HIGH);
digitalWrite(SWITCH3,HIGH);
digitalWrite(SWITCH4,HIGH);
}
memset(cmd,'\0',sizeof(cmd)/sizeof(char));
}
return 0;
}
代码还是比较简单,并成功实现了语音指令操作继电器
疑问: 语音模块通过串口传输过来的数据是"KKTD"、"GKTD"等这些字符串,但当我用语句:
if(strcmp(cmd,"KKTD") == 0)
{
digitalWrite(SWITCH1,LOW);
printf("ke ting deng yi da kai\n");
}
if(strcmp(cmd,"GKTD") == 0)
{
digitalWrite(SWITCH1,HIGH);
printf("ke ting deng yi guan bi\n");
}
使用strcmp()函数时,根本无法使继电器动作,也没有调试信息输出,显然语音模块通过串口传输失败。必须要用 strstr() 函数才行,不知道为什么。
|