亿迅智能制造网
工业4.0先进制造技术信息网站!
首页 | 制造技术 | 制造设备 | 工业物联网 | 工业材料 | 设备保养维修 | 工业编程 |
home  MfgRobots >> 亿迅智能制造网 >  >> Manufacturing Technology >> 制造工艺

制作 Arduino 麦克纳姆轮机器人:360° 全向移动 DIY 指南

概述

本教程将学习如何制作一台 Arduino 麦克纳姆轮机器人,它能向任意方向移动。这种独特的机动性是通过使用一种特殊车轮——麦克纳姆轮实现的。

您可以观看以下视频或阅读下面的文字教程。

我实际上设计并 3D 打印了这些车轮,因为购买它们有点贵。它们工作得相当不错,我必须说驾驶这个机器人平台非常有趣。我们可以使用 NRF24L01 无线收发模块无线控制机器人,或者在我的案例中,我使用我之前视频中制作的 DIY RC 发射器。

制作 Arduino 麦克纳姆轮机器人:360° 全向移动 DIY 指南

我还使其可以通过智能手机蓝牙控制。我制作了一个自定义 Android 应用程序,通过它我们可以控制麦克纳姆轮机器人向任意方向移动。此外,使用应用中的滑块还可以控制移动速度。

制作 Arduino 麦克纳姆轮机器人:360° 全向移动 DIY 指南

这台机器人平台的大脑是 Arduino Mega 开发板,它单独控制每个车轮。每个车轮连接在一个 NEMA 17 步进电机上,利用步进电机可精确控制的特性,我在应用中添加了一个很酷的功能:可编程自动移动。使用“保存”按钮可保存每个位置或步骤,然后机器人可自动运行并重复这些步骤。同一按钮也可暂停自动操作、重置或删除所有步骤以存储新步骤。

麦克纳姆轮机器人 3D 模型

首先,我使用 3D 建模软件设计了这台麦克纳姆轮机器人。机器人的基础平台是一个简单的盒子,我将用 8mm 厚的 MDF 板制作。

制作 Arduino 麦克纳姆轮机器人:360° 全向移动 DIY 指南

四个步进电机安装在平台上,麦克纳姆轮安装在电机轴上。

您可以在 Thangs 上找到并下载此 3D 模型,也可在浏览器中探索。

制作 Arduino 麦克纳姆轮机器人:360° 全向移动 DIY 指南

从 Thangs 下载组装 3D 模型。

STL 文件用于 3D 打印:

麦克纳姆轮工作原理

麦克纳姆轮是带有滚轮的车轮,滚轮安装在轮子圆周上。这些滚轮相对于车轮旋转轴呈对角线或 45 度角定位。这使得车轮在前进或后退时施加对角线方向的力。

制作 Arduino 麦克纳姆轮机器人:360° 全向移动 DIY 指南

因此,通过以特定模式旋转车轮,我们利用这些对角线力,使机器人能向任意方向移动。

我们还应注意,需要两种麦克纳姆轮,通常称为左手和右手麦克纳姆轮。它们的区别在于滚轮朝向,必须按特定位置安装在机器人上。每个车轮顶部滚轮的旋转轴应指向机器人中心。

制作 Arduino 麦克纳姆轮机器人:360° 全向移动 DIY 指南

这里快速演示机器人根据车轮旋转方向如何移动。

如果四个车轮都前进,机器人合成运动为前进;反之全后退则后退。向右移动时,右侧车轮需向内旋转,左侧车轮向外旋转,对角线滚轮产生的合力使机器人向右移动。向左移动则相反。仅旋转两个车轮也可实现对角线方向移动。

制作麦克纳姆轮机器人

尽管如此,现在让我展示如何构建这个机器人平台。如前所述,平台基座使用 8mm 厚 MDF 板。用台锯根据 3D 模型尺寸切割所有零件。

制作 Arduino 麦克纳姆轮机器人:360° 全向移动 DIY 指南

接下来用 3mm 钻头和 25mm 福斯纳钻头在侧板上开孔安装步进电机。零件准备好后开始组装。使用木胶和螺丝固定。最重要的是电机安装孔必须精确,以便所有车轮稍后与地面均匀接触。

