先生们女士们,我又回来了,还是我。上一次用了REST API把百度语音搞到树莓派上,但是识别的过程太慢了,大概8秒多,所以这次换成了android手机输入语音,在联通4G网络下,速度大概是3秒。还算不错的,下面是主要实现过程。
需要用到的东西如上图所示,一个手机,一个装有树莓派的小车,和一个电脑。此项目的运行原理以及主要代码如所示。
主要原理如上图所示,下面分三步来解决实现。
1、无线局域网
手机,小车和大电脑三个设备都是处于同一无线局域网内,你可以使用一个无线路由器或者手机热点来创建这个网络。
我推荐使用手机热点方式,这样就可以不受地域限制,拿着小车电脑到户外玩。对未来后期的扩展很有用,比如太阳能供电,物体人像辨别这些可能会添加的功能。
2、手机端代码
本文采用的是百度语音的最简代码来运行,这部分的代码已经在本站的下面文章做过较详细的讲解
《Android * 使用Android Studio运行百度语音的Hello World精简版》地址:
http://endback.com/2018/01/24/raspberry-pi-使用android手机语音控制树莓派小车/
如果没有看过上文的读者,请先到那边看一下。如果已经看过的读者,请直接来看重点。我们只需要把上文里提到的MainActivity.java代码里先添加一个函数:sendCommand(……),具体代码如下:
private void sendCommand(final String host, final int port, final String data) {
Thread thread = new Thread() {
@Override
public void run() {
try {
Socket socket = new Socket(host, port);
OutputStream outputStream = socket.getOutputStream();
outputStream.write((data).getBytes());
outputStream.flush();
System.out.println(socket);
InputStream is = socket.getInputStream();
byte[] bytes = new byte[1024];
int n = is.read(bytes);
System.out.println(new String(bytes, 0, n));
Handler handler = new Handler();
Message msg = handler.obtainMessage(0x124, new String(bytes, 0, n));
msg.sendToTarget();
is.close();
socket.close();
} catch (Exception e) {}
}
};
thread.start();
}
然后再在回调函数:public void onEvent(……) 里找到这句代码“txtResult.append(recogs[i]);”我们在这个代码的下面添加上面这个新建函数:
@Override
public void onEvent(String name, String params, byte[] data, int offset, int length) {
String logTxt = "name: " + name;
if (params != null && !params.isEmpty()) {
logTxt += " ;params :" + params;
try {
JSONObject json = new JSONObject(params);
if (name.equals(SpeechConstant.CALLBACK_EVENT_ASR_PARTIAL) && json.getString("result_type").equals("final_result")) {
//txtLog.append("final test::" + "\n" + json.getString("result_type"));
JSONArray arr = json.optJSONArray("results_recognition");
if (arr != null) {
int size = arr.length();
String[] recogs = new String[size];
for (int i = 0; i < size; i++) {
recogs[i] = arr.getString(i);
txtResult.append(recogs[i]);
////////添加到这里
sendCommand("192.168.43.57",18888,recogs[i]);
////////添加到这里
}
}
}
}catch (JSONException e) {
e.printStackTrace();
}
}
if (name.equals(SpeechConstant.CALLBACK_EVENT_ASR_PARTIAL)) {
if (params.contains("\"nlu_result\"")) {
if (length > 0 && data.length > 0) {
logTxt += ", 语义解析结果:" + new String(data, offset, length);
}
}
} else if (data != null) {
logTxt += " ;data length=" + data.length;
}
printLog(logTxt);
}
上面这个函数,第一个参数“192.168.43.57”就是服务器端的IP地址,第二个参数“18888”是端口号,自己设定的,你可以随便设定为88888或者99999什么的。第三个“recogs[i]”就是语音识别得到的最终结果。
设定好这一步之后,就可以先用android studio编译运行到手机上看看,只要运行成功,你可以先试着说话,不影响后续步骤。
3、服务器端代码
无线网弄好后,我们进入树莓派小电脑里设置无线网。先给树莓派小电脑插上鼠标键盘显示器,我安装的系统是带有图形界面的那个版本。本来我装的是没有图形界面的那个版本,但后来总是奔溃,很奇怪,还以为是sd卡的问题,但后来重装成图形界面版本以后就不会奔溃了。暂时无解。不管,先打开终端输入以下命令:
pi@raspberrypi:~ $ ifconfig
注意,这一步我是在把树莓派安装固定到小车上之前就完成了。得到IP地址,最后就可以把鼠标键盘显示器拔了。然后再在大电脑上通过SSH方式远程登录到树莓派小电脑上。
r0ck:~$ ssh 192.168.43.57 -l pi
上面的IP就是手机自动分配给树莓派小电脑的。登录进去以后,新建一个名为goSpeech.py的python文件并执行:
pi@raspberrypi:~/raspSpeech $ sudo nano goSpeech.py
输入以下服务器端的代码:
# -*- coding: utf-8 -*-
from socket import *
from time import ctime
#准备调用树莓派GPIO接口
import RPi.GPIO as GPIO
#可以在python中执行Linux命令行
import os
import time
import json
#使用BCM方式来调用树莓派针脚
GPIO.setmode(GPIO.BCM)
#初始化树莓派的IP地址和端口
#准备从安卓手机客户端发送消息
HOST = '192.168.43.57'
PORT = 18888
BUFSIZ = 1024
ADDR = (HOST, PORT)
#初始化小车四个电机和轮子所使用的针脚
right_IN1 = 20
right_IN2 = 21
left_IN3 = 19
left_IN4 = 26
#全部设置为电频输出
GPIO.setup(right_IN1,GPIO.OUT)
GPIO.setup(right_IN2,GPIO.OUT)
GPIO.setup(left_IN3,GPIO.OUT)
GPIO.setup(left_IN4,GPIO.OUT)
#频率都设置为100%
move_right_1 = GPIO.PWM(right_IN1,100)
move_right_2 = GPIO.PWM(right_IN2,100)
move_left_3 = GPIO.PWM(left_IN3,100)
move_left_4 = GPIO.PWM(left_IN4,100)
#开始启动时都设为0%
move_right_1.start(0)
move_right_2.start(0)
move_left_3.start(0)
move_left_4.start(0)
def forword():
#让小车前进
move_right_1.start(70)
move_right_2.start(0)
move_left_3.start(70)
move_left_4.start(0)
def reverse():
#让小车后退
move_right_1.start(0)
move_right_2.start(70)
move_left_3.start(0)
move_left_4.start(70)
def turnLeft():
#让小车左转弯
move_right_1.start(100)
move_right_2.start(0)
move_left_3.start(30)
move_left_4.start(0)
def turnRight():
#让小车右转
move_right_1.start(30)
move_right_2.start(0)
move_left_3.start(100)
move_left_4.start(0)
def stop():
#小车停止
move_right_1.start(0)
move_right_2.start(0)
move_left_3.start(0)
move_left_4.start(0)
try:
while True:
tcpSerSock = socket(AF_INET, SOCK_STREAM)
tcpSerSock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
tcpSerSock.bind(ADDR)
tcpSerSock.listen(5)
print '服务器运行中...'
tcpCliSock, addr = tcpSerSock.accept()
print '已连接地址:', addr
data = tcpCliSock.recv(BUFSIZ)
if not data:
break
tcpCliSock.send('get your data:%s\n[%s]' % (data, ctime()))
print data
tcpSerSock.close
if data == '前进' :
print "接收到前进指令"
forword()
print "正在执行前进指令"
if data == '后退' :
reverse()
if data == '左转' :
turnLeft()
if data == '右转' :
turnRight()
if data == '停下':
stop()
except KeyboardInterrupt:
GPIO.cleanup()
这个代码一旦运行后,就会随时等着接收来自android手机的消息,然后通过接收到的消息来进行GPIO的输出,从而控制小车行动。如下:
pi@raspberrypi:~/raspSpeech $ sudo python goSpeech.py
服务器运行中...
4、运行
此时,你可以通过安卓手机发出指令,然后服务器端收到消息后,在大电脑终端上会显示下面消息:
pi@raspberrypi:~/raspSpeech $ sudo python goSpeech.py
服务器运行中...
已连接地址: ('192.168.43.219', 45007)
开始
接收到前进指令
正在执行前进指令
服务器运行中...
已连接地址: ('192.168.43.219', 38276)
后腿
服务器运行中...
已连接地址: ('192.168.43.219', 53038)
后退
......
到了这一步,就可以拿着个手机控制小车玩啦,耶耶~
上海
http://xasgkfp.diytrade.com/
https://xasgkfp.diytrade.com/
http://cdfapiao.simplesite.com/
http://xakfp.simplesite.com/
赞一个
我想做一个可以实现语音控制的智能小车,但是代码一直改不好,python基础太差,想找大佬帮助完成代码,报酬合理要求就行,可以帮助一下我吗?微信(电话)18749442710,感谢
你好
wow, 这个有意思~~~~电机控制是使用了什么现成的组件吗?