arduino搭建机器人(来制作一个Arduino麦克纳姆轮机器人吧)
arduino搭建机器人(来制作一个Arduino麦克纳姆轮机器人吧)我们还应该注意到,我们需要两种类型的麦克纳姆轮,通常称为左手和右手麦克纳姆轮。它们之间的区别在于滚轮的方向,它们必须安装在机器人的特定位置。每个车轮上滚轮的旋转轴应指向机器人的中心。因此,通过以某些角度旋转车轮,我们利用这些对角线力,因此机器人可以向任何方向移动。麦克纳姆轮如何工作的麦克纳姆轮是一个车轮,在其圆周上有滚轮。这些滚轮对角地定位或与轮子的旋转轴成45度角。这使得当向后移动时轮子沿对角线方向施加力。
今天我们将介绍如何去建立一个Arduino麦克纳姆轮机器人机器人,它可以在任何方向进行移动。这种独特的机动性则是通过使用一种叫做麦克纳姆轮的特殊轮子来实现的。我们在之前的文章里也详细介绍了麦克纳姆轮,这里就不多介绍了。
首先,我们使用3D建模软件设计了这个麦克纳姆轮机器人。这个机器人的基础平台是一个简单的盒子,我们用8mm刻度MDF板来进行制作。
并会使用四个步进电机连接到该平台,麦克纳姆车轮连接到电机轴上
麦克纳姆轮如何工作的
麦克纳姆轮是一个车轮,在其圆周上有滚轮。这些滚轮对角地定位或与轮子的旋转轴成45度角。这使得当向后移动时轮子沿对角线方向施加力。
因此,通过以某些角度旋转车轮,我们利用这些对角线力,因此机器人可以向任何方向移动。
我们还应该注意到,我们需要两种类型的麦克纳姆轮,通常称为左手和右手麦克纳姆轮。它们之间的区别在于滚轮的方向,它们必须安装在机器人的特定位置。每个车轮上滚轮的旋转轴应指向机器人的中心。
制作麦克纳姆轮机器人
现在让我们回到正轨,我们是如何构建这个机器人平台的。正如之前所提到的,为了制作平台的基础,我们使用8mm刻度MDF板。首先使用台锯,根据3D模型尺寸切割所有部件。
接下来,使用3毫米钻头和25毫米Forstner钻头,我们在侧板上做了开口,用于连接步进电机。准备好后,我们继续组装,使用木胶和一些螺丝去固定它们。这里最重要的是精确制造电机的开口,以便所有的车轮随后都能与表面接触。
当然,你也可以3D打印这个基础平台,而不是使用MDF。我们选择了白色来作为这次机器人的基调。
接下来是麦克纳姆轮。轮子由两部分组成,外侧和内侧,用一些M4螺栓和螺母固定在一起。它们各有10个滚轮,以及专门设计用于安装NEMA 17步进电机的联轴器。
使用3d打印将元件打印出来,当然也可以到网上进行购买。
当我们准备好了3D打印零件,就可以开始制作滚筒轴了。我们使用了3毫米刻度钢丝。但轴的长度需要在40毫米左右,所以我们用一个旋转工具切割钢丝到这个长度。
我们开始使用四个M4螺栓和螺母固定两侧和轴连接器来组装麦克纳姆轮。螺栓的长度需要为45mm。
为了安装滚子,首先我们需要通过位于内侧圆周的孔轻轻插入轴。
然后我们可以插入一个小型M3垫圈,插入滚轮并将轴一直推入车轮外侧的槽中。我们使用了一个垫圈,因为我没有足够的空间在另一侧插入第二个垫圈。
我们为所有10个滚轮重复了这个过程。组装这些轮子实际上很简单,也很有趣。这里重要的是滚轮需要能够自由移动。
最后,我们在每个内孔中使用几滴AC胶,以确保轴不会松动。
好吧,一旦车轮准备就绪,我们就可以继续组装整个机器人了。首先,我们需要将步进电机连接到基础平台。为了将它们固定到位,我们使用长度为12mm的M3螺栓。
接下来,我们需要将轮子连接到电机的轴上。我制造的联轴器有一个用于插入M3螺母的槽,M3螺栓可以穿过该螺母,因此我们可以将车轮固定在轴上。
接下来,为了将顶盖固定到底座上,我们将螺纹杆连接在底座的两个角上,然后在盖子上的相同位置上打孔,因此就能够轻松插入并将盖子固定到底座上。
在底座的背面,我们制作了20mm的孔,将用于稍后连接电源开关,以及用于连接LED的5mm孔
电路原理图
现在我们介绍电路部分。完整电路图如下:
我们将使用四个DRV8825步进驱动器控制四个NEMA 17步进电机,我们也可以使用A4988步进驱动器。为了给步进机和整个机器人供电,我们将使用12V电源,这里使用了3S Li-Po电池,提供大约12V。我们使用的是NRF24L01模块进行无线通信,而对于蓝牙通信,我们使用的是HC-05蓝牙模块。我还包括一个简单的分压器,用于监控电池电压和一个LED连接,用于指示电池电压何时降至11V以下。还包括一个专用的5V电压调节器,可以提供大约3A的电流。
PCB设计图
当PCB电路板制作完成后,我们需要进行元器件装配。首先焊接较小的元件,电阻和电容。然后将插针焊接到PCB上,用于连接到Arduino开发板。
接下来,将所有母排针放置到位并焊接它们。至于步进电机连接和用于选择步进分辨率的引脚,我们使用的是插座公排针。这样我们就可以直接将电机连接到PCB,并使用跳线来选择步进分辨率。然后焊接接线端子和稳压器。
这样,PCB已经准备就绪,我们可以继续插入驱动器并将电机连接到它上面。首先,我们先放置了用于选择步进分辨率的跳线。通过将驱动器的MS3引脚连接到5V来选择16步分辨率。
然后在它们顶部放置了DRV8825驱动器,并连接了NRF24L01模块和HC-05蓝牙模块。现在我们可以简单地将PCB连接到Arduno板上。
接下来,我们将电池连接到相应的接线盒并将它们放入基础平台。
在这里,将电源开关插入到位并将其连接到另一个端子块。在电源开关正上方,我们还插入了电池指示灯LED。
现在剩下的就是将电机连接到PCB。我们应该注意到,当连接相对的电机时,我们也应该将它们的连接器连接在一起。因此,例如,向前命令,将两个马达沿相同方向移动,尽管它们实际上是翻转的,一个将顺时针旋转而另一个逆时针旋转。
最后,将盖子插入顶部,这样我们完成了这个麦克纳姆轮机器人的硬件组装部分。
最后贴一下使用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: http://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() {
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;
}
关注风火轮,技术之路常相伴,我们下期见!