1.智能小车概述
由于制作的初衷是送给我一岁多的闺女当作玩具的,所以给小车起名字叫–洋洋,闺女属羊的,就用了谐音。先来一睹洋洋的外貌:

再来张洋洋的正面:

2.树莓派简介
目睹洋洋的外貌后,开始我们的正文,该篇文章使用的是树莓派板子来作为控制核心——智能大脑,所以DIY冲动的朋友可以到各大商城购买一块最新版的树莓派,铛铛铛铛:

树莓派长这个样子,具体的各个插槽及接口都是什么意思呢,详细讲解的话会使该篇文章显得拖沓,放在其它篇幅讲解,目前不懂没关系,不会影响到我们制作智能小车的,跟着我一步步的进入探索之旅吧。
3.智能小车底盘的制作
3.1车轮的选择
既然是小车,当然就得有车轱辘,车轱辘的选择真是太多了,到各大商城上搜索,五花八门,看的真是眼花缭乱。首先得根据个人喜好选择车轮的外围尺寸,有人习惯大轮子,看起来酷酷蛮拉风,当然大轮子重量上比较重,导致还要给它配上一副功率相对大的电机–马达。我比较喜欢大一点的轮子,因为以后还要在此基础上添加很多的传感器,传感器可以帮助我们测距离,感应前方是否有人,周围环境的温度及湿度还有噪音的分贝等等,所以平台会比较大一点,基于大的轮子构建平台比较合适,是不是迫不及待的想动手制作属于你自己的玩具或者传感器站呢!
我选择的车轱辘:


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



六角联轴器与车轮链接起来后的样子:

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

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

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

4.链接电机和控制器
控制器的选择:
我们制作的两驱智能小车,使用的直流电机370。
电机规格:3V -33转/分钟 6V – 133转/分钟 12V – 258转/分钟
电机驱动器:L298N双H桥直流电机驱动器

4.1为L298N控制器供电
L298N控制器工作电压为5V。
有两种方式为L298N供电
1.通过板载5V输出使能接口提供稳定的5V电压(通过一个稳压芯片提供稳定的5V电压),使能帽不要拔出来,而且通过12V输入接口提供12V电压,电压不能大于12V电压,否则会烧毁稳压芯片,看着流泪吧!此时5V输入接口的功能改变为:对外提供5V电压。切记不能再对L298N提供电压,否则也会烧毁稳压芯片。
链接说明:12V输入接口通过一个开关(此时为断开状态)连接电源的”+”极,电源地(GND)链接电源的”-“极。
2.通过5V输入接口提供5V的电压,此时板载5V输出使能脚帽要拔出来。
链接说明:5V输入接口连接树莓派的2号引脚,电源地(GND)链接树莓派的6号引脚
从另一个角度说明”板载5V输出使能”:
对板载5V输出使能讲解一下:当通过12V输入接口提供12V的电压时,板载5V输出使能接口通过稳压芯片可以给板子提供稳定的5V电压是板子开始工作,这时5V输入接口变成了输出5V电压,一定不要通过5V输入接口提供5V的电压,否则,会烧毁稳压芯片的,切记!切记!切记!当提供的电压大于12V情况,必须拔掉板载5V输出使能帽,通过外部电源通过5V输入提供5V的电压。
理解了板载5V输出使能接口,5V输入接口的功能,接下来我们开始连线。
我们选择提供12V电压的电源为L298N供电,注意两点:
1.板载5V输出使能 为控制器供电
2.通过5V输入接口为树莓派供电(当使L298N为树莓派供电时,树莓派切记不要连接外部电源)
链接说明:
电源的正极出来后接一个开关(断开状态), 电源地(GND)链接电源的负极–这一步放在最后链接,等链接完成后再供电
5V输入接口链接树莓派 2号引脚, 树莓派6(GND)号引脚链接电源地(GND)
单片极IO输入链接树莓派的 19, 23, 22, 26号引脚
链接过程可以借助面包版
链接完成后,检查两遍线路,没问题后接通开关,查看指示灯的状态是否正确。
5 开始编程:
电机驱动器的工作原理

