教程:打造自己的Arduino六足机器人

0 / 830

转自:rohm,作者:Jan Gromes

https://techclass.rohm.com.cn/knowledge/tech-info/how-tos/arduino/how-to-arduino-hexapod-part-1-mechanics-and-wiring

这篇文章来源于DevicePlus.com英语网站的翻译稿。

图片

六足机器人是最炫酷的机器人之一,但是通常价格昂贵。原因之一是它们由多个零部件组成,并且使用18个伺服,而这些都需要由某些微控制器来供电和驱动。在本教程中,我将展示如何通过使用3D打印所有零部件并仅使用12个伺服来构建您自己的Arduino六足机器人,或简称为Ardupod。准备好了吗?那让我们开始吧!

硬件

  • • Arduino UNO (或其他可兼容Arduino的开发板)
  • • Adafruit 16通道PWM扩展板(或模块;但是,此处强烈建议使用该扩展板,因为它的原型面积很小)
  • • 12个带有金属齿轮的微型伺服(MG90S或其他同等规格产品)
  • • 4.8V或6V电池(镍氢、锂离子等)
  • • 60个M3螺栓+120个螺母和垫圈(仅用于身体,对于其他部件的安装您需要再另外添加)
  • • 6个相同的圆珠笔弹簧
  • • HC-SR04超声波测距模块(可选)