制作 Arduino 麦克纳姆轮机器人:360° 全向移动 DIY 指南

当然,您也可以 3D 打印这个基础平台,而不是用 MDF 制作,我将在网站文章中提供其 3D 文件。最后给底座和盖子喷白漆。

制作 Arduino 麦克纳姆轮机器人:360° 全向移动 DIY 指南

接下来是麦克纳姆轮。如前所述,购买较贵,所以我决定自己设计并 3D 打印。车轮由外侧和内侧两部分组成,用 M4 螺栓螺母固定。每个轮子有 10 个滚轮,并有专门设计的轴联轴器适配 NEMA 17 步进电机。

制作 Arduino 麦克纳姆轮机器人:360° 全向移动 DIY 指南
制作 Arduino 麦克纳姆轮机器人:360° 全向移动 DIY 指南

我用 Creality CR-10 3D 打印机打印所有麦克纳姆轮零件。

这是这款 3D 打印机的链接,如果您想了解。

制作 Arduino 麦克纳姆轮机器人:360° 全向移动 DIY 指南

拿到 3D 打印零件后,开始制作滚轮轴。使用 3mm 钢丝。轴长约 40mm,用旋转工具切割至长度。

制作 Arduino 麦克纳姆轮机器人:360° 全向移动 DIY 指南

开始组装麦克纳姆轮:用四个 M4 螺栓螺母固定两侧和轴联轴器。螺栓长度需 45mm。

制作 Arduino 麦克纳姆轮机器人:360° 全向移动 DIY 指南

安装滚轮:先将轴稍微穿过内侧圆周上的孔。

制作 Arduino 麦克纳姆轮机器人:360° 全向移动 DIY 指南

然后放入小 M3 垫圈、滚轮,将轴推入外侧轮子的槽中。我只用单个垫圈,因为另一侧没空间放第二个垫圈。

制作 Arduino 麦克纳姆轮机器人:360° 全向移动 DIY 指南

为所有 10 个滚轮重复此过程。组装这些轮子其实简单又有趣。重要的是滚轮必须能自由转动。

制作 Arduino 麦克纳姆轮机器人:360° 全向移动 DIY 指南

最后在每个内孔滴几滴 AC 胶水,确保轴不会松动。

制作 Arduino 麦克纳姆轮机器人:360° 全向移动 DIY 指南

轮子准备好后,继续组装整个机器人。首先将步进电机安装到底座平台。用长 12mm 的 M3 螺栓固定。

制作 Arduino 麦克纳姆轮机器人:360° 全向移动 DIY 指南

接下来将车轮安装到电机轴上。我制作的轴联轴器有插入 M3 螺母的槽,M3 螺栓穿过以固定车轮到轴上。

制作 Arduino 麦克纳姆轮机器人:360° 全向移动 DIY 指南

接下来为将顶盖固定到底座,在底座两个角落安装螺纹杆。盖子同位置开孔,以便轻松插入和固定盖子。

制作 Arduino 麦克纳姆轮机器人:360° 全向移动 DIY 指南

底座背面开 20mm 孔安装电源开关,以及 5mm 孔安装 LED。

电路图

现在进行电子部分。这是项目的完整电路图。

制作 Arduino 麦克纳姆轮机器人:360° 全向移动 DIY 指南

我们将使用四个 DRV8825 步进驱动器(也可用 A4988)控制四个 NEMA 17 步进电机。为步进电机和整个机器人供电使用 12V 电源,我这里用 3S 锂聚合物电池(约 12V)。无线通信用 NRF24L01 模块,蓝牙通信用 HC-05 蓝牙模块。我还加了一个简单的分压电路监测电池电压,和一个 LED 指示电池电压低于 11V 时亮起。

我还加了一个专用 5V 稳压器(可提供约 3A 电流)。这是可选的,但我计划在未来视频中将此项目与我的 Arduino 机械臂项目结合,届时需要 5V 驱动其舵机。

所需元件

PCB 设计

