EtherCAT运动控制卡开发教程之Qt(下):SCARA机械手正反解的建立

今天,正运动小助手给大家分享一下EtherCAT运动控制卡开发教程之Qt,主要介绍一下SCARA机械手正反解的建立。

ECI2828运动控制卡的硬件介绍

ECI2828系列控制卡支持最多达16轴直线插补、任意圆弧插补、空间圆弧、螺旋插补、电子凸轮、电子齿轮、同步跟随、虚拟轴、机械手指令等;采用优化的网络通讯协议可以实现实时的运动控制。

ECI2828系列运动控制卡支持以太网,232通讯接口和电脑相连,接收电脑的指令运行,可以通过EtherCAT总线和CAN总线去连接各个扩展模块,从而扩展输入输出点数或运动轴。

ECI2828系列运动控制卡的应用程序可以使用VC、VB、VS、C++、C#等多种高级语言编程来开发,程序运行时需要动态库zmotion.dll。调试时可以把ZDevelop软件同时连接到控制器,从而方便调试、方便观察。

在这里插入图片描述

一、Qt进行运动控制卡开发流程

1.新建Qt项目。

在这里插入图片描述

图1:新建Qt项目

在这里插入图片描述

图2:选择项目路径

在这里插入图片描述

图3:选择Qt编译套件(kits)

在这里插入图片描述

图4:选择基类

2.将函数库相关的文件复制到新建的项目中。

在这里插入图片描述

3.向新建的项目里面添加函数库的静态库。(zmotion.lib)

在这里插入图片描述

第一步:添加函数库1
在这里插入图片描述

第二步:添加函数库2
在这里插入图片描述

第三步:添加函数库3

4.添加函数库相关的头文件到项目中。

在这里插入图片描述

5.声明相关头文件,并定义连接句柄。

在这里插入图片描述

二、PC函数介绍

1.PC函数手册也在光盘资料里面,具体路径如下:“光盘资料\8.PC函数\函数库2.1\ZMotion函数库编程手册 V2.1.pdf”。
在这里插入图片描述

2.PC编程,一般如果网口对控制器和工控机进行链接。网口链接函数接口是ZAux_OpenEth();如果链接成功,该接口会返回一个链接句柄。通过操作这个链接句柄可以实现对控制器的控制。

ZAux_OpenEth()接口说明:

在这里插入图片描述

3.机械手逆解指令ZAux_Direct_Connframe介绍。

在这里插入图片描述

4.机械手正解指令ZAux_Direct_Connreframe介绍。3.机械手逆解指令ZAux_Direct_Connframe介绍。

在这里插入图片描述

三、Qt开发实现Scara机械手的正逆解

1.SCARA机械手正逆解例程界面如下。

在这里插入图片描述

2.SCARA机械手模型如下。

在这里插入图片描述

3.在构造函数里面调用链接控制器的接口ZAux_OpenEth(),与控制器进行链接,链接成功后启动定时器监控控制器的轴信息。

MainWindow::MainWindow(QWidget *parent) :

    QMainWindow(parent),

    ui(new Ui::MainWindow)

{

    int rint=0;

    //初始化窗体

    ui->setupUi(this);

    //定义按钮组并进行绑定

    btnGroup = new QButtonGroup(this);

    btnGroup->addButton(ui->ManualRev1,1);

    btnGroup->addButton(ui->ManualFwd1,2);

    btnGroup->addButton(ui->ManualRev2,3);

    btnGroup->addButton(ui->ManualFwd2,4);

    btnGroup->addButton(ui->ManualRev3,5);

    btnGroup->addButton(ui->ManualFwd3,6);

    btnGroup->addButton(ui->ManualRev4,7);

    btnGroup->addButton(ui->ManualFwd4,8);

    connect(btnGroup, SIGNAL(buttonPressed(int)), this, SLOT(ManualRev1_pressed(int)));

    connect(btnGroup, SIGNAL(buttonReleased(int)), this, SLOT(ManualRev1_released(int)));

    //系统启动自动连接控制器

    rint = ZAux_OpenEth("127.0.0.1", &g_handle);

    //如果链接成功则启动定时器

    if(rint==0)

    {

        startTimer(50);

    }

}