软件

  • • Arduino IDE
  • • SolidWorks或其他3D建模软件
  • • AI千集(https://aiqianji.com/openoker/ArduPod)– 您在这里可以找到所有用于打印的 Arduino源代码和3D模型

其他工具

  • • 3D 打印机
  • • 非常建议使用万用表、烙铁和电钻等其他工具

设计

如上所述,本次所设计的六足机器人仅需要12个伺服来移动六条腿。这意味着每条腿只配有两个伺服,具有两个自由度(DOF)。与通常的每条腿有三个伺服相比,这种方法有几个优点。我们将需要更少的功率以及更少的处理时间来驱动伺服。但是,移除一个伺服也意味着我们牺牲了一个自由度,因此在对机器人进行稳定爬行的编程上会更具有挑战性。

为了弥补缺少一个伺服所带来的缺陷,所有腿部都有一个可以将伺服的角运动转换为腿部线性运动的机械系统。

该机制内含一个弹簧。弹簧的作用是对在打印过程中造成的所有误差进行补偿。另外,弹簧还可以提供更强大的支撑力,从而有助于实现更自然的爬行运动。您可以在任何地方获取弹簧。比如,圆珠笔里的小弹簧就可以用在这里,但是您可能需要稍微修剪一下长度。请确保您所获取的弹簧可以压缩,并且足够支撑机器人的重量。此外,在开始打印零部件之前,请确保弹簧适用于打印好的部件 leg_1和 leg_1_seg_1。

组装

接下来,欢迎进入本文中最难的部分:组装腿部。无论是在构建上还是编程上,这都属于相当高阶的一个项目。我们将假设打算制造这台机器人的人对于使用诸如电钻和烙铁之类的设备具有基本的操作技能。

图片

图1:腿部组装概览

图片

图2:腿部组装细节

图片

图3:组装好的腿部

组装腿部时,请始终记得必须在每两个需要上下移动的塑料件之间放置一个垫圈。您可能需要用电钻调整孔的大小,保证螺栓能够自由旋转。同时,请注意每个螺栓需要两个螺母。

图片

图4:连接腿部关节:塑料件(黑色)和金属件(浅灰色)

这对于保持整个支撑系统的正常工作十分重要。组装腿部时,请确保不要将底部螺母拧得太紧,并调整至使塑料部件仍可以自由移动。然后,顶部螺母要尽可能拧到最紧。底部螺母保证了所有部件的自由移动,而顶部螺母保证了所有部件的紧固连接。如果您的螺母拧的过松,那么腿部会变得非常不稳定;如果拧的过紧,将会对伺服带来不必要的负载。对腿部的调整可能要经过几次尝试才能完成。这是本教程中最重要的部分,因此请确保正确完成此步骤。

伺服通过一个小小的“三角臂”来固定在适当位置,这种三角臂通常用于将伺服齿轮轴连接到您想要移动的任何物体上。但是,在这种情况下,三角臂的位置将会被固定,以便当伺服运转时,它也会自行移动,从而使腿部移动。

请确保您使用的是金属齿轮伺服,而不是塑料齿轮伺服!在这种应用中如果使用塑料齿轮,不仅强度比金属的低,而且其齿轮也可能会很快就损坏。

图片

图5:伺服附件细节。确保三角臂固定在适当位置。

伺服支架分为三部分,使其更易于打印。假设零部件是用丙烯晴丁二烯苯乙烯(ABS)打印的,那么可以使用丙酮来稍微溶解ABS,然后将这三部分粘在一起,再使其变干。或者,如果您有条件使用更高质量的3D打印机,也可以一次性打印出整个部件。

图片

图6:伺服支架组装细节

六足机器人的剩余部分就没有那么复杂了:机身身体由两块板组成,我们可以在其上安装所需的所有电子设备、电池和传感器。您可以在打印之前设定好用于安装电子设备的孔,也可以在打印之后再钻孔。所有零部件和打印说明均可在 Github上获取。

图片

图7:组装好的身体:“A”为上板,“B”为底板。您还可以看到安装在伺服上的超声波传感器。

成功!到这里,您已经完成了机器人的组装,完成了本教程中最困难的部分。如果出现了什么问题,请不要担心,再次进行尝试。如有必要,请尝试对打印件进行微调,然后查看是否有效。

接线

到目前为止,这是最简单的部分了,因为我们将使用 Adafruit PWM扩展板来完成大部分工作。我们把扩展板连接到 Arduino,然后把伺服连接到扩展板。如果您使用的模块无法直接连接到 Arduino,只需要将SDA、SCL以及 V+连接到 Arduino相应引脚即可(详细信息请参见下图)。

您可能已经注意到了,这里有一个放置电容器的位置,但是却没有电容器。不用担心,这是有意为之!当许多伺服同时运转时,电流峰值将达到几安培。电容器将用来消除这些尖峰。您可能需要这种电容器来确保所有伺服的电源稳定。对于这种目的,使用电解电容器是最合适的,但是对电容值的选择更多的是凭借猜测,而不是确切的科学计算。通常来说,电容值越大越好。电容器的电压应略高于电池电压,因此,如果使用6V电池为所有伺服供电,那么6.3V 4700µF应该可以满足需求。

图片

图8:接线图

在扩展板上,您还会注意到有一个单独的电源端子。那是因为 Arduino本身无法提供足够的电流来一次运行一个以上或两个以上的伺服,需要将电池连接到此端子以及 Arduino电源输入端(VIN和GND引脚)。

就是这样,基本的接线已经完成!如果需要,您还可以添加更多模块和传感器,例如超声波测距仪。

图片

图9:接线细节:建议将所有连接到同一条腿上的伺服的电缆困扎在一起。这样,您将就知道哪条电缆通向哪个伺服。而且,这样看起来也会比一团缠结的线缆更美观一些。

图片

图10:带有 HC-SR04超声波传感器的接线图

在本教程中,我将添加一个超声波传感器,以使机器人能够在附近有障碍物的情况下移动。我之所以选择 HC-SR04,是因为它们非常便宜,并且易于与 Arduino一起使用。而且,这种特定传感器的形状类似于眼睛,您可以借此来分辨出机器人在看什么!

我将传感器安装在一个额外的伺服上(有关安装细节请参见图7)。对该传感器进行接线也非常简单,只是请注意不要将VCC引脚直接连接到电池上!如果您使用的是6V电池,这样连接可能会损坏传感器。将VCC引脚连接到 Arduino 5V输出端,并将GND连接到GND。您可以将TRIG和ECHO引脚连接到剩下的任何数字引脚上,但要记得在代码中对它们进行适当设置。我将它们连接到引脚3(TRIG)和引脚2(ECHO)上,因为我想在需要串行端口的情况下保持引脚0和1断开。

结论

现在,您应该已经完成了所有硬件的组装。接通电源之前,强烈建议您对所建立的每个连接进行测试和确认。

希望您到目前为止没有遇到很棘手的问题。如果您对该设计有任何改进的建议,请在 Github上与我交流!请继续关注本项目的第二部分,我们将进入到下一阶段,进一步研究分析逆动力学,并且对这个神奇的 Arduino六角机器人(或者Ardupod )进行编程。

接下来您将看到的是 ArduPod一次伸展所有腿部!

第二部分:编程

在本项目的第二部分中,我们将继续进行项目中相对容易的内容—编程。对六足机器人进行编程通常有两种不同的方法。第一种是仅仅弄清楚机器人向前行走的一系列伺服运转。显然,这是一个艰难却鲜见成效的工作—您所设计的代码无法直接应用于另一台六足机器人上。所以第二种被称为逆运动学的方法应运而生。但是首先,我们需要改进板载微控制器。

硬件

  • • Arduino Mega
  • • Adafruit 16通道PWM扩展板(或模块;但是,此处强烈建议使用该扩展板,因为它的原型面积很小)
  • • 12个带有金属齿轮的微型伺服(MG90S或其他同等规格产品)
  • • 4.8V或6V电池(镍氢、锂离子等)
  • • 60个M3螺栓+120个螺母和垫圈(仅用于身体,对于其他部件的安装您需要再另外添加)
  • • 6个相同的圆珠笔弹簧
  • • HC-SR04超声波测距模块(可选)

软件

UNO -> Mega

在上一篇文章中,我们建议在本项目中使用Arduino UNO。但是,在使用UNO时我遇到了一个问题:它没有足够的SRAM内存来进行逆运动学模型正常运行时所需的所有计算。这些计算大多数是用浮点数来完成的。每个数字在使用时将占用4个字节的内存,是整型的两倍。虽然看起来不多,但是UNO只有2kB的RAM,其中一些还会被全局变量占用。如果我们为所有全局变量和其他局部变量保留0.5kB,那么将剩下1.5kB的可用内存,这仅能供384个浮点数占用。384可能看起来挺多,但是对于1K模型所产生的数据量是不够的(请阅读下面的“算法”部分找到相关原因)。所以我们必须想办法获取更大的内存。

实现该目的最简单的办法是将UNO更改为MEGA。MEGA和UNO是兼容的,所以对于原理图不用进行修改。另外,使用MEGA不仅可以为计算部分获取四倍多的RAM,还意味着将有八倍以上的闪存可用于我们的程序存储。我们很可能不会所有都用到,但是有更大的预留空间总是好的。以下是改进后的Fritzing原理图,如果您使用的是Arduino MEGA最新版本 (Rev 3),更换的过程很简单,跟断开UNO之后连接MEGA的过程一样。下面示意图以供参考。

图片

图1:PWM扩展板改进后原理图

图片

图2:PWM模块和HC-SR04超声波传感器改进后原理图

现在,我们来探究一些物理原理、所用到的大量数学知识以及少量代码。

逆运动学简介

可能有些人还记得,在高中的时候,物理课中有一部分内容叫做“运动学”。简单地说,这是力学领域中对一个目标对象(或一个点)运动的描述。这意味着在运动学中,您将使用数学公式和模型来对单个点的已知运动进行分析。顾名思义,逆运动学(IK)恰恰相反:通过一系列数学公式来反推并创建运动。

在机器人领域,通常使用的算法只能根据相应的端点运动来计算所有关节的运动。现在,您可以清楚地看到逆运动学在伺服运动编程部分的难题上所具有的优势——它是可以通用的。从理论上来说,仅一个算法就可以处理机器人所执行的任何运动。从使用者的角度来说,它非常易于使用—您只需要告诉机器人向左转90°,然后直行1米就可以了,而不必考虑每个伺服的位置。

模型

在以上段落中,一个词不断出现:一个(数学)模型。虽然听起来很难,但是对于六足机器人这个项目来说,模型非常简单:机器人能够机械性的所达到的任何位置都可以由一组七个点来定义。一个用于身体,另外六个用于腿部。如果您查看了AP_Utils库(可在AI千集上获取 https://aiqianji.com/openoker/ArduPod),特别是里面的AP_Utils.h,就会看到关于这些点的定义(包含在其他内容中):

struct body {float x;float y;float z;float facing;};
struct leg {uint8_t number;bool move;float phi;float z;};

您可以看到在AP_Utils类中它们被声明为私有结构。

body origin;leg legs[6];

将这些结构私有化有以下两个原因:

  1. 用户不应具有随意修改这些值的权限。这些结构的存在是为了追踪机器人的当前位置,因此,只有当机器人真正产生运动的时候这些结构才会发生变化。假如用户想要更改当前的原点的 z 坐标,会导致IK模型发生不可预测的变化—这显然是不可取的。
  2. 通常,将共有函数和一个类中的变量数量控制到最低,是一种良好的编程习惯(尤其在C++中)。因此这样做可以提高安全性,并利于API的轻松实现。

如果需要,我们可以将这些点可视化。现在,我们的整个机器人由七个点来表示(图3)。

图片

图3:IK模型的图形表示。简而言之,这就是六足机器人“认为”它所看起来的样子。红点是身体,蓝点是腿。

这些结构用于追踪所有腿部的位置以及机器人本身的位置。您可能注意到了,腿部的位置仅由两个坐标来定义:phiz。这是因为每条腿只有两个自由度,因此只能沿着两个轴进行移动。现在可以通过身体的xyz 坐标来对所有位置进行定义。每条腿的* phi* 和 z 坐标的范围是-1到1,并且仅确定了腿相对于身体的位置。尽管现在来看这种复杂性似乎是不必要的,但是实际上这比每次运动后计算每条腿的 xyz 坐标容易得多。phi 坐标表示水平运动,z表示垂直运动。

图片

图4:带有phi轴和z轴的腿部细节

算法

现在,我们对于机器人有了足够简单的数学表达,但是还没有用它来做任何事。下一步就是研究如何通过仅仅修改该模型来实现伺服的运转。我们需要完成的程序是将输入作为一组点坐标,并将其转换为伺服的运行。

这时候另一个问题就出现了,而这次,仅仅替换成另一个Arduino无法解决。当启动伺服时,我们可能需要使大部分伺服同时运转。但是,Arduino(以及所有与此相关的AVRs)一次只能执行一项任务。这意味着如果我们如果想平稳地运转伺服,就需要一个一个进行启动。如果仅仅将伺服从一端直接运转到另一端,整个过程将非常不稳定。

解决该问题的一种方法是事先计算好所有伺服的位置,然后迭代这些数据,并对所有伺服进行设置。因为Arduino MEGA的时钟频率是16MHz,所以所有伺服虽然在实际过程中以很小的增量进行离散化运转,但是整体表现出来的运行过程是连续流畅的。尽管它们只是静态图像的集合,但是这和视频中所产生的连续运动的效果一致。人脑无法对视觉信息进行快速处理。如果我们在每一次位置变换之后添加一个50毫秒的延迟,则很明显,伺服运转实际上是由小的增量所组成的。

这也是我们必须更换Arduino的原因。如果我们想要运行每一个伺服,那么我们需要大量的内存来存储刚刚所计算出的坐标。如果我们运转所有的伺服,我们将需要600个浮点数来存储运动坐标,因为每个伺服都至少需要50个位置才能产生平滑连续的运转效果。600个浮点数大约是 2.3 kB的RAM—这已经超过了UNO的容量。

在AP_Utils库中,将位置转换为伺服运转状况的是traceLeg()setLegs() 函数。traceLeg() 函数仅进行计算:当提供了目标末端的 *phi *和 z 坐标时,它将以坐标数组的形式创建一个路径。路径可以具有多种形状,当前支持的是线形(从一个点到另一个点的简单直线)、圆弧和椭圆弧。后两种路径可以使步行变得更加容易。第二种函数 setLegs() 将根据 traceLeg的结果来移动所有指定的支腿,但是,所有这些对常规用户是隐藏的。整个方案的重点是尽可能地方便用户使用。最终用户将无需直接设置 setLegs() ,而仅需调用与行走直接相关的函数即可。

现在我们开始进入IK编程的最后一步,即真正的行走。我们已经完成了所有基础工作:我们创建了一个模型来对所有事物进行追踪,我们可以运行多个伺服,甚至可以使伺服的运转变得相对平滑连续。在以下内容中,支腿的编号与下图中的编号相对应:

图片

图5:支腿编号

该编号系统同时与您在库中找到的代码一致。

我们先从简单的操作开始:在场地上转向。通常,在为支腿设定新的位置时,您必须保证其中三条腿在地面上。这背后的原因很明显—除非您可以非常快地移动支腿,不然机器人将失去稳定性并跌倒。我们可以分几步使机器人转向:

1. 将支腿0、2和4移动到phi 坐标最大值处(最大水平角)。

图片

图6:转向步骤1(支腿0、2和4)

2. 对支腿1、3和5进行相同操作。

图片

图7:转向步骤2(支腿1、3和5)

3. 身体转向。这一步是通过沿与步骤1-3中相反的方向运行所有水平方向的伺服来完成的。因为所有的支腿都在地面上且不能移动,所以可以移动的只有身体。

图片

图8:转向步骤3

对这些步骤进行重复执行后,机器人可以转弯80°。当然,只要不是在过程中一直保持 *phi *轴最大坐标位置,可以实现小于该角度的转向。得益于 traceLeg() 函数背后的巧妙算法,我们不必计算支腿的任何 z 坐标值—这些计算会自动进行,并形成圆或椭圆的形状。您可以在以下视频中观察到这一过程。

最后一步是行走。具体来说,我们希望它至少能向前行走。六足机器人的行走算法有很多种,但大多数算法都基于有三个自由度的支腿。我们的支腿只有两个自由度,因此我们必须自己进行一些设计。我所提出的方法虽然没有达到预期的速度,但是这种方法是最易于编程的,并且易于观察过程中的现象。

1. 首先,支腿0和3向前移动

图片

图9:行走步骤1(支腿0和3)

2. 然后,支腿2和5向相同方向移动

图片

图10:行走步骤2(支腿2和5)

3. 对支腿1和4进行相同操作

图片

图11:行走步骤4(支腿1和4)

4. 现在,身体移动向前,开始重复执行整个过程。

图片

图12:行走步骤4

基本避障功能

您可能已经注意到了,库中有一部分专门用于SR04超声波测距仪。这是为了获取有关机器人所处环境的一些信息。当然,一个固定不动的传感器是不够的,因此在上一篇文章中我们在一个额外的伺服上也安装了一个传感器。

我相信大多数尝试制造六足机器人的人对超声波测距仪的工作原理是有一定程度了解的。对于与该传感器的接口我建议您使用 AP_Utils::sr04_median 函数。它可以提供库中所有SR04函数最准确的结果。您甚至可以输出数据的单位,目前可以支持毫米、厘米和米!

重要提示: 请注意,您需要Adafruit PWM驱动程序库来使AP_Utils运行,您可以点击此处(https://github.com/adafruit/Adafruit-PWM-Servo-Driver-Library)下载。下载完成后,和其他Arduino库一样对其进行安装。

以下是一个非常简单的“自主”模式的示例,使用了到目前为止我们所讨论的所有内容:行走、转向和从SR04中读取距离。如果您认真阅读了这篇文章,那么应该能完全理解以下代码中最重要部分的内容。

Arduino 代码

#include <AP_Utils.h>
//define the pins that the SR04 is connected to
#define TRIG 3
#define ECHO 2
//create an instance of AP_Utils class
AP_Utils ardupod;
//you will have to supply your own offsets here
//see examples/calibration.ino for details
int offsets[16] = {5, 0, 0, -7, 10, -3, 6, -4, 3, -5, 10, -3, 0, 0, 0, 0};
void setup() {
 //reset the robot
 ardupod.begin(offsets);
}
void loop() {
 //take one step directly forward
 ardupod.walk(0, 1);
 //if an obstacle is closer than 20 cm, we have to turn
 if(sr04_median(TRIG, ECHO, CM, 100, 500) < 20.0) {
   //turn 90 degrees to the right
   ardupod.turn(90);
 }
}

结论

恭喜您完成了这个最具挑战性的项目之一!做得很好!在尝试使您自己的Ardupod行走之前,请确认同时运行示例文件夹中的 calibration.inoservo_test.ino。这对于正确设置所有伺服至关重要,这样伺服才不会被损坏!在下一篇文章中,我们可能对此项目进行最后一次探索,以对一些机械性能较差的点进行改善,以及,更重要的是,增加一些改进的功能,例如远程控制。

图片


第三部分:远程控制

在本系列的第三部分也就是最后一部分,我们将为机器人添加最后一个部件:遥控器。此外,我们对支脚进行了一些细微的改进,使它们能够在任何类型的基底表面都能更加稳定。首先,我们会介绍经过细微修改的支腿机制,然后将HC-05蓝牙连接到Arduino以实现无线控制。最后,我们将编写一个Processing应用程序,这样我们就不必为ArduPod的每次移动使用书面指令了。

硬件

  • • 第一部分获得的六足机器人
  • • HC-05 蓝牙模块
  • • 1 kΩ 电阻和 1.8 kΩ (or 2.2 kΩ) 电阻

软件

  • • Arduino IDE
  • • Processing 3.2.3
  • • GitHub – 包含最新源代码
  • • Release 1.0.0 – 或者,您可以在此处下载v1.0.0的源代码。如果GitHub上的代码有重要的API破坏性更新,这些代码仍然可以像本文描述的那样运行。

工具

  • • 烙铁

改善支腿

我自己制造六足机器人的时候,面临的最大难题是支腿在光滑表面上很不稳定。通常,在支腿上添加某种防滑材料就可以很轻松地解决这个问题。但是,这个机器人的支腿与地面间的接触面积太小了。增大支腿与地面的接触面积对防滑效果大有帮助,同时还能改善支腿的整体稳定性。

图片

图1:旧的支腿(左)和新的支腿(右)

在上图中,您可以看到支腿的底部增加了一个支撑零件。与其他零件一样,该零件也是使用黑色ABS材料通过3D打印机制造的。在我的GitHub上可以找到其他零件的模型。

图片

图2:添加到支腿上的新零件。请注意底部的深绿色防滑层

现在我们可以在支脚底部添加防滑层了。我用了一块绿色的凝胶垫。这种材料即使在非常轻的负载下也不会发生打滑。如果您无法获取这种材料,其他选择就非常少了(比如橡胶)。可以试试看哪种材料最适合您的机器人。然后从材料上切下六个圆圈,将这些圆圈粘在脚上,这一步就完成了!

我要做的下一个改进比支脚要复杂一些。在当前系统中,伺服只在一个地方与支腿连接。这会使结构中产生一个薄弱点,该薄弱点将会承受大部分的负载,这可能导致在某个时刻发生断裂。在图3中,您可以看到当前的附着系统和旁边新的附着系统。

图片

图3:旧的附着系统(左)和新的附着系统(右)

我们注意到所添加的新零件使伺服可以在两个位置进行连接:轴上(之前的连接点)和伺服的相对侧。将带有旋钮的小垫子粘贴到伺服上可以为伺服提供额外的支撑。现在,伺服连接在两个位置上,负载分配在这两点之间。这样就可以进行更好的运动控制。

无线 Arduino

现在我们已经解决了支腿的问题,可以来连接HC-05蓝牙模块了,通过该模块可以对机器人进行无线控制。由于所有的控件都由Arduino来操控,我们的主要任务是向其发送指令。

与Arduino之间进行无线通信的方法主要有以下几种:

  1. RF 模块 – 这是最基本的(也是最便宜的)无线通信方式。通常,它们在单个无线电频带(433, 868 或915 MHz)中运行,并且需要在用户端进行一些设置。RF模块的主要优点是通信距离远(可达数百米)和功耗相对较低。
  2. LoRa – LoRa模块类似于上述RF模块,但使用了特殊的调制方式,使其在相同功耗的前提下可以实现更大范围的通信(可达几千米)。当然,代价是传输速度极慢,最大传输速度仅为每秒几百位。
  3. WiFi – WiFi 模块是使Arduino可以连接到网络的快速简便的方法,但是范围通常相当有限。而且,该模块的功耗会很高。
  4. GSM – 这是使您的手机可以正常工作的技术。GSM模块相对于其他选项具有很大的优势:只要有信号就可以实现通信,即使Arduino和目标PC相距数百公里。GSM的最大缺点是它需要大量电源—在某些情况下,电流消耗可能会上升到几安培,这时仅使用电池就很难完成供电了。
  5. ZigBee 技术 – XBee模块通常比此处提到的其他模块要贵,但是它们很容易与Arduino交互。这些模块是作为蓝牙的替代产品而开发的,通常来说通信距离可达75米。
  6. 蓝牙 – 这就是我在本项目中最后决定使用的模块。蓝牙非常易于使用,在本项目中,范围有限并不是什么大问题:我们没有打算让ArduPod去跑到距离计算机几十米以外的地方进行一次大型探险。并且,大多数智能手机都具有蓝牙功能,如果您打算编写一个智能手机应用程序,那么通过该模块就可以轻松完成。

因此,我们将在该项目中使用蓝牙模块。我使用HC-05蓝牙模块,主要是因为它是最便宜、最常见的模块。由于该模块的作用就像一个串行COM端口,因此HC-05与Arduino的连接非常容易,如下面的Fritzing示意图所示:

图片

图4:HC-05蓝牙模块和Arduino Mega的接线图

图片

图5:将HC-05蓝牙模块连接到Arduino Mega

该模块由Arduino供电。HC-05的TX引脚直接连接到Arduino上的RX1引脚。但是,因为HC-05的逻辑电平为3.3V,而Arduino在5V下运行,所以HC-05的RX引脚上必须有一个简易分压器来降低电压。R1的值应为1 kΩ,R2的值可以为1.8 kΩ或2.2 kΩ。我使用2.2 kΩ的电阻,因为找不到阻值为1.8 kΩ的电阻,但是对于该模块,使用两种电阻的任何一个都可以正常工作。

目前,Arduino还不知道它正在通过蓝牙模块进行通信。从Arduino的角度来说,这跟通过电缆连接完全相同。这就是为什么我们不需要在Arduino上进行任何设置,因为该模块自行处理所有事情—至少在最常见的情形下是这样。

下一步是设置HC-05蓝牙模块。我使用的PC没有内置的蓝牙接口,因此必须使用USB蓝牙适配器。

首先,我们必须将PC与蓝牙模块配对。

  • • 将适配器连接到PC,并在完成驱动程序的安装后,在“控制面板”中找到“设备和打印机”窗口。然后,打开已经连接了HC-05的Arduino。HC-05上的红色LED灯将开始迅速闪烁。这意味着HC-05当前没有连接到任何其他设备上。
  • • 在“设备和打印机”中,单击“添加设备”,您的计算机会自动找到HC-05,单击该图标,当弹出“选择配对设备”窗口时,选择中间的选项(“输入设备的配对代码”)。HC-05的默认配对代码为1234。这并不是很安全,我们可以随时更改此代码。不过,控制六脚机器人又需要多少安全性呢?
  • • 成功添加设备后,HC-05上的LED灯现在应该每两秒钟闪烁一次—这表示它已经连接到另一台设备。

此时,最好验证一下所有连接是否正确。启动Arduino IDE并上传以下草图:

void setup() {
 Serial1.begin(9600);
 while(!Serial1);
 Serial1.println("Hello world!");
}

String input;
void loop() {
 if(Serial1.available() > 0) {
   input = Serial1.readString();
   Serial1.println(input);
 }
}

上传完成后,返回“设备和打印机”窗口,找到我们之前与PC配对的HC-05模块。右键单击HC-05图标,然后点击“硬件”选项。在这里,您会找到Windows分配给该模块的COM端口编号。这将是我们用于与ArduPod通信的COM端口。返回Arduino IDE,在菜单>工具>端口中选择正确的COM端口,然后启动串行监视器。输入几个字符,然后按下Enter键。这些字符将被发送到您刚刚指定的COM端口,并出现Arduino的响应。

到目前为止一切正常吗?很好!现在我们已经完成了“困难”的部分,让我们进行一些有趣的部分:在Processing中编写图形应用程序。

Processing

我假设正在阅读本文的您已经对Processing的语言有基本的了解。虽然Processing的语言与Arduino语言非常相似 – setuploop/draw这些主函数都相同—但是它们还是不同的。Arduino语言几乎与C++相同,而Processing是基于Java语言。因此,虽然语法相似,两者之间还是存在重大差异。下面,我会尽我所能地把我所创建的应用程序描述出来。

显然,我们希望该应用程序具有良好的图形用户界面(GUI)。Processing非常着重于绘图形状(因此主循环函数名称为 – draw),所以对于图形设计人员而言使用Processing很便捷。但是,我几乎不具有该领域的任何技能,因此我将通过使用库来帮助我创建外观精美的GUI。

Processing有几种库,可以提供不同的设计方案,但是我个人最喜欢的是controlP5库。您可以点击此处(https://www.sojamo.de/libraries/controlP5/)访问该网站,以详细了解该库的更多信息。另外,该库中几乎包含了所有示例。您可以在网站上找到另一个有用的东西是完整版JavaDoc参考。网站上的下载版本已经有些过时,因此强烈建议您使用Processing的库管理器。在编写程序时我们将使用最新版的Processing,即Processing 3.2.3。该应用程序以及源代码可在(https://aiqianji.com/openoker/ArduPod/src/master/processing/ardupodRemote)上找到。

现在,让我们来看一下应用程序的实际外观。

图片

图6:ArdupodRemote Processing 应用程序

好吧,控件有点多是不是?左侧有一个大的灰色神秘盒子,有很多可以按下的按钮,而右侧则有点奇怪,看起来像是雷达。如您所见,我用红色数字标记了所有部件,这是每个控件的作用:

  1. 串行输出:这是提供运行状况信息的主要来源。串行端口上显示的所有内容都会被写入这里,同时还有来自应用程序本身的通知。
  2. 串行输入和命令提示符:如果要直接向串行端口发送内容,可以在此处输入并按下Enter键发送。这主要在调试应用程序的时候用的,但是会保留在界面上,以防什么时候您极其需要直接向机器人发送某些内容。
  3. 超声波扫描仪:就我个人来说,这是所有功能中最酷的一个。当您按下“扫描”按钮(数字7)时,超声波传感器将旋转180度并在每个角度进行距离测量。距离数据被发送到应用程序,然后被可视化。

图片

图7:扫描输出示例。扫描区域为狭窄的走廊。

即使没有相机,您也可以通过该功能快速简便地了解周围环境。

  1. 手动旋转传感器:不言自明,通过该滑块可以将带有超声波传感器的伺服设置到特定位置。
  2. 距离输出:每次进行距离测量,测量结果都会在此处显示。
  3. 测量按钮:按下该按钮时,传感器将进行一次距离测量并将其显示在距离输出区域中。
  4. 扫描按钮:如上所述,按下该按钮将开始对周围区域进行超声波扫描。
  5. COM端口选择:启动应用程序后,您必须选择适当的COM端口以用于所有的通信。所有可用的COM端口将在此处显示。
  6. 连接按钮:选择正确的COM端口后,按此按钮进行连接 。如果运行出现问题,相关的错误将会被打印到串行输出区域,以帮助您进行修复。
  7. 断开连接按钮:当您出于任何原因需要从端口断开连接时,就可以按下此按钮。
  8. 移动控制:这是构建该应用程序的目的所在。W键向前移动,S键向后移动,A和D键控制左转和右转。就是这么简单!可以单击这些按钮,或者按下相应键盘。单击后,机器人将朝向对应的方向迈出一步。按住键盘键时,机器人将持续朝该方向移动,直到您松开当前按钮或按下一个新按钮。

您可能已经想到了,这个应用程序比我们实际所需要的复杂得多,实在无法逐条解释所有的内容。因此,我们将仅了解代码中最重要的以下部分:控制事件处理,串行通信和Arduino端。

控制事件处理

使用GUI编写应用程序时,我们需要了解的第一件事是:“单击按钮后会发生什么?”幸运的是,controlP5库为我们处理了大多数事宜。让我们从以下代码中看一个简单场景。

import controlP5.*;

ControlP5 cp5;
void setup() {
 size(400,400);
 cp5 = new ControlP5(this);

 cp5.addButton("click me!")
    .setValue(0)
    .setColorForeground(color(215, 0, 0))
    .setColorBackground(color(175, 0, 0))
    .setColorActive(color(255, 0, 0))
    .setPosition(100,100)
    .setSize(200,200)
    ;
}

public void controlEvent(ControlEvent theEvent) {
 if(theEvent.getController().getName().equals("click me!")) {
   println("Why would you trust a big red button?!");
 }
}

void draw() {}

图片

图8:controlP5示例

首先,我们必须导入库并创建controlP5类的实例。然后,在setup函数中,我们创建一个名为“click me!”的新按钮。最后一部分是 controlEvent函数。每当任何 controlP5的元素创建事件时(在我们的示例中,是每次单击按钮时),都会调用该函数。然后,我们可以检查是哪个元素导致了该事件的发生,如果是出于“click me!”按钮,那么将会打印出一些文本。controlP5库包含了有关解释如何使用其所提供的控制元素的示例,所以我们将会来简单了解一下远程控制应用程序中实际所包含的内容。

基本事件处理与上面的示例完全相同,都是通过controlEvent函数进行处理。除此之外,还增加了两个函数 – keyPressed 以及 keyReleased,用于处理键W、A、S和D的输入,以允许使用键盘进行移动控制。您可能会注意到,与示例不同,在setup函数中并没有设置任何的控制元素。所有的元素设置都被移到了第二个选项卡guiElements中,并通过setupGui函数进行调用。因此,在主选项卡ardupodRemote中的代码很少。通常,对不同的内容设计分隔的代码块是一种很好的编程习惯,因为这样更易于阅读和理解代码。

现在,我们对图形和控件的工作原理有了基本的了解,可以尝试解义那些将要通过端口传输的所有数据了。

串行通信和状态码

我们已经在两端都设置了蓝牙连接,但是还需要创建双方都遵循的某种尽可能简明快捷的“协议”。由于所有从串行端口传入的数据在两端都会被释义为字符串数据类型,因此我创建了一个非常简单的“数据包”结构。

前两个字符XY是该数据包的状态码,作用是让应用程序知道有效负载中所包含信息的种类。例如,如果应用程序接收到数据包“*82Starting PWM … ”,它将在串行输出框中写入以下内容:“[INFO] [SETUP] Starting PWM … *”。下表列出了当前已经实现的代码:

0
1 [ECHO]
2 [SETUP]
3 [TRACE]
4 [SR04]
5 [PWM]
6 [ERROR]
7 [WARN]
8 [INFO]
9 >
10 [CMD]
11 [APP]

请注意,在该应用程序中,代码40用于扫描数据,代码41用于单次的距离测量。

像之前一样,第一个字符X将用于确定如何处理有效负载。但是,这次我们只使用了少数的指令。

t 将传感器转到有效负载中的指定位置
m 测量距离
n 开始扫描
w[s] 向前一步
a[s] 向左一步
s[s] 向后一步
d[s] 向右一步

Arduino 端

到目前为止,我们已经成功将蓝牙连接到Arduino端和PC端,还编写了一个很酷的GUI的应用程序,并创建了一个与Arduino通信的协议,但是仍然缺少一些东西:可能在我们发送数据的时候Arduino没有响应。我们需要Arduino运行一个程序来定期检查串行端口,以在出现可用数据时进行处理。让我们来看一下之前用于验证蓝牙连接的代码草图:

void setup() {
 Serial1.begin(9600);
 while(!Serial1);
 Serial1.println("01Hello sir!");
}

String input;
void loop() {
 if(Serial1.available() > 0) {
   input = Serial1.readString();
   switch(input.charAt(0)) {
     case ‘n’:
       //ultrasonic scan
     case ‘m’:
       //measure distance
     //and so on...
   }
 }
}

一旦将数据设置为input中的变量,我们就可以使用它来进行所有操作了。例如,如果要查看刚刚到达的指令类型,我们可以使用input.charAt(0)。此内置函数将返回字符串输入的第一个字符,该字符将与上表中的指令之一相对应。

请注意,通常,每次要将新的草图上传到Arduino时,都必须断开HC-05模块的连接,但是由于我们使用的是Arduino Mega,就有了四个单独的硬件串行端口!因此,我们只需要将蓝牙连接到剩余的端口之一就可以同时进行这些操作了。

需要记住的另外一件事是,与使用USB的连接不同,通过蓝牙将Arduino连接到PC不会经常重置Arduino。为了正确启动,您必须手动按下Arduino的重置按钮!

结论

六足机器人是一个相当复杂的项目。与往常一样,该项目还有很大的提升空间。目前,唯一板载的传感器是超声波测距仪,但是由于我们使用的Arduino Mega还有很多闲置处理能力,我们可以添加其他传感器以获取更高级的功能。

对,您已经通过ArduPod的上一篇教程实现了!本教程分为三部分来尽可能全面地讲述所有内容。如果您有任何疑问或者改进的建议,请随时在AI千集(https://aiqianji.com/openoker/ArduPod/issues)上与我分享您的想法。您可以前往“Issues”区域创建一个新的问题。如果您已经进入到我的页面中并且喜欢该项目,可以留下一颗星。当然,如果您打算构建自己的ArduPod,请一定要与世界分享您的创造!