正运动技术
正运动技术

协助伙伴成功,是我们的价值所在

The value of Zmotion is to bring customers more success!

首页 / 支持与服务 / 技术分享

Technical support

技术分享

简单易用的运动控制卡(四):函数库的封装

    今天,正运动小助手给大家分享一下运动控制卡之ECI3808如何进行函数库的封装工作。

    一  ECI3808硬件介绍

    

    1.功能介绍

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

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

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

   1.jpg

    2.硬件接口

    2.jpg

   3.jpg

    3.控制器基本信息

    4.jpg

    二   C++进行运动控制开发

   

    1.新建MFC项目并添加函数库

    (1)在VS2015菜单“文件”→“新建”→“项目”,启动创建项目向导。

   5.jpg

    (2)选择开发语言为“VisualC++”和程序类型“MFC应用程序”。

   6.jpg

    (3)点击下一步即可。

    7.jpg

    (4)选择类型为“基于对话框”,下一步或者完成。

   8.jpg

    (5)找到厂家提供的光盘资料,路径如下(64位库为例)。

    A.进入厂商提供的光盘资料找到“8.PC函数”文件夹,并点击进入。

  9.jpg

    B.选择“函数库2.1”文件夹。

    10.jpg

    C.选择“Windows平台”文件夹。

    11.jpg

    D.根据需要选择对应的函数库这里选择64位库。

    12.jpg

    E.解压C++的压缩包,里面有C++对应的函数库。

    13.jpg

    F.函数库具体路径如下。

    14.jpg

    (6)将厂商提供的C++的库文件和相关头文件复制到新建的项目里面。

   15.jpg

    (7)在项目中添加静态库和相关头文件。

    A.先右击项目文件,接着依次选择:“添加”→“现有项”。

    16.jpg

    B.在弹出的窗口中依次添加静态库和相关头文件。

    (8)声明用到的头文件和定义控制器连接句柄。

   17.jpg

    至此项目新建完成,可进行MFC项目开发。

    2.查看PC函数手册,熟悉相关函数接口。

    (1)PC函数手册也在光盘资料里面,具体路径如下:“光盘资料\8.PC函数\函数库2.1\ZMotion函数库编程手册V2.1.pdf”

    18.jpg

    (2)链接控制器,获取链接句柄。

  19.jpg

    (3)利用直接basic命令发送实现功能函数。

    A.ZAux_DirectCommand函数直接下发命令执行basic功能块,指令运行速度快,但是需要加载缓冲的指令不能成功执行,能够成功执行的下发指令推荐使用,加快效率。

20.jpg

    B.ZAux_Execute函数直接下发命令执行basic功能块,执行指令速度会阻塞,执行速度慢一些,所有能够执行的字符串命令都可以成功执行。

 21.jpg

    C.一次性读取多个轴位置,从对应的modbus寄存器读出。

