一板网电子技术论坛

风筝
发表于: 2018-10-26 15:13:22 | 显示全部楼层

在本篇文章中,我们将学习如何使用Arduino开发板制作一个简易的机械臂(Robot Arm),可以使用定制的Android应用程序进行无线控制和编程。我将向您展示制作的整个过程,从设计和3D打印机器人部件,到连接电子元件和编程Arduino,以及开发我们自己的Android应用程序来控制机械臂。


简介

使用应用程序中的滑块,我们可以手动控制机械臂的每个伺服或轴的运动。使用“保存”按钮,我们可以记录每个位置或步骤,然后机器人手臂可以自动运行并重复这些步骤。使用同一个按钮,我们可以暂停自动操作以及重置或删除所有步骤,以便我们可以记录新的步骤。


Arduino机械臂的3D模型

首先,我使用Solidworks 3D建模软件设计了机械臂的模型。机械臂有5个自由度。

Arduino-Robot-Arm-3D-Model.jpg


对于前面的3个轴:腰部、肩部和肘部,使用的是MG996R伺服电机,而另外2个轴,腕部滚动和腕部间距,以及夹具我使用了较小的SG90微型伺服电机。


您可以通过下面的链接下载这些3D模型。

●    Arduino机械臂3D模型STEP文件: Arduino Robot Arm 3D Model STEP File.rar (318.43 KB, 下载次数: 688)

●    用于3D打印的STL文件: Arduino Robot Arm STL Files.rar (372.99 KB, 下载次数: 595)


3D打印机械臂

我使用的3D打印机型号是Creality CR-10,通过这个设备,我3D打印了Arduino机械臂的所有部件。

Creality-CR-10-3D-Printer-Robot-Arm-Base-Part-768x432.jpg


在这里,我想向Banggood.com致谢,为我提供这款超棒的3D打印机。 Creality CR-10的打印质量令人惊叹,其价格也非常出色,它的预装配率接近90%。

Creality-CR-10-Preassembled-768x434.jpg


为了完成组装,我们只需使用一些螺栓和支架连接上部和下部框架,然后使用提供的电缆将电子组件与控制箱连接。

Assembling-Creality-CR-10-3D-Printer.jpg


在尝试之前,建议检查滚轮是否足够紧,如果不紧,可以使用偏心螺母将它们拧紧。在调平3D打印机床之后,您就可以将3D创作变为现实。

Arduino-Robot-Arm-Parts-768x513.jpg


我使用了几个小时的时间完成了Arduino机械臂的所有部件。


组装机械臂

在本节中,我们将准备组装机械臂。首先使用其螺钉将第一台伺服电机连接的基座上。然后在伺服电机的输出轴上我固定了一个圆形喇叭螺栓。

assembling-the-robot-arm-768x432.jpg


在基座上面,放置上盖并用两个螺丝固定。

Arduino-Robot-Arm-Base-Assembly-768x432.jpg


在这个部位,仍是先安装伺服电机,然后将圆形喇叭放到下一个部件上,然后使用输出轴上的螺栓将它们固定在一起。

robotic-arm-sholder-arm-768x432.jpg


我们在这里可以注意到,在肩轴上最好包括某种弹簧,或者像本例中,我使用橡皮筋固定伺服,因为这个伺服器还承载了其余臂的整个重量。

Robot-arm-shoulder-axis-strenght-added-with-a-rubber-band-768x432.jpg


以类似的方式,我继续组装机械臂的剩余部分。至于夹具机构,我使用了大约4毫米的螺栓和螺母来组装。

3D-Printer-Robot-Arm-768x432.jpg


最后,我将夹具机构安装到最后一个伺服机构上,完成了Arduino机器人手臂。

Arduino-Robotic-Arm-3D-Printed-768x801.jpg


Arduino机械臂电路图

接下来是连接电子产品。该项目的电路图实际上非常简单。我们只需要一个Arduino开发板和一个HC-05蓝牙模块与智能手机进行通信。六个伺服电机的控制引脚连接到Arduino开发板的六个数字引脚。

Arduino-Robot-Arm-Schematic-Circuit-Diagram-768x473.png


为了给伺服电机供电,我们需要一个5V电源,但这必须由外部电源供电,因为Arduino无法提供所有需要的电流。电源必须能够提供至少2A的电流。这样,一旦我们将所有组件连接在一起,我们就可以继续编写Arduino代码,以及制作Android应用程序。


