1.介绍
最近搞了一个四轴机械臂,准备给机械臂做一个控制界面系统,刚好就拿迪文屏来做,主要用旋转控件来做,看了一下旋转控件的功能,发现是可以满足机械臂控制系统的需求。本来想用新版设计软件来做的,不过制作过程中有些控制有问题,所以这次设计最终还是用老版设计软件完成的。
2.设计想法
上面提到主要用旋转控件来做,原因是机械臂的动作是旋转的,而我想把机械臂的动作实时反应到屏幕上,而这就需要用到旋转控件了,几轴就需要用几个。不像以往的机械臂控制系统,只反应个机械臂的角度数值,而是要反应机械臂的动作,真正实时的在屏幕上能看到机械臂当前的姿态。
3.设计
还是素材的准备,为了让界面富有科技感,我采用的都是比较有科技化的元素,下面是我设计的界面和机械臂的元素。
图1
这次设计主要分为三个界面,分别是首页界面、控制界面、自动界面,首先是首页设计,这里就是一个普通的背景+基础触摸。
图2
接下来就是控制界面了,控制界面相对比较复杂,需要放上机械臂的所有部件,界面左边是机械臂实时的反馈情况,右边是控制功能,同时还有切换到Auto的界面。从设计界面上看,左边的机械臂比较凌乱,这是正常的因为用到的是旋转控件,而旋转控件只能向正方向旋转,而我为了让机械臂的状态能回到负方向,所以图片都是旋转到最左边的图片。
图3
最后就是自动界面了,这个界面左边和控制界面是一样的,实时反应机械臂的状态。右边则是记录自动时所需要的动作的。可以添加和删除动作,最多可以记录5个动作
图4
界面设计完成,接下来就是代码设计了。 第一步是要获取当前控制的角度。
- <font face="宋体" size="3" color="#000000">//获取机械臂状态
- void get_arm_config_status()
- {
- u8 i = 0;
-
- for(i = 0;i < 4;i++)
- {
- arm_angle_value[i] = Read_Dgus(0x1100 + i * 2);
- //Write_Dgus(0x1110 + i * 2, Va[i]);
- }
- }</font>
复制代码
之后就是设计机械臂的运动,机械臂的运动是需要过程的,所以设置完角度后,机械臂是缓慢运动到指定位置的,而不是立马跳到指定位置的,所以这里需要一个过程,而且为了让系统电源压力小,所以需要一个轴一个轴的进行运动,下面是设计代码。- <font face="宋体" size="3" color="#000000">//设置机械臂角度
- void set_arm_angle()
- {
- int i = 0;
- for(i = 0;i < 4;i++)
- {
- if(arm_angle_value[i] != arm_angle_value_last[i])
- {
- if(arm_angle_value[i] < arm_angle_value_last[i])
- {
- arm_angle_value_last[i]--;
- }
- else
- {
- arm_angle_value_last[i]++;
- }
- Write_Dgus(0x1110 + i * 2, arm_angle_value_last[i]);
- if(i == 1) //第二轴运动
- {
- u16 armiii_pos_x = 0;
- u16 armiii_pos_y = 0;
- u16 armiv_pos_x = 0;
- u16 armiv_pos_y = 0;
-
- armiii_pos_x = sin((float)(225 - arm_angle_value_last[i]) * TRIGONOMETRIC) * 80 + armii_start_pos[0];
- armiii_pos_y = cos((float)(225 - arm_angle_value_last[i]) * TRIGONOMETRIC) * 80 + armii_start_pos[1];
- armiv_pos_x = sin((float)(180 - arm_angle_value_last[i+1]) * TRIGONOMETRIC) * 83 + armiii_pos_x;
- armiv_pos_y = cos((float)(180 - arm_angle_value_last[i+1]) * TRIGONOMETRIC) * 83 + armiii_pos_y;
-
- armiii_current_pos[0] = armiii_pos_x;
- armiii_current_pos[1] = armiii_pos_y;
- OneSendData4(armiii_pos_x/256);
- OneSendData4(armiii_pos_x%256);
- OneSendData4(armiii_pos_y/256);
- OneSendData4(armiii_pos_y%256);
- Write_Dgus(0x2100 + 4, armiii_pos_x); //第三轴的位置
- Write_Dgus(0x2100 + 5, armiii_pos_y);
- Write_Dgus(0x2200 + 4, armiv_pos_x); //第三轴的位置
- Write_Dgus(0x2200 + 5, armiv_pos_y);
- }
- else if(i == 2)
- {
- u16 armiv_pos_x = sin((float)(180 - arm_angle_value_last[i]) * TRIGONOMETRIC) * 83 + armiii_current_pos[0];
- u16 armiv_pos_y = cos((float)(180 - arm_angle_value_last[i]) * TRIGONOMETRIC) * 83 + armiii_current_pos[1];
-
- Write_Dgus(0x2200 + 4, armiv_pos_x); //第三轴的位置
- Write_Dgus(0x2200 + 5, armiv_pos_y);
- }
- break;
- }
- }
- }</font>
复制代码
这里设计了对所有的按键做处理,其中添加和开始是自动界面需要的,下面是具体设计代码。 - <font face="宋体" size="3" color="#000000">//获取按键状态
- void get_key_status(u16 addr)
- {
- u16 Va=Read_Dgus(addr);
- //u16 V1=Read_Dgus(0x0f01);
- if(Va != 0x0000)
- {
- if(Va == 0x0001) //复位
- {
- Write_Dgus(0x1100 + 0, 0);
- Write_Dgus(0x1100 + 2, 0);
- Write_Dgus(0x1100 + 4, 0);
- Write_Dgus(0x1100 + 6, 90);
- }
- else if(Va == 0x0002) //添加
- {
- if(arm_auto_cnt < 5)
- {
- u8 i = 0;
- u8 send_str[30] = {0};
- for(i = 0;i < 4;i++)
- {
- arm_auto_list[arm_auto_cnt][i] = arm_angle_value[i];
- }
- 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]);
- write_dgus_vp(0x1500 + 0x20 * arm_auto_cnt, send_str, 16);
- arm_auto_cnt++;
- }
-
- }
- else if(Va == 0x0003) //开始
- {
- auto_start_flag = 1;
- auto_start_cnt = 0;
- }
- else if(Va == 0x0004) //停止
- {
- auto_start_flag = 0;
- Write_Dgus(0x1100 + 0, arm_angle_value_last[0]);
- Write_Dgus(0x1100 + 2, arm_angle_value_last[1]);
- Write_Dgus(0x1100 + 4, arm_angle_value_last[2]);
- Write_Dgus(0x1100 + 6, arm_angle_value_last[3]);
- }
- else if(Va >= 0x0010 && Va <= 0x0014) //删除内容
- {
- u16 delete_select = Va - 0x0010;
- if(arm_auto_cnt > delete_select) //有删除的内容
- {
- u8 i = 0;
- u8 send_str[30] = {0};
- for(i = delete_select;i < arm_auto_cnt - 1;i++)
- {
- memcpy(arm_auto_list[i], arm_auto_list[i + 1], 8);
- }
- memset(arm_auto_list[i], 0, 8);
- for(i = delete_select;i < arm_auto_cnt - 1;i++)
- {
- 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]);
- write_dgus_vp(0x1500 + 0x20 * i, send_str, 16);
- }
- memset(send_str, 0, 30);
- write_dgus_vp(0x1500 + 0x20 * i, send_str, 16);
- arm_auto_cnt--;
- }
- }
- Write_Dgus(addr, 0);
- }
- }</font>
复制代码
最后就是自动动作功能了,主要采用了一个标志位判断是否需要自动运动,同时自动运动需要两个位置才能进行。自动运动的功能,就是判断当前位置是否到达运动的位置,如果到了,就可以开始下一个动作了。 - <font face="宋体" size="3" color="#000000">//自动运动
- void auto_run()
- {
- if(auto_start_flag == 1 && arm_auto_cnt >= 2) //动作必须两个及以上
- {
- if(memcmp(arm_angle_value, arm_auto_list[auto_start_cnt], 8) != 0) //不等于
- {
- Write_Dgus(0x1100 + 0, arm_auto_list[auto_start_cnt][0]);
- Write_Dgus(0x1100 + 2, arm_auto_list[auto_start_cnt][1]);
- Write_Dgus(0x1100 + 4, arm_auto_list[auto_start_cnt][2]);
- Write_Dgus(0x1100 + 6, arm_auto_list[auto_start_cnt][3]);
- }
- else if(memcmp(arm_angle_value_last, arm_auto_list[auto_start_cnt], 8) == 0) //当前运动等于目标
- {
- auto_start_cnt++;
- if(auto_start_cnt >= arm_auto_cnt)
- {
- auto_start_cnt = 0;
- }
- }
- }
- }</font>
复制代码
4.演示 给大家看看实际的效果图。 首页效果图
默认位置控制效果图。
进行角度控制的效果图。
自动运动时的效果图。 5.总结 这个设计想法来源于我之前做的一个机械臂上位机,感觉在迪文屏上也可以实现,就试了以下,果然没有问题,后面加上实际的机械臂后,我再给大家看一下实际的效果。
|