4.通过定时器更新控制器各个轴的位置和速度信息。

//定时器事件

void MainWindow::timerEvent(QTimerEvent *event)

{

    QString Str;

    float TempData;

    //获取J1的位置数据

    ZAux_Direct_GetMpos(g_handle, ui->AxisIdJ1->text().toInt(), &TempData);

    Str = QString("%1").arg(TempData);

    ui->DposJ1->setText(Str);

    //获取J2的位置数据

    ZAux_Direct_GetMpos(g_handle, ui->AxisIdJ2->text().toInt(), &TempData);

    Str = QString("%1").arg(TempData);

    ui->DposJ2->setText(Str);

    //获取Ju的位置数据

    ZAux_Direct_GetMpos(g_handle, ui->AxisIdJu->text().toInt(), &TempData);

    Str = QString("%1").arg(TempData);

    ui->DposJu->setText(Str);

    //获取Jz的位置数据

    ZAux_Direct_GetMpos(g_handle, ui->AxisIdJz->text().toInt(), &TempData);

    Str = QString("%1").arg(TempData);

    ui->DposJz->setText(Str);

    //获取x的位置数据

    ZAux_Direct_GetMpos(g_handle, ui->AxisIdX->text().toInt(), &TempData);

    Str = QString("%1").arg(TempData);

    ui->DposX->setText(Str);

    //获取y的位置数据

    ZAux_Direct_GetMpos(g_handle, ui->AxisIdY->text().toInt(), &TempData);

    Str = QString("%1").arg(TempData);

    ui->DposY->setText(Str);

    //获取U的位置数据

    ZAux_Direct_GetMpos(g_handle, ui->AxisIdU->text().toInt(), &TempData);

    Str = QString("%1").arg(TempData);

    ui->DposU->setText(Str);

    //获取Z的位置数据

    ZAux_Direct_GetMpos(g_handle, ui->AxisIdZ->text().toInt(), &TempData);

    Str = QString("%1").arg(TempData);

    ui->DposZ->setText(Str);

}

5.通过正逆解切换按钮实现Scara机械手正逆解的切换。

//建立机械手模型

void MainWindow::on_ManipulModel_clicked()

{

    int JogAxislist[4]={ui->AxisIdJ1->text().toInt(),ui->AxisIdJ2->text().toInt(),ui->AxisIdJu->text().toInt(),ui->AxisIdJz->text().toInt()};

    int AxisList[4]={ui->AxisIdX->text().toInt(),ui->AxisIdY->text().toInt(),ui->AxisIdU->text().toInt(),ui->AxisIdZ->text().toInt()};

    int MtypeJ=0,MtypeX=0;

    //初始化机械手参数

    ManipulParaInit();

    ZAux_Direct_GetMtype(g_handle,ui->AxisIdJ1->text().toInt(),&MtypeJ);

    ZAux_Direct_GetMtype(g_handle,ui->AxisIdX->text().toInt(),&MtypeX);

    //停止轴运动

    ZAux_Direct_Rapidstop(g_handle,2);

    if(MtypeJ == 33)

    {

        ZAux_Direct_Base(g_handle,4,AxisList);

        ZAux_Direct_Connreframe(g_handle ,4 , AxisList, 1, 0, 4,JogAxislist);

        ui->ManipulModel->setText("正解模式");

        //修改手动按钮的文本信息

        ui->ManualRev1->setText("J1-");

        ui->ManualRev2->setText("J2-");

        ui->ManualRev3->setText("Ju-");

        ui->ManualRev4->setText("Jz-");

        ui->ManualFwd1->setText("J1+");

        ui->ManualFwd2->setText("J2+");

        ui->ManualFwd3->setText("Ju+");

        ui->ManualFwd4->setText("Jz+");

    }

    else

    {

        ZAux_Direct_Base(g_handle,4,JogAxislist);

        ZAux_Direct_Connframe(g_handle ,4 , JogAxislist, 1, 0, 4,AxisList);

        ui->ManipulModel->setText("逆解模式");

        ui->ManualRev1->setText("X-");

        ui->ManualRev2->setText("Y-");

        ui->ManualRev3->setText("U-");

        ui->ManualRev4->setText("Z-");

        ui->ManualFwd1->setText("X+");

        ui->ManualFwd2->setText("Y+");

        ui->ManualFwd3->setText("U+");

        ui->ManualFwd4->setText("Z+");

    }

}

