极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 2098|回复: 0

12自由度六足机器人实现原地舞蹈功能

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

1. 功能描述
      R111样机是一款拥有12个自由度的串联仿生六足机器人。本文示例所实现的功能为:R111样机12自由度六足机器人原地舞蹈。

2. 结构说明
      R111样机(R111b)由6个2自由度连杆仿生腿结构组成,2自由度连杆仿生腿两两对称组合,分别构成机器昆虫的三对足。三对足之间由零件结合固定,从而构成机器昆虫的本体,呈现出非常规整的模块化结构。
       该2自由度串联结构由舵机1和舵机2驱动,其中舵机1实现腿部前后摆动,舵机2实现腿部的上下抬伸。其中抬伸通过一个平行四连杆ABCD作为传动结构以增加腿部的行程和增强腿部运动的稳定性。

3. 电子硬件
在这个示例中,我们采用了以下硬件,请大家参考:

主控板
Basra主控板(兼容Arduino Uno)
扩展板SH-SR舵机扩展板
舵机标准舵机
电池7.4V锂电池

电路连接说明:
因为12自由度六足机器人结构上装有12个舵机,所以将采用 SH-SR舵机扩展板 。
舵机接线顺序:1、3; 4、 5; 6、 8;11、13;15、 21;24、26。


4. 功能实现
上位机:Controller 1.0
下位机编程环境:Arduino 1.8.19
4.1初始位置的设定
① 将Controller下位机程序servo.ino直接下载到主控板。这段代码供Controller上位机与主控板通信,并允许调试舵机。代码如下:
  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-16 https://www.robotway.com/

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

  7. #include <Tlc5940.h>

  8. #include <tlc_servos.h>


  9. int data_array[2] = {0,0};   //servo_pin: data_array[0], servo_value: data_array[1];

  10. String data = "";


  11. boolean dataComplete = false;


  12. void setup() {

  13.   Serial.begin(9600);

  14.   Tlc.init(0);

  15.   tlc_initServos();

  16.   delay(1000);

  17. }


  18. void loop() {



  19.   while(Serial.available())

  20.   {

  21.     int B_flag, P_flag, T_flag;

  22.     data = Serial.readStringUntil('\n');

  23.     data.trim();

  24.     for(int i=0;i<data.length();i++)

  25.     {

  26.       //Serial.println(data[i]);

  27.       switch(data[i])

  28.       {

  29.         case '#':

  30.           B_flag = i;  

  31.         break;

  32.         case 'P':

  33.         {

  34.           String pin = "";

  35.           P_flag = i;

  36.           for(int i=B_flag+1;i<P_flag;i++)

  37.           {

  38.             pin+=data[i];

  39.           }

  40.           data_array[0] = pin.toInt();

  41.         }

  42.         break;

  43.         case 'T':

  44.         {

  45.           String angle = "";

  46.           T_flag = i;

  47.           for(int i=P_flag+1;i<T_flag;i++)

  48.           {

  49.             angle += data[i];

  50.           }

  51.           data_array[1] = map(angle.toInt(), 500, 2500, 0, 180);

  52.         }

  53.         break;

  54.         default: break;

  55.       }     

  56.     }

  57.    

  58.     /*

  59.     Serial.println(B_flag);

  60.     Serial.println(P_flag);

  61.     Serial.println(T_flag);

  62.    

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

  64.     {

  65.       Serial.println(data_array[i]);

  66.     }

  67.     */

  68.    

  69. dataComplete = true;

  70.   }



  71.   if(dataComplete)

  72.   {

  73.     tlc_setServo(data_array[0], data_array[1]);

  74.     Tlc.update();

  75.     dataComplete = false;

  76.   }




  77. }
复制代码

下载完成后,保持主控板和电脑的USB连接,并打开主控板电源,以便利用上位机进行调试。
② 双击打开Controller 1.0b.exe:

