本文主要是介绍对讲机联动模块开发(树莓派文字转语音模块对接),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
最近公司方面有个业务需求,因为我们做的是智慧社区项目,有一块涉及到车辆异常出库报警,比如车辆被盗是。
这时候如何能快速的通知到安保人员呢?原来想法是给安保人员配一台PAD,或者在手机上安装个APP,但这样也有很大的弊端。而安保人员人人必备对讲机,所以考虑能不能和对讲机联动。
自然就想到了TTS(TextToSpeech),之前和小i、科大讯飞、华声捷通都用过合作,对这块业务还算比较熟悉,本来打算在树莓派上直接内置一个TTS应用就行了,但这三家都没有免费的SDK,收费的还挺贵,所以这个想法基本就放弃了,但就在最后一刻,发现科大讯飞竟然有TTS芯片!!!
XFS5152CE,科大讯飞中英文语音合成芯片,淘宝搜了一下,竟然发现了做好的模块,一个是科大讯飞自己做的(98元),还有一个是基于SYN6288芯片做的(57元),于是都买回来测试了一下,SYN6288跟XFS5152CE一比简直就是扔货,所以这里就不说关于SYN6288的开发了,如果有时间的话,可以单独做一篇。
废话到此为止,干货在下面!
首先需要准备几样东西
一对对讲机、一条手咪线、一块TTS模块,另外,我还开了一块底板,一会做介绍。
先说TTS模块的对接方式
根据XFS5152CE的开发文档,我们用到RXD、TXD、GND、V3.3、RDY四个引脚,当TTS有语音输出的时候RDY会输出高电平,这块一会我们用来控制手台的信道占用(就是我们手动按下呼叫按钮),严重说一下,这里用的电压是3.3V的,因为后面我们控制继电器的时候用的是5V的,这里千万表混了,要不然98块钱就会化作一缕青烟……
先用TTS模块做测试,科大讯飞也提供测试程序了,我们只要把模块用串口线接到电脑上(TTL电平),用他们的软件测试就行了,还没有做下一步和对讲机联动的,先用个耳机试试声音。
当然那我们这里肯定还是要写程序的。
而且仍然用的是JAVA和RXTX做,如果不清楚树莓派上怎么调试的,出门左转,有一篇专门介绍树莓派3配置串口的文章。
直接上代码
package com.marssoft.jyphon;
import gnu.io.CommPortIdentifier;
import gnu.io.PortInUseException;
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;
import gnu.io.UnsupportedCommOperationException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.TooManyListenersException;
/**
* 科大讯飞XFS5152CE芯片语音合成测试程序。
* @author Mars.CN
*
*/
public class TTS {
public static final byte STATE_IDLE =0X4F; //空闲状态
public static final byte STATE_USE =0X4E; //占用中状态
public static final byte STATE_INITED = 0X4A; //初始化成功
public static final byte STATE_SUCCESS = 0X41; //正确的命令帧
public static final byte STATE_ERROR = 0X45; //错误的命令帧
public static final byte STATE_NULL = 0X00; //设备空
public static final byte COMMAND_QUERY_STATE = 0X21; //查询状态命令
public static final byte COMMAND_POWER_MODE_SAVING =( byte )0X88; //设置为省点模式
public static final byte COMMAND_POWER_MODE_USEING =( byte )0XFF; //设置为唤醒模式
public static final byte COMMAND_TTS =0X01; //语音合成命令
public static final byte COMMAND_STOP =0X02; //停止语音合成
public static final byte COMMAND_SUSPEND =0X03; //暂停合成
public static final byte COMMAND_RECOVERY =0X04; //回复合成
private SerialPort port = null ;
private InputStream in = null ;
private OutputStream out = null ;
private TTS() {}
/**
* 初始化串口。
* @param name
*/
private TTS(String name) {
//获得本地所有串口列表,这里其实只能获得ttyS开头的串口
Enumeration<CommPortIdentifier> portList = CommPortIdentifier.getPortIdentifiers();
while (portList.hasMoreElements()){
//获得串口的标识符
CommPortIdentifier portId = portList.nextElement();
//通过标识符得到串口名字,并判断这个名字是不是我们需要的那个串口
if (portId.getName().equals( "/dev/" +name)){
SerialPort p= null ;
try {
//如果确实是我们需要的串口,则打开这个串口
//open(串口占用进程名称,串口等待超时时间)
p = (SerialPort) portId.open( "TTSTest" , 2000);
//给串口一个数据到达侦听(触发器)
p.addEventListener( new EventListener());
//把数据到达通知打开
p.notifyOnDataAvailable( true );
//设置串口的波特率,参数依次是(波特率,数据位,停止位,校验位)
p.setSerialPortParams(9600,SerialPort. DATABITS_8 , SerialPort. STOPBITS_1 ,SerialPort. PARITY_NONE );
//获得输入输出流,方便操作。
out = p.getOutputStream();
in = p.getInputStream();
port =p;
} catch (PortInUseException e) {
e.printStackTrace();
} catch (TooManyListenersException e) {
e.printStackTrace();
} catch (UnsupportedCommOperationException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 打开串口
*
* @param port
*/
public static final TTS open(String name) {
TTS serial = new TTS(name);
if (serial. port != null ){
return serial;
}
return null ;
}
/**
* 发送数据。
* @param data
*/
public void send( byte [] data){
try {
out .write(data);
out .flush();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 播放信息
* @param msg
*/
public byte play(String msg){
if ( port != null ){
try {
//把文字内容转换成GB2312编码的二进制数据(我记得硬件里用的都是GBK,如果有问题的话大家用GBK试试看)
byte [] mdata = msg.getBytes( "GB2312" );
//根据语音合成指令,协议头三个字节,分别是帧头0XFD,数据长度高字节,数据长度低字节,语音合成命令0X01,编码类型0X00(GB2312),后面是数据
byte [] datas = new byte [5+mdata. length ];
datas[0]=( byte )0xFD;
datas[1]=( byte )((datas. length -3)/256);
datas[2]=( byte )((datas. length -3)%256);
datas[3]= COMMAND_TTS ;
System.arraycopy(mdata, 0, datas, 5, mdata. length );
// System.out.println(HexFormat.format(datas));
//发送开始合成
out .write(datas);
return STATE_SUCCESS ;
} catch (IOException e) {
e.printStackTrace();
return STATE_ERROR ;
}
}
return STATE_NULL ;
}
/**
* 关闭串口。
*/
public void close(){
//当然,这里可以做一下事件侦听,再给close加个参数,这样在串口异常报错的时候能能捕获到了。
port .close();
port = null ; out = null ; in = null ;
}
private class EventListener implements SerialPortEventListener{
@Override
public void serialEvent(SerialPortEvent event) {
switch (event.getEventType()) {
//这些属性应该跟串口特性有关,我还没搞清楚,暂时不解释
case SerialPortEvent. BI :
case SerialPortEvent. OE :
case SerialPortEvent. FE :
case SerialPortEvent. PE :
case SerialPortEvent. CD :
case SerialPortEvent. CTS :
case SerialPortEvent. DSR :
case SerialPortEvent. RI :
case SerialPortEvent. OUTPUT_BUFFER_EMPTY :
break ;
case SerialPortEvent. DATA_AVAILABLE : //获取到串口返回信息
int d = 0;
do {
try {
//读取一个串口返回之,并判断这个返回值是什么状态。
d = in .read();
switch (d){
case STATE_INITED :
System. out .println( "初始化成功" );
break ;
case STATE_SUCCESS :
System. out .println( "命令正确" );
break ;
case STATE_ERROR :
System. out .println( "命令错误" );
break ;
case STATE_IDLE :
System. out .println( "设备空闲" );
break ;
case STATE_USE :
System. out .println( "语音合成中" );
break ;
}
} catch (IOException e){
return ;
}
}
while (d != -1);
System. out .println( "退出关闭" );
close(); //这里一定要用close()方法关闭串口,释放资源
break ;
default :
break ;
}
}
}
/**
* 测试语音
* @param args
*/
public static void main(String[] args) {
TTS tts = TTS.open( "S45" );
if (tts!= null ){
//发送测试语音
tts.play( "sound 101 你好世界 Hello world" );
} else {
System. out .println( "串口初始化失败!" );
}
}
}
芯片的开发指南
http://www.iflytek.com/upload/contents/2014/07/53be5e3ec4047.pdf
具体其他语音合成的方式,大家可以去参考一下开发文档,包括一些提示音的设置。
现在语音已经可以正常合成了,现在我们看如何做成一个和对讲机联动的成品。
和对讲机联动,用到了RDY引脚,当语音播放的时候,RDY引脚处于高电平,这时候我们给这个引脚加一个继电器,高电平是继电器导通,这样就把手咪线正负极导通了,也就相当于我们手动按下了对讲键,手咪线有四根,按我这个版本,黄色的是PPT(按键),红色的是MIC+,绿色的是负极,蓝色的是耳机线,直接按照这样接线就行了。
为此,我做了一块底板,上面有个继电器,再把讯飞的TTS模块焊上去,左边留下串口接口,右边留下手咪线的接口。
需要注意的是,对讲机的驱动用5V,讯飞TTS模块驱动用3.3V,正好树莓派就提供者两种电压输出,所以在树莓派一段,留的是RX、TX、GND、Vcc5V、Vcc3.3V五个口,依次对应GPIO14(8)、GPIO15(10)、GND(6)、5V(4)、3V(1),不明白的可以度娘一个树莓派3的GPIO图看看。
注意接线的时候,TX对应树莓派的RX,RX对应树莓派的TX
这篇关于对讲机联动模块开发(树莓派文字转语音模块对接)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!