极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 2785|回复: 0

3自由度并联绘图机器人实现写字功能(二)

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

1. 功能说明
     本文示例将实现R305b样机3自由度并联绘图机器人写字的功能。本实验使用的样机是用探索者兼容零件制作的。


2. 电子硬件

     在这个示例中,采用了以下硬件,请大家参考:

主控板
Basra主控板(兼容Arduino Uno)
扩展板
Bigfish2.1扩展板
传感器触碰传感器
电池7.4V锂电池

3. 功能实现
3.1建立坐标系

       我们需要先对3自由度并联绘图机器人进行极限位置调节,下图中为左极限位置,右极限位置与其对称。3自由度并联绘图机器人绘图主要由图中所示两个伺服电机控制。


3.2 硬件连接
          ① 触碰传感器连接Bigfish扩展板A0端口
          ② 左侧舵机连接Bigfish扩展板D4号引脚
          ③ 右侧舵机连接Bigfish扩展板D7号引脚
          ④ 控制底部连杆的舵机连接到Bigfish扩展板D11号引脚


3.3 示例程序
编程环境:Arduino 1.8.19
实现思路:接通电源后,等待3秒,按下触碰传感器,3自由度并联绘图机器人开始依次写出“王”、“云”、“飞”三个汉字。  
将参考例程(ThreeServo_Writing.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-04-03 https://www.robotway.com/

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

  7. /*******************************************************************************************************

  8. 实现功能:

  9.          三自由度舵机组成的机械臂实现写字;



  10. 实现思路:

  11.           接通电源后,等待3秒,按下触碰传感器,3自由度并联绘图机器人开始依次写出“王”、“云”、“飞”三个汉字



  12. 实验接线:

  13.          触碰传感器接到A0;

  14.          控制左边连杆的舵机接到D4;

  15.          控制右边连杆的舵机接到D7;

  16.          控制底部连杆的舵机接到D11;

  17. *******************************************************************************************************/


  18. #include <Servo.h> //驱动舵机需要的函数库


  19. #define SERVOLEFTNULL 500      //左侧舵机转动到0度的值

  20. #define SERVORIGHTNULL 500     //右侧舵机转动到0度的值


  21. #define SERVOFAKTORLEFT 603    //左侧舵机转动到0度右侧舵机转动到90度时的值

  22. #define SERVOFAKTORRIGHT 610   //左侧舵机转动到90度右侧舵机转动到180度时的值


  23. #define LIFT0 1500             //落笔写字时舵机转动的值

  24. #define LIFT1 1800             //一笔写完换笔时舵机转动的值

  25. #define LIFT2 1400             //初始及完成写字后抬笔时舵机的值


  26. #define SERVOPINLEFT 4         //定义左边舵机要连接的引脚;

  27. #define SERVOPINRIGHT 7        //定义右边舵机要连接的引脚;

  28. #define SERVOPINLIFT 11        //定义底部舵机要链接的引脚;


  29. #define TouchSensor A0         //触碰传感器连接的引脚


  30. #define LIFTSPEED 1500         //定义抬笔落笔时舵机转动的速度


  31. #define L1 90                  //定义与舵机相连杆的长度 mm  

  32. #define L2 117.6               //定义与舵机相连杆的端点铰接处中心到笔中心的距离 mm

  33. #define L3 31.6                //定义中间杆顶端铰接处中心到笔的距离 mm


  34. #define X1 40.0                //定义左侧舵机中心轴到原点在X方向上的距离

  35. #define Y1 -42                 //定义左侧舵机中心轴到X轴的垂直距离

  36. #define X2 111.4               //定义右侧舵机中心轴到原点在X方向上的距离

  37. #define Y2 -42                 //定义右侧舵机中心轴到到X轴的垂直距离


  38. //坐标系建立第一象限,X轴方向为140mm,Y轴方向为120mm,选取坐标点时Y值建议大于70

  39. int coAry[10][10][2] = {         


  40.               //汉字   王

  41.               {{25,110},{0,0},{51,110},{1,1}},

  42.               {{26,98},{0,0},{49,98},{1,1}},

  43.               {{25,84},{0,0},{51,84},{1,1}},

  44.               {{37,110},{0,0},{37,84},{1,1}},


  45.               //汉字   云

  46.               {{61,110},{0,0},{81,110},{1,1}},

  47.               {{58,100},{0,0},{85,100},{1,1}},

  48.               {{68,100},{0,0},{62,85},{86,85},{1,1}},

  49.               {{80,96},{0,0},{91,82},{1,1}},

  50.             

  51.               //汉字   飞

  52.               {{99,110},{0,0},{114,110},{114,98},{115,90},{115,86},{118,84},{121,82},{126,88},{1,1}},

  53.               {{121,103},{0,0},{116,98},{122,94},{1,1}}

  54.                         

  55. };



  56. int servoLift = LIFT2;


  57. Servo servo1; //声明舵机1

  58. Servo servo2; //声明舵机2

  59. Servo servo3; //声明舵机3


  60. volatile double lastX = 25;   //笔初始坐标值

  61. volatile double lastY = 110;


  62. void setup() {

  63.   Serial.begin(9600);        //开启串口通信

  64.   servo1.attach(SERVOPINLEFT);

  65.   servo2.attach(SERVOPINRIGHT);

  66.   servo3.attach(SERVOPINLIFT);   //声明舵机引脚;

  67.   servo3.writeMicroseconds(LIFT0+500); //初始化机械身躯的高度;

  68.   drawTo(lastX,lastY); //舵机初始角度;

  69.   delay(3000);

  70. }


  71. void Waiting() //直到触碰传感器触发,程序开始运行

  72. {

  73.   while(digitalRead(TouchSensor)){

  74.     delay(2);

  75.   }

  76.   delay(1000);

  77. }


  78. void loop() {

  79.   Waiting();//直到触碰传感器触发,程序开始运行

  80.   if(1)

  81.   {     

  82.     if(!servo1.attached()) servo1.attach(SERVOPINLEFT);

  83.     if(!servo2.attached()) servo2.attach(SERVOPINRIGHT);

  84.     if(!servo3.attached()) servo3.attach(SERVOPINLIFT);   

  85.     lift(2);

  86.     //汉字坐标处理

  87.     for(int i=0;i<10;i++)

  88.     {

  89.       for(int j=0;j<10;j++)

  90.       {

  91.         int x = coAry[i][j][0];

  92.         int y = coAry[i][j][1];               

  93.         if(x == 0 && y == 0)

  94.         {

  95.           lift(0);

  96.           continue;

  97.         }

  98.         else if(x == 1 && y == 1)

  99.         {

  100.           lift(1);

  101.           break;

  102.         }      

  103.         drawTo(x,y);      

  104.       }

  105.     }

  106.     lift(2);   

  107.     servo1.detach();

  108.     servo2.detach();

  109.     servo3.detach();           

  110.   }

  111.   delay(1/0); //程序一直处于等待状态;(类似于死循环)

  112. }


  113. //抬笔舵机转动函数,三个动作,落笔、换笔、起笔, 0 ,1, 2

  114. void lift(char lift)

  115. {

  116.   switch(lift)

  117.   {

  118.     case 0:

  119.         Serial.println("lift0");

  120.         if(servoLift >= LIFT0)

  121.         {

  122.           while(servoLift >= LIFT0)

  123.           {

  124.             servoLift--;

  125.             servo3.writeMicroseconds(servoLift);

  126.             delayMicroseconds(LIFTSPEED);

  127.           }

  128.         }

  129.         else

  130.         {

  131.            while(servoLift <= LIFT0)

  132.            {

  133.              servoLift++;

  134.              servo3.writeMicroseconds(servoLift);

  135.              delayMicroseconds(LIFTSPEED);

  136.            }

  137.         }

  138.     break;

  139.     case 1:

  140.         Serial.println("lift1");

  141.         if(servoLift >= LIFT1)

  142.         {

  143.           while(servoLift >= LIFT1)

  144.           {

  145.             servoLift--;

  146.             servo3.writeMicroseconds(servoLift);

  147.             delayMicroseconds(LIFTSPEED);

  148.           }

  149.         }

  150.         else

  151.         {

  152.           while(servoLift <= LIFT1)

  153.           {

  154.             servoLift++;

  155.             servo3.writeMicroseconds(servoLift);

  156.             delayMicroseconds(LIFTSPEED);

  157.           }

  158.         }

  159.     break;

  160.     case 2:

  161.         Serial.println("lift2");

  162.         if(servoLift >= LIFT2)

  163.         {

  164.           while(servoLift >= LIFT2)

  165.           {

  166.             servoLift--;

  167.             servo3.writeMicroseconds(servoLift);

  168.             delayMicroseconds(LIFTSPEED);

  169.           }

  170.         }

  171.         else

  172.         {

  173.           while(servoLift <= LIFT2)

  174.           {

  175.             servoLift++;

  176.             servo3.writeMicroseconds(servoLift);

  177.             delayMicroseconds(LIFTSPEED);

  178.           }

  179.         }

  180.     break;

  181.     default:break;

  182.   }

  183. }


  184. //笔移动函数,参数为点坐标值,计算两点坐标距离来控制笔移动

  185. void drawTo(double pX, double pY) {

  186.   double dx, dy, c;

  187.   int i;



  188.   Serial.println(pX);

  189.   Serial.println(pY);


  190.   // dx dy of new point

  191.   dx = pX - lastX;

  192.   dy = pY - lastY;

  193.   //path lenght in mm, times 4 equals 4 steps per mm

  194.   c = floor(10 * sqrt(dx * dx + dy * dy));


  195.   if (c < 1) c = 1;


  196.   for (i = 0; i <= c; i++) {

  197.     // draw line point by point

  198.     set_XY(lastX + (i * dx / c), lastY + (i * dy / c));

  199.   }


  200.   lastX = pX;

  201.   lastY = pY;

  202. }



  203. double return_angle(double a, double b, double c) {

  204.   // cosine rule for angle between c and a

  205.   return acos((a * a + c * c - b * b) / (2 * a * c));

  206. }



  207. //用各种三角函数把位置坐标换算成舵机的角度,如何计算,请参考

  208. //http://www.thingiverse.com/thing:248009/

  209. void set_XY(double Tx, double Ty)

  210. {

  211.   delay(1);

  212.   double dx, dy, c, a1, a2, Hx, Hy;


  213.   // calculate triangle between pen, servoLeft and arm joint

  214.   // cartesian dx/dy

  215.   dx = Tx - X1;

  216.   dy = Ty - Y1;


  217.   // polar lemgth (c) and angle (a1)

  218.   c = sqrt(dx * dx + dy * dy); //

  219.   a1 = atan2(dy, dx); //

  220.   a2 = return_angle(L1, L2, c);



  221.   //Serial.println(floor(((M_PI-a1 - a2) * SERVOFAKTORLEFT) + SERVOLEFTNULL));


  222.   servo1.writeMicroseconds(floor(((M_PI-a1 - a2) * SERVOFAKTORLEFT) + SERVOLEFTNULL));


  223.   // calculate joinr arm point for triangle of the right servo arm

  224.   a2 = return_angle(L2, L1, c);

  225.   Hx = Tx + L3 * cos((a1 - a2 + 0.621) + M_PI); //36,5掳

  226.   Hy = Ty + L3 * sin((a1 - a2 + 0.621) + M_PI);


  227.   // calculate triangle between pen joint, servoRight and arm joint

  228.   dx = Hx - X2;

  229.   dy = Hy - Y2;


  230.   c = sqrt(dx * dx + dy * dy);

  231.   a1 = atan2(dy, dx);

  232.   a2 = return_angle(L1, (L2 - L3), c);



  233.   //Serial.println(floor(((M_PI - a1 + a2) * SERVOFAKTORRIGHT) + SERVORIGHTNULL));


  234.   servo2.writeMicroseconds(floor(((M_PI - a1 + a2) * SERVOFAKTORRIGHT) + SERVORIGHTNULL));


  235. }
复制代码

4. 资料下载

资料内容:

​①写字2-例程源代码
​②写字2-样机3D文件
资料下载地址:https://www.robotway.com/h-col-205.html

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

回复

使用道具 举报

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

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

Archiver|联系我们|极客工坊

GMT+8, 2024-4-28 18:19 , Processed in 0.057177 second(s), 17 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

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