使用树莓派制作智能小车

智能小车演示视频

摘要:该项目我会开源,大家一起参与进来,对智能小车进行完善。一定要牢记树莓派的GPIO引脚不能输入大于3.3V的电压,否则树莓派变砖。

智能小车实现的功能

  • 超声波测距
  • 四路红外避障
  • 检测周围环境的湿度
  • 检测周围环境的温度
  • 监控及拍照
  • 与人的交互,语音控制

1.智能小车概述

由于制作的初衷是送给我一岁多的闺女当作玩具的,所以给小车起名字叫--洋洋,闺女属羊的,就用了谐音。先欣赏一下智能小车的容貌


使用树莓派制作智能小车_第1张图片
来张侧面图

使用树莓派制作智能小车_第2张图片
来张正面图

2.树莓派简介

智能小车的大脑是一块信用卡大小的树莓派板子,所以DIY冲动的朋友可以到各大商城购买一块最新版的树莓派,铛铛铛铛:


使用树莓派制作智能小车_第3张图片
树莓派第三代张这个样子——正面照

简单介绍:

  • Micro-USB Power--电源插槽
  • CPU
  • 四个USB接口
  • 一个HDMI接口
  • 一个耳机插孔,也可以输出视频
  • 40个GPIO引脚
  • 一个SD卡插槽,没有硬盘
  • 一个网线插口,自带无线网卡
  • 树莓派相机插槽

所有具体接口如何使用,详细讲解的话会使该篇文章显得拖沓,放在其它篇幅讲解,目前不懂没关系,不影响到我们制作智能小车。跟着我一步步的进入探索之旅吧。

  • Micro-USB Power,树莓派供电接口

1.电源适配器 5V 2A

使用树莓派制作智能小车_第4张图片
IMG_20170527_193957

2.移动电源 输出5V 2.1A

注意:Pi没有板载稳压芯片,只能且必须用5V的电源给Pi供电。如果电压过大,Pi会永久“变砖”,等着流泪吧!

3.智能小车底盘的制作

  • 3.1车轮的选择

有车轱辘才称得上车。
车轱辘的选择真是太多了,到各大商城上搜索,五花八门,看的真是眼花缭乱。根据个人喜好选择车轮的外围尺寸,有人习惯大轮子,看起来酷酷蛮拉风,当然大轮子重量上比较重,导致还要给它配上一副功率相对大的电机。
我比较喜欢大一点的轮子,因为以后还要在此基础上添加很多的传感器:
超声波传感器测距离,感应前方多少米有人。
温度传感器测量周围环境的温度;
湿度传感器测量周围环境的湿度;
红外传感器测量前后左右方是否接近物体;
等一系列的传感器。所以平台会比较大一点,基于大的轮子构建平台比较合适。在你的大脑里是否构建出一副你自己喜欢的小车模型呢。是否迫不及待想动手制作属于你自己的玩具或者传感器站呢!
我选择的车轱辘:


使用树莓派制作智能小车_第5张图片
车轮外侧
使用树莓派制作智能小车_第6张图片
车轮内侧

外围尺寸:6.5CM
车轮宽度:2.6Cm
孔径(上面右图所示):六边形(边长7mm, 对边到对边是12mm)
选择配套的六角联轴器链接车轮(圆柱内孔径:5mm):


使用树莓派制作智能小车_第7张图片
六角联轴器图一
使用树莓派制作智能小车_第8张图片
六角联轴器图二
使用树莓派制作智能小车_第9张图片
链接六角联轴器与车轮的螺丝

六角联轴器与车轮链接起来后的样子:
使用树莓派制作智能小车_第10张图片
图片发自App

到此,车轱辘部分组装完成。
  • 3.2电机的选择

上文也提到,想让小车自己动起来,那就少不了驱动小车前进的电机。电机选择也不那么容易,能提供足够的力量的同时不能太贵,手头碎银不多嘛,其次最好跟六角联轴器配套,电机的轴径匹配六角联轴器的内径,这样安装起来省很多麻烦。由于六角联轴器的孔径为5mm,选择电机时,我们首当其冲的就是电机对外突出的轴的直径也为5mm,这样直接插入到六角联轴器孔中,再次用小螺丝(购买六角联轴器时会提供,并没有展示固定用的小螺丝)固定一下就完成电机与轮子的组装。
我选择的电机的轴径为4mm,第一次制作没有考虑那么多,不过有六角联轴器有固定螺丝,可以很好的把电机轴跟六角联轴器固定在一起。


使用树莓派制作智能小车_第11张图片
370直流电机

电机规格说明:3v -33转/分钟 6V - 133转/分钟 12V - 258转/分钟

