【开源获奖案例】四轴机械臂控制系统

                                                ——来自迪文开发者论坛

 

本期为大家推送迪文开发者论坛获奖开源案例——四轴机械臂控制系统。工程师采用T5L智能屏,基于DGUS软件“旋转指示”控件实现机械臂的实时位置显示,并通过串口控制机械臂的运动过程。不同以往只展示机械臂的角度数值,该方案可以实现在屏幕上实时显示机械臂的旋转状态。除此之外,工程师还增加了机械臂自动运动功能。

【演示视频】

完整开发资料含迪文屏DGUS工程资料与C51代码,获取方式:

1. 前往迪文开发者论坛获取:/index.html/forum.php?mod=viewthread&tid=8596&_dsign=692ed954

2.微信公众号中回复“四轴机械臂”获取。

UI素材展示】

UI素材可根据实际的应用进行多样化的设计,工程师设计了一套富有科技感的界面。

1

2

【UI开发示例】

3

C51代码设计】

(1)获取机械臂当前控制的角度

//获取机械臂状态

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]);

    }

}

(2)机械臂的运动过程设计:使机械臂根据设置的角度,缓慢移动到指定位置。

//设置机械臂角度

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;

        }

    }

}

(3)按键设计:开发者设计了复位、添加、删除、开始、停止按键功能

//获取按键状态

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);

    }

}

(4)机械臂自动运动功能

//自动运动

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;

            }

        }

    }

}