为了保持电子元件整齐并消除接线混乱,我使用 EasyEDA 免费在线电路设计软件设计了定制 PCB。该 PCB 实际上作为 Arduino MEGA 扩展板,可直接插在 Arduino Mega 板顶部。我使用顶层和底层走线。对于未使用的 Arduino 引脚,我包含了排针连接以备将来使用。还包含 12V、5V 和 GND 连接引脚,以及选择驱动器细分分辨率的引脚。

制作 Arduino 麦克纳姆轮机器人:360° 全向移动 DIY 指南

这是 PCB 设计项目文件链接。设计完成后生成制造所需的 Gerber 文件。

Gerber 文件:

然后从 JLCPCB 订购 PCB(他们也是本视频赞助商)。

制作 Arduino 麦克纳姆轮机器人:360° 全向移动 DIY 指南

拖放 Gerber 文件上传后可在查看器中检查 PCB。一切正常后选择所需 PCB 属性。这次我选蓝色 PCB 以匹配 Arduino 板颜色。现在可按合理价格下单。注意:首次在 JLCPCB 下单可获最多 10 块 PCB 仅需 2 美元。

制作 Arduino 麦克纳姆轮机器人:360° 全向移动 DIY 指南

几天后 PCB 到货。质量很好,与设计完全一致。

制作 Arduino 麦克纳姆轮机器人:360° 全向移动 DIY 指南

PCB 组装

现在组装 PCB。先焊接较小元件:电阻和电容。然后插入并焊接公排针到 PCB,用于连接 Arduino 板。

制作 Arduino 麦克纳姆轮机器人:360° 全向移动 DIY 指南

接下来放置并焊接所有母排针。步进电机连接和细分选择引脚用公排针,这样可直接连接电机并用跳线帽选择细分。然后焊接接线端子、电位器和稳压器。

制作 Arduino 麦克纳姆轮机器人:360° 全向移动 DIY 指南

PCB 现已准备好,继续插入驱动器并连接电机。先放置细分选择跳线帽。我将驱动器的 MS3 引脚接 5V 选择 1/16 细分。

制作 Arduino 麦克纳姆轮机器人:360° 全向移动 DIY 指南

然后在其上放置 DRV8825 驱动器,连接 NRF24L01 模块和 HC-05 蓝牙模块。现在可直接将 PCB 插到 Arduino 板上。

制作 Arduino 麦克纳姆轮机器人:360° 全向移动 DIY 指南

接下来将电池连接到相应接线端子并放入底座平台。

制作 Arduino 麦克纳姆轮机器人:360° 全向移动 DIY 指南

这里安装电源开关并连接到另一个接线端子。电源开关正上方安装电池指示 LED。

制作 Arduino 麦克纳姆轮机器人:360° 全向移动 DIY 指南

剩下的就是将电机连接到 PCB。注意:连接对侧电机时,其连接器也应相反连接。这是为后续编程方便,使得例如前进命令能让两个电机同向旋转,尽管它们实际翻转,一个顺时针一个逆时针。

制作 Arduino 麦克纳姆轮机器人:360° 全向移动 DIY 指南

最后插入顶盖,麦克纳姆轮机器人项目完成。

制作 Arduino 麦克纳姆轮机器人:360° 全向移动 DIY 指南

麦克纳姆轮机器人 Arduino 代码

本视频剩下的就是看 Arduino 代码。其实有两个独立的 Arduino 代码:一个用 NRF24L01 模块控制,另一个用智能手机控制。

使用 NRF24L01 模块控制的 Arduino 代码

