本部分讲解控制树莓派的 GPIO 输出信号 以此来控制电机驱动

#####硬件准备
搭建小车需要下面这些硬件:

  • L298N 电机驱动模块,买好一点,便宜的易烧
  • 小车平台(车身+4个轮子+4个电机,淘)
  • 12v可充电电池,给电机供电
  • 移动电源,树莓派供电
  • 杜邦线若干
  • M2 铜质隔离柱若干,M2 螺丝 + 螺母若干(固定原件用)
  • 电线绑带,固定不规则部件用

另外有一些可以增加幸福感的可选工具/部件

  • 树莓派专用风扇 + 外壳,配上散热片,跟温度危机说拜拜
  • 小型电钻,亚克力板打孔,想钻哪里钻哪里
  • 万用表,戳一下就知道哪里出问题
  • 电烙铁,万一把什么元件给掰断了…
  • 女朋友,在你把 L298N 搞烧了之后给你安慰
  • 外接显示器,提升敲代码幸福感
  • 好了,不说废话了…

######硬件连线
先来看看 L298N 电机模块:


L298N 就是集成了集成了 L298N 芯片跟一些电子元件的电路板子。输出端口标记 跟 内部原理图 如下,淘宝上盗了两张图:


简单说一下这些输入输出端口的作用:

  • 输出A/B:输出A含端口OUT1/2两个端口,输出B含OUT3/4两个端口,用于电机直接供电,输出A连接左边电机的红线跟黑线;输出B类似
  • 板载使能:决定 L298N 是否工作,板子上用跳线帽跟高电平输出短接,就是永远有效的意思
  • 12v供电:板子供电,接 12v 电源的正极
  • 供电GND:接12v电源的负极,注意这里要跟 Pi GPIO 共地,否则无法识别来自 Pi GPIO 的电平信号
  • 5v供电:这是一个5v电压输出,可以给其他微控制器供电。貌似连上 Pi 之后能让 Pi 启动,但是不能正常进入系统
  • 通道A使能:决定输出A是否可用,通道B使能类似,跟板载使能一样,用跳线帽短接了。后面我们需要拔掉,来控制车子转弯
  • 逻辑输入:IN1为高时OUT1输出12v电压,为低时OUT1为0v。其他类似,IN2对应OUT2,IN3对应OUT3,IN4对应OUT4

然后将板子跟电机连起来,说说我的连线方案,左边电机红线(正极)连OUT1,黑线(负极)接OUT2;右边电机红线接OUT4,黑线接OUT3。下面说说 Pi GPIO 输出。


GPIO 就是 General Purpose Input Output (通用输入/输出)。 树莓派里代码控制 GPIO 针脚输出有两种方式,用 C 或者用 Python,无疑 Python 是最方便的。之前我配置 vim + python 时安装的 python-dev 貌似已经包含了 gpio 库,如果你的 pi 上没有 gpio 库的话,可以用下面的命令来安装

1
2
3
4
5
#Python2安装GPIO库需要输入命令:
sudo apt-get install python-rpi.gpio

#Python3安装GPIO库需要输入命令:
sudo apt-get install python3-rpi.gpio

安装好之后可以利用命令来输出 gpio 的针脚信息:

1
gpio readall


那么板子上哪个是 Pin1 呢,板子朝上,USB 口对着自己,左上角就是 Pin1。此外反过来看看,Pin1 的焊点是正方形的。简单解释一下 Name 一栏不同种类针脚的含义:

  • SDA/SCL:DA 表示 data,数据信号;CL 表示 clock,时钟信号。 如果想要扩展 Pi 的 GPIO 针脚会用到这两个针口,IIC协议通讯用的
  • GPIO:就是我们可以用来作为输入输出的针脚
  • TxD/RxD:跟其他串行设备连接的时候会用到这两个针脚,t for transmit and r for receive
  • MOSI/MISO:MOSI Master Output Slave Input,MISO Master Input Slave Output,用于 SPI(串行外设接口)通信
  • SCLK:串行时钟信号
  • CE0/CE1:作为接通两路SPI的片选信号。它们跟 MOSI,MISO,SCLK 一起构成跟 SPI 模块通讯的信号组

接下来,你可以根据你的布线需求选用合适的 GPIO 接口,连接到 L298N 上的这些针脚上:通道A使能,4个逻辑输入,通道B使能,放一个我的连接图。图会比较杂乱,因为我除了连 L298N 还连了摄像头云台的两个舵机的电源跟他们的控制线:


