迪文科技论坛

 找回密码
 立即注册
搜索
查看: 233|回复: 0

【2023.7.23获奖项目】四轴机械臂控制系统

[复制链接]

567

主题

167

回帖

1万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
11978
发表于 2024-1-11 13:33:48 | 显示全部楼层 |阅读模式
1.介绍
最近搞了一个四轴机械臂,准备给机械臂做一个控制界面系统,刚好就拿迪文屏来做,主要用旋转控件来做,看了一下旋转控件的功能,发现是可以满足机械臂控制系统的需求。本来想用新版设计软件来做的,不过制作过程中有些控制有问题,所以这次设计最终还是用老版设计软件完成的。

2.设计想法
上面提到主要用旋转控件来做,原因是机械臂的动作是旋转的,而我想把机械臂的动作实时反应到屏幕上,而这就需要用到旋转控件了,几轴就需要用几个。不像以往的机械臂控制系统,只反应个机械臂的角度数值,而是要反应机械臂的动作,真正实时的在屏幕上能看到机械臂当前的姿态。

3.设计
还是素材的准备,为了让界面富有科技感,我采用的都是比较有科技化的元素,下面是我设计的界面和机械臂的元素。




图1


这次设计主要分为三个界面,分别是首页界面、控制界面、自动界面,首先是首页设计,这里就是一个普通的背景+基础触摸。



图2


接下来就是控制界面了,控制界面相对比较复杂,需要放上机械臂的所有部件,界面左边是机械臂实时的反馈情况,右边是控制功能,同时还有切换到Auto的界面。从设计界面上看,左边的机械臂比较凌乱,这是正常的因为用到的是旋转控件,而旋转控件只能向正方向旋转,而我为了让机械臂的状态能回到负方向,所以图片都是旋转到最左边的图片。



图3


最后就是自动界面了,这个界面左边和控制界面是一样的,实时反应机械臂的状态。右边则是记录自动时所需要的动作的。可以添加和删除动作,最多可以记录5个动作



图4


界面设计完成,接下来就是代码设计了。
第一步是要获取当前控制的角度。

  1. <font face="宋体" size="3" color="#000000">//获取机械臂状态
  2. void get_arm_config_status()
  3. {
  4.     u8 i = 0;
  5.    
  6.     for(i = 0;i < 4;i++)
  7.     {
  8.         arm_angle_value[i] = Read_Dgus(0x1100 + i * 2);
  9.         //Write_Dgus(0x1110 + i * 2, Va[i]);
  10.     }
  11. }</font>
复制代码

之后就是设计机械臂的运动,机械臂的运动是需要过程的,所以设置完角度后,机械臂是缓慢运动到指定位置的,而不是立马跳到指定位置的,所以这里需要一个过程,而且为了让系统电源压力小,所以需要一个轴一个轴的进行运动,下面是设计代码。
  1. <font face="宋体" size="3" color="#000000">//设置机械臂角度
  2. void set_arm_angle()
  3. {
  4.     int i = 0;
  5.     for(i = 0;i < 4;i++)
  6.     {
  7.         if(arm_angle_value[i] != arm_angle_value_last[i])
  8.         {
  9.             if(arm_angle_value[i] < arm_angle_value_last[i])
  10.             {
  11.                 arm_angle_value_last[i]--;
  12.             }
  13.             else
  14.             {
  15.                 arm_angle_value_last[i]++;
  16.             }
  17.             Write_Dgus(0x1110 + i * 2, arm_angle_value_last[i]);
  18.             if(i == 1)  //第二轴运动
  19.             {
  20.                 u16 armiii_pos_x = 0;
  21.                 u16 armiii_pos_y = 0;
  22.                 u16 armiv_pos_x = 0;
  23.                 u16 armiv_pos_y = 0;
  24.                
  25.                 armiii_pos_x = sin((float)(225 - arm_angle_value_last[i]) * TRIGONOMETRIC) * 80 + armii_start_pos[0];
  26.                 armiii_pos_y = cos((float)(225 - arm_angle_value_last[i]) * TRIGONOMETRIC) * 80 + armii_start_pos[1];
  27.                 armiv_pos_x = sin((float)(180 - arm_angle_value_last[i+1]) * TRIGONOMETRIC) * 83 + armiii_pos_x;
  28.                 armiv_pos_y = cos((float)(180 - arm_angle_value_last[i+1]) * TRIGONOMETRIC) * 83  + armiii_pos_y;               
  29.                
  30.                 armiii_current_pos[0] = armiii_pos_x;
  31.                 armiii_current_pos[1] = armiii_pos_y;

  32.                 OneSendData4(armiii_pos_x/256);
  33.                 OneSendData4(armiii_pos_x%256);
  34.                 OneSendData4(armiii_pos_y/256);
  35.                 OneSendData4(armiii_pos_y%256);

  36.                 Write_Dgus(0x2100 + 4, armiii_pos_x);   //第三轴的位置
  37.                 Write_Dgus(0x2100 + 5, armiii_pos_y);
  38.                 Write_Dgus(0x2200 + 4, armiv_pos_x);   //第三轴的位置
  39.                 Write_Dgus(0x2200 + 5, armiv_pos_y);
  40.             }
  41.             else if(i == 2)
  42.             {
  43.                 u16 armiv_pos_x = sin((float)(180 - arm_angle_value_last[i]) * TRIGONOMETRIC) * 83 + armiii_current_pos[0];
  44.                 u16 armiv_pos_y = cos((float)(180 - arm_angle_value_last[i]) * TRIGONOMETRIC) * 83 + armiii_current_pos[1];
  45.                
  46.                 Write_Dgus(0x2200 + 4, armiv_pos_x);   //第三轴的位置
  47.                 Write_Dgus(0x2200 + 5, armiv_pos_y);
  48.             }
  49.             break;
  50.         }
  51.     }
  52. }</font>