/* === Arduino Mecanum Wheels Robot === Radio control with NRF24L01 by Dejan, www.HowToMechatronics.com Libraries: RF24, https://github.com/tmrh20/RF24/ AccelStepper by Mike McCauley: https://www.airspayce.com/mikem/arduino/AccelStepper/index.html */
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <AccelStepper.h>
RF24 radio(48, 49); // nRF24L01 (CE, CSN)
const byte address[6] = "00001";
unsigned long lastReceiveTime = 0;
unsigned long currentTime = 0;
// Define the stepper motors and the pins the will use
AccelStepper LeftBackWheel(1, 42, 43); // (Type:driver, STEP, DIR) - Stepper1
AccelStepper LeftFrontWheel(1, 40, 41); // Stepper2
AccelStepper RightBackWheel(1, 44, 45); // Stepper3
AccelStepper RightFrontWheel(1, 46, 47); // Stepper4
int wheelSpeed = 1500;
// Max size of this struct is 32 bytes - NRF24L01 buffer limit
struct Data_Package {
  byte j1PotX;
  byte j1PotY;
  byte j1Button;
  byte j2PotX;
  byte j2PotY;
  byte j2Button;
  byte pot1;
  byte pot2;
  byte tSwitch1;
  byte tSwitch2;
  byte button1;
  byte button2;
  byte button3;
  byte button4;
};
Data_Package data; //Create a variable with the above structure
void setup() {
  // Set initial seed values for the steppers
  LeftFrontWheel.setMaxSpeed(3000);
  LeftBackWheel.setMaxSpeed(3000);
  RightFrontWheel.setMaxSpeed(3000);
  RightBackWheel.setMaxSpeed(3000);
  radio.begin();
  radio.openReadingPipe(0, address);
  radio.setAutoAck(false);
  radio.setDataRate(RF24_250KBPS);
  radio.setPALevel(RF24_PA_LOW);
  radio.startListening(); // Set the module as receiver
  Serial.begin(115200);
}
void loop() {
  // Check whether we keep receving data, or we have a connection between the two modules
  currentTime = millis();
  if ( currentTime - lastReceiveTime > 1000 ) {
    // If current time is more then 1 second since we have recived the last data, that means we have lost connection
    resetData(); // If connection is lost, reset the data. It prevents unwanted behavior, for example if a drone jas a throttle up, if we lose connection it can keep flying away if we dont reset the function
  }
  // Check whether there is data to be received
  if (radio.available()) {
    radio.read(&data, sizeof(Data_Package)); // Read the whole data and store it into the 'data' structure
    lastReceiveTime = millis(); // At this moment we have received the data
  }
  // Set speed - left potentiometer
  wheelSpeed = map(data.pot1, 0, 255, 100, 3000);
  if (data.j1PotX > 150) { moveSidewaysLeft(); }
  else if (data.j1PotX < 100) { moveSidewaysRight(); }
  else if (data.j1PotY > 160) { moveForward(); }
  else if (data.j1PotY < 100) { moveBackward(); }
  else if (data.j2PotX < 100 & data.j2PotY > 160) { moveRightForward(); }
  else if (data.j2PotX > 160 & data.j2PotY > 160) { moveLeftForward(); }
  else if (data.j2PotX < 100 & data.j2PotY < 100) { moveRightBackward(); }
  else if (data.j2PotX > 160 & data.j2PotY < 100) { moveLeftBackward(); }
  else if (data.j2PotX < 100) { rotateRight(); }
  else if (data.j2PotX > 150) { rotateLeft(); }
  else { stopMoving(); }
  // Execute the steps
  LeftFrontWheel.runSpeed();
  LeftBackWheel.runSpeed();
  RightFrontWheel.runSpeed();
  RightBackWheel.runSpeed();
  // Monitor the battery voltage
  int sensorValue = analogRead(A0);
  float voltage = sensorValue * (5.0 / 1023.00) * 3; // Convert the reading values from 5v to suitable 12V i
  // If voltage is below 11V turn on the LED
  if (voltage < 11) { digitalWrite(led, HIGH); }
  else { digitalWrite(led, LOW); }
}
void moveForward() {
  LeftFrontWheel.setSpeed(wheelSpeed);
  LeftBackWheel.setSpeed(wheelSpeed);
  RightFrontWheel.setSpeed(wheelSpeed);
  RightBackWheel.setSpeed(wheelSpeed);
}
void moveBackward() {
  LeftFrontWheel.setSpeed(-wheelSpeed);
  LeftBackWheel.setSpeed(-wheelSpeed);
  RightFrontWheel.setSpeed(-wheelSpeed);
  RightBackWheel.setSpeed(-wheelSpeed);
}
void moveSidewaysRight() {
  LeftFrontWheel.setSpeed(wheelSpeed);
  LeftBackWheel.setSpeed(-wheelSpeed);
  RightFrontWheel.setSpeed(-wheelSpeed);
  RightBackWheel.setSpeed(wheelSpeed);
}
void moveSidewaysLeft() {
  LeftFrontWheel.setSpeed(-wheelSpeed);
  LeftBackWheel.setSpeed(wheelSpeed);
  RightFrontWheel.setSpeed(wheelSpeed);
  RightBackWheel.setSpeed(-wheelSpeed);
}
void rotateLeft() {
  LeftFrontWheel.setSpeed(-wheelSpeed);
  LeftBackWheel.setSpeed(-wheelSpeed);
  RightFrontWheel.setSpeed(wheelSpeed);
  RightBackWheel.setSpeed(wheelSpeed);
}
void rotateRight() {
  LeftFrontWheel.setSpeed(wheelSpeed);
  LeftBackWheel.setSpeed(wheelSpeed);
  RightFrontWheel.setSpeed(-wheelSpeed);
  RightBackWheel.setSpeed(-wheelSpeed);
}
void moveRightForward() {
  LeftFrontWheel.setSpeed(wheelSpeed);
  LeftBackWheel.setSpeed(0);
  RightFrontWheel.setSpeed(0);
  RightBackWheel.setSpeed(wheelSpeed);
}
void moveRightBackward() {
  LeftFrontWheel.setSpeed(0);
  LeftBackWheel.setSpeed(-wheelSpeed);
  RightFrontWheel.setSpeed(-wheelSpeed);
  RightBackWheel.setSpeed(0);
}
void moveLeftForward() {
  LeftFrontWheel.setSpeed(0);
  LeftBackWheel.setSpeed(wheelSpeed);
  RightFrontWheel.setSpeed(wheelSpeed);
  RightBackWheel.setSpeed(0);
}
void moveLeftBackward() {
  LeftFrontWheel.setSpeed(-wheelSpeed);
  LeftBackWheel.setSpeed(0);
  RightFrontWheel.setSpeed(0);
  RightBackWheel.setSpeed(-wheelSpeed);
}
void stopMoving() {
  LeftFrontWheel.setSpeed(0);
  LeftBackWheel.setSpeed(0);
  RightFrontWheel.setSpeed(0);
  RightBackWheel.setSpeed(0);
}
void resetData() {
  // Reset the values when there is no radio connection - Set initial default values
  data.j1PotX = 127;
  data.j1PotY = 127;
  data.j2PotX = 127;
  data.j2PotY = 127;
  data.j1Button = 1;
  data.j2Button = 1;
  data.pot1 = 1;
  data.pot2 = 1;
  data.tSwitch1 = 1;
  data.tSwitch2 = 1;
  data.button1 = 1;
  data.button2 = 1;
  data.button3 = 1;
  data.button4 = 1;
}

