制作 Arduino 麦克纳姆轮机器人:360° 全向移动 DIY 指南
概述
本教程将学习如何制作一台 Arduino 麦克纳姆轮机器人,它能向任意方向移动。这种独特的机动性是通过使用一种特殊车轮——麦克纳姆轮实现的。
您可以观看以下视频或阅读下面的文字教程。
我实际上设计并 3D 打印了这些车轮,因为购买它们有点贵。它们工作得相当不错,我必须说驾驶这个机器人平台非常有趣。我们可以使用 NRF24L01 无线收发模块无线控制机器人,或者在我的案例中,我使用我之前视频中制作的 DIY RC 发射器。

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

这台机器人平台的大脑是 Arduino Mega 开发板,它单独控制每个车轮。每个车轮连接在一个 NEMA 17 步进电机上,利用步进电机可精确控制的特性,我在应用中添加了一个很酷的功能:可编程自动移动。使用“保存”按钮可保存每个位置或步骤,然后机器人可自动运行并重复这些步骤。同一按钮也可暂停自动操作、重置或删除所有步骤以存储新步骤。
麦克纳姆轮机器人 3D 模型
首先,我使用 3D 建模软件设计了这台麦克纳姆轮机器人。机器人的基础平台是一个简单的盒子,我将用 8mm 厚的 MDF 板制作。

四个步进电机安装在平台上,麦克纳姆轮安装在电机轴上。
您可以在 Thangs 上找到并下载此 3D 模型,也可在浏览器中探索。

从 Thangs 下载组装 3D 模型。
STL 文件用于 3D 打印:
麦克纳姆轮工作原理
麦克纳姆轮是带有滚轮的车轮,滚轮安装在轮子圆周上。这些滚轮相对于车轮旋转轴呈对角线或 45 度角定位。这使得车轮在前进或后退时施加对角线方向的力。

因此,通过以特定模式旋转车轮,我们利用这些对角线力,使机器人能向任意方向移动。
我们还应注意,需要两种麦克纳姆轮,通常称为左手和右手麦克纳姆轮。它们的区别在于滚轮朝向,必须按特定位置安装在机器人上。每个车轮顶部滚轮的旋转轴应指向机器人中心。

这里快速演示机器人根据车轮旋转方向如何移动。
如果四个车轮都前进,机器人合成运动为前进;反之全后退则后退。向右移动时,右侧车轮需向内旋转,左侧车轮向外旋转,对角线滚轮产生的合力使机器人向右移动。向左移动则相反。仅旋转两个车轮也可实现对角线方向移动。
制作麦克纳姆轮机器人
尽管如此,现在让我展示如何构建这个机器人平台。如前所述,平台基座使用 8mm 厚 MDF 板。用台锯根据 3D 模型尺寸切割所有零件。

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

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

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


我用 Creality CR-10 3D 打印机打印所有麦克纳姆轮零件。
这是这款 3D 打印机的链接,如果您想了解。

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

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

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

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

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

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

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

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

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

底座背面开 20mm 孔安装电源开关,以及 5mm 孔安装 LED。
电路图
现在进行电子部分。这是项目的完整电路图。

我们将使用四个 DRV8825 步进驱动器(也可用 A4988)控制四个 NEMA 17 步进电机。为步进电机和整个机器人供电使用 12V 电源,我这里用 3S 锂聚合物电池(约 12V)。无线通信用 NRF24L01 模块,蓝牙通信用 HC-05 蓝牙模块。我还加了一个简单的分压电路监测电池电压,和一个 LED 指示电池电压低于 11V 时亮起。
我还加了一个专用 5V 稳压器(可提供约 3A 电流)。这是可选的,但我计划在未来视频中将此项目与我的 Arduino 机械臂项目结合,届时需要 5V 驱动其舵机。
所需元件
- 步进电机 – NEMA 17
- DRV8825 步进驱动器
- NRF24L01 收发器模块
- HC-05 蓝牙模块
- 锂聚合物电池
- Arduino Mega 开发板
PCB 设计
为了保持电子元件整齐并消除接线混乱,我使用 EasyEDA 免费在线电路设计软件设计了定制 PCB。该 PCB 实际上作为 Arduino MEGA 扩展板,可直接插在 Arduino Mega 板顶部。我使用顶层和底层走线。对于未使用的 Arduino 引脚,我包含了排针连接以备将来使用。还包含 12V、5V 和 GND 连接引脚,以及选择驱动器细分分辨率的引脚。

这是 PCB 设计项目文件链接。设计完成后生成制造所需的 Gerber 文件。
Gerber 文件:
然后从 JLCPCB 订购 PCB(他们也是本视频赞助商)。

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

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

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

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

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

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

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

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

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

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

麦克纳姆轮机器人 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 的数字。

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

您可以在此下载此应用及可编辑项目文件:
对于使用此应用编程自动机器人移动:按“保存”按钮时将步进电机当前位置存入数组。按“运行”按钮时调用 runSteps() 自定义函数,通过 for 和 while 循环执行所有存储的步骤。
希望您喜欢这个教程并学到新知识。欢迎在下方评论区提问,查看我的 Arduino 项目合集。
制造工艺
- 蓝牙控制树莓派机器人:语音反馈功能构建指南
- 舵机驱动避障机器人:基于 Arduino 与 HC-SR04 构建
- Arduino UNO 自制循迹小车:从零构建自主巡线机器人
- Arduino Nano 语音控制机器人:蓝牙 + 手机 APP 实现
- PiBot:Arduino驱动的88键钢琴机器人,精准演奏MIDI乐曲
- LittleArm 2C:3D 打印 Arduino 机械臂 - STEM 教学专用,坚固易装
- 自主家庭助理机器人 O'nine - ROS + Alexa 语音控制 + 机械臂 + 麦克纳姆轮全向移动
- 通过专用 Android App 蓝牙控制 Arduino 机械臂
- 适用于 Arduino 项目的智能室内导航机器人套件
- WiDC:Wi-Fi FPV 机器人 - 远程控制与实时视频传输
- Arduino 打造会说话的智能人形机器人「Mofiza」
- 自制 AI 助手机器人:Arduino 与 Python 协同实现语音交互与肢体动作