机电控制是智能车最重要的输出功能,假如您使用 Jetbot 官方的自行打印车体并用组装方式来搭建智能小车的话,就需要搭配下图这个 “DC-Stepper-Motor” 控制板,因为 3D 打印车体是根据这个控制板所设计的。
只要在淘宝上输入 “DC-Stepper-Motor” 关键字,就能找到非常多的供应商,价位在 30~50 人民币之间,不过出货都是以上图左边的散件为主,需要将四个关键位置自己加以焊接,其他用不上的部分可以不用处理。
这个控制板是由一个 PCA9685 的 PWM 控制芯片与两个 TB6612 电机驱动芯片所组成,与 Jetson 设备、TT 电机之间形成如下图的接线关系。由 PCA9685 接收来自 Jetson 设备 I2C 总线的指令,然后驱动 TB6612 芯片按照 PWM 控制信号对两个 TT 电机,透过改变电流大小去调整电机转速与方向,来执行 Jetbot 小车的移动。
但是这里有个在 “Jetbot 实战系列 06:I2C 总线与 PiOLED” 所遗留的问题需要先解决,因为 PiOLED 显示屏也要接上一组 3V3/GND 供电与 SDA/SCL 接脚,已经将 Jetson 的 1~6 引脚全部占用,那么这个 DC-Stepper-Motor 控制板的 SDA/SCL 该如何与 Jetson 的 I2C 引脚对接呢?
这个显示屏的选项有三种,Jetbot 原厂使用下图最左边的 Adafruit 原厂显示屏,然后按照 https://jetbot.org/master/hardware\_setup.htm的第 10 步骤,在上面焊接 6 根 90 度弯曲引脚,再透过杜邦线与 DC-Stepper-Motor 控制板上的 3V3/GND 与 SDA/SCL 的四个脚位对接,如此一来只需要一组 I2C 总线就能完成在 PiOLED 屏上显示与控制 DC-Stepper-Motor 用途,在总线上的资源调用是最节省的。
但这种 Adafruit 显示屏在国内的售价大约在 120~150 人民币,比中间的国产显示器的 30~50 人民币足足高出 4~5 倍,而且还需要额外的 6 根接脚的焊接作业,其实并不是个优选的方案。
这里推荐一个既省钱又省力的方案:
1.使用上图中间(2 号)的国产 PiOLED 显示屏,线路上不需要做任何调整,按照标准方式插上 Jetson 设备的 1~6 引脚位置,如下图左;
2.如上图,使用 Jetson 设备上另一组 I2C 总线(27 脚位的 SDA 与 28 脚位的 SCL)、3V3(17 脚位)与 GND(20 脚位),与 DC-Stepper-Motor 控制板上的四根引脚对接,也能执行相同的控制任务;
3.调整控制代码里面的总线编号,在项目中 ~/jetbot/jetbot/robot.py 就是用来控制这个 DC-Stepper-Motor 的 PWM 信号,将第 14 行代码中的“default\_value=1” 改成 “default\_value=0” 就可以,如下: i2c_bus = traitlets.Integer(default_value=0).tag(config=True)
如果是使用 Docker 容器的方式,修改代码之后需要重新创建 base 与 jupyter 两个容器,请执行以下代码,就能让修改的配置生效:
`cd ~/jetbot/docker && ./disable.sh
source configure.sh
只需要重建base与jupyter两个容器
cd base && ./build.sh && cd ..
cd jupyter && ./build.sh && cd ..
./enable.sh $HOME/jetbot`
这样就能用原本 I2C\_2 执行 PiOLED 显示内容,另一组 I2C\_1 处理机电控制的部分,总的来说会是最简单轻松的处理方式。
前面提到 DC-Stepper-Motor 控制版是由 PCA9685 与 TB6612 两种芯片所组成,前者在 I2C 总线应用领域是非常重要的一个 PWM 控制器,后者则是根据 PWM 的控制信号为 TT 电机提供对应电流控制的芯片,透过二者的协作让 Jetbot 用最简便的元器件,搭建完整功能的车轮控制体系。
Jetbot 已经针对这两个芯片提供高级封装的接口,极大程度减少我们的代码复杂度,但是为了让读者能在这过程中,对于 I2C 总线与这些控制芯片的协作有进一步理解,能更广泛地在 Jetson 设备上开发出更丰富的机电控制应用,因此占用一些篇幅来讲解一下这两个控制器的基本工作与 Jetbot 里面的底层代码内容。
PWM控制信号与PCA9685控制器
这里最重要的关键技术是“脉冲宽度调制(PWM,Pulse width modulation)”控制信号,负责调节对机电设备的电源供给量,但并不对设备提供电源,就像水龙头的功能是负责调节水量而并不具备供水能力是一样的,水龙头是大家所熟悉的“人机界面”,我们只要简单地调节水龙头来控制水流量就像,至于埋藏在墙里的供水管道有多复杂,通常不太引人们注意,除非漏水或阻塞!
目前大部分嵌入式设备都提供这个功能,包括 Jetson 系列开发套件里也都提供一组 PWM 引脚(32 与 33),不过这必须先经过前面讲解过的 jetson-io.py 工具进行配置,并且重启之后才能使用。但除非您要开发的应用只需要非常单纯地控制一个设备,否则一组 PWM 顶多能做个 “LED 闪灯”这类最基础的入门小实验而已。
PCA9685 芯片是能提供 16 个 PWM 通道的控制芯片,用 1 组 I2C 总线就能控制高达 16 组机电设备,在机器人、机械手臂或无人机等应用领域是非常合适的,毕竟 I2C 总线在设备上的数量是相对稀缺的。在 https://i2cdevices.org/device... 设备地址列表中,可以看到 PCA9685 地址编号横跨 0x40~0x7F 的半壁江山,就能显示这个芯片在 I2C 应用领域的高使用性。
这个信号控制器需要独立的 2.5V~5.5V 电源来支持其运作,在控制板上以 “VCC” 作为标识,由于所需要的电流非常小,可以直接使用主控设备(如 Jetson Nano 2GB)上扩充引脚的合适电源与 GND,也不会影响主控设备的稳定性,另外再加上一组来自主控设备上的 I2C 总线的 SDA/SCL 输入就可以开始工作。
控制板上有另一个 “V+” 标识的电源输入,是真正要对舵机(下图左)、电机马达(下图右)等动力设备提供电力的供电源。
根据设备不同转速、扭力、转距等参数有不同的工作电流,总的来说一路舵机的最基本工作电流在 100 毫安以上、一个电机马达的待机状态最少就需要 250 毫安,实际所需要预留的供电量往往是这个最低量的 2~3 倍以上,这样的用电级别就不是 Jetson Nano 2GB 这类嵌入设备所能供应的,必须依赖一个独立供电源才足以支撑。
网上大部分提到的 PCA9685 控制板,指的是下图中间这种 16 路 PWM 舵机驱动板,左边的接脚与 Jetson Nano 2GB 的 I2C 与电源的引脚相连,下面有编号 0~15 总共 16 组引脚可以接上右边的各种舵机。控制板中间可以看到 “PWM/V+/GND” 的印刷字样,上方白色电源孔接到独立供电系统,这样就能轻松地组合多机械手臂的应用。
读者可以自行采购这类舵机控制板,去搭建组合机械手臂或者二维/三维可旋转的摄像头的项目,透过指定控制板上的 0~15 通道(channel)编号的 PWM 值,进而控制每个舵机的独立工作。
TB6612电机驱动器与电机供电
这是个俗称为“H 桥”的直流电机控制器,主要因为其核心电路形状酷似字母“H”而得名,其功能就是根据所接收的 PWM 信号,为电机马达提供对应的电流,每个 TB6612 芯片可以控制一对(两个)电机马达的转速与方向。
在 DC-Stepper-Motor 控制板上(如下图中),可以看到两边各有一个 “6612FNC” 芯片,每个芯片占用 PCA9685 一个通道,各自控制两组电源供应线路,每一组都有正(红线)负(黑线)两极的线,与最右边 TT 减速电机进行对接。
这个芯片的每个桥都为电机提供 1.2A 的高电流,每组两个电机就至少需要 2.4A 以上电流,这绝对不是 Jetson Nano 2GB 这类嵌入设备所能供应的,必须依赖独立的 5V 电源才足以满足。
在 Jetbot 项目中只需要用到 1 个通道的两个电机组就可以,5V 电源由市售的充电宝来担任,但受到这种电源的供电能力所局限,后面要进行的 Jetbot 范例全都是“慢速低电流”的应用,读者可以在过程中尝试将电机转速调到最大,会发现很容易因为供电不足而导致整套 Jetbot 掉电。
Jetbot的控制代码
在 ~/jetbot/jetbot 下面的 robot.py 与 motor.py 两个代码,就是为这个项目提供的两个不同阶层的调用库,在这里简单做个说明,读者可以根据这些定义进行调整,改写成适用于其他项目的代码:
robot.py:
1.定义“以小车为单位”的“前进/后退/左转/右转/停止”等 5 个动作,可以自行修改 “speed=” 参数去调整行进速度。
2.这是个高阶封装的开发接口,主要调用 Python 版的 Adafruit_MotorHAT 库以及下面的 motor.py 所定义的函数。
3.这里会使用到的几个参数,主要对应上层 robot.py 的参数如下
(1)i2c_bus:必须根据实际使用的 I2C 总线去设置编号,如果使用 I2C_2 总线则 “default_value=1”,如果使用 I2C_1 总线则 “default_value=0”。
(2)motor_channel:将 “left” 设为 “1”、“right” 设为 “2”,这些设定会传给 motor.py 中,去判断该对那个接口输出对应 PWM 的电流。
motor.py:
1.定义“以电机为单位”的“前进/后退/停止”等 3 个动作。
2.调用 Python 版的 Adafruit_MotorHAT 库,定义与 DC-Stepper-Motor 控制板直接互动的低阶接口,作为 robot.py 的基础函数库。
3.这里会使用到的几个参数,主要对应上层 robot.py 的参数如下:
(1)driver:对应到 robot.py 的 I2C 总线编号
(2)channal:对应 robot.py 的左右轮 “motor_channel”
(3)ina/inb:根据左右通道去设置实际电流输出口的位置编号
以上将两个代码中最重要的关键提取出来简单说明,其实还是比较简单的,只要捋清楚上面参数之间的关系,就能很轻松地调整代码内容。
这两个代码是针对 TB6612 驱动的车轮应用所设计的,并不适用于舵机用途,但是只要清楚这些调用逻辑之后,其实代码内容同样是“根据 PWM 值给设备供给电流”的操作过程,最关键的工作就是先确认设备所对应的接脚编号,其他的代码就是指派工作而已,并没有什么技术难度。
强烈推荐读者可以基于本文所讲解的技术内容,先试着将网上众多树莓派小型项目移植到 Jetson 设备上,例如 LED 灯闪烁控制、多维度摄像头云台等机械手臂相关应用,也可以到 https://developer.nvidia.com/... 这个英伟达开发社区优选项目中,寻找合适的范例。