绿林网页 发表于 2012-10-14 00:03:29

利用pc语音识别通过串口语音控制电路

本帖最后由 绿林网页 于 2012-10-14 10:50 编辑

这是另一种语音控制,它不需要语音控制电路板,而是利用win7系统自带的语音识别功能,用上位机通过串口发送指令给Arduino,从而控制电路做相应动作
看图:
电脑 麦克 Arduino板子 发光二极管


在上位机上可以设置语音指令,对着电脑麦克风,说出语音指令,Arduino就会执行对应的指令,控制发光二极管的 点亮 熄灭 闪烁
http://www.56.com/u22/v_NzUxMzk0Mjc.html
微博地址:
http://weibo.com/1785094373/z0liAirpA
很容易扩展更多的指令来完成一些声控功能!

yimenwang 发表于 2012-10-14 10:40:44

好东西,楼主是否介意开源一下呢,大家也好学习一下.哈哈

绿林网页 发表于 2012-10-14 11:55:33

yimenwang 发表于 2012-10-14 10:40 static/image/common/back.gif
好东西,楼主是否介意开源一下呢,大家也好学习一下.哈哈

当然可以,我还在测试中,先发上来大家一起研究吧

ttyp 发表于 2012-10-14 11:59:18

嗯,想法不错,目前手机上的读书语音功能都是利用电脑网络,arduino处理不了的东西发给电脑到是一个不错的方案:lol

绿林网页 发表于 2012-10-14 12:00:29

接线图就不需要了吧,哈很简单
直接上代码吧

上位机:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;

namespace pc
{
    public partial class Form1 : Form
    {
      private StringBuilder builder = new StringBuilder();
      private SerialPort comm = new SerialPort();
      private string[] commarr = null;
      private int commmaxlen = 0;
      public Form1()
      {
            InitializeComponent();
      }

      private void SerialInit()
      {
            string[] ports = SerialPort.GetPortNames();
            Array.Sort(ports);
            comboPortName.Items.AddRange(ports);
            comboPortName.SelectedIndex = comboPortName.Items.Count > 0 ? 0 : -1;
            comboBaudrate.SelectedIndex = comboBaudrate.Items.IndexOf("9600");
            comm.RtsEnable = true;
            comm.DataReceived += comm_DataReceived;
      }
      void comm_DataReceived(object sender, SerialDataReceivedEventArgs e)
      {
            int n = comm.BytesToRead;
            byte[] buf = new byte;
            comm.Read(buf, 0, n);
            builder.Remove(0, builder.Length);
            builder.Append(Encoding.ASCII.GetString(buf));
            this.Invoke((EventHandler)(delegate
            {
                txGet.AppendText(builder.ToString());
                txGet.ScrollToCaret();
            }));
      }
      private void buttonSend_Click(object sender, EventArgs e)
      {
            if (comm.IsOpen)
            {
                int n = 0;
                txGet.AppendText("-->" + txSend.Text + "\r\n");
                txGet.ScrollToCaret();
                if (newline_cb.Checked)
                {
                  comm.Write(txSend.Text + "\r\n");
                }
                else
                {
                  comm.Write(txSend.Text);
                }
                n = txSend.Text.Length;
                txSend.Clear();
            }
            else
            {
                MessageBox.Show("请先打开端口");
            }
      }

      private void buttonOpenClose_Click(object sender, EventArgs e)
      {
            if (comm.IsOpen)
            {
                comm.Close();
            }
            else
            {
                commarr = comm_tb.Lines;
                if (commarr.Length == 0) { MessageBox.Show("请先设置语音指令"); return; }
                foreach (string tstr in commarr)
                {
                  if (tstr.IndexOf('@') > commmaxlen) commmaxlen = tstr.IndexOf('@');
                }
                try
                {
                  comm.PortName = comboPortName.Text;
                  comm.BaudRate = int.Parse(comboBaudrate.Text);
                  comm.Open();
                }
                catch (Exception ex)
                {
                  comm = new SerialPort();
                  MessageBox.Show(ex.Message);
                  return;
                }
            }
            buttonOpenClose.Text = comm.IsOpen ? "关闭" : "打开";
      }

      private void Form1_Load(object sender, EventArgs e)
      {
            SerialInit();
            timer1.Enabled = true;
      }

      private void Form1_FormClosing(object sender, FormClosingEventArgs e)
      {
            if (comm.IsOpen)
            {
                comm.Close();
            }
      }

      private void timer1_Tick(object sender, EventArgs e)
      {
            if (comm.IsOpen)
            {
                portstatus_lbl.Text = "已连接...";
                portstatus_lbl.ForeColor = Color.Blue;
                txSend.Focus();
            }
            else
            {
                portstatus_lbl.Text = "未连接";
                portstatus_lbl.ForeColor = Color.Red;
            }
            //movesend();
      }