本示例中使用的组件如下:

●    3个MG996R伺服电机

●    3个SG90微型伺服电机

●    HC-05蓝牙模块

●    Arduino开发板

●    5V/2A电源

●    连接导线

跳转到指定楼层
风筝
发表于: 2018-10-26 17:10:59 | 显示全部楼层

Arduino机械臂代码

由于代码有点长,为了更好地理解,我将分段解释程序的源代码。 在本文的末尾处,我将列出完整的源代码。


首先,我们需要包含SoftwareSerial库,用于蓝牙模块的串行通信和servo库。 这两个库都包含在Arduino IDE中,因此您无需从外部安装它们。 然后我们需要定义六个伺服电机、HC-05蓝牙模块和一些用于存储伺服电机当前和先前位置的变量,以及用于存储自动模式的位置或步骤的数组。

  1. #include <SoftwareSerial.h>
  2. #include <Servo.h>
  3. Servo servo01;
  4. Servo servo02;
  5. Servo servo03;
  6. Servo servo04;
  7. Servo servo05;
  8. Servo servo06;
  9. SoftwareSerial Bluetooth(3, 4); // Arduino(RX, TX) - HC-05 Bluetooth (TX, RX)
  10. int servo1Pos, servo2Pos, servo3Pos, servo4Pos, servo5Pos, servo6Pos; // current position
  11. int servo1PPos, servo2PPos, servo3PPos, servo4PPos, servo5PPos, servo6PPos; // previous position
  12. int servo01SP[50], servo02SP[50], servo03SP[50], servo04SP[50], servo05SP[50], servo06SP[50]; // for storing positions/steps
  13. int speedDelay = 20;
  14. int index = 0;
  15. String dataIn = "";
复制代码

setup()函数中,我们需要初始化伺服电机和蓝牙模块,并将机械臂移动到其初始位置。 我们使用write()函数来做到这一点,它只是将伺服电机移动到0到180度的任何位置。

  1. void setup() {
  2.   servo01.attach(5);
  3.   servo02.attach(6);
  4.   servo03.attach(7);
  5.   servo04.attach(8);
  6.   servo05.attach(9);
  7.   servo06.attach(10);
  8.   Bluetooth.begin(38400); // Default baud rate of the Bluetooth module
  9.   Bluetooth.setTimeout(1);
  10.   delay(20);
  11.   // Robot arm initial position
  12.   servo1PPos = 90;
  13.   servo01.write(servo1PPos);
  14.   servo2PPos = 150;
  15.   servo02.write(servo2PPos);
  16.   servo3PPos = 35;
  17.   servo03.write(servo3PPos);
  18.   servo4PPos = 140;
  19.   servo04.write(servo4PPos);
  20.   servo5PPos = 85;
  21.   servo05.write(servo5PPos);
  22.   servo6PPos = 80;
  23.   servo06.write(servo6PPos);
  24. }
复制代码