我们不着急把电机跟车轱辘固定在一起,因为还缺少一个电机的固定座。固定座的作用把电机固定在小车的透明亚克力板(俗称塑料板)。
选择电机固定座,商城中搜索“电机座”,寻找符合我们条件的电机座。电机座上的小孔径一方面负责与亚克力版固定在一起,另一方面负责与电机固定在一起。选择小孔孔径为3mm大小,这个很重要,因为电机前端固定孔直径为3mm。
需要注意的细节太多了,一环扣一环,环环相扣,而且在北京,基本没有DIY的五金店,DIY全都是南方的企业在做,而且北方并没有代理商,只能网上购买。
制作过程中,杜邦线(就是细细的电线,制作成两头方便插拔的)不够了,到一个大型的建材批发城,被人一脸鄙视加不屑的“轰”了出来,无奈。
如果你嫌麻烦,或者动手能力差的话,那么就购买成品的玩具小车底盘(含有马达的那种更省事)。

电机电源

12V电池

使用树莓派制作智能小车_第12张图片
IMG_20170525_171800
  • 3.3智能小车车体的制作

挑来挑去,选择了如下的电机座(每个小孔径直径3mm),不配备螺丝与螺帽,更没有垫片,说到垫片不得不说六角联轴器,也是没有配备垫片的,一个小小的垫片折射出了国内的工业标准跟某些回家还是有差距的距离的。