恩,确实是乱到不行。接下来就是安排两个电源的安放位置并且将他们固定好。做的时候在一个旧音响上面翻到一个就开关,所以顺便接上了 L298N 的电源输入线里面,就是顶端那个正方形的白色小方块。板子、树莓派,摄像头云台之间的固定我都用了隔离柱,我敢说比我在网上查资料时看到的所有方案都优雅,毕竟我看到的资料是小数啊哈哈哈。后期有钱,打算入手一台3d打印机,自己做外壳。上我的图:


车头那块蓝色的就是 12v 的充电电池组,用来给 L298N 也就是电机供电。车屁股那坨紫色的是从一个旧移动电源里面拆出来的电池组,电路板(USB口跟充电口)固定在了底部。能这么方便地使用铜柱子,还是拜我的工具所赐,没错,就是文首提到的提升幸福感工具之一:电钻


相信我,你会爱上并享受打洞的过程的!连好了线之后,就没有硬件什么事了。

######Python控制小车运动
好了,那么到底怎么用 GPIO 这个库来控制 GPIO 信号输出呢,倍儿简单:

1
2
3
4
5
6
7
8
9
import RPi.GPIO as gpio

outPinNum = 11

gpio.setmode(gpio.BOARD)
gpio.setup(outPinNum, gpio.OUT)
gpio.output(outPinNum, gpio.LOW)

gpio.cleanup()

简单到不用解释,不过还是让我解释一下,再放一次这个图:

  • gpio.BOARD 指定了使用板子的针脚顺序编号来命名针脚,就是上面针脚输出图里面的 Physical 一栏里面的数字。另外一种命名方式是 BCM(Broadcom SOC channel),使用这种方式的时候,使用的针脚序号就是上图中 “GPIO” 后面跟着的数字。你的程序里里面只能够指定一种命名方式
  • gpio.OUT 将针脚的工作模式设置为输出,对应的还有 gpio.IN
  • gpio.cleanup() 注意每次在程序结束执行之前都要进行清理,否则这个针脚将一直被占用,除非你重启

利用 GPIO 口作为输入也倍儿简单:

1
2
3
4
5
6
7
8
9
import RPi.GPIO as GPIO

inPinNum = 13

pio.setmode(gpio.BOARD)
gpio.setup(inPinNum, gpio.IN)
inValue = GPIO.input(inPinNum)

gpio.cleanup()

简单,不解释了。不过值得注意的是,使用针脚输入的时候,需要采取一些防护措施保证输入电压不超过某个阈值,比如5v,否则可能会对 Pi 造成伤害。


具体到控制小车运动,代码就不上了,无非就是一大串的 gpio.out() 代码,下面提供一下代码的设计思路就好:

前提:OUT1 连接左边电机正极,OUT2 连接左边电机负极;OUT4连接右边电机正极,OUT3连接右边电机负极,并且电机的铁片朝向车外
小车前进:输出A/B使能端均为高电平,IN1高电平 -> OUT1 12v,IN2低电平 -> OUT2 0v,IN4高电平 -> OUT4 12v,IN3低电平 -> OUT3 0v
小车后退:vice versa
小车左转:输出A使能端低电平->左边电机停止运转,输出B使能端高电平->右边电机正常运转
小车右转:vice versa


思路如此简单。另外小车转弯控制其实还有另外一种更好的办法,利用脉宽调制(PWM)。简单的说,PWM 技术就是不停的通断电路并控制通断持续的时间片段长度来控制用电器在单位时间内实际得到的电能。树莓派1代B型的26个针脚里,有一个特殊的GPIO口是支持硬件PWM的,不过从B+开始不知道什么原因这个很实用的接口被去掉了。


虽然可以用 gpio 库提供的 PWM 方法来达到软件模拟的效果,但是不稳定,特别是需要的 PWM 信号多的时候就更加不稳定了,因为 PWM 是利用线程来实现的。建议可以用 PI 外接一个 Arduino 板子。Arduino 一共提供了6个 PWM 针脚。


下一篇系列文章将研究怎么用捕获键盘输入来控制小车。

#####参考资料
1.iOS开发 Socket网络编程
2.iOS Socket UDP编程-C语言版
3.Swift - 使用socket进行通信
4.树莓派GPIO入门


系列上一篇:Raspberry Pi 小车移动监控I — 摄像头
工程源代码:Github地址