      private void txSend_TextChanged(object sender, EventArgs e)
      {
            if (comm.IsOpen)
            {
                string commstr = txSend.Text.Trim();
                if (string.IsNullOrEmpty(commstr)) return;
                if (commarr.Length == 0) { MessageBox.Show("请先设置语音指令"); return; }
                commstr = commstr + "@";
                string sendtxt = "";
                foreach (string tstr in commarr)
                {
                  if (tstr.StartsWith(commstr))
                  {
                        sendtxt = tstr.Replace(commstr, "").Trim();
                        break;
                  }
                }
                if (sendtxt.Length>0)
                {
                  comm.Write(sendtxt);// + "\r\n"
                  txGet.AppendText("-->" + sendtxt + "\r\n");
                  txGet.ScrollToCaret();                  
                  sendtxt = "";
                  txSend.Clear();
                }
                else
                {   
                  if (commstr.Length-1 > commmaxlen)
                  {
                        txSend.Clear();
                  }
                }                                                                                                                                             
            }
            else
            {
                MessageBox.Show("请先打开端口");
            }
      }

      private void comm_tb_TextChanged(object sender, EventArgs e)
      {
            commarr = comm_tb.Lines;
            foreach (string tstr in commarr)
            {
                if (tstr.IndexOf('@') - 1 > commmaxlen) commmaxlen = tstr.IndexOf('@') - 1;
            }
         }
    }
}


Arduino代码
String sdata="";
String mode="out";
void setup()
{
Serial.begin(9600);
pinMode(12,OUTPUT);
digitalWrite(12,LOW);
Serial.println("start...");
}

void loop()
{
while (Serial.available() > 0)
{
    sdata += char(Serial.read());
    delay(2);
}
if(sdata.length()>0)
{
    mode=sdata;       
    sdata="";
    Serial.print(">--");
    Serial.println(mode);
}
modeshow();
}
void modeshow()
{
if(mode=="light")
{
    digitalWrite(12,HIGH);
}
else if(mode=="blink")
{
    digitalWrite(12,HIGH);
    delay(100);
    digitalWrite(12,LOW);
    delay(100);
}
else if(mode=="out")
{
    digitalWrite(12,LOW);
}
}





在控制面板里,打开win7的语音识别功能,就可以啦,右边编辑框里输入好语音指令就可以测试了。

ttyp 发表于 2012-10-14 12:05:32

使用电脑mic收集资料的啊,我还以为你有板子收集语音发给电脑处理呢,电脑应该只做处理的工作,数据采集应该交给前端arduino

绿林网页 发表于 2012-10-14 14:16:27

ttyp 发表于 2012-10-14 12:05 static/image/common/back.gif
使用电脑mic收集资料的啊,我还以为你有板子收集语音发给电脑处理呢,电脑应该只做处理的工作,数据采集应该 ...

是的啊,就是为了省去语音板子,要是用语音板子,不用PC也可以直接实现控制呀

沧海笑1122 发表于 2012-10-15 09:46:09

这是一个很有价值的尝试,支持楼主。
关于语音识别板子,它有特定的使用场合,那就是互动玩具,或者对体积、便携性有要求的场合,但是正因为其迷你,所以功能和PC上位机+arduino是有差别的。
所以,两个方向都应该尝试,适用于不同用途,有交叉但并不大。

ttyp 发表于 2012-10-15 10:29:18

绿林网页 发表于 2012-10-14 14:16 static/image/common/back.gif
是的啊,就是为了省去语音板子,要是用语音板子,不用PC也可以直接实现控制呀

我的意思是你现在的麦克风只能接到电脑上,而电脑基本是固定的不能移动,我是想最好接在arduino上,用一块简单的声音采集板子(不带分析功能,只要录音就行),采集到声音上传给电脑分析,然后发出指令给arduino,这样麦克风就可以移动了,电脑甚至可以是部署在公网的服务器,只要保留接口就可以了

ttyp 发表于 2012-10-15 10:33:12

这样的好处是把界面层和底层分离了,pc就像一个云,方便部署,实用性强

绿林网页 发表于 2012-10-15 14:15:29

ttyp 发表于 2012-10-15 10:33 static/image/common/back.gif
这样的好处是把界面层和底层分离了,pc就像一个云,方便部署,实用性强

最好是通过把无线麦克风发射端安装到Arduino的设备上,麦克风接收端插入电脑,实现单独的无线控制音频传输,就和无线视频一样,不能直接借助arduino来传输视频!

wasdpkj 发表于 2012-12-2 17:22:20

上位机可以共享出来吗?光有代码不够吧

兔巴哥 发表于 2013-2-23 20:18:06

楼主,问一下上机位怎么搞啊,是什么意思啊 ,小白求教。。。。

florgx 发表于 2013-2-25 17:56:54

这个帖子精湛啊!我喜欢:lol

瘦网虫 发表于 2013-2-26 09:47:54

不错!现在android和iphone里面都有语音识别软件,今后扩展的话,可以考虑。
页: [1] 2
查看完整版本: 利用pc语音识别通过串口语音控制电路