极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 2473|回复: 0

Delta并联机械臂实现电磁铁搬运功能

[复制链接]
发表于 2023-3-17 09:32:59 | 显示全部楼层 |阅读模式
本帖最后由 机器谱 于 2023-3-17 09:32 编辑

1. 功能说明
    R037样机是一款Delta并联机械臂。本文示例将利用Delta并联机械臂实现不同点定点搬运磁铁物料的效果。


2. 结构说明
    Delta并联机械臂,其驱动系统采用精度较高的42步进电机;传动系统为丝杠和万向球节;执行末端为搭载电磁铁的圆盘支架。



3. Delta机械臂运动学算法
    这里给大家介绍一种Delta并联机械臂的运动轨迹解法,通过控制电机的转动参数,最终求解出电磁铁圆盘支架的运动轨迹规律,样机采用R037b
       该机械臂由3个丝杠平台构成,通过并联的方式同时控制同一个端点的运动;三个丝杠位于一个正三角形边线的中心位置,连杆采用球头万向节连杆结构。


① 首先我们建立一个空间直角坐标系,该直角坐标系以三个丝杠平台在俯视图方向投影的内切圆心为原点,x轴与tower1和tower3之间的连线平行,y轴过tower2,其中z=0的平面设置在三个限位开关所在平面。


② 建立坐标系之后,我们可以得出3个限位开关Z轴投影的坐标为A=(-msin(60°),mcos(60°),0);B=(0,m,0);C=(msin(60°),mcos(60°),0);其中m为在xy投影面上正三角形的内切圆心到B点的距离。


③确定各限位开关的位置(即确定各丝杠平台上滑块的初始位置),丝杠平台的运动可简化为如下:【其中N点为滑块初始位置,Q点为端点初始位置,P为Q点在丝杠平台上Z轴的投影;N1,P1,Q1点为丝杠平台运动后的位,T点为某一固定点,假设为delta机械臂上端点在Z向可以运动的最大值在丝杠平台Z向的投影点】


④逆运动学是根据Q1点的位置确定NN1的距离。      
在图中有几个可以通过测量得到已知值,分别是连杆长度NQ/N1Q1、NT的距离、终点Q1点的坐标;假设我们输入的量是终点Q1的坐标(X1,Y1,Z1);这里需要注意的是Z1坐标为负值,为了方便理解在后面的推导中我们都对Z1取绝对值。    

我们需要计算的是NN1的距离:

其中Q1的Z坐标与P1的Z坐标一致,所以NP1为已知量为Q1的Z坐标值Z1,即可以将上面的公式改为:

这里我们只需要计算出N1P1的值即可:

其中NIQ1为连杆长度,可通过测量得知,所以这里面需要我们计算出Q1P1。      

⑤求出Q1P1:【该长度我们可以通过两点坐标距离公式得出,借助俯视图投影进行计算】



为方便计算Q1P1,图中我们将N,N1,P,P1,T点都投影到Z为0的点,则Q1(X1,Y1,0)。

根据点坐标公式可得:

综上所述:

注意前面我们对Z1取了一次绝对值,实际Z1为负值,

所以最终推导公式为:


这样我们就求出了NN1(丝杠移动距离)与Q1(执行端运动的终点)坐标的关系。

4. 功能实现
4.1 电子硬件
在这个示例中,我们采用了以下硬件,请大家参考:

主控板
Basra主控板(兼容Arduino Uno)
扩展板Bigfish2.1
SH-ST扩展板
传感器触碰传感器
电机步进电机
电池11.1v动力电池
其它
电磁铁、USB线

4.2 电路连接说明
① 硬件连接-电子元件


各轴步进电机与SH-ST步进电机扩展板的接线顺序如下(从上至下):
X:红蓝黑绿
Y:红蓝黑绿
Z:黑绿红蓝

② 硬件连接-限位传感器


各个轴的限位传感器(触碰)与Bigfish扩展板的接线如下:
X:A0
Y:A3
Z:A4

③ 电磁铁连在Bigfish扩展板的D5、D6接口上。

4.3 编写程序
编程环境:Arduino 1.8.19