③ 点击联机,选择对应的端口号,波特率设置为9600,如下图所示:


控制块内容说明如下:


④ 此时上位机软件已经与下位机建立通信连接,我们拖动舵机引脚号对应的滑块即可对舵机进行角度调节。下图为软件中各个按钮说明:

软件各按钮说明

转换后的数据

⑤ 设置面板说明:点击左上角设置-设置面板,即可打开(如下图)。点击对应序号的复选框即可控制软件主界面中相应控制块的显示和隐藏,以及全部显示和全部隐藏等;点击重置按钮,可将各个控制块恢复初始位置;点击确定可关闭设置界面。


⑥ 控制块任意位置拖动:如下图,可拖动至需要的形状。

变化后的形状
注:每次重启会恢复初始位置

3.2 示例程序
调试好角度后,将角度参数复制到下面的12自由度六足机器人原地舞蹈的参考例程(robot_dance.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-16 https://www.robotway.com/

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

  7. #include <Arduino.h>

  8. #include <avr/pgmspace.h>

  9. #include "Config.h"

  10. #include <Tlc5940.h>

  11. #include <tlc_servos.h>

  12. int count_input = 0;

  13. boolean _b = false;

  14. /**************+++++++++++动作组数组,请将转换后的动作组数据粘贴到相应的动作组中+++++++***************************/

  15. const PROGMEM int actionInit[] = {

  16.   1090, 1790, 1220, 980, 650, 1800, 1020, 1330, 520, 1155, 1260, 2020,

  17.   1090, 1790, 1220, 980, 650, 1800, 1020, 1330, 520, 1155, 1260, 2020,

  18. };

  19. const PROGMEM int actionLeft[] = {

  20. };

  21. const PROGMEM int actionRight[] = {

  22. };

  23. const PROGMEM int actionBack[] = {

  24. };

  25. const PROGMEM int actionDance[] = {

  26. };

  27. const PROGMEM int actionDance[] = {

  28.   1660, 1230, 1220, 980, 1280, 1190, 1020, 1330, 1090, 1155, 1260, 1540,

  29.   1090,1790,1220,980,650,1800,1020,1330,520,1155,1260,2020,

  30.   1490,1590,1220,980,850,1400,1020,1330,1320,1155,1260,2020,

  31.   1490,1590,1220,980,850,1400,1020,1330,1320,1155,1700,1700,

  32.   1490,1590,1220,980,850,1400,1020,1330,1320,1155,1700,2020,

  33.   1090,1790,1220,980,650,1800,1020,1330,520,1155,1260,2020,

  34.   1490,1590,1220,980,850,1400,1020,1330,520,1155,1260,1220,

  35.   1490,1590,1220,980,850,1400,1020,1330,800,700,1260,1220,

  36.   1490,1590,1220,980,850,1400,1020,1330,520,700,1260,1220,

  37.   1090,1790,1220,980,650,1800,1020,1330,520,1155,1260,2020,

  38.   1670,1190,1220,980,1370,1100,1020,1330,1100,1155,1260,1430,

  39.   1090,1190,1220,980,1370,1800,620,1730,1100,1155,1260,1430,

  40.   1090,1190,1220,980,1370,1100,620,1730,1100,1155,1260,1430,

  41.   1670,1190,1220,980,1370,1800,620,1730,1100,1155,1260,1430,

  42.   1090,1190,1220,980,1370,1100,620,1730,1100,1155,1260,1430,

  43.   1090,1190,1220,980,1370,1800,700,1570,1100,1155,1260,1430,

  44.   1670,1190,1220,980,1370,1100,700,1570,1100,1155,1260,1430,

  45.   1670,1190,1220,980,1370,1100,700,1570,520,520,1930,2020,

  46.   1670,1190,1220,980,1370,1100,700,1570,800,520,1930,1700,

  47.   1670,1190,1220,980,1370,1100,700,1570,520,520,1930,2020,

  48.   1670,1190,1220,980,1370,1100,700,1570,800,520,1930,1700,

  49.   1670,1190,1220,980,1370,1100,700,1570,1100,1155,1260,1430,

  50.   1670,1190,1220,980,1370,1100,1020,1330,1100,1155,1260,1430,

  51.   1670,1190,1220,980,1370,1100,1020,1330,1100,1155,1260,1430,

  52.   1670,1190,1220,980,900,1590,1020,1330,720,1155,1260,1430,

  53.   1320,1540,1220,980,1370,1100,1020,1330,1100,1155,1260,1830,

  54.   1670,1190,1220,980,1370,1100,1020,1330,1100,1155,1260,1430,

  55.   1320,1410,1220,980,1370,1100,1020,1330,1100,1155,1260,1950,

  56.   1300,1670,1220,980,1370,1100,1020,1330,1100,1155,1260,1600,

  57.   1670,1190,1220,980,940,1540,1020,1330,920,1155,1260,1430,

  58.   1670,1190,1220,980,1235,1480,1020,1330,580,1155,1260,1430,

  59.   1670,1190,1220,980,940,1540,1020,1330,920,1155,1260,1430,

  60.   1670,1190,990,1210,940,1540,1140,1100,920,1400,1060,1430,

  61.   1300,1670,990,1210,1370,1100,1140,1100,1100,1400,1060,1600,

  62.   1320,1540,990,1210,1370,1100,1140,1100,1100,1400,1060,1830,

  63.   1670,1190,990,1210,1370,1100,1140,1100,1100,1400,1060,1430,

  64.   1670,1190,990,1210,1370,1100,1140,1100,1100,1400,1060,1430,

  65.   1670,1190,1280,920,1370,1100,920,1410,1100,1030,1410,1430,

  66.   1670,1190,990,1210,1370,1100,1140,1100,1100,1400,1060,1430,

  67.   1670,1190,1280,920,1370,1100,920,1410,1100,1030,1410,1430,

  68.   1670,1190,1220,980,1370,1100,1020,1330,1100,1155,1260,1430,

  69. };


  70. /**************************+++++---------分割线--------++++++*******************************************************/


  71. //动作组数组长度获取函数,增加动作组时需要按如下格式添加:actPwmNum[增加的动作组序号] = sizeof(增加的动作组名称) / sizeof(增加的动作组名称[0]);

  72. void act_length()

  73. {

  74.   actPwmNum[0] = (sizeof(actionMove) / sizeof(actionMove[0]))/servo_num;

  75.   actPwmNum[1] = (sizeof(actionLeft) / sizeof(actionLeft[0]))/servo_num;

  76.   actPwmNum[2] = (sizeof(actionRight) / sizeof(actionRight[0]))/servo_num;

  77.   actPwmNum[3] = (sizeof(actionBack) / sizeof(actionBack[0]))/servo_num;

  78.   actPwmNum[4] = (sizeof(actionDance) / sizeof(actionDance[0]))/servo_num;

  79.   actPwmNum[5] = (sizeof(actionInit) / sizeof(actionInit[0]))/servo_num;

  80. }


  81. //map映射函数

  82. long map_servo(long x, long in_min, long in_max, long out_min, long out_max)

  83. {

  84.   return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;

  85. }


  86. //PWM 转换为舵机角度的函数,增加动作组时需要修改

  87. void vlaue2angle(int p, int act)

  88. {

  89.   switch(act)

  90.   {

  91.     case 0:   value_cur[p] = map_servo(pgm_read_word_near(actionMove + p + servo_num * count_input), 500, 2500, 0, 180);   break;

  92.     case 1:   value_cur[p] = map_servo(pgm_read_word_near(actionLeft + p + servo_num * count_input), 500, 2500, 0, 180);   break;

  93.     case 2:   value_cur[p] = map_servo(pgm_read_word_near(actionRight + p + servo_num * count_input), 500, 2500, 0, 180);   break;

  94.     case 3:   value_cur[p] = map_servo(pgm_read_word_near(actionBack + p + servo_num * count_input), 500, 2500, 0, 180);   break;

  95.     case 4:   value_cur[p] = map_servo(pgm_read_word_near(actionDance + p + servo_num * count_input), 500, 2500, 0, 180); break;

  96.     case 5:   value_cur[p] = map_servo(pgm_read_word_near(actionInit + p + servo_num * count_input), 500, 2500, 0, 180); break;

  97.     default: break;

  98.   }

  99. }


  100. //舵机初始化函数,动作组第一行为舵机初始化值

  101. void servo_init(int act, int num)

  102. {  

  103.   if(!_b)

  104.   {

  105.     for(int i=0;i<servo_num;i++)

  106.     {

  107.       vlaue2angle(i, act);

  108.       tlc_setServo(servo_pin[i], value_cur[i]);

  109.       value_pre[i] = value_cur[i];

  110.     }

  111.     Tlc.update();

  112.     //delay(1000);

  113.   }



  114.   num == 1 ? _b = true : _b = false;


  115. }


  116. //舵机移动函数,参数: act:动作组宏定义名称 ;num:动作组执行的次数,num > 0 ;

  117. void servo_move(int act, int num)

  118. {  

  119.   float value_delta[servo_num] = {};

  120.   float in_value[servo_num] = {};

  121.   servo_init(act, num);

  122.   for(int i=0;i< num * actPwmNum[act];i++)

  123.   {

  124.     count_input++;

  125.    

  126.     if(count_input == actPwmNum[act])

  127.     {

  128.       count_input = 0;

  129.       continue;

  130.     }

  131.     for(int i=0;i<servo_num;i++)

  132.     {

  133.       vlaue2angle(i, act);

  134.       in_value[i] = value_pre[i];

  135.       value_delta[i] = (value_cur[i] - value_pre[i]) / frequency;

  136.     }

  137.     for(int i=0;i<frequency;i++)

  138.     {

  139.       for(int k=0;k<servo_num;k++)

  140.       {

  141.         in_value[k] += value_delta[k];  

  142.         value_pre[k] = in_value[k];

  143.       }

  144.       for(int j=0;j<servo_num;j++)

  145.       {      

  146.         tlc_setServo(servo_pin[j], in_value[j]);

  147.         delayMicroseconds(servo_speed);

  148.       }

  149.       Tlc.update();

  150.     }

  151.     delayMicroseconds(action_delay);

  152.   }

  153. }

  154. /********************************************************-------分割线--------****************************************************/

  155. //初始化函数

  156. void setup() {

  157.   Serial.begin(9600);     //开启串口通信,波特率9600

  158.   Tlc.init(0);

  159.   tlc_initServos();

  160.   act_length();

  161.   delay(action_delay);

  162. }


  163. //主函数,跳舞

  164. void loop() {

  165.     servo_move(action_dance, 2);

  166.     delay(100);

  167. }
复制代码
       对于机器人来说,实现某一个自身结构的极限动作并不难,难度在于如何让动作变得有节奏-舞蹈。因为机器人无法达到人体的柔和度,所以为了让机器人跳舞更具有观赏性,建议大家选择节奏点清晰的音乐,尝试根据音乐节奏来设计舞蹈动作。

4. 扩展样机
      改变足对之间的连接零件,就可以扩展出不同的样机,甚至还可以考虑在足对之间加入关节,使其具备更丰富的自由度。

5. 资料下载

资料内容:
①样机3D文件
②原地舞蹈-例程源代码
③Controller1.0b资料包
④音乐素材.mp3
资料下载地址:
https://www.robotway.com/h-col-197.html


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

使用道具 举报

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

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

Archiver|联系我们|极客工坊

GMT+8, 2024-3-29 20:40 , Processed in 0.042342 second(s), 17 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

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