最近和幾位本學院的研究生師兄師姐參加研究生電子設計大賽,自己也來折騰下之前沒有搞完的語音控制小車。恰巧自己負責的是語音控制這部分,折騰了幾天也差不多搞定啦…把自己的折騰套路總結一下,給一起折騰的小伙伴點經驗之談…
一、配置樹莓派
我們這次使用的最新的樹莓派3,鏡像直接是官網下載的Raspbian。這也是讓我感覺最有樹莓派感覺的一個系統。主要是sudo raspi-config的配置。
1和2最好都是設置一下,然后3看自己愛好吧;4的里面我都是重新設置的,包括時區、語言和字體。字體最好下載(apt-get install ttf-wqy-zenhei)。然后第八的那些串口、引腳的功能最好都打開
配置WiFi:樹莓派3是自帶WiFi的,所以啟動正常的話是可以直接連接的;如果沒有,就iwlist scan 掃描一下。
更新源:apt-get update,apt-get upgrade。
二、語音聊天和語音控制引腳。
引腳的控制方法很多的,python GPIO、wiringPi、BCM2835 C Library。
在這里我使用的是wiringPi(C語言);
安裝wiringPi:
1 sudo apt-get install git-core 2 git clone git://git.drogon.net/wiringPi 3 cd wiringPi 4 ./build
編輯腳本控制引腳電平高低:
首先創建個目錄:
1 cd ~ 2 mkdir scripts 3 cd scripts
然后編輯腳本light內容:
1 #!/bin/bash 2 if [ $# > 1 ] 3 then 4 /usr/local/bin/gpio mode 4 out 5 if [[ "$1" = "on" ]] 6 then 7 /usr/local/bin/gpio write 4 on 8 fi 9 10 if [[ "$1" = "off" ]] 11 then 12 /usr/local/bin/gpio write 4 off 13 fi 14 fi
這里的4對應的是樹莓派的引腳16(GEN 4),相關文檔大家可以自行查閱。
賦給腳本權限:
1 chmod u+x light
然后就可以檢驗是否可以通過命令行控制引腳啦…
1 ./light on 2 ./light off
下面就是通過語音來控制。我幾乎嘗試了可以用的所有的語音識別SDK,科大訊飛、百度語音、Google…事實證明Google是最棒的,但是對於我們牆內玩家是真的頭疼…
我最后采用的還是百度的API,因為個人喜歡python,恰好碰到一個百度的python開源程序。
直接上代碼:
1 -*- coding: utf-8 -*- 2 3 import numpy as np 4 from datetime import datetime 5 import wave 6 import time 7 import urllib, urllib2, pycurl 8 import base64 9 import json 10 import os 11 import sys 12 reload(sys) 13 sys.setdefaultencoding( "utf-8" ) 14 15 save_count = 0 16 save_buffer = [] 17 t = 0 18 sum = 0 19 time_flag = 0 20 flag_num = 0 21 filename = 'asr.wav' 22 duihua = '1' 23 24 def getHtml(url): 25 page = urllib.urlopen(url) 26 html = page.read() 27 return html 28 29 def get_token(): 30 apiKey = "Ll0c53MSac6GBOtpg22ZSGAU" 31 secretKey = "44c8af396038a24e34936227d4a19dc2" 32 auth_url = "https://openapi.baidu.com/oauth/2.0/token?grant_type=client_credentials&client_id=" + apiKey + "&client_secret=" + secretKey; 33 res = urllib2.urlopen(auth_url) 34 json_data = res.read() 35 return json.loads(json_data)['access_token'] 36 37 def dump_res(buf): 38 global duihua 39 print "字符串類型" 40 print (buf) 41 a = eval(buf) 42 print type(a) 43 if a['err_msg']=='success.': 44 #print a['result'][0]#終於搞定了,在這里可以輸出,返回的語句 45 duihua = a['result'][0] 46 print duihua 47 48 def use_cloud(token): 49 fp = wave.open(filename, 'rb') 50 nf = fp.getnframes() 51 f_len = nf * 2 52 audio_data = fp.readframes(nf) 53 cuid = "7519663" #產品id 54 srv_url = 'http://vop.baidu.com/server_api' + '?cuid=' + cuid + '&token=' + token 55 http_header = [ 56 'Content-Type: audio/pcm; rate=8000', 57 'Content-Length: %d' % f_len 58 ] 59 60 c = pycurl.Curl() 61 c.setopt(pycurl.URL, str(srv_url)) #curl doesn't support unicode 62 #c.setopt(c.RETURNTRANSFER, 1) 63 c.setopt(c.HTTPHEADER, http_header) #must be list, not dict 64 c.setopt(c.POST, 1) 65 c.setopt(c.CONNECTTIMEOUT, 30) 66 c.setopt(c.TIMEOUT, 30) 67 c.setopt(c.WRITEFUNCTION, dump_res) 68 c.setopt(c.POSTFIELDS, audio_data) 69 c.setopt(c.POSTFIELDSIZE, f_len) 70 c.perform() #pycurl.perform() has no return val 71 72 # 將data中的數據保存到名為filename的WAV文件中 73 def save_wave_file(filename, data): 74 wf = wave.open(filename, 'wb') 75 wf.setnchannels(1) 76 wf.setsampwidth(2) 77 wf.setframerate(SAMPLING_RATE) 78 wf.writeframes("".join(data)) 79 wf.close() 80 81 token = get_token() 82 key = '05ba411481c8cfa61b91124ef7389767' 83 api = 'http://www.tuling123.com/openapi/api?key=' + key + '&info=' 84 85 while(True): 86 os.system('arecord -D "plughw:1,0" -f S16_LE -d 5 -r 8000 /home/pi/Desktop/2016-6-25/asr.wav') 87 use_cloud(token) 88 print duihua 89 info = duihua 90 duihua = "" 91 request = api + info 92 response = getHtml(request) 93 dic_json = json.loads(response) 94 95 a = dic_json['text'] 96 print type(a) 97 unicodestring = a 98 99 # 將Unicode轉化為普通Python字符串:"encode" 100 utf8string = unicodestring.encode("utf-8") 101 102 print type(utf8string) 103 print str(a) 104 url = "http://tsn.baidu.com/text2audio?tex="+dic_json['text']+"&lan=zh&per=0&pit=1&spd=7&cuid=8297904&ctp=1&tok=24.9ae6d50d24d1c222c4019be4c70613e7.2592000.1469358913.282335-8297904" 105 os.system('mplayer "%s"'%(url))
這是網上大神自己給樹莓派自己寫的Python腳本,然后我自己修改的如下可以實現語音控制引腳開燈和關燈。
1 # -*- coding: utf-8 -*- 2 3 import numpy as np 4 from datetime import datetime 5 import wave 6 import time 7 import urllib, urllib2, pycurl 8 import base64 9 import json 10 import os 11 import sys 12 reload(sys) 13 sys.setdefaultencoding( "utf-8" ) 14 15 save_count = 0 16 save_buffer = [] 17 t = 0 18 sum = 0 19 time_flag = 0 20 flag_num = 0 21 filename = 'asr.wav' 22 commun = '1' 23 answer = '1' 24 def getHtml(url): 25 page = urllib.urlopen(url) 26 html = page.read() 27 return html 28 29 def get_token(): 30 apiKey = "Ll0c53MSac6GBOtpg22ZSGAU" 31 secretKey = "44c8af396038a24e34936227d4a19dc2" 32 auth_url = "https://openapi.baidu.com/oauth/2.0/token?grant_type=client_credentials&client_id=" + apiKey + "&client_secret=" + secretKey; 33 res = urllib2.urlopen(auth_url) 34 json_data = res.read() 35 return json.loads(json_data)['access_token'] 36 37 def dump_res(buf): 38 global duihua 39 print "字符串類型" 40 print (buf) 41 a = eval(buf) 42 print type(a) 43 if a['err_msg']=='success.': 44 commun = a['result'][0] 45 print duihua 46 47 def use_cloud(token): 48 fp = wave.open(filename, 'rb') 49 nf = fp.getnframes() 50 f_len = nf * 2 51 audio_data = fp.readframes(nf) 52 cuid = "7519663" #產品id 53 srv_url = 'http://vop.baidu.com/server_api' + '?cuid=' + cuid + '&token=' + token 54 http_header = [ 55 'Content-Type: audio/pcm; rate=8000', 56 'Content-Length: %d' % f_len 57 ] 58 59 c = pycurl.Curl() 60 c.setopt(pycurl.URL, str(srv_url)) #curl doesn't support unicode 61 #c.setopt(c.RETURNTRANSFER, 1) 62 c.setopt(c.HTTPHEADER, http_header) #must be list, not dict 63 c.setopt(c.POST, 1) 64 c.setopt(c.CONNECTTIMEOUT, 30) 65 c.setopt(c.TIMEOUT, 30) 66 c.setopt(c.WRITEFUNCTION, dump_res) 67 c.setopt(c.POSTFIELDS, audio_data) 68 c.setopt(c.POSTFIELDSIZE, f_len) 69 c.perform() #pycurl.perform() has no return val 70 71 # 將data中的數據保存到名為filename的WAV文件中 72 def save_wave_file(filename, data): 73 wf = wave.open(filename, 'wb') 74 wf.setnchannels(1) 75 wf.setsampwidth(2) 76 wf.setframerate(SAMPLING_RATE) 77 wf.writeframes("".join(data)) 78 wf.close() 79 83 84 while(True): 85 os.system('arecord -D "plughw:1,0" -f S16_LE -d3 -r 8000 /home/pi/Desktop/2016-6-25/asr.wav') 86 use_cloud(token) 87 print commun 88 site = commun89 if "開" in site: #在返回的文本里尋找“開” 90 answer = '好的,正在為您開燈,請稍后' 91 url = "http://tsn.baidu.com/text2audio?tex="+answer+"&lan=zh&per=0&pit=1&spd=7&cuid=8297904&ctp=1&tok=24.9ae6d50d24d1c222c4019be4c70613e7.2592000.1469358913.282335-8297904" 92 os.system('mplayer "%s"'%(url)) 93 os.system('cd /home/pi/Desktop/scripts&&./light on') 94 if "關" in site: 95 answer = '好的,正在為您關燈,請稍后' 96 url = "http://tsn.baidu.com/text2audio?tex="+answer+"&lan=zh&per=0&pit=1&spd=7&cuid=8297904&ctp=1&tok=24.9ae6d50d24d1c222c4019be4c70613e7.2592000.1469358913.282335-8297904" 97 os.system('mplayer "%s"'%(url)) 98 os.system('cd /home/pi/Desktop/scripts&&./light off
下面給大家一個現場演示視頻。
http://v.youku.com/v_show/id_XMTYyMzIxMDc5Ng==.html
參考文章:
http://www.xiaopeiqing.com/posts/2337.html;(中大一位名為xieshundao博士師兄的貼,非常感謝師兄的幫助和人教誨…)
http://blog.csdn.net/haven200/article/details/50659499;
http://computers.tutsplus.com/articles/how-to-control-a-lamp-with-voice-commands-and-a-raspberry-pi--mac-60825;
http://www.urlteam.org/2016/05/python%E8%AF%AD%E9%9F%B3%E6%99%BA%E8%83%BD%E5%AF%B9%E8%AF%9D%E8%81%8A%E5%A4%A9%E6%9C%BA%E5%99%A8%E4%BA%BA%EF%BC%8Clinux%E6%A0%91%E8%8E%93%E6%B4%BE%E5%8F%8C%E5%B9%B3%E5%8F%B0%E5%85%BC%E5%AE%B9/;
http://blog.csdn.net/happen23/article/details/45821697;
http://www.modified.systems/archives/tag/voicecommand;
23:26:422016-06-27