对讲机联动模块开发(树莓派文字转语音模块对接)

阅读: 评论:0

对讲机联动模块开发(树莓派文字转语音模块对接)

对讲机联动模块开发(树莓派文字转语音模块对接)

最近公司方面有个业务需求,因为我们做的是智慧社区项目,有一块涉及到车辆异常出库报警,比如车辆被盗是。 这时候如何能快速的通知到安保人员呢?原来想法是给安保人员配一台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 = Element();                //通过标识符得到串口名字,并判断这个名字是不是我们需要的那个串口                if (Name().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 = Bytes( "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 (EventType()) {                 //这些属性应该跟串口特性有关,我还没搞清楚,暂时不解释              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( "串口初始化失败!" );           }      } }
芯片的开发指南 .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

本文发布于:2024-02-03 07:45:19,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170691751949624.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:模块   对讲机   语音   文字   树莓派
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23