说明: 这里使用 RF24 库进行无线电通信,AccelStepper 库控制步进电机。首先定义所有连接引脚、程序所需变量,在 setup 部分设置步进电机最大速度并开始无线电通信。

在 loop 部分开始读取来自 RC 发射器的数据。RC 发射器代码及通信工作原理详见我的相关教程。

根据接收数据,例如左摇杆前推其值大于 160 时调用 moveForward() 自定义函数。查看该函数可见它只是将电机速度设为正值。后退则设为负值。其他方向移动只需按开头解释的方式适当设置车轮旋转即可。

为执行这些命令,loop 部分需为所有步进电机调用 runSpeed() 函数。loop 部分还读取分压器来自电池的模拟输入,据此得知电池电压何时降至 11V 以下以点亮指示 LED。

使用智能手机控制的 Arduino 代码

/* === Arduino Mecanum Wheels Robot === Smartphone control via Bluetooth by Dejan, www.HowToMechatronics.com Libraries: RF24, https://github.com/tmrh20/RF24/ AccelStepper by Mike McCauley: https://www.airspayce.com/mikem/arduino/AccelStepper/index.html */
#include <SoftwareSerial.h>
#include <AccelStepper.h>
SoftwareSerial Bluetooth(A8, 38); // Arduino(RX, TX) - HC-05 Bluetooth (TX, RX)
// Define the stepper motors and the pins the will use
AccelStepper LeftBackWheel(1, 42, 43); // (Type:driver, STEP, DIR) - Stepper1
AccelStepper LeftFrontWheel(1, 40, 41); // Stepper2
AccelStepper RightBackWheel(1, 44, 45); // Stepper3
AccelStepper RightFrontWheel(1, 46, 47); // Stepper4
#define led 14
int wheelSpeed = 1500;
int dataIn, m;
int lbw[50], lfw[50], rbw[50], rfw[50]; // for storing positions/steps
int index = 0;
void setup() {
  // Set initial seed values for the steppers
  LeftFrontWheel.setMaxSpeed(3000);
  LeftBackWheel.setMaxSpeed(3000);
  RightFrontWheel.setMaxSpeed(3000);
  RightBackWheel.setMaxSpeed(3000);
  Serial.begin(38400);
  Bluetooth.begin(38400); // Default baud rate of the Bluetooth module
  Bluetooth.setTimeout(1);
  delay(20);
  pinMode(led, OUTPUT);
}
void loop() {
  // Check for incoming data
  if (Bluetooth.available() > 0) {
    dataIn = Bluetooth.read(); // Read the data
    if (dataIn == 0) { m = 0; }
    if (dataIn == 1) { m = 1; }
    if (dataIn == 2) { m = 2; }
    if (dataIn == 3) { m = 3; }
    if (dataIn == 4) { m = 4; }
    if (dataIn == 5) { m = 5; }
    if (dataIn == 6) { m = 6; }
    if (dataIn == 7) { m = 7; }
    if (dataIn == 8) { m = 8; }
    if (dataIn == 9) { m = 9; }
    if (dataIn == 10) { m = 10; }
    if (dataIn == 11) { m = 11; }
    if (dataIn == 12) { m = 12; }
    if (dataIn == 14) { m = 14; }
    // Set speed
    if (dataIn >= 16) { wheelSpeed = dataIn * 10; Serial.println(wheelSpeed); }
  }
  if (m == 4) { moveSidewaysLeft(); }
  if (m == 5) { moveSidewaysRight(); }
  if (m == 2) { moveForward(); }
  if (m == 7) { moveBackward(); }
  if (m == 3) { moveRightForward(); }
  if (m == 1) { moveLeftForward(); }
  if (m == 8) { moveRightBackward(); }
  if (m == 6) { moveLeftBackward(); }
  if (m == 9) { rotateLeft(); }
  if (m == 10) { rotateRight(); }
  if (m == 0) { stopMoving(); }
  //Serial.println(dataIn);
  // If button "SAVE" is pressed
  if (m == 12) {
    if (index == 0) {
      LeftBackWheel.setCurrentPosition(0);
      LeftFrontWheel.setCurrentPosition(0);
      RightBackWheel.setCurrentPosition(0);
      RightFrontWheel.setCurrentPosition(0);
    }
    lbw[index] = LeftBackWheel.currentPosition(); // save position into the array
    lfw[index] = LeftFrontWheel.currentPosition();
    rbw[index] = RightBackWheel.currentPosition();
    rfw[index] = RightFrontWheel.currentPosition();
    index++; // Increase the array index
    m = 0;
  }
  if (m == 14) {
    runSteps();
    if (dataIn != 14) {
      stopMoving();
      memset(lbw, 0, sizeof(lbw)); // Clear the array data to 0
      memset(lfw, 0, sizeof(lfw));
      memset(rbw, 0, sizeof(rbw));
      memset(rfw, 0, sizeof(rfw));
      index = 0; // Index to 0
    }
  }
  LeftFrontWheel.runSpeed();
  LeftBackWheel.runSpeed();
  RightFrontWheel.runSpeed();
  RightBackWheel.runSpeed();
  // Monitor the battery voltage
  int sensorValue = analogRead(A0);
  float voltage = sensorValue * (5.0 / 1023.00) * 3; // Convert the reading values from 5v to suitable 12V i
  //Serial.println(voltage);
  // If voltage is below 11V turn on the LED
  if (voltage < 11) { digitalWrite(led, HIGH); }
  else { digitalWrite(led, LOW); }
}
void runSteps() {
  for (int i = index - 1; i >= 0; i--) {
    // Run through all steps(index)
    LeftFrontWheel.moveTo(lfw[i]);
    LeftFrontWheel.setSpeed(wheelSpeed);
    LeftBackWheel.moveTo(lbw[i]);
    LeftBackWheel.setSpeed(wheelSpeed);
    RightFrontWheel.moveTo(rfw[i]);
    RightFrontWheel.setSpeed(wheelSpeed);
    RightBackWheel.moveTo(rbw[i]);
    RightBackWheel.setSpeed(wheelSpeed);
    while (LeftBackWheel.currentPosition() != lbw[i] & LeftFrontWheel.currentPosition() != lfw[i] & RightFrontWheel.currentPosition() != rfw[i] & RightBackWheel.currentPosition() != rbw[i]) {
      LeftFrontWheel.runSpeedToPosition();
      LeftBackWheel.runSpeedToPosition();
      RightFrontWheel.runSpeedToPosition();
      RightBackWheel.runSpeedToPosition();
      if (Bluetooth.available() > 0) {
        // Check for incomding data
        dataIn = Bluetooth.read();
        if ( dataIn == 15) {
          // If button "PAUSE" is pressed
          while (dataIn != 14) {
            // Wait until "RUN" is pressed again
            if (Bluetooth.available() > 0) {
              dataIn = Bluetooth.read();
              if ( dataIn == 13) { stopMoving(); break; }
            }
          }
        }
        if (dataIn >= 16) { wheelSpeed = dataIn * 10; dataIn = 14; }
        if ( dataIn == 13) { break; }
      }
    }
  }
  // Go back through steps
  for (int i = 1; i <= index - 1; i++) {
    // Run through all steps(index)
    LeftFrontWheel.moveTo(lfw[i]);
    LeftFrontWheel.setSpeed(wheelSpeed);
    LeftBackWheel.moveTo(lbw[i]);
    LeftBackWheel.setSpeed(wheelSpeed);
    RightFrontWheel.moveTo(rfw[i]);
    RightFrontWheel.setSpeed(wheelSpeed);
    RightBackWheel.moveTo(rbw[i]);
    RightBackWheel.setSpeed(wheelSpeed);
    while (LeftBackWheel.currentPosition() != lbw[i] & LeftFrontWheel.currentPosition() != lfw[i] & RightFrontWheel.currentPosition() != rfw[i] & RightBackWheel.currentPosition() != rbw[i]) {
      LeftFrontWheel.runSpeedToPosition();
      LeftBackWheel.runSpeedToPosition();
      RightFrontWheel.runSpeedToPosition();
      RightBackWheel.runSpeedToPosition();
      //Serial.print(" current: ");
      //Serial.println(LeftBackWheel.currentPosition());
      if (Bluetooth.available() > 0) {
        // Check for incomding data
        dataIn = Bluetooth.read();
        if ( dataIn == 15) {
          // If button "PAUSE" is pressed
          while (dataIn != 14) {
            // Wait until "RUN" is pressed again
            if (Bluetooth.available() > 0) {
              dataIn = Bluetooth.read();
              if ( dataIn == 13) { stopMoving(); break; }
            }
          }
        }
        if (dataIn >= 16) { wheelSpeed = dataIn * 10; dataIn = 14; }
        if ( dataIn == 13) { break; }
      }
    }
  }
}
void moveForward() {
  LeftFrontWheel.setSpeed(wheelSpeed);
  LeftBackWheel.setSpeed(wheelSpeed);
  RightFrontWheel.setSpeed(wheelSpeed);
  RightBackWheel.setSpeed(wheelSpeed);
}
void moveBackward() {
  LeftFrontWheel.setSpeed(-wheelSpeed);
  LeftBackWheel.setSpeed(-wheelSpeed);
  RightFrontWheel.setSpeed(-wheelSpeed);
  RightBackWheel.setSpeed(-wheelSpeed);
}
void moveSidewaysRight() {
  LeftFrontWheel.setSpeed(wheelSpeed);
  LeftBackWheel.setSpeed(-wheelSpeed);
  RightFrontWheel.setSpeed(-wheelSpeed);
  RightBackWheel.setSpeed(wheelSpeed);
}
void moveSidewaysLeft() {
  LeftFrontWheel.setSpeed(-wheelSpeed);
  LeftBackWheel.setSpeed(wheelSpeed);
  RightFrontWheel.setSpeed(wheelSpeed);
  RightBackWheel.setSpeed(-wheelSpeed);
}
void rotateLeft() {
  LeftFrontWheel.setSpeed(-wheelSpeed);
  LeftBackWheel.setSpeed(-wheelSpeed);
  RightFrontWheel.setSpeed(wheelSpeed);
  RightBackWheel.setSpeed(wheelSpeed);
}
void rotateRight() {
  LeftFrontWheel.setSpeed(wheelSpeed);
  LeftBackWheel.setSpeed(wheelSpeed);
  RightFrontWheel.setSpeed(-wheelSpeed);
  RightBackWheel.setSpeed(-wheelSpeed);
}
void moveRightForward() {
  LeftFrontWheel.setSpeed(wheelSpeed);
  LeftBackWheel.setSpeed(0);
  RightFrontWheel.setSpeed(0);
  RightBackWheel.setSpeed(wheelSpeed);
}
void moveRightBackward() {
  LeftFrontWheel.setSpeed(0);
  LeftBackWheel.setSpeed(-wheelSpeed);
  RightFrontWheel.setSpeed(-wheelSpeed);
  RightBackWheel.setSpeed(0);
}
void moveLeftForward() {
  LeftFrontWheel.setSpeed(0);
  LeftBackWheel.setSpeed(wheelSpeed);
  RightFrontWheel.setSpeed(wheelSpeed);
  RightBackWheel.setSpeed(0);
}
void moveLeftBackward() {
  LeftFrontWheel.setSpeed(-wheelSpeed);
  LeftBackWheel.setSpeed(0);
  RightFrontWheel.setSpeed(0);
  RightBackWheel.setSpeed(-wheelSpeed);
}
void stopMoving() {
  LeftFrontWheel.setSpeed(0);
  LeftBackWheel.setSpeed(0);
  RightFrontWheel.setSpeed(0);
  RightBackWheel.setSpeed(0);
}