6.通过手动按钮,根据当前的机械手模式进行手动运动。
//按钮1按下

void MainWindow::ManualRev1_pressed(int Id)

{

    int MtypeJ,MtypeX;

    ZAux_Direct_GetMtype(g_handle,ui->AxisIdJ1->text().toInt(),&MtypeJ);

    ZAux_Direct_GetMtype(g_handle,ui->AxisIdX->text().toInt(),&MtypeX);

    //如果是逆解

    if(MtypeJ == 33)

    {

        switch (Id)

        {

            case 1: ZAux_Direct_Single_Vmove(g_handle,ui->AxisIdX->text().toInt(),-1);

                    break;

            case 2: ZAux_Direct_Single_Vmove(g_handle,ui->AxisIdX->text().toInt(),1);

                    break;

            case 3: ZAux_Direct_Single_Vmove(g_handle,ui->AxisIdY->text().toInt(),-1);

                    break;

            case 4: ZAux_Direct_Single_Vmove(g_handle,ui->AxisIdY->text().toInt(),1);

                    break;

            case 5: ZAux_Direct_Single_Vmove(g_handle,ui->AxisIdU->text().toInt(),-1);

                    break;

            case 6: ZAux_Direct_Single_Vmove(g_handle,ui->AxisIdU->text().toInt(),1);

                    break;

            case 7: ZAux_Direct_Single_Vmove(g_handle,ui->AxisIdZ->text().toInt(),-1);

                    break;

            case 8: ZAux_Direct_Single_Vmove(g_handle,ui->AxisIdZ->text().toInt(),1);

                    break;

            default:

                    break;

        }

    }

    //如果是正解

    else if(MtypeX == 34)

    {

        switch (Id)

        {

            case 1: ZAux_Direct_Single_Vmove(g_handle,ui->AxisIdJ1->text().toInt(),-1);

                    break;

            case 2: ZAux_Direct_Single_Vmove(g_handle,ui->AxisIdJ1->text().toInt(),1);

                    break;

            case 3: ZAux_Direct_Single_Vmove(g_handle,ui->AxisIdJ2->text().toInt(),-1);

                    break;

            case 4: ZAux_Direct_Single_Vmove(g_handle,ui->AxisIdJ2->text().toInt(),1);

                    break;

            case 5: ZAux_Direct_Single_Vmove(g_handle,ui->AxisIdJu->text().toInt(),-1);

                    break;

            case 6: ZAux_Direct_Single_Vmove(g_handle,ui->AxisIdJu->text().toInt(),1);

                    break;

            case 7: ZAux_Direct_Single_Vmove(g_handle,ui->AxisIdJz->text().toInt(),-1);

                    break;

            case 8: ZAux_Direct_Single_Vmove(g_handle,ui->AxisIdJz->text().toInt(),1);

                    break;

            default:

                    break;

        }

    }

}

//按钮1松开

void MainWindow::ManualRev1_released(int Id)

