一、所需材料/工具
- Raspberry Pi 3
- L298N电机驱动板
- 带套的小电机马达四个
- 四个直径五厘米的小轮子
- 一个USB声音输出转换器
- 一个USB麦克风
- 一对USB小喇叭
- 一个双USB口10000毫安充电宝
- 两个超声波传感器
- 杜邦线公对母/母对母总40根左右
- PVC材质9毫米厚模型板一个
- 小电钻一个
- 电烙铁、尖嘴钳,剥线钳,斜嘴钳,小号梅花口螺丝刀,美工刀,铅笔,尺子各一个
- 扎带25厘米长30根
- 一个无线路由器和一根网线
- 键盘鼠标显示器
- 树莓派摄像头
- 小舵机
二、制作过程简述
选用了长40厘米宽30厘米的PVC材质板,用美工刀就可以很方便的切割出各种形状。其实不用搞什么造型,直接一块白板的用也行,只是太呆板,影响制作心情,所以还是切了点样子出来。
上面是初始设计的版本,计划采用两个L298N驱动板来分别驱动两个电机,就像下面这样的
后来发现,只需要一个就够了,还能省电。于是改进之后就变成了这样。
把红外感应器放在了车底盘下面,两个超声波传感器就绑在车头,用来避障。硬件组装的这个过程,也就是切割底盘,规划位置,用小电钻打洞,然后再用扎带绑起来,大家一看就能明白。这里需要特别说明的是用电烙铁焊接马达线,以及剥线钳的使用。
我是新手,第一次用电烙铁,按照网上的视频来做,可是网上发视频的老兄都是熟练手,太快了,有些过程还是没有看清。最后就自己琢磨着搞,发现只要把锡线放在要焊接的位置处,用加热完全的电烙铁尖尖凑过去,那个锡线就融化在电烙铁上面了,再把那个小水滴一样的锡点到小马达和电线的捆绑处,基本点上去3秒就凝固了。用同样方法,把所有小马达和电线都焊接好。再用电源测试四个小马达能否正常转动,能转就说明没问题。
其实不用电烙铁也行的,只要把电线在小马达的铜片上紧紧的绕几道,再用钳子压一压,不会脱落就行。
连接好小马达,就要做个USB电源接线口,一端插充电宝,一端插L298N电机驱动板。随便找来根不用的USB线,用剥线钳卡擦剪断,然后剥线,去了外皮后就能看到红黑绿白四根线,把绿白剪断,用不到,那是传输数据的,只要红色正极线和黑色负极线。再用剥线钳剥掉外壳,露出丝就行,到这步就算制作好了。
三、线路连接
线路连接就是用杜邦线,如果长度不够,可以一段插一段的连接过来的,没问题,随便插。
这里要一提的是,L298N驱动板的12V接口接电源正极红线,GND负极接黑线。还有一个5v接口不用接任何线。
树莓派上的40个针脚接线关系如下图所示
其实大家可以随便选针脚的,我标注出来的那些淡蓝色接口,具备一些特殊功能,但如果你不启用的话,它们也还是和绿色的那些接口一样可以随便用。
四、驱动代码
首先安装百度语音sdk,我是下载来,进入到文件夹里面,用下面命令安装的
pi@raspberrypi:~/voiceAction/aip-python-sdk $ sudo python setup.py install
全部驱动的代码如下所示
# -*- coding: utf-8 -*-
#下载安装完百度sdk后,在aip文件夹旁边新建此py文件
from aip import AipSpeech
#准备调用树莓派GPIO接口
import RPi.GPIO as GPIO
#可以在python中执行Linux命令行
import os
import time
import json
#使用BCM方式来调用树莓派针脚
GPIO.setmode(GPIO.BCM)
#录音为wav格式音频文件,然后转换为pcm格式
def makePCM():
#录音,"plughw:1,0"表示从USB话筒设备录音,这句命令最终录制完的格式就是百度要求的16k音质
os.system('sudo arecord -D "plughw:1,0" -f S16_LE -d 3 -r 16000 voiceAction.wav')
print '完成3秒录音'
#用ffmpeg方法转换格式
os.system('sudo ffmpeg -y -i voiceAction.wav -acodec pcm_s16le -f s16le -ac 1 -ar 16000 voiceAction.pcm')
print '完成pcm转换'
#读取本地音频文件
def get_file_content(filePath):
with open(filePath, 'rb') as fp:
return fp.read()
#获取语音识别结果
def getVoiceText():
makePCM()
#初始化 API KEY,SECRET KEY,APP ID
#这些值需要在http://ai.baidu.com注册账号,登录后在百度云管理中心可以找到
apiKey = 'u28sdeEjg68HUnIIyYOURS1K'
secretKey = 'beqrz96VO7y7xjA38NiWn32HhntEm3GT'
appID = '10557187'
#调用百度sdk文件的AipSpeech方法进行token验证
client = AipSpeech(appID,apiKey,secretKey)
if os.path.exists('voiceAction.pcm'):
#上传voiceAction.pcm文件到百度服务器进行语音识别
result = client.asr(get_file_content('voiceAction.pcm'), 'pcm', 16000, {
'lan': 'zh',
})
#用json方式返回数据
json_result = json.dumps(result)
strtestObj = json.loads(json_result)
try:
#得到语音识别后的结果
lists = strtestObj["result"]
print lists[0]
return lists[0]
except KeyError:
return False
else:
return False
#初始化超声波传感器使用到的树莓派针脚
Trig_Pin_right = 23
Echo_Pin_right = 24
Trig_Pin_left = 17
Echo_Pin_left = 27
#右超声波传感器针脚,输出电频
GPIO.setup(Trig_Pin_right, GPIO.OUT)
#右超声波传感器针脚,接收信号
GPIO.setup(Echo_Pin_right, GPIO.IN)
#左超声波传感器针脚,输出电频
GPIO.setup(Trig_Pin_left, GPIO.OUT)
#左超声波传感器针脚,接收信号
GPIO.setup(Echo_Pin_left, GPIO.IN)
#初始化小车四个电机和轮子所使用的针脚
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(60)
move_right_2.start(0)
move_left_3.start(60)
move_left_4.start(0)
#把输出频率设置为60%让小车慢慢跑,因为百度语音识别需要上传到服务器然后再回传到本地
#大概耗时3秒左右,跑太快的话小车可能来不及完成指令就撞墙,虽然有超声波避障。
def reverse():
#让小车后退
move_right_1.start(0)
move_right_2.start(100)
move_left_3.start(0)
move_left_4.start(100)
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.stop()
move_right_2.stop()
move_left_3.stop()
move_left_4.stop()
def getRightDistance():
#右超声波传感器获取距离
GPIO.output(Trig_Pin_right, GPIO.LOW)
time.sleep(0.002)
GPIO.output(Trig_Pin_right, GPIO.HIGH)
time.sleep(0.00001)
GPIO.output(Trig_Pin_right, GPIO.LOW)
while GPIO.input(Echo_Pin_right)==0:
pass
t1 = time.time()
while GPIO.input(Echo_Pin_right)==1:
pass
t2 = time.time()
return (t2-t1)*340*100/2
def getLeftDistance():
#左超声波传感器获取距离
GPIO.output(Trig_Pin_left, GPIO.LOW)
time.sleep(0.002)
GPIO.output(Trig_Pin_left, GPIO.HIGH)
time.sleep(0.00001)
GPIO.output(Trig_Pin_left, GPIO.LOW)
while GPIO.input(Echo_Pin_left)==0:
pass
t1 = time.time()
while GPIO.input(Echo_Pin_left)==1:
pass
t2 = time.time()
return (t2-t1)*340*100/2
try:
while True:
print '开始录音'
makePCM()
print '结束录音和转换'
if getVoiceText() == u'前进,' :
forword()
if getVoiceText() == u'后退,' :
reverse()
if getVoiceText() == u'左转弯,' :
turnLeft()
if getVoiceText() == u'右转弯,' :
turnRight()
if getVoiceText() == u'停下,':
stop()
except KeyboardInterrupt:
GPIO.cleanup()
不包含驱动红外感应器和舵机的代码,为什么?先暂时搁置,因为计划中要完成语音控制和对话后再做进一步优化,加入图像识别跟随这些东西。但百度语音的离线版不支持树莓派,所以正在想办法找替代或解决的方案。
至少到这一步,已经可以让树莓派小车跑起来并且用语音也能控制了,如果忽略百度语音在线识别平均8秒的反馈时间的话,到这一步就能欢快的玩耍了。
总结
在做此树莓派小车之前,我是某运营商技术部人员,后来辞职做了2年卖泰国货的电商,负责仓库管理和市场运营,基本不碰代码了,偶尔用PHP、javascript这些维护下自己的Wordpress小博客。完成此小车共耗时累计33天,无论是硬件还是python算是入门了。所以入门难度并不大。
总的硬件开销大概800左右.当然如果算上MacBook Air 2017的话还得加6000元,把以前的15款15寸顶配pro卖了后买的Air。之前我还兼职做视频,用pro真是爽,现在不做了,就需要高电量好手感易携带的稳定电脑,所以换Air。
题外话
究竟是python好还是go好,PHP棒还是java神,windows好还是Linux好,MacBook Air好还是pro好,哈哈,这些话题我从不参与,只要是能满足需求解决需求的东西,就是好东西。
欢迎大家批评指正,共同学习进步,未来二十年,不被智械淘汰。
我想做一个可以实现语音控制的智能小车,但是代码一直改不好,python基础太差,想找大佬帮助完成代码,报酬合理要求就行,可以帮助一下我吗?微信(电话)18749442710,感谢
怎么卖?
做的真不错啊,可以留一个联系方式吗想和您深入交流一下。
arecord命令录音成pcm格式是怎么使用的?能说一下吗?
楼主的makePCM()函数中把wav使用FFmpeg转换成pcm ,我尝试了很多次都失败,后来直接使用 arecord命令录音成pcm格式,省去 了转换格式这一步骤。(树莓派安装FFmpeg费了我好长时间)
而且还是全能型的
我去,高科技人才
不错很棒!
我觉得用树莓派不大好做更精细的IO控制了,精度不够,容易被别的更高优先级的系统任务打断掉~个人感受
真好,厉害,点赞!
赞!
很不错。这不应该被百度ai采访吗
噢!复查了一下,上面的是测试语音控制的代码,避障的那部分代码被删了忘了加入,下面补上:
就加在“前进”里。
(疑?上面的代码,为什么没有缩进?print 'back' 和 time.sleep(3) 要缩进四格,系统调不过来竟然)