说明: 另一个用 Android 应用控制机器人的代码非常相似,工作方式相同。这里不需要无线电模块,而是定义蓝牙模块并在 setup 部分初始化其通信。同样,先读取来自智能手机或 Android 应用的传入数据,据此告诉机器人向哪个方向移动。

查看 Android 应用可见它只是在按钮按下时通过蓝牙发送 0-15 的数字。

制作 Arduino 麦克纳姆轮机器人:360° 全向移动 DIY 指南

该应用使用 MIT App Inventor 在线制作,更多细节请参阅我的相关教程。

制作 Arduino 麦克纳姆轮机器人:360° 全向移动 DIY 指南

您可以在此下载此应用及可编辑项目文件:

对于使用此应用编程自动机器人移动:按“保存”按钮时将步进电机当前位置存入数组。按“运行”按钮时调用 runSteps() 自定义函数,通过 for 和 while 循环执行所有存储的步骤。

希望您喜欢这个教程并学到新知识。欢迎在下方评论区提问,查看我的 Arduino 项目合集。

制造工艺

  1. 蓝牙控制树莓派机器人:语音反馈功能构建指南
  2. 舵机驱动避障机器人:基于 Arduino 与 HC-SR04 构建
  3. Arduino UNO 自制循迹小车:从零构建自主巡线机器人
  4. Arduino Nano 语音控制机器人:蓝牙 + 手机 APP 实现
  5. PiBot:Arduino驱动的88键钢琴机器人,精准演奏MIDI乐曲
  6. LittleArm 2C:3D 打印 Arduino 机械臂 - STEM 教学专用,坚固易装
  7. 自主家庭助理机器人 O'nine - ROS + Alexa 语音控制 + 机械臂 + 麦克纳姆轮全向移动
  8. 通过专用 Android App 蓝牙控制 Arduino 机械臂
  9. 适用于 Arduino 项目的智能室内导航机器人套件
  10. WiDC:Wi-Fi FPV 机器人 - 远程控制与实时视频传输
  11. Arduino 打造会说话的智能人形机器人「Mofiza」
  12. 自制 AI 助手机器人:Arduino 与 Python 协同实现语音交互与肢体动作