使用树莓派制作智能小车_第13张图片
电机固定座
电机固定座(¥4.5)一个小小的铁片竟然值这个价格,如果你有条件的话很容易制作出来的,不必花这冤枉钱,我没有电钻,没办法钻孔。
既然没有配备螺丝,那我们还要购买3mm的螺丝及3mm的螺帽,我也是第一次知道购买螺丝只是螺丝并没有螺帽,螺帽还得花钱购买。我第一次买回来后,傻眼了并么有螺帽,抓狂~~~这样网购的事情来来回回还几次,真是隔行如隔山啊,不亲身体验事情的原本,根本没有身临其境的感受。
3mm的螺丝,3mm的螺帽,3mm的垫片。一切就绪,开始组装。等等,哪里不对劲,安装在哪里呢,还缺少一个亚克力板(俗称塑料板)作为小车的载体。开始选择小车板吧,根据自己的喜好,我选择了:透明200 3003mm规格的板子。
我购买的板子是没有钻孔的,需要自己想办法钻孔,这里推荐你购买已经钻过孔的小车板子,注意一点的是孔的直径大小为3mm,需要固定电机座,孔之间的距离跟电机座上面的孔距离一直,否则也是没有用的。
钻孔的过程是极其手疼的,因为我没有电钻。所以对于喜欢DIY的朋友来说,一把电钻是必不可少的工具。
1.把四个电机固定座固定在亚克力板上(
2.把小车后面两个轮子固定在车上,由于我们制作的是两后驱动小车,所以把电机固定在后面的电机座上,把车轮固定在电机轴上。
3.固定前面两个轮子。
前面两个车轮如何固定呢?
我的做法不是最好的,因为之前选车轮子时决定了我现在必须按照如下步骤安装车轮子:
首先我们需要两个轴承,两根直径5mm长度8cm的两根小钢棍当作小车的前轴(我们称之为A,B轴,方便下文描述),与左右车轮相连接。
想办法把两个轴承通过电机座固定在小车板上,因为车轮上安装轴承有相当大的困难,我试图寻找解决方案,结果放弃了。
然后再分别把A,B轴固定在两个轴承上,固定好以后。就可以分别在A,B轴上安装车轮了,安装起来相对简单。
到此,智能小车的底盘制作完成。来个全景图:
使用树莓派制作智能小车_第14张图片
智能小车底盘完整图

4.链接电机和控制器

控制器的选择标准

我们制作的两驱智能小车,使用的直流电机370。

电机规格说明:3V -33转/分钟 6V - 133转/分钟 12V - 258转/分钟

电机驱动器输出电压不能低于3V,否则电机不工作。

L298N双H桥直流电机驱动器


使用树莓派制作智能小车_第15张图片
L298N电机驱动器

引入一个词--"跳线帽"

跳线帽的作用是控制线路板上电流流动的小开关。

使用树莓派制作智能小车_第16张图片
IMG_20170527_212410

马达A输出----------控制小车左后轮电机的旋转;
马达B输出----------控制小车右后轮电机的旋转;
12V输入-------------链接外部电源"+"极;
电源地----------------链接外部电源"-"极;
单片机I/O控制输入--链接树莓派GPIO引脚;
A通道使能----------默认跳线帽(可拔掉)链接上面5V引脚;
B通道使能----------默认跳线帽(可拔掉)链接上面5V引脚;
板载5V输出使能----默认跳线帽(可拔掉)链接两个引脚;
5V输入----------------该接口功能与板载5V输出使能有关;

  • 4.1L298N控制器使用说明

L298N电机控制器工作电压为5V。
L298N电机控制器输出电压与供电电源电压大小有关,供电电源电压越大输出的电压也就越大。

L298N板子供电方式

方式一:板载5V输出使能供电
板载5V输出使能不拔跳线帽,板子有一个稳压芯片把12V输入的电压稳定在5V,通过板载5V输出使能给电机控制器供电。

通过12V输入的电压不能大于12V,否则会烧毁稳压芯片。
5V输入变成了对外提供5V电压接口。不能再通过改接口输入电压,否则会烧毁稳压芯片。

方式二:5V输入

拔掉板载5V输出使能跳线帽。通过5V输入5V的电压

一定要拔掉板载5V输出使能跳线帽,5V输入接口输入稳定的5V电压。切记不要大于5V。

杜邦线


使用树莓派制作智能小车_第17张图片
1495779235172

公对公


使用树莓派制作智能小车_第18张图片
IMG_20170527_213823

母对母


使用树莓派制作智能小车_第19张图片
IMG_20170527_213844

公对母


IMG_20170527_213908

链接说明:

12V电源连接一个开关

使用树莓派制作智能小车_第20张图片
IMG_20170525_171940

链接时开关保持断开状态

使用树莓派制作智能小车_第21张图片
IMG_20170525_172056

与面包版链接

使用树莓派制作智能小车_第22张图片
IMG_20170525_172206

Pi的GPIO引脚输入电压一定不要大于3.3V

需要配备一个万用表来测试各种输入输出电压,对于调式程序有很大的帮助。


使用树莓派制作智能小车_第23张图片
1495777497857

从另一个角度说明"板载5V输出使能":
12V输入接入12V的电压时,板载5V输出使能通过稳压芯片可以给板子提供稳定的5V电压。控制器开始工作。这时5V输入接口变成了5V输出,对外提供稳定的5V电压 ,切记一定不要再输入任何电压,否则,会烧毁稳压芯片的,切记!切记!切记!
12V输入接入大于12V电压,5V输出使能必须拔掉跳线帽。控制器的工作电压由5V输入提供。
理解了板载5V输出使能接口,5V输入接口的功能,接下来我们开始连线。

电源地,接地,GND这些词表达的都是一个意思。

板载5V输出使能拔掉跳线帽。
使能A拔掉跳线帽。
使能B拔掉跳线帽。
5V输入接树莓派5V输出引脚(2/4),电源地接链接树莓派GND引脚(6/9/14/20/25/30/34/39)。
12V输入接电源正极。电源地接电源负极。
链接过程可以借助面包版。
链接完成后,检查两遍线路,没问题后接通开关,查看指示灯的状态是否正确。

5 开始编程:

  • 5.1电机驱动器的工作原理
使用树莓派制作智能小车_第24张图片
电机控制器工作原理

B输出与A一致。

  • 5.2Python代码实现

因为我们使用RPi.GPIO库,只需用下列命令向树莓派引脚发送高低电平就可控制电机的旋转。

GPIO.setup(PinNumber, GPIO.OUTPUT)
GPIO.out(PinNumber, GPIO.HIGH)
GPIO.out(PinNumber, GPIO.LOW)

一个交互式Python脚本修改电机控制器的输入信号,对电机进行控制。
链接好电机和电源以后,为了测试不同命令的执行效果,把智能小车的后轮抬高,防止在地上乱跑。只有在修复了代码中的Bug以后(不要太乐观,错误总是伴随着你粗心和兴奋而来)才能进行下一个环节,在不同的环境下测试效果。现在的工作相当于在生产车间对车辆进行改造。

IN1 -13脚
IN2 -11脚
ENA -15脚
IN3 -40脚
IN4 -38脚
ENB-36脚

把后轮抬高离开地面,创建一个Python脚本,名为car.py:

# -*- coding:utf-8 -*-
import RPi.GPIO as GPIO
import time

class Car():
        def __init__(self, left_in1, left_in2, left_ena, right_in3, right_in4, right_enb, low_electrical_level, hight_electrical_level):
        GPIO.setwarnings(False)
        GPIO.setmode(GPIO.BOARD)
        
        self.left_in1 = left_in1
        self.left_in2 = left_in2
        self.left_ena = left_ena
        if self.left_ena > 0:
            GPIO.setup(self.left_ena, GPIO.OUT)
        
        GPIO.setup(self.left_in1, GPIO.OUT)
        GPIO.setup(self.left_in2, GPIO.OUT)
                
        self.right_in3 = right_in3
        self.right_in4 = right_in4
        self.right_enb = right_enb
        
        
        GPIO.setup(self.right_in3, GPIO.OUT)
        GPIO.setup(self.right_in4, GPIO.OUT)
        if self.right_enb > 0:
            GPIO.setup(self.right_enb, GPIO.OUT)

        self.hight_electrical_level = hight_electrical_level
        self.low_electrical_level = low_electrical_level

    '''
        右边轮子前进
        '''
    def rFoward(self):
        GPIO.output(self.right_in3, self.hight_electrical_level)
        GPIO.output(self.right_in4, self.low_electrical_level)
        if self.right_enb > 0:
            GPIO.output(self.right_enb, self.hight_electrical_level)
    
    
    '''
        左边轮子前进
        '''
    def lFoward(self):
        GPIO.output(self.left_in1, self.hight_electrical_level)
        GPIO.output(self.left_in2, self.low_electrical_level)
        if self.left_ena > 0:
            GPIO.output(self.left_ena, self.hight_electrical_level)
    
    '''
        右边轮子后退
        '''
    def rBackward(self):
        GPIO.output(self.right_in3, self.low_electrical_level)
        GPIO.output(self.right_in4, self.hight_electrical_level)
        if self.right_enb > 0:
            GPIO.output(self.right_enb, self.hight_electrical_level)
    
    '''
        左边边轮子后退
        '''
    def lBackward(self):
        GPIO.output(self.left_in1, self.low_electrical_level)
        GPIO.output(self.left_in2, self.hight_electrical_level)
        if self.left_ena > 0:
            GPIO.output(self.left_ena, self.hight_electrical_level)
    
    '''
    左边轮子停止
        '''
    def lStop(self):
        if self.left_ena > 0:
            GPIO.output(self.left_ena, self.low_electrical_level)
        else:
            GPIO.output(self.left_in2, self.low_electrical_level)
            GPIO.output(self.left_in1, self.low_electrical_level)
            
    '''
        右边轮子停止
        '''
    def rStop(self):
        if self.right_enb > 0:
            GPIO.output(self.right_enb, self.low_electrical_level)
        else:
            GPIO.output(self.right_in3, self.low_electrical_level)
            GPIO.output(self.right_in4, self.low_electrical_level)
    '''
        小车前进
        '''
    def moveForward(self):
        self.lFoward()
        self.rFoward()
    
    '''小车后退
        '''
    def moveBackground(self):
        self.lBackward()
        self.rBackward()
    
    '''小车右转
        '''
    def spinRight(self):
       self.rFoward()
       self.lBackward()
    
    '''小车左转
        '''
    def spinLeft(self):
        self.rBackward()
        self.lFoward()
    
    '''
        小车停止--左边及右边轮子都停止
        '''
    def stop(self):
        self.lStop()
        self.rStop()

    def cleanup(self):
        GPIO.cleanup()

def instanceCar():
    return Car(11, 13, 15, 38, 40, 36, 0, 1)

保存。然后命令运行car.py查看运行效果:

sudo python3 car.py

如果正确无误,车轮会向前旋转2秒,暂停,再向后旋转两秒,然后停止旋转,试试其他的值,熟悉小车的状态。
接下来编写一个脚本controlcar.py,使用字符菜单来控制智能小车的行走轨迹。

import time
import os
import subprocess as call
import car
import camera

car = car.instanceCar()


def raw_input(content):
    return str(input(content))

if __name__ == "__main__":
    try:
        while True:
            #Get command from user
            os.system ("clear")
            print ("W = forward")
            print ("Z = background")
            print ("A = left")
            print ("D = right")
            print ("S = stop")

            print("t = take pictures")
            print("v = record video")

            command = raw_input("Enter command(Q to quit)")
            
            if (command == "w" or command == "W" ):
                car.moveForward()
                time.sleep(5)
                car.stop()
                continue
            elif (command == "a" or command == "A" ):
                car.spinLeft()
                time.sleep(5)
                car.stop()
                continue
            elif (command == "z" or command == "Z" ):
                car.moveBackground ()
                time.sleep (5)
                car.stop()
                continue
            elif (command == "d" or command == "D" ):
                car.spinRight()
                time.sleep(5)
                car.stop()
                continue
            elif (command == "s" or command == "S" ):
                car.stop()
                time.sleep(5)
                continue
            elif "q" == command or "Q" == command:
                car.stop()
                car.cleanup()
                break
            else:
                print("Enter Error")
                continue
            
  except (KeyboardInterrupt, SystemExit):
        car.stop()
        GPIO.clearup()
              

保存。命令执行脚本controlcar.py


sudo pyhton3 controllcar.py

运行结果如下所示的命令窗口:

使用树莓派制作智能小车_第25张图片
0CFD6F34-7C24-4B61-9CF2-015B5245D7E4

对电机驱动器L298N操作不清楚的,可到这里查看具体使用

四路红外避障

使用树莓派制作智能小车_第26张图片
图片发自App

监控及拍照

你可能感兴趣的:(使用树莓派制作智能小车)