22.jpg

    D.一次性读取多个IN状态位置,从对应的modbus寄存器读出。

   23.jpg

    3.MFC开发控制器硬件外设读写例程。

    (1)例程界面如下。

 24.jpg

    (2)链接按钮的事件处理函数中调用链接控制器的接口函数ZAux_OpenEth(),与控制器进行链接,链接成功后启动定时器1监控控制器状态。

   

            //网口链接控制器

            void CSingle_move_Dlg::OnOpen()

            {

                 char   buffer[256]; 

                 int32 iresult;

                 //如果已经链接,则先断开链接

                 if(NULL != g_handle)

                 {

                    ZAux_Close(g_handle);

                    g_handle = NULL;

                 }

                 //从IP下拉框中选择获取IP地址

                 GetDlgItemText(IDC_IPLIST,buffer,255);

                 buffer[255] = '\0';

                 //开始链接控制器

                 iresult = ZAux_OpenEth(buffer, &g_handle);

                 if(ERR_SUCCESS != iresult)

                 {

                    g_handle = NULL;

                    MessageBox(_T("链接失败"));

                    SetWindowText("未链接");

                    return;

                 }

                 //链接成功开启定时器1

                 SetWindowText("已链接");

                 SetTimer( 1, 100, NULL );  

            }

    (3)通过定时器监控控制器状态。

   

            void CFuncWrapperDlg::OnTimer(UINT_PTR nIDEvent)

            {

                // TODO: 在此添加消息处理程序代码和/或调用默认值

                if (NULL == g_handle)

                {

                    MessageBox(_T("链接断开"));

                    return;

                }

              

                if (nIDEvent == 1)

                {

                    uint8 pValueList[2] = "";

                    //读取0-15in状态

                    ZAux_GetModbusIn(g_handle,0,15, pValueList);

                    //设置控件显示

                    SetMutiIn(pValueList[0], 0);

                    SetMutiIn(pValueList[1], 1);

                  

                    float dposvalue[4] ;

                    CString dposStatus = "";

                    //位置获取

                    ZAux_GetModbusDpos(g_handle, 4,dposvalue);

                    //轴0位置设置

                    dposStatus.Format("轴0位置:%.2f", dposvalue[0]);

                    GetDlgItem(IDC_DPOS0)->SetWindowText(dposStatus);

                    //轴1位置设置

                    dposStatus.Format("轴1位置:%.2f", dposvalue[1]);

                    GetDlgItem(IDC_DPOS1)->SetWindowText(dposStatus);

                    //轴2位置设置

                    dposStatus.Format("轴2位置:%.2f", dposvalue[2]);

                    GetDlgItem(IDC_DPOS2)->SetWindowText(dposStatus);

                    //轴3位置设置

                    dposStatus.Format("轴3位置:%.2f", dposvalue[3]);

                    GetDlgItem(IDC_DPOS3)->SetWindowText(dposStatus);

                

                    //ad值获取

                    uint16 advalue[2];

                    CString adStatus = "";

                    //获取ad状态

                    GetMutiAd(g_handle,2, advalue);

                    //AD1设置

                    adStatus.Format("AIN0:%.3f mv", advalue[0] * 1.0 / 4096 * 10000);

                    GetDlgItem(IDC_AIN0)->SetWindowText(adStatus);

                    //AD1设置

                    adStatus.Format("AIN1:%.3f mv", advalue[1] * 1.0 / 4096 * 10000);

                    GetDlgItem(IDC_AIN1)->SetWindowText(adStatus);

                }

                CDialogEx::OnTimer(nIDEvent);

            }

    (4)利用对应modbus_reg寄存器内的值一次性获取AD值内容的函数。

    25.jpg

 

            int CFuncWrapperDlg::GetMutiAd(ZMC_HANDLE handle, int inum, uint16 * pValueList)

            {

                int iresult = 0;

                //获取reg寄存器中的值,获取到ad的大小

                iresult = ZAux_Modbus_Get4x(handle, 14000, inum, pValueList);

                return iresult;

            }

    (5)通过断开按钮的事件处理函数来断开与控制卡的连接。

   

            void CSingle_move_Dlg::OnClose()        //断开链接

            {

                 // TODO: Add your control notification handler code here

                 if(NULL != g_handle)

                 {

                    KillTimer(1);                  //关定时器

                    KillTimer(2);

                    ZAux_Close(g_handle);

                    g_handle = NULL;

                    SetWindowText("未链接");

                 }

            }

    (6)通过单位时间运动按钮的事件处理函数来设置对应轴的参数以及当前轴单位时间内的运动距离。

   

            void CFuncWrapperDlg::OnBnClickedButtonpt()

            {

                // TODO: 在此添加控件通知处理程序代码

                ZAux_Direct_SetUnits(g_handle,m_AxisNum, (float)GetDlgItemInt(IDC_UNITS));

                ZAux_Direct_SetAtype(g_handle,m_AxisNum, (float)GetDlgItemInt(IDC_ATYPE));

                ZAux_Direct_SetSpeed(g_handle,m_AxisNum, (float)GetDlgItemInt(IDC_SPEED));

                ZAux_Direct_SetAccel(g_handle,m_AxisNum, (float)GetDlgItemInt(IDC_ACCEL));

                ZAux_Direct_SetDecel(g_handle,m_AxisNum, (float)GetDlgItemInt(IDC_DECEL));

                ZAux_Direct_SetSramp(g_handle,m_AxisNum, (float)GetDlgItemInt(IDC_SRAMP));

              

                if (m_MoveType == 1)

                {

                    int nTicks = 0;

                    float nDistance = 0;

                    nTicks = GetDlgItemInt(IDC_EDITTICK);

                    nDistance = GetDlgItemInt(IDC_EDITUNITS);

                    //调用单位时间相对运动

                    Zaux_MovePt(g_handle, m_AxisNum, nTicks, nDistance);

                }

                else if (m_MoveType == 0)

                {

                    int nTicks = 0;

                    float nDistance = 0;

                    nTicks = GetDlgItemInt(IDC_EDITTICK);

                    nDistance = GetDlgItemInt(IDC_EDITUNITS);

                    //调用单位时间相对运动

                    Zaux_MoveAbsPt(g_handle, m_AxisNum, nTicks, nDistance);

                }

            }

    (7)利用ZAux_DirectCommand函数封装MOVE_PT指令以及MOVE_PTABS指令进行对应运动。

               

            //单位时间绝对运动

            int CFuncWrapperDlg::Zaux_MoveAbsPt(ZMC_HANDLE handle, int nAxis, int nTicks, float nDistance)

            {

                int iresult = 0;

                char cmdbuff[2048];

                char cmdbuffAck[2048];

                char tempbuff[2048];

                CString str = "";

                float ainValue[1] = { 0 };

                sprintf(tempbuff, "base(%d)\n", nAxis);

                //生成命令

                sprintf(cmdbuff, "move_ptabs(%d,%f)", nTicks,nDistance);

                strcat(tempbuff, cmdbuff);

                //判断是否超过一次性发送字节数

                if (strlen(tempbuff) > 1000 || strlen(tempbuff) < 0)

                {

                    return 1;

                }

                //调用命令执行函数

                iresult = ZAux_DirectCommand(handle, tempbuff, cmdbuffAck, 2048);

                return iresult;

                }

            }

              

            //单位时间相对运动

            int CFuncWrapperDlg::Zaux_MovePt(ZMC_HANDLE handle, int nAxis, int nTicks, float nDistance)

            {    

                int iresult = 0;

                char cmdbuff[2048];

                char cmdbuffAck[2048];

                char tempbuff[2048];

                CString str = "";

                float ainValue[1] = { 0 };

                sprintf(tempbuff, "base(%d)\n", nAxis);

                //生成命令

                sprintf(cmdbuff, "move_pt(%d,%f)", nTicks, nDistance);

                strcat(tempbuff, cmdbuff);

                //判断是否超过一次性发送字节数

                if (strlen(tempbuff) > 1000 || strlen(tempbuff) < 0)

                {

                    return 1;

                }

                //调用命令执行函数

                iresult = ZAux_DirectCommand(handle, tempbuff, cmdbuffAck, 2048);

                return iresult;

                }

            }

26.jpg

    三  调试与监控

    

    编译运行例程,同时通过ZDevelop软件连接控制器对控制器状态进行监控。

    1.通过ZDevelop软件的ADDA视图进行监控模拟量输入输出对应的值可以看到读取出来的一致。

  27.jpg

    2.通过ZDevelop软件的示波器进行单位时间的运动距离。

    (1)单位时间相对位置变化。

 28.jpg

    (2)单位时间绝对位置变化。

   29.jpg

    3.ZDevelop软件调试视频。

    本次,正运动技术简单易用的运动控制卡(四):函数库的封装,就分享到这里。

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

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


30.jpg


邮箱留言

Copyright © 2013 正运动技术有限公司 Design by Zmotion 版权所有   粤ICP备13037187号    Powered by www.zmotion.com.cn 运动控制器-运动控制卡

在线咨询