复制代码

这里设计了对所有的按键做处理,其中添加和开始是自动界面需要的,下面是具体设计代码。
  1. <font face="宋体" size="3" color="#000000">//获取按键状态
  2. void  get_key_status(u16 addr)
  3. {
  4.     u16 Va=Read_Dgus(addr);
  5.     //u16  V1=Read_Dgus(0x0f01);
  6.     if(Va != 0x0000)
  7.     {           
  8.         if(Va == 0x0001)    //复位
  9.         {
  10.             Write_Dgus(0x1100 + 0, 0);
  11.             Write_Dgus(0x1100 + 2, 0);
  12.             Write_Dgus(0x1100 + 4, 0);
  13.             Write_Dgus(0x1100 + 6, 90);
  14.         }
  15.         else if(Va == 0x0002)   //添加
  16.         {
  17.             if(arm_auto_cnt < 5)
  18.             {
  19.                 u8 i = 0;
  20.                 u8 send_str[30] = {0};
  21.                 for(i = 0;i < 4;i++)
  22.                 {
  23.                     arm_auto_list[arm_auto_cnt][i] = arm_angle_value[i];
  24.                 }
  25.                 sprintf(send_str, "I:%d II:%d III:%d IV:%d", arm_auto_list[arm_auto_cnt][0], arm_auto_list[arm_auto_cnt][1], arm_auto_list[arm_auto_cnt][2], arm_auto_list[arm_auto_cnt][3]);
  26.                 write_dgus_vp(0x1500 + 0x20 * arm_auto_cnt, send_str, 16);
  27.                 arm_auto_cnt++;
  28.             }
  29.             
  30.         }
  31.         else if(Va == 0x0003)   //开始
  32.         {
  33.             auto_start_flag = 1;
  34.             auto_start_cnt = 0;
  35.         }
  36.         else if(Va == 0x0004)   //停止
  37.         {
  38.             auto_start_flag = 0;
  39.             Write_Dgus(0x1100 + 0, arm_angle_value_last[0]);
  40.             Write_Dgus(0x1100 + 2, arm_angle_value_last[1]);
  41.             Write_Dgus(0x1100 + 4, arm_angle_value_last[2]);
  42.             Write_Dgus(0x1100 + 6, arm_angle_value_last[3]);
  43.         }
  44.         else if(Va >= 0x0010 && Va <= 0x0014)   //删除内容
  45.         {
  46.             u16 delete_select = Va - 0x0010;
  47.             if(arm_auto_cnt > delete_select)   //有删除的内容
  48.             {
  49.                 u8 i = 0;
  50.                 u8 send_str[30] = {0};
  51.                 for(i = delete_select;i < arm_auto_cnt - 1;i++)
  52.                 {
  53.                     memcpy(arm_auto_list[i], arm_auto_list[i + 1], 8);
  54.                 }
  55.                 memset(arm_auto_list[i], 0, 8);
  56.                 for(i = delete_select;i < arm_auto_cnt - 1;i++)
  57.                 {
  58.                     sprintf(send_str, "I:%d II:%d III:%d IV:%d\0", arm_auto_list[i][0], arm_auto_list[i][1], arm_auto_list[i][2], arm_auto_list[i][3]);
  59.                     write_dgus_vp(0x1500 + 0x20 * i, send_str, 16);
  60.                 }
  61.                 memset(send_str, 0, 30);
  62.                 write_dgus_vp(0x1500 + 0x20 * i, send_str, 16);
  63.                 arm_auto_cnt--;
  64.             }
  65.         }
  66.         Write_Dgus(addr, 0);
  67.     }
  68. }</font>
复制代码

最后就是自动动作功能了,主要采用了一个标志位判断是否需要自动运动,同时自动运动需要两个位置才能进行。自动运动的功能,就是判断当前位置是否到达运动的位置,如果到了,就可以开始下一个动作了。
  1. <font face="宋体" size="3" color="#000000">//自动运动
  2. void auto_run()
  3. {
  4.     if(auto_start_flag == 1 && arm_auto_cnt >= 2)   //动作必须两个及以上
  5.     {
  6.         if(memcmp(arm_angle_value, arm_auto_list[auto_start_cnt], 8) != 0) //不等于
  7.         {
  8.             Write_Dgus(0x1100 + 0, arm_auto_list[auto_start_cnt][0]);
  9.             Write_Dgus(0x1100 + 2, arm_auto_list[auto_start_cnt][1]);
  10.             Write_Dgus(0x1100 + 4, arm_auto_list[auto_start_cnt][2]);
  11.             Write_Dgus(0x1100 + 6, arm_auto_list[auto_start_cnt][3]);
  12.         }
  13.         else if(memcmp(arm_angle_value_last, arm_auto_list[auto_start_cnt], 8) == 0) //当前运动等于目标
  14.         {
  15.             auto_start_cnt++;
  16.             if(auto_start_cnt >= arm_auto_cnt)
  17.             {
  18.                 auto_start_cnt = 0;
  19.             }
  20.         }
  21.     }
  22. }</font>
复制代码

4.演示
给大家看看实际的效果图。
首页效果图
图5

默认位置控制效果图。
图6

进行角度控制的效果图。
图7

自动运动时的效果图。

图8

5.总结
这个设计想法来源于我之前做的一个机械臂上位机,感觉在迪文屏上也可以实现,就试了以下,果然没有问题,后面加上实际的机械臂后,我再给大家看一下实际的效果。





本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

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

本版积分规则

QQ|Archiver|手机版|小黑屋|迪文科技论坛 ( 京ICP备05033781号-1 )

GMT+8, 2024-11-24 11:22 , Processed in 0.077478 second(s), 22 queries .

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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