因为我们使用RPi.GPIO库,只需用下列命令向树莓派引脚发送高低电平就可控制电机的旋转。
1 |
<span class="pln">GPIO</span><span class="pun">.</span><span class="pln">setup</span><span class="pun">(</span><span class="typ">PinNumber</span><span class="pun">,</span><span class="pln"> GPIO</span><span class="pun">.</span><span class="pln">OUTPUT</span><span class="pun">)</span><span class="pln"> GPIO</span><span class="pun">.</span><span class="kwd">out</span><span class="pun">(</span><span class="typ">PinNumber</span><span class="pun">,</span><span class="pln"> GPIO</span><span class="pun">.</span><span class="pln">HIGH</span><span class="pun">)</span><span class="pln"> GPIO</span><span class="pun">.</span><span class="kwd">out</span><span class="pun">(</span><span class="typ">PinNumber</span><span class="pun">,</span><span class="pln"> GPIO</span><span class="pun">.</span><span class="pln">LOW</span><span class="pun">)</span> |
我们可以一个交互式Python脚本修改电机控制器的输入信号,对电机进行控制。
链接好电机和电源以后,为了测试不同命令的执行效果,把智能小车的后轮抬高,防止在地上乱跑。只有在修复了代码中的Bug以后(不要太乐观,错误总是伴随着你粗心和兴奋而来)才能进行下一个环节,在不同的环境下测试效果。现在的工作相当于在生产车间对车辆进行改造。
IN1 – 19脚
IN2 – 23脚
IN3 – 24脚
IN4 – 26脚
把后轮抬高离开地面,创建一个Python脚本,名为car.py:
1 |
<span class="kwd">import</span> <span class="typ">RPi</span><span class="pun">.</span><span class="pln">GPIO </span><span class="kwd">as</span><span class="pln"> GPIO </span><span class="kwd">import</span><span class="pln"> time GPIO</span><span class="pun">.</span><span class="pln">setwarinings</span><span class="pun">(</span><span class="kwd">False</span><span class="pun">)</span><span class="pln"> GPIO</span><span class="pun">.</span><span class="pln">setmode</span><span class="pun">(</span><span class="pln">GPIO</span><span class="pun">.</span><span class="pln">BOARD</span><span class="pun">)</span><span class="pln"> gpio_in1 </span><span class="pun">=</span> <span class="lit">19</span><span class="pln"> gpio_in2 </span><span class="pun">=</span> <span class="lit">23</span><span class="pln"> gpio_in3 </span><span class="pun">=</span> <span class="lit">24</span><span class="pln"> gpio_in4 </span><span class="pun">=</span> <span class="lit">26</span><span class="pln"> GPIO</span><span class="pun">.</span><span class="pln">setup</span><span class="pun">(</span><span class="pln">gpio_in1</span><span class="pun">,</span><span class="pln"> GPIO</span><span class="pun">.</span><span class="pln">OUT</span><span class="pun">)</span><span class="pln"> GPIO</span><span class="pun">.</span><span class="pln">setup</span><span class="pun">(</span><span class="pln">gpio_in2</span><span class="pun">,</span><span class="pln"> GPIO</span><span class="pun">.</span><span class="pln">OUT</span><span class="pun">)</span><span class="pln"> GPIO</span><span class="pun">.</span><span class="pln">setup</span><span class="pun">(</span><span class="pln">gpio_in3</span><span class="pun">,</span><span class="pln"> GPIO</span><span class="pun">.</span><span class="pln">OUT</span><span class="pun">)</span><span class="pln"> GPIO</span><span class="pun">.</span><span class="pln">setup</span><span class="pun">(</span><span class="pln">gpio_in4</span><span class="pun">,</span><span class="pln"> GPIO</span><span class="pun">.</span><span class="pln">OUT</span><span class="pun">)</span> <span class="kwd">def</span><span class="pln"> lForward</span><span class="pun">():</span><span class="pln"> GPIO</span><span class="pun">.</span><span class="pln">output</span><span class="pun">(</span><span class="pln">gpio_in1</span><span class="pun">,</span><span class="pln"> GPIO</span><span class="pun">.</span><span class="pln">LOW</span><span class="pun">)</span><span class="pln"> GPIO</span><span class="pun">.</span><span class="pln">output</span><span class="pun">(</span><span class="pln">gpio_in1</span><span class="pun">,</span><span class="pln"> GPIO</span><span class="pun">.</span><span class="pln">HIGH</span><span class="pun">)</span> <span class="kwd">def</span><span class="pln"> rForward</span><span class="pun">():</span><span class="pln"> GPIO</span><span class="pun">.</span><span class="pln">output</span><span class="pun">(</span><span class="pln">gpio_in3</span><span class="pun">,</span><span class="pln"> GPIO</span><span class="pun">.</span><span class="pln">HIGH</span><span class="pun">)</span><span class="pln"> GPIO</span><span class="pun">.</span><span class="pln">output</span><span class="pun">(</span><span class="pln">gpio_in4</span><span class="pun">,</span><span class="pln"> GPIO</span><span class="pun">.</span><span class="pln">LOW</span><span class="pun">)</span> <span class="kwd">def</span><span class="pln"> rBackground</span><span class="pun">():</span><span class="pln"> GPIO</span><span class="pun">.</span><span class="pln">output</span><span class="pun">(</span><span class="pln">gpio_in3</span><span class="pun">,</span><span class="pln"> GPIO</span><span class="pun">.</span><span class="pln">LOW</span><span class="pun">)</span><span class="pln"> GPIO</span><span class="pun">.</span><span class="pln">output</span><span class="pun">(</span><span class="pln">gpio_in4</span><span class="pun">,</span><span class="pln"> GPIO</span><span class="pun">.</span><span class="pln">HIGH</span><span class="pun">)</span> <span class="kwd">def</span><span class="pln"> lBackground</span><span class="pun">():</span><span class="pln"> GPIO</span><span class="pun">.</span><span class="pln">output</span><span class="pun">(</span><span class="pln">gpio_in1</span><span class="pun">,</span><span class="pln"> GPIO</span><span class="pun">.</span><span class="pln">HIGH</span><span class="pun">)</span><span class="pln"> GPIO</span><span class="pun">.</span><span class="pln">output</span><span class="pun">(</span><span class="pln">gpio_in2</span><span class="pun">,</span><span class="pln"> GPIO</span><span class="pun">.</span><span class="pln">LOW</span><span class="pun">)</span> <span class="kwd">def</span><span class="pln"> lStop</span><span class="pun">():</span><span class="pln"> GPIO</span><span class="pun">.</span><span class="pln">output</span><span class="pun">(</span><span class="pln">gpio_in1</span><span class="pun">,</span><span class="pln"> GPIO</span><span class="pun">.</span><span class="pln">LOW</span><span class="pun">)</span><span class="pln"> GPIO</span><span class="pun">.</span><span class="pln">output</span><span class="pun">(</span><span class="pln">gpio_in2</span><span class="pun">,</span><span class="pln"> GPIO</span><span class="pun">.</span><span class="pln">LOW</span><span class="pun">)</span> <span class="kwd">def</span><span class="pln"> rStop</span><span class="pun">():</span><span class="pln"> GPIO</span><span class="pun">.</span><span class="pln">output</span><span class="pun">(</span><span class="pln">gpio_in3</span><span class="pun">,</span><span class="pln"> GPIO</span><span class="pun">.</span><span class="pln">LOW</span><span class="pun">)</span><span class="pln"> GPIO</span><span class="pun">.</span><span class="pln">output</span><span class="pun">(</span><span class="pln">gpio_in4</span><span class="pun">,</span><span class="pln"> GPIO</span><span class="pun">.</span><span class="pln">LOW</span><span class="pun">)</span> <span class="kwd">def</span><span class="pln"> allStop</span><span class="pun">():</span><span class="pln"> lStop</span><span class="pun">()</span><span class="pln"> rStop</span><span class="pun">()</span><span class="pln"> lForward</span><span class="pun">()</span><span class="pln"> rForward</span><span class="pun">()</span><span class="pln"> time</span><span class="pun">.</span><span class="pln">sleep</span><span class="pun">(</span><span class="lit">2</span><span class="pun">)</span><span class="pln"> lBackground</span><span class="pun">()</span><span class="pln"> rBackground</span><span class="pun">()</span><span class="pln"> time</span><span class="pun">.</span><span class="pln">sleep</span><span class="pun">(</span><span class="lit">2</span><span class="pun">)</span><span class="pln"> allStop</span><span class="pun">()</span> |
保存后,用下面命令运行car.py查看运行效果:
1 |
<span class="pln">sudo python3 car</span><span class="pun">.</span><span class="pln">py</span> |
如果正确无误,车轮会向前旋转2秒,暂停,再向后旋转两秒,然后停止旋转,试试其他的值,熟悉小车的状态。
接下来编写一个脚本controlcar.py,使用字符菜单来控制智能小车的行走轨迹。
1 |
<span class="kwd">import</span><span class="pln"> car </span><span class="kwd">if</span><span class="pln"> __name__ </span><span class="pun">==</span> <span class="str">"__main__"</span><span class="pun">:</span> <span class="kwd">try</span><span class="pun">:</span> <span class="kwd">while</span> <span class="kwd">True</span><span class="pun">:</span> <span class="kwd">print</span><span class="pun">(</span><span class="str">"W to car forward"</span><span class="pun">)</span> <span class="kwd">print</span><span class="pun">(</span><span class="str">"X to car background"</span><span class="pun">)</span> <span class="kwd">print</span><span class="pun">(</span><span class="str">"A to car turnLeft"</span><span class="pun">)</span> <span class="kwd">print</span><span class="pun">(</span><span class="str">"D to car turnRight"</span><span class="pun">)</span> <span class="kwd">print</span><span class="pun">(</span><span class="str">"S to car stop"</span><span class="pun">)</span> <span class="kwd">print</span><span class="pun">(</span><span class="str">"Q to exit"</span><span class="pun">)</span><span class="pln"> user_choice </span><span class="pun">=</span><span class="pln"> input</span><span class="pun">(</span><span class="str">"Choice:"</span><span class="pun">)</span> <span class="kwd">if</span><span class="pln"> user_choice </span><span class="pun">==</span> <span class="str">"W"</span> <span class="kwd">or</span><span class="pln"> user_choice </span><span class="pun">==</span> <span class="str">"w"</span><span class="pun">:</span><span class="pln"> car</span><span class="pun">.</span><span class="pln">forward</span><span class="pun">()</span> <span class="kwd">elif</span><span class="pln"> user_choice </span><span class="pun">==</span> <span class="str">"X"</span> <span class="kwd">or</span><span class="pln"> user_choice </span><span class="pun">==</span> <span class="str">"x"</span><span class="pun">:</span><span class="pln"> car</span><span class="pun">.</span><span class="pln">background</span><span class="pun">()</span> <span class="kwd">elif</span><span class="pln"> user_choice </span><span class="pun">==</span> <span class="str">"A"</span> <span class="kwd">or</span><span class="pln"> user_choice </span><span class="pun">==</span> <span class="str">"a"</span><span class="pun">:</span><span class="pln"> car</span><span class="pun">.</span><span class="pln">turnLeft</span><span class="pun">()</span> <span class="kwd">elif</span><span class="pln"> user_choice </span><span class="pun">==</span> <span class="str">"D"</span> <span class="kwd">or</span><span class="pln"> user_choice </span><span class="pun">==</span> <span class="str">"d"</span><span class="pun">:</span><span class="pln"> car</span><span class="pun">.</span><span class="pln">turnRight</span><span class="pun">()</span> <span class="kwd">elif</span><span class="pln"> user_choice </span><span class="pun">==</span> <span class="str">"S"</span> <span class="kwd">or</span><span class="pln"> user_choice </span><span class="pun">==</span> <span class="str">"s"</span><span class="pun">:</span><span class="pln"> car</span><span class="pun">.</span><span class="pln">allStop</span><span class="pun">()</span> <span class="kwd">elif</span><span class="pln"> user_choice </span><span class="pun">==</span> <span class="str">"Q"</span> <span class="kwd">or</span><span class="pln"> user_choice </span><span class="pun">==</span> <span class="str">"q"</span><span class="pun">:</span><span class="pln"> GPIO</span><span class="pun">.</span><span class="pln">cleanup</span><span class="pun">()</span> <span class="kwd">break</span> <span class="kwd">else</span><span class="pun">:</span> <span class="kwd">print</span><span class="pun">(</span><span class="str">"Enter Error!!!"</span> <span class="pun">)</span> <span class="kwd">catch</span><span class="pun">(</span><span class="typ">ValueError</span><span class="pun">)</span><span class="pln"> GPIO</span><span class="pun">.</span><span class="pln">cleanup</span><span class="pun">()</span> <span class="kwd">print</span><span class="pun">(</span><span class="str">"valueError"</span><span class="pun">)</span> |
保存,用下列命令执行脚本controlcar.py
1 |
<span class="pln">sudo pyhton3 controllcar</span><span class="pun">.</span><span class="pln">py</span> |
得到如图所示的命令窗口:
1 |
<span class="pln">W to car forward X to car background A to car turnLeft D to car turnRight S to car stop Q to exitChoice</span><span class="pun">:</span> |
对电机驱动器L298N操作不清楚的,可到这里查看具体使用