树莓派小车·能跑能语音控制制作过程分享
coshep 发布于2017-12 浏览:12478 回复:12
2
收藏

一、所需材料/工具

  • 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好,哈哈,这些话题我从不参与,只要是能满足需求解决需求的东西,就是好东西。

欢迎大家批评指正,共同学习进步,未来二十年,不被智械淘汰。

收藏
点赞
2
个赞
共12条回复 最后由用户已被禁言回复于2022-04
#13smile19973回复于2021-01

我想做一个可以实现语音控制的智能小车,但是代码一直改不好,python基础太差,想找大佬帮助完成代码,报酬合理要求就行,可以帮助一下我吗?微信(电话)18749442710,感谢

0
#12wenwu0623回复于2020-11

怎么卖?

0
#11那是·谁回复于2020-11

做的真不错啊,可以留一个联系方式吗想和您深入交流一下。

0
#10幻风Magic_wind回复于2018-10
#9 zb68218回复
楼主的makePCM()函数中把wav使用FFmpeg转换成pcm ,我尝试了很多次都失败,后来直接使用 arecord命令录音成pcm格式,省去 了转换格式这一步骤。(树莓派安装FFmpeg费了我好长时间)
展开

arecord命令录音成pcm格式是怎么使用的?能说一下吗?

 

0
#9zb68218回复于2018-03

楼主的makePCM()函数中把wav使用FFmpeg转换成pcm ,我尝试了很多次都失败,后来直接使用 arecord命令录音成pcm格式,省去 了转换格式这一步骤。(树莓派安装FFmpeg费了我好长时间)

0
#8daipeng_hi回复于2018-01

而且还是全能型的

0
#7daipeng_hi回复于2018-01

我去,高科技人才

0
#6goJhou回复于2018-01

不错很棒!

 

我觉得用树莓派不大好做更精细的IO控制了,精度不够,容易被别的更高优先级的系统任务打断掉~个人感受

0
#5shoranxfyzhy回复于2017-12

真好,厉害,点赞!

0
#4txlang21回复于2017-12

赞!

0
#3用户已被禁言回复于2017-12

很不错。这不应该被百度ai采访吗

1
#2coshep回复于2017-12

噢!复查了一下,上面的是测试语音控制的代码,避障的那部分代码被删了忘了加入,下面补上:

        rightDistance = int( getRightDistance() )
        leftDistance = int( getLeftDistance() )
        
        print 'Right Distance:%0.2f cm' % getRightDistance()
        print 'Left Distance:%0.2f cm' % getLeftDistance()

        if rightDistance > 80 and leftDistance > 80 :
            forword()
        if rightDistance < 50 or leftDistance < 50 :
            reverse()
	    print 'back'
	    time.sleep(3)
            turnRight()
            print 'turn right'
            
        time.sleep(1)

就加在“前进”里。

(疑?上面的代码,为什么没有缩进?print 'back' 和 time.sleep(3) 要缩进四格,系统调不过来竟然)

1
TOP
切换版块