接下来,在loop()函数中,使用Bluetooth.available()函数,我们不断检查是否有智能手机传入的数据。 如果为true,则使用readString()函数将数据读取为字符串并将其存储到dataIn变量中。 根据到达的数据,我们将告诉机械臂该做什么。

  1. // Check for incoming data
  2.   if (Bluetooth.available() > 0) {
  3.     dataIn = Bluetooth.readString();  // Read the data as string
复制代码

Arduino机械臂控制Android应用程序

我们现在来看看Android应用程序,看看它实际发送给Arduino开发板的数据类型。

Arduino-Robot-Arm-Control-Android-App.png


我使用MIT App Inventor在线应用程序制作了该应用程序,以下是它的工作原理。在顶部,我们有两个按钮,用于将智能手机连接到HC-05蓝牙模块。然后在左侧我们有一个机械臂的图像,在右侧我们有六个用于控制伺服电机的滑块和一个用于速度控制的滑块。

Android-App-development-with-MIT-App-Inventor-768x545.png


每个滑块都有适合机械臂关节的不同的初始值、最小值和最大值。在应用程序的底部,我们有三个按钮:SAVE、RUN和RESET,通过它我们可以编程机械臂使其实现自动运行。下面还有一个标签,显示我们保存的步骤数。

现在让我们看看应用程序背后的程序或模块。首先,在左侧,我们有用于将智能手机连接到蓝牙模块的模块。

Android-App-Bluetooth-Connection-with-Arduino-768x781.png


然后我们有用于伺服位置控制的滑块和用于编程机械臂的按钮块。因此,如果我们更改滑块的位置,通过使用蓝牙函数.SendText,我们会向Arduino开发板发送一段文本。该文本由一个前缀组成,该前缀指示哪个滑块被更改以及滑块的当前值。

Android-Apps-Sliders-Blocks-768x610.png


以下是上述的MIT App Inventor项目的下载文件:

●    Arduino机械臂控制MIT App Inventor项目文件: Arduino_Robot_Arm_Control.rar (24.15 KB, 下载次数: 354)


因此,在Arduino中,使用startsWith()函数,我们检查每个传入数据的前缀,这样就可以知道接下来要做什么。例如,如果前缀是“s1”,我们知道需要移动伺服编号1。使用substring()函数得到剩余的文本,或者是位置值,我们将其转换为整数并使用该值将伺服电机移动到该位置。

  1. // If "Waist" slider has changed value - Move Servo 1 to position
  2.     if (dataIn.startsWith("s1")) {
  3.       String dataInS = dataIn.substring(2, dataIn.length()); // Extract only the number. E.g. from "s1120" to "120"
  4.       servo1Pos = dataInS.toInt();  // Convert the string into integer
复制代码

在这里我们可以简单地调用write()函数,然后伺服将转到该位置,但是这样伺服将以其最大速度运行,这对于机械臂来说太快了。 相反,我们需要控制伺服的速度,所以我使用了一些FOR循环,以便通过在每次迭代之间实现延迟时间来逐渐将伺服从前一个位置移动到当前位置。 通过改变延迟时间,您可以改变伺服的速度。

  1. // We use for loops so we can control the speed of the servo
  2.       // If previous position is bigger then current position
  3.       if (servo1PPos > servo1Pos) {
  4.         for ( int j = servo1PPos; j >= servo1Pos; j--) {   // Run servo down
  5.           servo01.write(j);
  6.           delay(20);    // defines the speed at which the servo rotates
  7.         }
  8.       }
  9.       // If previous position is smaller then current position
  10.       if (servo1PPos < servo1Pos) {
  11.         for ( int j = servo1PPos; j <= servo1Pos; j++) {   // Run servo up
  12.           servo01.write(j);
  13.           delay(20);
  14.         }
  15.       }
  16.       servo1PPos = servo1Pos;   // set current position as previous position
  17.     }
复制代码

相同的方法适用于驱动机械臂的每个轴。


在它们下面是SAVE按钮。 如果我们按下SAVE按钮,每个伺服电机的位置将存储在一个数组中。 每按一次,索引就会增加,因此数组会逐步填充。

  1. // If button "SAVE" is pressed
  2.     if (dataIn.startsWith("SAVE")) {
  3.       servo01SP[index] = servo1PPos;  // save position into the array
  4.       servo02SP[index] = servo2PPos;
  5.       servo03SP[index] = servo3PPos;
  6.       servo04SP[index] = servo4PPos;
  7.       servo05SP[index] = servo5PPos;
  8.       servo06SP[index] = servo6PPos;
  9.       index++;                        // Increase the array index
  10.     }
复制代码

然后,如果我们按下RUN按钮,我们调用运行存储步骤的runservo()自定义函数。 我们来看看这个函数。 该函数中我们一遍又一遍地运行存储的步骤,直到我们按下RESET按钮。 使用FOR循环,我们遍历存储在数组中的所有位置,同时我们检查是否有来自智能手机的传入数据。 此数据可以是RUN / PAUSE按钮,用于暂停机器人,如果再次单击则继续自动执行。 此外,如果我们改变速度滑块位置,我们将使用该值来改变下面FOR循环中每次迭代之间的延迟时间,这将控制伺服电机的速度。

  1. // Automatic mode custom function - run the saved steps
  2. void runservo() {
  3.   while (dataIn != "RESET") {   // Run the steps over and over again until "RESET" button is pressed
  4.     for (int i = 0; i <= index - 2; i++) {  // Run through all steps(index)
  5.       if (Bluetooth.available() > 0) {      // Check for incomding data
  6.         dataIn = Bluetooth.readString();
  7.         if ( dataIn == "PAUSE") {           // If button "PAUSE" is pressed
  8.           while (dataIn != "RUN") {         // Wait until "RUN" is pressed again
  9.             if (Bluetooth.available() > 0) {
  10.               dataIn = Bluetooth.readString();
  11.               if ( dataIn == "RESET") {     
  12.                 break;
  13.               }
  14.             }
  15.           }
  16.         }
  17.         // If SPEED slider is changed
  18.         if (dataIn.startsWith("ss")) {
  19.           String dataInS = dataIn.substring(2, dataIn.length());
  20.           speedDelay = dataInS.toInt(); // Change servo speed (delay time)
  21.         }
  22.       }
  23.       // Servo 1
  24.       if (servo01SP[i] == servo01SP[i + 1]) {
  25.       }
  26.       if (servo01SP[i] > servo01SP[i + 1]) {
  27.         for ( int j = servo01SP[i]; j >= servo01SP[i + 1]; j--) {
  28.           servo01.write(j);
  29.           delay(speedDelay);
  30.         }
  31.       }
  32.       if (servo01SP[i] < servo01SP[i + 1]) {
  33.         for ( int j = servo01SP[i]; j <= servo01SP[i + 1]; j++) {
  34.           servo01.write(j);
  35.           delay(speedDelay);
  36.         }
  37.       }
复制代码

在上文中已经解释过这些IF语句和FOR循环,使用相同的方式,我们将伺服电机移动到下一个位置。 最后,如果我们按下RESET按钮,将清除数组中的所有数据到零,并将索引重置为零,这样我们就可以用新的动作重新编程机械臂。

  1. // If button "RESET" is pressed
  2.     if ( dataIn == "RESET") {
  3.       memset(servo01SP, 0, sizeof(servo01SP)); // Clear the array data to 0
  4.       memset(servo02SP, 0, sizeof(servo02SP));
  5.       memset(servo03SP, 0, sizeof(servo03SP));
  6.       memset(servo04SP, 0, sizeof(servo04SP));
  7.       memset(servo05SP, 0, sizeof(servo05SP));
  8.       memset(servo06SP, 0, sizeof(servo06SP));
  9.       index = 0;  // Index to 0
  10.     }
复制代码

整篇文章就是这样,现在我们可以好好享受机械臂带来的乐趣。


以下是Arduino机械臂的完整代码: main.rar (1.81 KB, 下载次数: 421)

回复

使用道具 举报

1153635534
发表于: 2018-11-1 13:44:43 | 显示全部楼层

这个控制我控制不好,拖动控制不知道怎么回事,请问是往右拖是逆时针还是顺时针,还是一下顺时针一下逆时针
回复

使用道具 举报

风筝
发表于: 2018-11-1 21:55:37 | 显示全部楼层

1153635534 发表于 2018-11-1 13:44
这个控制我控制不好,拖动控制不知道怎么回事,请问是往右拖是逆时针还是顺时针,还是一下顺时针一下逆时针 ...

向右是顺时针 以最终的设置为角度
回复

使用道具 举报

1153635534
发表于: 2018-11-9 14:03:17 | 显示全部楼层

这个舵机都是多少角度的
回复

使用道具 举报

1153635534
发表于: 2018-11-9 14:15:45 | 显示全部楼层

风筝 发表于 2018-11-1 21:55
向右是顺时针 以最终的设置为角度

关于舵机是数字舵机还是模拟舵机都是什么角度的
回复

使用道具 举报

风筝
发表于: 2018-11-10 07:51:44 | 显示全部楼层

1153635534 发表于 2018-11-9 14:15
关于舵机是数字舵机还是模拟舵机都是什么角度的

模拟舵机 角度180度就可以了
回复

使用道具 举报

1153635534
发表于: 2018-11-13 20:32:43 | 显示全部楼层

大神,QQ是多少,我有一些问题想问你
回复

使用道具 举报

1153635534
发表于: 2018-11-14 09:50:07 | 显示全部楼层

我用的是数字舵机,但是每次转变位置时,舵机会卡在一个位置,这是为什么
回复

使用道具 举报

Urian
发表于: 2019-1-11 13:14:43 | 显示全部楼层

你好,请问你是怎么供电的呢?用Arduino UNO板可以驱动得了6个舵机吗?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

主题 685 | 回复: 1421



手机版|

GMT+8, 2023-2-6 11:20 , Processed in 0.028921 second(s), 4 queries , Gzip On, MemCache On. Powered by Discuz! X3.4

YiBoard一板网 © 2015-2022 地址:河北省石家庄市长安区高营大街 ( 冀ICP备18020117号 )

快速回复 返回顶部 返回列表