{

    int MtypeJ,MtypeX;

    ZAux_Direct_GetMtype(g_handle,ui->AxisIdJ1->text().toInt(),&MtypeJ);

    ZAux_Direct_GetMtype(g_handle,ui->AxisIdX->text().toInt(),&MtypeX);

    //如果是逆解

    if(MtypeJ == 33)

    {

       switch (Id)

       {

           case 1: ZAux_Direct_Single_Cancel(g_handle,ui->AxisIdX->text().toInt(),2);

                   break;

           case 2: ZAux_Direct_Single_Cancel(g_handle,ui->AxisIdX->text().toInt(),2);

                   break;

           case 3: ZAux_Direct_Single_Cancel(g_handle,ui->AxisIdY->text().toInt(),2);

                   break;

           case 4: ZAux_Direct_Single_Cancel(g_handle,ui->AxisIdY->text().toInt(),2);

                   break;

           case 5: ZAux_Direct_Single_Cancel(g_handle,ui->AxisIdU->text().toInt(),2);

                   break;

           case 6: ZAux_Direct_Single_Cancel(g_handle,ui->AxisIdU->text().toInt(),2);

                   break;

           case 7: ZAux_Direct_Single_Cancel(g_handle,ui->AxisIdZ->text().toInt(),2);

                   break;

           case 8: ZAux_Direct_Single_Cancel(g_handle,ui->AxisIdZ->text().toInt(),2);

                   break;

           default:

                   break;

       }

    }

    //如果是正解

    else if(MtypeX == 34)

    {

       ZAux_Direct_Single_Cancel(g_handle,ui->AxisIdJ1->text().toInt(),2);

       switch (Id)

       {

           case 1: ZAux_Direct_Single_Cancel(g_handle,ui->AxisIdJ1->text().toInt(),2);

                   break;

           case 2: ZAux_Direct_Single_Cancel(g_handle,ui->AxisIdJ1->text().toInt(),2);

                   break;

           case 3: ZAux_Direct_Single_Cancel(g_handle,ui->AxisIdJ2->text().toInt(),2);

                   break;

           case 4: ZAux_Direct_Single_Cancel(g_handle,ui->AxisIdJ2->text().toInt(),2);

                   break;

           case 5: ZAux_Direct_Single_Cancel(g_handle,ui->AxisIdJu->text().toInt(),2);

                   break;

           case 6: ZAux_Direct_Single_Cancel(g_handle,ui->AxisIdJu->text().toInt(),2);

                   break;

           case 7: ZAux_Direct_Single_Cancel(g_handle,ui->AxisIdJz->text().toInt(),2);

                   break;

           case 8: ZAux_Direct_Single_Cancel(g_handle,ui->AxisIdJz->text().toInt(),2);

                   break;

           default:

                   break;

       }

    }

}

四、例程移植到Linux设备上

1.Linux对应架构的库复制到项目文件夹里面。

在这里插入图片描述

2.向新建的项目里面添加函数库的静态库。(libzmotion.so)

在这里插入图片描述

添加函数库1

在这里插入图片描述

添加函数库2

在这里插入图片描述

添加函数库3

3.重新编译即可运行。

在这里插入图片描述

效果运行图

五、调试与监控

编译运行例程,同时连接ZDevelop软件进行调试,对运动控制的轴参数和运动情况进行监控。

同时可以通过机械手仿真工具ZRobotView,对机械手进行仿真测试。

1.ZDevelop软件监控机械手参数。

(1)例程效果图。

在这里插入图片描述

(2)关节轴Mtype=33,表示机械手为逆解模式。

在这里插入图片描述

(3)虚拟轴Mtype=34,表示机械手为正解模式。
在这里插入图片描述

2.ZRobotView的机械手仿真效果图。

在这里插入图片描述

3.操作真演示视频。

EtherCAT运动控制卡开发教程之Qt(下):SCARA机械手正反解的建立

在这里插入图片描述

本次,正运动技术EtherCAT运动控制卡开发教程之Qt(下):SCARA机械手正反解的建立,就分享到这里。

更多精彩内容请关注“正运动小助手”公众号,需要相关开发环境与例程代码,请咨询正运动技术销售工程师:400-089-8936。

本文由正运动技术原创,欢迎大家转载,共同学习,一起提高中国智能制造水平。文章版权归正运动技术所有,如有转载请注明文章来源。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

正运动技术

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值