简介
如果您对机器人感兴趣,现在是建造机器人的最佳时机。 价格公道的基本部件,种类丰富的微控制器平台,随处可见的在线论坛支持,这些因素使机器人变得平民化,人们可以凭借兴趣自己动手组装机器人。 本文研究了机器人领域的一个激动人心的新增部件,该部件由 DFRobot* 开发,请点击 DFRobot.com获取该部件。 该部件被称为“Devastator”,是一种它具备机器人移动坦克平台,能够出色地实现基本功能,如到处移动和检测对象。 它也具备一些高级特性,例如拍照后自动上传至云! 英特尔® Edison 模块的新增部件是设备“大脑”的最佳选择,能够提供图像分析所需的处理能力,可以通过蓝牙*远程控制,甚至可以通过 Wi-Fi* 连接至互联网。
组装 Devastator 机器人
在开始之前,请务必验证并熟悉所有部件,并预留 2 到 3 个小时的时间完成项目。 网上的说明非常简单明了,但是需要集中注意力。
请准备以下部件:
- 一个 2 - 4 毫米的小型十字螺丝刀和平头螺丝刀。
- 一个活动扳手或尖嘴钳。
首先需要下载 Devastator 说明,请访问 https://www.dfrobot.com/(搜索 Devastator)。 选择 Edison 版本。 截止本文撰写之时,部件编号为 #ROB0125。
组装之后,通过这个业余技能水平项目,您将更深入地了解基本机器人结构。 最终,您能够熟练组装通用坦克底盘的轴、轮、电子装置及两种电机。
首先安装轴,然后将两个直流电机连接到履带传动链轮。 在橡胶接触地面前,不要安装履带(连接)。 首次运行前,需要在店铺内进行几项测试。 将轴连接到底座时,建议留出 1 厘米的间隙。 上述内容可参阅说明。
然后,在底板建造电池组和主板。 需要指出的是,请使用塑料压铆螺母柱,防止焊点接触金属。否则会引起接地,对电路造成不可修复的损坏。 将自己接地,或者凭借常识小心使用主板。
最后,连接所有电路,准备实验室台架测试。 记录建造过程中所连接的针脚。 请记住,在 Romeo 开发板中,硬件 PWM(脉冲宽度调制)的针脚数为 3 针、5 针、6 针和 9 针。 将绝缘胶带缠绕在裸露的引线周围,如图片中直流电机上的接线柱。 另外,建议您将所有电线连接在一起,确保没有明线通过接线板接地。
下表总结了本项目所选的引角。 突出显示 PWM 针脚:3、5、6 和 9。
针 | 数字 GPIO 连接 |
2 | 存在红外线 |
3 | 转动架底部旋转伺服电机 |
4 | 超声波测距仪 (Comp) |
5 | 转动架顶部倾斜伺服电机 |
6 | 蜂鸣器 |
7 | 左 LED 灯 |
8 | 右 LED 灯 |
9 | 超声波测距仪 (Vcc、Gnd 和 PWM) |
10 | 空白 |
11 | 空白 |
12 | 空白 |
13 | 空白 |
此时,无论是否具有网络摄像头或距离检测支持,您都可以选择继续。 顶部面板通过 4 组 M4 螺母螺栓固定,您也可以继续建造顶部转动架(也被称为 6 脚底座旋转套件)。 顶部部件是底部伺服电机的基座,支持顶部转动架和附加传感器(网络摄像头和距离检测器)旋转。 建造 6 脚底座需要不到半小时的时间。
建造顶部转动架(6 脚)
建造转动架时,请不要拧紧螺丝钉,避免接触伺服电机。 底部和顶部伺服电机的设计导致这个错误很常见。 请再次熟悉坦克的整体结构,了解所有的工作部件。 收尾之前,再次检查电线是否正确连接。 如果选择使用顶部转动架,建议使用外加电源输入插座。 这样,可以稳定伺服电机的额外功耗,满足更高的功率突增要求(使用 Wi-Fi 无线电引起的)。
机器人基础知识
在启动机器人之前,让我们回顾机器人基础知识,以了解其内部原理,加深对机器人电子学的基本认识。
电压与电流
微控制器与附属组件的额定电压通常为 5.0 伏或 3.3 伏,额定电流不足 1 安培。 电压表示任何指定时间内通过设备的潜在电量。 在处理电子设备时,有必要了解电压和电流的不同,避免毁坏设备。
微控制器主板的输入电压为 9 - 12 伏,甚至更高,然而,对于每个连接至主板的组件,工作额定电压与最大额定电压低很多。 通过微控制器主板上的降压型转换器将电压降至安全等级。 电压高于设备的额定电压时,设备将烧毁,遭受潜在破坏。 面向英特尔® Edison 模块的 Romeo 开发板已经配备了降压型电压转换器。 如欲了解更多信息,请访问维基百科*: https://en.wikipedia.org/wiki/Voltage_regulator_module
电压表示潜在电量,电流表示任何指定时间内,实际通过设备的电量。 您可能听过一句话“造成生命危险的是电流,而不是电压。” 根据定义,电压只是电源(如墙、电池)一端的潜在电量。 只有形成电路,才会有电流经过。电流流速通常受第三个因素控制 - 电阻。
电路的最常见介质是铜线,电阻极低,1 英寸的铜线电阻只有 8.82e - 6 欧姆。 相比之下,人类皮肤在最极端条件下(潮湿环境中)的电阻是 1000 欧姆。 人类能感知 0.001 安(1 毫安)左右的电流,10 毫安的电流将引起肌肉收缩。 因为多数微控制器将电压限制在 20 伏以内,如此低的电流中工作不会产生安全隐患。
功耗
为了维持运转,所有组件需要使用(消耗)一定的电流。 如果施加了额外负载,电机对电流的需求将增加。 因此,直流电机特别需要一个外加电源,电源电压应高于 LED、传感器等其他组件。 使用直流电机时,一定要配备电机控制器和二极管保护装置,避免开关电机时出现反电动势。 如欲了解有关此话题的更多详细信息,可以在线搜索 “直流电机”与“反电动势”。
常见电压与电流范围示例:
设备 / 组件 | 直流电压 | 最小 / 最大电流 |
英特尔® Edison 模块 | 7 伏 - 15 伏 | 1 安输入 |
200 毫安消耗(开启 Wi-Fi 时达到 600 毫安) | ||
英特尔® Edison GPIO Pin @3.3 伏 | 1.8 伏 - 3 伏输出 | 24 毫安 |
英特尔® Edison GPIO Pin @5 伏 | 1.8 伏 - 3 伏输出 | 32 毫安 |
常见 LED | 1.8 伏 - 4 伏 | 20 毫安 |
有刷直流电机 | 6 伏 - 9 伏 | 取决于堵转电流 |
制动器
制动器受微控制器控制。 常见制动器包括电机、LED 与蜂鸣器。 每种设备对这些组件的控制方式各不相同。 例如,通过连接与限流电阻器相结合的 GPIO 针,可以开启或关闭 LED。 只需让电流通过二极管,二极管便会发光。 电流越多,二极管越亮。 然而,脉冲宽度调制 (PWM) 技术可以有效控制电机,该技术以快速切换开关的方式控制输入电机的电压。
PWM 基础知识
直流电机没有连续流动的电流。 它采用脉冲宽度调制 (PWM) 技术,能快速打开或关闭电流。 使用 PWM 时,电机开启时间由基础信号(以特定频率振荡)和“工作周期”(波振荡时信号频率较高(开启)的总时间)控制。 如果已知基于硬件的定时器产生 1 赫兹(每秒一次)的频率,将工作周期设置为 0.5,灯会闪烁(开启 0.5 秒,关闭 0.5 秒)。 将信号开启的时间设置为 1 秒时,灯闪烁的频率会降低。
伺服电机
伺服电机和直流电机工作原理相似,但是前者拥有准确的位置精度,能在特定位置停止并保持不动。 如欲获取有关伺服电机的详尽介绍,请访问: 伺服电机简介
传感器
检测对象存在和感知对象距离的能力使机器人更加智能。 PIR(被动红外)利用标准 GPIO 针脚,可以用于检测电磁场的变化。 由于所有物体都会发出辐射,这个敏感的设备甚至能够检测出细微的光线变化。 https://en.wikipedia.org/wiki/Passive_infrared_sensor
另一个非常出色的传感器是超声波测距传感器(一种距离指示器)。 该传感器使用超声波测量对象的距离,通过对象反射回来的声波来检测返回时间。 和警用雷达速度检测器上的老式雷达相似,但是有所不同,传感器使用的是声波,而非无线电波。 这个设备价格便宜,但是只能用于短距离测距,而且周围环境必须清洁,不能有灰尘或雪。
了解面向英特尔® Edison 模块的 Romeo 开发板
Romeo 开发板为 Devastator 机器人大脑提供多种能力,如移动电机、感知环境和开关指示灯的能力。 该平台包含 14 个 GPIO 针 (4 个 PWM)、内置 H 桥电机驱动程序、SPI 与 I2C 功能、针对外部电源连接的专用连接和一个英特尔® Edison 模块,是一个支持入门级移动机器人项目的强大开发板。 这个平台的优势是它的可扩展性。 底盘性能出色,可以随意在上面添加或安装外加电源与组件。 如欲获取更多信息,请访问 DFRobot.com,下载 Romeo 开发板的完整示意图。
电源
DFRobot* Devastator 套件配备的标准电池组是 6x1.5 v AA 电池组,总源电压为 9 伏。 最大输入电压能够支持高达 12 伏的外加电源输入。 需要注意的是,尽管外加电压可以作为输入电压,但是在任意指定时间,开发板为 GPIO 针提供 3.3 伏电压,还要为电机控制器电路提供单独的控制电压。 可以连接标有“伺服电源”的单独电源插座,为伺服控制提供外加电源。 如果整个平台只在 9V (AA x 6) 电池组上运行,并行操作(如直流电机定向移动、伺服电机平移和 Wi-Fi 上传激增)几乎耗尽 9V 电池组的电量。 直流电机驱动程序自身需要的恒定电流是每个电机 2 安。 提前了解了这些,强烈建议您购买可充电电池。 坦克开启后,将在短距离内迅速耗尽 AA 标准碱性电池中额定 2,500 毫安的电量。 可以添加一组 9 伏可充电电池,输入电压将达到 18 伏。 此外,针对伺服电机插座的单独输入电源也是非常不错的选择,为开发板提供外加电源,减少主输入的电流功耗。 如果选择连接伺服输入,不要高于伺服电机和连接设备的输入电压。
电机控制
如示意图所示,直流电机连接至电源输入插座附近,直接连接至 H 桥驱动程序 IC(该驱动程序 IC 执行前向运动和反向运动所需的电压偏置)。 英特尔® Edison 模块是开发板的主要控制器,电机控制器 IC 实际由一个 Atmel ATMega8 MCU 驱动。 伺服电机分别连接至 GPIO 轨 PWM 专用针脚,通过计时信号驱动(和其他伺服控制一样)。 如上文所述,如果选择为伺服输入补充额外电压,不要高于伺服电机的输入电压。
数据与串行连接
相对于输入电源,开发板的另一端是 micro-USB 连接。 带有 COM 标记的串行连接可能是您使用的第一个连接。 该端口支持连接至英特尔® Edison 模块,启动终端 shell 会话,进而配置 Edison,连接 Wi-Fi,甚至在外壳内配置并下载附加软件组件。 但是不能进行数据传输。第二个连接是 USB/OTG 连接,主要用于上传 Arduino* 风格方案至开发板。 建议您连接线缆,在工作台测试时断开与电脑的连接。 由于是物理连接,多次插入和拔出增加损坏输入端口的风险。 最初的测试将频繁地连接与断开,所以建议使用电脑的连接,而不是开发板的微型连接。
有一个附加连接值得一提 - FTDI 连接。 需要更新开发板上的 ATMega8 固件,以解决 I2C 稳定性方面的已知问题。 更新对保证直流电机正常运转非常必要,会在后面的章节介绍。
固件编码
为了设备的有效运转,必须创建软件,并上传至英特尔® Edison 模块。 可以采用多种不同方法。
首先,因为英特尔® Edison 模块运行 linux* 操作系统 (Yocto Linux),一种方法就是编写一个 C、C++ 或 Python* 程序,并在操作系统上直接运行(和其他在 Linux 操作系统上运行的应用相同)。 社区里已经存在许多库,可以获取英特尔® Edison 模块上的所有硬件。 可以免费安装库(如简单的 GPIO 针访问、Wi-Fi 与 Bluetooth),并利用库编码。 只需编写一个程序,运行标准 make 程序,便可创建可执行程序。
在 Edison 模块编程的第二种方法是使用大家所熟悉的 Arduino* 库和 IDE,本文对第二种方法进行了详细说明。 利用 Arduino 编程非常简单,通过 CLLoader Arduino 仿真器(一个运行在 Linux 操作系统上的服务)即可在英特尔® Edison 模块上编程。 英特尔® Edison 模块上,该服务设置为默认运行,无需上传或运行 Arduino 方案。 和其它 Arduino MCU 兼容性平台相同,只需连接到开发板,并上传方案。 可以通过简单的 ps 命令来验证 clloader 程序是否在 Linux shell 中运行。
使用 Arduino 开始编程前,请访问 https://www.arduino.cc/en/Main/Software,以下载最新版 Arduino IDE。
最后,最新版英特尔 XDK® 支持通过 Wi-Fi 上传方案。 XDK 使用的开发语言是 Node JavaScript* (Node.JS*),在现有库和封装器中不断发展。 编译并上传应用至守护程序,后者在英特尔® Edison 模板上直接运行,运行方式和 Arduino 方案相似,但是通过不同的服务。
设置
在进行外设测试前,首先确保所有固件是最新版,并且安装了驱动程序。 连接至 COM 端口(不是 OTG 端口),确保其可见。通过执行 Windows* 的“设备管理器”,并导航至端口,以纠正串行 COM 端口上的波特率。 该连接是默认串行连接,可以用于远程访问设备,并运行一个 Linux shell 会话。
然后,连接至数据 OTG 连接。 通过该连接,将方案与代码更新为英特尔® Edison 模块。
下载英特尔® Edison 模块的相关软件
驱动程序与设置
https://software.intel.com/zh-cn/iot/hardware/edison/downloads
Flashtool 固件
https://software.intel.com/zh-cn/using-flash-tool-lite
最后,下载最新版 Poky 映像,运行 flashtool,并利用最新版 Linux 映像更新英特尔® Edison 模块。
https://software.intel.com/zh-cn/iot/hardware/edison/downloads
通过 FTDI 连接更新 ATMega8* MCU
通过本次更新,将获取最新版 ATMega8,确保修复全部 I2C 故障,该故障会引起电机启动问题!
https://www.dfrobot.com/wiki/index.php/Romeo_for_Edison_Controller_SKU:_DFR0350#Atmega8_Firmware_Upgrade
利用 PuTTY 配置英特尔® Edison 模块通过端口识别的串行设置进行连接,并运行 ssh 命令(ssh 作为不带密码的“根”)。 请务必按 enter 键以完成连接。
请点击以下链接下载 PuTTY: http://www.putty.org/
运行 “configure-edison -setup”,按照提示完成安装。 在 Wi-Fi 可用的情况下,可以选择连接到 Wi-Fi。
更新英特尔® Edison 模块,支持方案加载启动
对于默认脚本加载器,Poky 映像的最新分发包没有正确设置加载器权限。 该步骤强制执行,确保上传的最后一个映像在设备下次开机时执行。 共有 4 个需要上传的文件。
下载更新文件
https://github.com/gameswarp/edison-clloader
备份当前文件,然后利用 WinSCP将下载文件传输到 /opt/edison 文件夹。
下载 WinSCP: https://winscp.net/eng/download.php
上传文件后,选择新文件并点击 F9,将 4 个文件更改为可执行文件。
可以通过 diff 命令来验证新上传的脚本是否产生变化,也可以手动验证。
如欲了解有关该流程的更多详细信息,请访问: https://communities.intel.com/thread/77945
导入 Arduino* 库
Arduino basics 能够连接并识别设备,正确安装开发板驱动程序和库,下载常见库支持,并将其安装到正确位置。
添加库支持非常简单,和查找代码,在 Arduino\library 文件夹中复制文件夹和文件一样简单。 Arduino IDE 还有一个 “Import As Zip” 选项,但是如果库供应商没有遵循正确的流程与结构,这个选项不可用。 最关键的是,将库添加至 Arduino 和在库文件夹中创建文件夹一样简单。 您还会发现,多数库配有示例子文件夹,下一次启动时,将在 Arduino IDE 下的下拉框中显示详细示例。 如欲了解更多信息,请访问以下链接: https://www.arduino.cc/en/Reference/Libraries
安装 Arduino IDE
步骤 1: 确保 Arduino IDE 配备有英特尔® Edison 模块 i686 开发板支持。 通过英特尔® Edison 模块的安装程序安装最新版 Arduino 后,将配备该支持。
请确保已经安装了英特尔® Edison 模块 i696 开发板支持: [Tools--►Boards--►Board Manager]
步骤 2: 安装 DFRobot 库
https://github.com/ouki-wang/Devastator-Tank-Mobile-Platform-with-Edison
将 DevastatorEdison文件夹复制到 Arduino Library 文件夹中。
[SKETCH--►Include Library--►Manage Libraries].
搜索 DFRobot,并单击 Install按钮。
步骤 3: 运行快速测试
为了验证 DFRobot 库支持是否可用,需要创建快速方案,并引用库提供的类别。 如果代码开始编译,可以进行设备的预发布测试。 如果代码没有开始编译,重启 Arduino IDE 或手动验证库是否正确安装。
#include <DFRobot.h> #include <IIC1.h> DFrobotEdison leftMotor; void setup() {} void loop() {}
预发布测试
在发布测试版 Devastator 机器人前,建议对一系列基本框架测试进行编码,确保功能正常。 预先执行稳定可以尽早确认缺陷,缩短今后特性开发的周转时间。
基本测试
- 控制电机 - 前进、后退、左转与右转
- 开启灯
- 开启蜂鸣器
- 对象检测
总的来说,请务必缓慢运行测试,验证了较小范围内操作后,才能全速或全角运行电机。 本项目测试案例集应当确保每一个组件可操作。 将输出预期行为的 Serial.print() 命令添加至记录控制台,这样做非常有用。 提前完成上述操作将增加您在环境中运行的信心。 DFRobot 套件(电气零件配件盒)中有一个组件,轮间隙较大,非常适合用作底座。不管是否连接履带,都可以进行 DFRobot 预发布测试。
示例 API
- IsObjectDetected()
- SoundBuzzer()
- FlashLights()
- StopMotors()
- TurnLeft()
- TurnRight()
- SetDirection()
- GoStraight()
- TurnAround()
- Backup()
- StartupWarning()
传感器测试
/* * This example will test the following items: * - PIR Sensor * - Left and Right LEDs * - Buzzer * OVERVIEW: * On Presence, flash lights and emit tone. * Tone should change each time PIR is triggered * * Matt Chandler * Intel, Corp. * December 2016 */ byte presencePin = 2; byte leftLED = 7; byte rightLED = 8; byte buzzerPin = 6; bool buzzerOn=true; void setup() { pinMode(presencePin, INPUT); pinMode(leftLED, OUTPUT); pinMode(rightLED, OUTPUT); pinMode(buzzerPin, OUTPUT); Serial.begin(9600); } void loop(){ if (IsObjectDetected()) { flashLights(); soundBuzzer(); } } bool IsObjectDetected() { return digitalRead(presencePin)==1 ? true:false; } void soundBuzzer() { if (!buzzerOn) return; int delay=200; unsigned int buzzerTone = 100; for(int i=0;i<4;i++) { tone(buzzerPin, buzzerTone, delay); } noTone(buzzerPin); } void flashLights() { digitalWrite(leftLED,1); delay(200); digitalWrite(leftLED,0); delay(500); digitalWrite(rightLED,1); delay(200); digitalWrite(rightLED,0); }
MOTOR TEST
/* * Sample DFRobot Motor Tests * * goStraight(), turnLeft(), turnRight(), stopMotors() * * Matt Chandler * Intel, Corp. * December, 2016 */ #include <DFRobot.h> #include <IIC1.h> DFrobotEdison leftMotor; DFrobotEdison rightMotor; bool directionToggle = false; byte currentSpeedRight = 0; byte currentSpeedLeft = 0; byte leftLED = 7; byte rightLED = 8; byte DIRECTION_LEFT = 0; byte DIRECTION_RIGHT = 1; byte startupDelaySeconds = 5; void setup() { leftMotor.begin(M2); rightMotor.begin(M1); pinMode(leftLED, OUTPUT); pinMode(rightLED, OUTPUT); Serial.begin(9600); } void loop(){ startupWarning(); goStraight(150, 2);//speed, distance turnLeft(45, 2); goStraight(150, 2);//speed, distance turnRight(45, 2); goStraight(150, 2);//speed, distance stopMotors(); backup(150,2); } void startupWarning() { stopMotors(); Serial.println(""); Serial.print("Getting ready in "); Serial.print(startupDelaySeconds); Serial.println(" seconds"); for (int i=startupDelaySeconds; i > 0; i--) { Serial.print(""); Serial.print(i); digitalWrite(leftLED,1); digitalWrite(rightLED,1); delay(500); digitalWrite(leftLED,0); digitalWrite(rightLED,0); delay(500); } Serial.println(""); Serial.println("GO!!"); } void setDirection(const uint8_t dir) { leftMotor.setDirection(dir); rightMotor.setDirection(dir); } void goStraight(byte speed) { stopMotors(); setDirection(ANTICLOCKWISE); leftMotor.setSpeed(speed); rightMotor.setSpeed(speed); } void stopMotors() { leftMotor.stop(); rightMotor.stop(); delay(1000); } void goStraight(byte speed, int durationSeconds) { Serial.println(""); Serial.println("Going straight"); currentSpeedRight = speed; currentSpeedLeft = speed; delay(500); goStraight(speed); delay(durationSeconds*1000); } void backup(byte speed, int durationSeconds) { stopMotors(); setDirection(CLOCKWISE); leftMotor.setSpeed(speed); rightMotor.setSpeed(speed); delay(durationSeconds*1000); } void turnLeft(byte angle, int durationSeconds) { turn(DIRECTION_LEFT, angle, durationSeconds*1000); } void turnRight(byte angle, int durationSeconds) { turn(DIRECTION_RIGHT, angle, durationSeconds*1000); } void turn(byte direction, byte angle, byte durationMS) { DFrobotEdison motor; String directionText; byte directionPin; //Ensure going straight first byte currentSpeed = currentSpeedLeft = currentSpeedRight; if (direction == DIRECTION_LEFT) { directionText = "Left"; motor = leftMotor; directionPin = leftLED; } else { directionText = "Right"; motor = rightMotor; directionPin = rightLED; } delay(500); digitalWrite(directionPin,1); // Take current right speed and lower left motor by mapped value //Convert angle to speed where 0 is straight ahead byte newSpeed = map(angle, 0, 90, 0, currentSpeed); Serial.print("Turning "); Serial.print(directionText); Serial.print(" at angle "); Serial.print(angle); Serial.print("Current Speed: "); Serial.println(currentSpeed); Serial.print("New speed: "); Serial.println(newSpeed); delay(250); motor.setSpeed(newSpeed); Serial.print("Turning "); Serial.print(directionText); Serial.print(" now for "); Serial.print(durationMS/1000); Serial.println(" seconds."); delay(durationMS); digitalWrite(directionPin,0); Serial.println(""); }
准备上路
<img a9="" alt="" src=" c8=""="" default="" df="" edison="" files="" https:="" managed="" p="" sites="" software.intel.com="" title=""英特尔机器人、构造" usb="">
您的机器人已经通过了基本测试,现在可以完成组装了。 在执行最后步骤之前,建议您上传一份空白方案或简单的灯光闪烁测试,以避免开启坦克时执行之前的电机代码。 关闭电池,然后谨慎地将履带放置于坦克两侧的链轮。 闪存一份之前创建的测试移动方案,断开 USB 连接,并将您的坦克放到地上。 打开电池开关,开始执行方案!
以下是一个基本方案,帮助您开启探索之旅。 在调转方向前,建议执行 motorOff() 调用,希望您修改代码,并乐在其中。
按需行进
/* * Sample DFRobot Motor and Lights test * * Wait for PIR Sensor detection * Go Forward * Turn Around 2 x 180' * Return to position by backing up * If object is detected in rear, attempt to go around it by altering angle * * * * Matt Chandler * Intel, Corp. * December, 2016 */ #include <DFRobot.h> #include <IIC1.h> bool testFlag = false; DFrobotEdison leftMotor; DFrobotEdison rightMotor; byte presencePin = 2; byte leftLED = 7; byte rightLED = 8; bool directionToggle = false; byte currentSpeedRight = 0; byte currentSpeedLeft = 0; byte DIRECTION_LEFT = 0; byte DIRECTION_RIGHT = 1; byte startupDelaySeconds = 5; double turnAroundTimeSeconds = 4; byte turnAroundSpeed = 100; byte buzzerPin = 6; bool buzzerOn=true; void setup() { leftMotor.begin(M1); rightMotor.begin(M2); pinMode(leftLED, OUTPUT); pinMode(rightLED, OUTPUT); Serial.begin(9600); } void loop(){ stopMotors(); if (IsObjectDetected()) { startupWarning(); if(testFlag) { turnAround(); stopMotors(); } else { goStraight(200, 6);//speed, distance turnAround(); //180 goStraight(200, 2);//speed, distance turnAround(); backup(200,8); //Go backwards if(IsObjectDetected()) { soundBuzzer(); backup(200,4); Serial.println("Object Detected"); goStraight(200, 2);//speed, distance turnLeft(45, 4); turnRight(45, 4); goStraight(200, 3);//speed, distance } turnAround(); } } } void startupWarning() { Serial.println(""); Serial.print("Getting ready in "); Serial.print(startupDelaySeconds); Serial.println(" seconds"); for (int i=startupDelaySeconds; i > 0; i--) { Serial.print(""); Serial.print(i); digitalWrite(leftLED,1); digitalWrite(rightLED,1); delay(500); digitalWrite(leftLED,0); digitalWrite(rightLED,0); delay(500); } Serial.println(""); Serial.println("GO!!"); soundBuzzer(); } void setDirection(const uint8_t dir) { leftMotor.setDirection(dir); rightMotor.setDirection(dir); } void goStraight(byte speed) { stopMotors(); rightMotor.setDirection(ANTICLOCKWISE); leftMotor.setDirection(ANTICLOCKWISE); delay(500); leftMotor.setSpeed(speed); rightMotor.setSpeed(speed); } void backup(byte speed, int durationSeconds) { stopMotors(); rightMotor.setDirection(CLOCKWISE); leftMotor.setDirection(CLOCKWISE); leftMotor.setSpeed(speed); rightMotor.setSpeed(speed); delay(durationSeconds*1000); } void stopMotors() { Serial.println("Stopping motors"); leftMotor.stop(); rightMotor.stop(); delay(3000); } void goStraight(byte speed, int durationSeconds) { Serial.println(""); Serial.println("Going straight"); currentSpeedRight = speed; currentSpeedLeft = speed; goStraight(speed); delay(durationSeconds*1000); } void turnLeft(byte angle, int durationSeconds) { turn(DIRECTION_LEFT, angle, durationSeconds*1000); } void turnRight(byte angle, int durationSeconds) { turn(DIRECTION_RIGHT, angle, durationSeconds*1000); } void turnAround() { stopMotors(); Serial.println("Turning around"); leftMotor.setDirection(CLOCKWISE); rightMotor.setDirection(ANTICLOCKWISE); rightMotor.setSpeed(turnAroundSpeed); leftMotor.setSpeed(turnAroundSpeed); delay(turnAroundTimeSeconds*1000); stopMotors(); Serial.println("Turned around"); rightMotor.setDirection(ANTICLOCKWISE); rightMotor.setDirection(ANTICLOCKWISE); } void turn(byte direction, byte angle, int durationMS) { if (angle==90) { Serial.println("Angle is 90, turning around"); turnAround(); return; } DFrobotEdison turningMotor; DFrobotEdison oppositeMotor; String directionText; byte directionPin; //Ensure going straight first byte currentSpeed = currentSpeedLeft = currentSpeedRight; if (direction == DIRECTION_LEFT) { directionText = "Left"; turningMotor = leftMotor; oppositeMotor = rightMotor; directionPin = leftLED; } else { directionText = "Right"; turningMotor = rightMotor; oppositeMotor = leftMotor; directionPin = rightLED; } delay(1000); digitalWrite(directionPin,1); // Take current right speed and lower left motor by mapped value //Convert angle to speed where 0 is straight ahead byte newSpeedOfTurningMotor = map(angle, 0, 90, 0, currentSpeed); Serial.print("Turning "); Serial.print(directionText); Serial.print(" at angle "); Serial.println(angle); Serial.print("Current Speed: "); Serial.println(currentSpeed); Serial.print("New speed: "); Serial.println(newSpeedOfTurningMotor); delay(250); turningMotor.setSpeed(newSpeedOfTurningMotor); Serial.print("Turning "); Serial.print(directionText); Serial.print(" now for "); Serial.print(durationMS/1000); Serial.println(" seconds."); delay(durationMS); digitalWrite(directionPin,0); Serial.println(""); turningMotor.setSpeed(currentSpeed); oppositeMotor.setSpeed(currentSpeed); } bool IsObjectDetected() { return digitalRead(presencePin)==1 ? true:false; } void flashLights(byte seconds) { for (int i=0;i<seconds;i++) { digitalWrite(leftLED,1); delay(200); digitalWrite(leftLED,0); delay(seconds); digitalWrite(rightLED,1); delay(200); digitalWrite(rightLED,0); } } void soundBuzzer() { if (!buzzerOn) return; int delay=200; unsigned int buzzerTone = 100; for(int i=0;i<4;i++) { tone(buzzerPin, buzzerTone, delay); } noTone(buzzerPin); }
高级策略
机器人已经可以移动了,您可以继续改进 Arduino 代码库中的代码,或者扩展上文提到的不同开发选项。 有一个开发选项将使您直接通过 C 开发或英特尔 XDK® 中的 JavaScript 封装器,深入了解 mraa (读音为 “m-rah”)Linux 库。 迁移至英特尔 XDK® 后,可以通过无线方式对程序进行编程,这个特性非常不错,使您无需连接到设备,便可上传经典 Arduino 方案。 如欲了解更多高级特性,包括 mraa 讨论及 Wi-Fi 摄像头功能,请查看以下其他文章:
关于作者
Matt Chandler 是英特尔公司的一名高级软件工程师,负责大规模物联网项目的支持工作。
参考资料
Arduino* 下载
https://www.arduino.cc/en/Main/Software
DFRobot* 产品说明
https://www.dfrobot.com/wiki/index.php/Romeo_for_Edison_Controller_SKU:_DFR0350
WinSCP 下载 – 面向安全文件传输
https://winscp.net/eng/download.php
PuTTY 下载 – 确保外壳安全访问 Edison
http://www.putty.org/
被动红外检测 (PID) 传感器 Wiki
https://en.wikipedia.org/wiki/Passive_infrared_sensor
确保保存方案 - 利用 Poky distro 修复已知映像,截至 2016 年 6 月
https://communities.intel.com/thread/77945
伺服电机简介
http://www.sciencebuddies.org/science-fair-projects/project_ideas/Robotics_ServoMotors.shtml
蜂鸣器示例代码
https://www.arduino.cc/en/Tutorial/ToneMelody?from=Tutorial.Tone
USB OTG 连接
https://en.wikipedia.org/wiki/USB_On-The-Go
声明
本文件不构成对任何知识产权的授权,包括明示的、暗示的,也无论是基于禁止反言的原则或其他。
英特尔明确拒绝所有明确或隐含的担保,包括但不限于对于适销性、特定用途适用性和不侵犯任何权利的隐含担保,以及任何对于履约习惯、交易习惯或贸易惯例的担保。
本文包含尚处于开发阶段的产品、服务和/或流程的信息。 此处提供的信息可随时改变而毋需通知。 联系您的英特尔代表,了解最新的预测、时间表、规格和路线图。
本文件所描述的产品和服务可能包含使其与宣称的规格不符的设计缺陷或失误。 这些缺陷或失误已收录于勘误表中,可索取获得。
索取本文件中提的、包含订单号的文件的复印件,可拨打1-800-548-4725,或登陆www.intel.com/design/literature.htm。
英特尔、Intel 标识、Intel RealSense 和英特尔实感是英特尔在美国和/或其他国家的商标。
*其他的名称和品牌可能是其他所有者的资产。
**该示例源代码根据英特尔示例源代码许可协议发布。
英特尔公司 © 2016 年版权所有。