Delta机械臂有两种运动方式:第一种是自动运行搬运;第二种是用电脑发送指令,然后再根据指令运动。      
这里仅列出Delta机械臂自动运行搬运(Delta.ino)的程序:【其它的程序源码可下载文末资料获取】
  1. /*------------------------------------------------------------------------------------

  2.   版权说明:Copyright 2023 Robottime(Beijing) Technology Co., Ltd. All Rights Reserved.

  3.            Distributed under MIT license.See file LICENSE for detail or copy at

  4.            https://opensource.org/licenses/MIT

  5.            by 机器谱 2023-02-08 https://www.robotway.com/                                 

  6. ------------------------------------------------------------------------------------*/

  7. #include "Arduino.h"

  8. #include <AccelStepper.h>

  9. #include <MultiStepper.h>

  10. #include "Configuration.h"


  11. AccelStepper stepper_x(1, 2, 5);      //tower1

  12. AccelStepper stepper_y(1, 3, 6);      //tower2

  13. AccelStepper stepper_z(1, 4, 7);      //tower3

  14. //AccelStepper stepper_a(1, 12, 13);


  15. MultiStepper steppers;


  16. float delta[NUM_STEPPER];                        

  17. float cartesian[NUM_AXIS] = {0.0, 0.0, 0.0};         //当前坐标

  18. float destination[NUM_AXIS];                         //目标坐标

  19. boolean dataComplete = false;


  20. float down = -111;

  21. float up = -105;


  22. /*********************************************Main******************************************/

  23. void setup() {

  24.   Serial.begin(9600);

  25.   pinMode(EN, OUTPUT);


  26.   steppers.addStepper(stepper_x);

  27.   steppers.addStepper(stepper_y);

  28.   steppers.addStepper(stepper_z);


  29.   stepperSet(1600, 400.0);

  30.   stepperReset();

  31.   delay(1000);


  32.   Get_command(0, 0, down);

  33.   Process_command();



  34.   delay(1000);

  35. }


  36. void loop() {

  37.   float r = 25;

  38.   float x1 = 0.0;

  39.   float y1 = 0.0;


  40.   Get_command(25, 0, down);

  41.   Process_command();

  42.   delay(1000);



  43.   for(int i=0;i<2;i++){

  44.     for(float i=0.0;i<=360;i+=10){

  45.       x1 = r * cos(i / 180 * 3.141592);

  46.       y1 = r * sin(i / 180 * 3.141592);

  47.      

  48.       Get_command(x1, y1, down);

  49.       Process_command();                                    

  50.     }

  51.   }

  52.   delay(1000);


  53.   for(int j=0;j<2;j++){

  54.     for(float i=360.0;i>=0;i-=10){

  55.       x1 = r * cos(i / 180 * 3.141592);

  56.       y1 = r * sin(i / 180 * 3.141592);

  57.      

  58.       Get_command(x1, y1, down);

  59.       Process_command();                                    

  60.     }

  61.   }

  62.   delay(1000);




  63.   Get_command(0, 0, down);

  64.   Process_command();  



  65.   test();

  66.   delay(1000);



  67.   stepperReset();

  68.   delay(1000);



  69. }


  70. /***************************************Get_commond*******************************************/

  71. void Get_command(float _dx, float _dy, float _dz){  

  72.   destination[0] = _dx;

  73.   destination[1] = _dy;

  74.   destination[2] = _dz;



  75.   if(destination[0] == 0 && destination[1] == 0 && destination[2] == 0){

  76.       stepperReset();  

  77.   }

  78.   else

  79.   {

  80.       dataComplete = true;

  81.   }



  82.   if(serial_notes){

  83.    Serial.print("destinationPosition: ");

  84.    Serial.print(destination[0]);

  85.    Serial.print(" ");

  86.    Serial.print(destination[1]);

  87.    Serial.print(" ");

  88.    Serial.println(destination[2]);

  89.   }


  90. }


  91. /***************************************Process_command***************************************/

  92. void Process_command(){

  93.   if(dataComplete){

  94.     digitalWrite(EN, LOW);

  95.    

  96.     if(cartesian[0] == destination[0] && cartesian[1] == destination[1] && cartesian[2] == destination[2]){

  97.       return;  

  98.     }

  99.     else

  100.     {


  101.       Line_DDA(destination[0], destination[1], destination[2]);

  102.     }

  103.    

  104.   }

  105.   dataComplete = false;

  106.   digitalWrite(EN, HIGH);

  107. }


  108. /************************************************** DDA ************************************************/

  109. void Line_DDA(float x1, float y1, float z1)

  110. {

  111.   float x0, y0, z0;         // 当前坐标点

  112.   float cx, cy;             // x、y 方向上的增量



  113.   x0 = cartesian[0];y0 = cartesian[1];z0 = cartesian[2];

  114.    

  115.   int steps = abs(x1 - x0) > abs(y1 - y0) ? abs(x1 - x0) : abs(y1 - y0);



  116.   cx = (float)(x1 - x0) / steps;

  117.   cy = (float)(y1 - y0) / steps;



  118.   for(int i = 0; i <= steps; i++)

  119.   {

  120.     cartesian[0] = x0 - cartesian[0];

  121.     cartesian[1] = y0 - cartesian[1];

  122.     cartesian[2] = z1 - cartesian[2];


  123.     calculate_delta(cartesian);

  124.    

  125.     stepperSet(1350.0, 50.0);

  126.     stepperMove(delta[0], delta[1], delta[2]);



  127.     cartesian[0] = x0;

  128.     cartesian[1] = y0;

  129.     cartesian[2] = z1;



  130.     x0 += cx;

  131.     y0 += cy;

  132.    

  133.     if(serial_notes){

  134.       Serial.print("currentPosition: ");

  135.       for(int i=0;i<3;i++){

  136.          Serial.print(cartesian[i]);

  137.          Serial.print(" ");

  138.       }   

  139.       Serial.println();

  140.       Serial.println("-------------------------------------------------");

  141.     }


  142.   }


  143. }


  144. /***************************************calculateDelta****************************************/

  145. void calculate_delta(float cartesian[3])

  146. {

  147.   if(cartesian[0] == 0 && cartesian[1] == 0 && cartesian[2] == 0){

  148.       delta[0] = 0; delta[1] =0; delta[2] = 0;

  149.   }

  150.   else

  151.   {

  152.       delta[TOWER_1] = sqrt(delta_diagonal_rod_2

  153.                        - sq(delta_tower1_x-cartesian[X_AXIS])

  154.                        - sq(delta_tower1_y-cartesian[Y_AXIS])

  155.                        ) + cartesian[Z_AXIS];

  156.       delta[TOWER_2] = sqrt(delta_diagonal_rod_2

  157.                        - sq(delta_tower2_x-cartesian[X_AXIS])

  158.                        - sq(delta_tower2_y-cartesian[Y_AXIS])

  159.                        ) + cartesian[Z_AXIS];

  160.       delta[TOWER_3] = sqrt(delta_diagonal_rod_2

  161.                        - sq(delta_tower3_x-cartesian[X_AXIS])

  162.                        - sq(delta_tower3_y-cartesian[Y_AXIS])

  163.                        ) + cartesian[Z_AXIS];


  164.      for(int i=0;i<3;i++){

  165.         delta[i] = ((delta[i] - 111.96) * stepsPerRevolution / LEAD);

  166.      }

  167.   }


  168.   if(serial_notes){

  169.       Serial.print("cartesian x="); Serial.print(cartesian[X_AXIS]);

  170.       Serial.print(" y="); Serial.print(cartesian[Y_AXIS]);

  171.       Serial.print(" z="); Serial.println(cartesian[Z_AXIS]);

  172.    

  173.       Serial.print("delta tower1="); Serial.print(delta[TOWER_1]);      

  174.       Serial.print(" tower2="); Serial.print(delta[TOWER_2]);

  175.       Serial.print(" tower3="); Serial.println(delta[TOWER_3]);

  176.   }


  177. }


  178. /****************************************stepperMove******************************************/

  179. void stepperMove(long _x, long _y, long _z){            

  180.     long positions[3];

  181.     positions[0] = _x;                        //steps < 0, 向下运动 ; steps > 0, 向上运动

  182.     positions[1] = _y;

  183.     positions[2] = _z;


  184.     steppers.moveTo(positions);

  185.     steppers.runSpeedToPosition();


  186.     stepper_x.setCurrentPosition(0);

  187.     stepper_y.setCurrentPosition(0);

  188.     stepper_z.setCurrentPosition(0);

  189. }


  190. /****************************************stepperSet******************************************/

  191. void stepperSet(float _v, float _a){

  192.   stepper_x.setMaxSpeed(_v);                  //MaxSpeed: 650

  193.   stepper_x.setAcceleration(_a);  

  194.   stepper_y.setMaxSpeed(_v);

  195.   stepper_y.setAcceleration(_a);

  196.   stepper_z.setMaxSpeed(_v);

  197.   stepper_z.setAcceleration(_a);


  198. }


  199. /****************************************stepperReset******************************************/

  200. void stepperReset(){

  201.   digitalWrite(EN, LOW);



  202.   if(cartesian[2] != 0){

  203.     Get_command(0, 0, cartesian[2]);

  204.     Process_command();

  205.     digitalWrite(EN, LOW);

  206.   }



  207.   while(digitalRead(SENSOR_TOWER1) && digitalRead(SENSOR_TOWER2) && digitalRead(SENSOR_TOWER3)){

  208.     stepperMove(10, 10, 10);

  209.   }


  210.   stepperSet(1200.0, 100.0);

  211.   stepperMove(-400, 0, 0);

  212.   while(digitalRead(SENSOR_TOWER1)){

  213.     stepperMove(10, 0, 0);

  214.    

  215.   }


  216.   stepperMove(0, -400, 0);

  217.   while(digitalRead(SENSOR_TOWER2)){

  218.     stepperMove(0, 10, 0);

  219.   }


  220.   stepperMove(0, 0, -400);

  221.   while(digitalRead(SENSOR_TOWER3)){

  222.     stepperMove(0, 0, 10);

  223.   }


  224.   for(int i=0;i<3;i++){

  225.      cartesian[i] = 0.0;

  226.   }  


  227.   if(serial_notes) Serial.println("resetComplete!");


  228.   digitalWrite(EN, HIGH);

  229. }


  230. /*************************************************** electromagnet *************************************************************/

  231. void putUp(){

  232.    digitalWrite(9, HIGH);

  233.    digitalWrite(10, LOW);

  234. }


  235. void putDown(){

  236.    digitalWrite(9, LOW);

  237.    digitalWrite(10, LOW);

  238. }


  239. /**************************************************   test    ******************************************************************/

  240. void test(){

  241.     Get_command(0, 0, down);

  242.     Process_command();

  243.     delay(500);

  244.     putUp();



  245.     Get_command(0, 0, up);

  246.     Process_command();  

  247.     Get_command(25, 0, up);

  248.     Process_command();


  249.     Get_command(25, 0, down);

  250.     Process_command();  

  251.     putDown();

  252.     delay(500);

  253.     putDown();

  254.     putUp();


  255.     Get_command(25, 0, up);

  256.     Process_command();   

  257.     Get_command(0, 25, up);

  258.     Process_command();   


  259.     Get_command(0, 25, down);

  260.     Process_command();

  261.     putDown();  

  262.     delay(500);

  263.     putDown();

  264.     putUp();


  265.     Get_command(0, 25, up);

  266.     Process_command();   

  267.     Get_command(-25, 0, up);

  268.     Process_command();   


  269.     Get_command(-25, 0, down);

  270.     Process_command();  

  271.     putDown();

  272.     delay(500);

  273.     putUp();


  274.     Get_command(-25, 0, up);

  275.     Process_command();   

  276.     Get_command(0, -25, up);

  277.     Process_command();   


  278.     Get_command(0, -25, down);

  279.     Process_command();  

  280.     putDown();

  281.     delay(500);

  282.     putUp();


  283.     Get_command(0, -25, up);

  284.     Process_command();   

  285.     Get_command(25, 0, up);

  286.     Process_command();   


  287.     Get_command(25, 0, down);

  288.     Process_command();   

  289.     putDown();

  290.     delay(500);

  291.     putUp();


  292.     Get_command(25, 0, up);

  293.     Process_command();   

  294.     Get_command(0, 0, up);

  295.     Process_command();   


  296.     Get_command(0, 0, down);

  297.     Process_command();   

  298.     delay(500);

  299.     putDown();

  300. }
复制代码

5. 扩展
     下图是另一种外观的Delta机械臂(R037c),控制原理完全一样。


4. 资料下载
​资料内容:
​①例程源代码
​②样机3D文件
​资料下载地址:https://www.robotway.com/h-col-194.html


想了解更多机器人开源项目资料请关注 机器谱网站 https://www.robotway.com
回复

使用道具 举报

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

本版积分规则 需要先绑定手机号

Archiver|联系我们|极客工坊

GMT+8, 2024-4-25 20:47 , Processed in 0.042158 second(s), 17 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

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