Zmotion快速入门之EtherCAT通信

新阁教育-喜科堂付工原创文章

本案例采用Zmotion运动控制卡与伺服驱动器进行EtherCAT通信,从而实现对伺服电机的相关控制。

硬件连接

因为采用总线的原因,所以基本上不用接线,硬件原理图如下所示:

 

 

将PC通过Ethernet连接至运动控制卡,然后运动控制卡的EtherCAT接至伺服驱动器,伺服驱动器与伺服电机之间通过配套电缆进行连接。

快速上手

第一次使用时,最好的方式就是看编程手册,并结合官方提供的案例来学习使用。

Zmotion厂家提供的配套资料,我会传到公众号里,需要的小伙伴,可以后台回复 Zmotion 获取

在保证硬件没有问题的前提下(这里主要是指伺服驱动器,至少能够手动转起来),打开 ZMC光盘资料\8.PC编程相关\函数库2.1\windows平台\64位库\C#\例程\例程8-总线控制运动 中的源程序,运行起来如下所示:

 

 

这里有两个地方要注意,不然是运行不起来的。

  • 案例中提供的ECAT初始化.bas文件,最大轴数是32,需要根据实际情况修改,否则会报错,我这里改成16。

 

 如果伺服没有接限位开关,轴状态应该是30H,表示正负限位报警,需要将正负限位禁用掉,具体操作是通过ZDevelop将FWD_IN和REV_IN设置为-1,当然后续可以通过代码实现。

 

 

这两点注意,伺服电机就应该可以动起来了。

软件开发

后续的软件开发主要就是封装应用,Zmotion的使用会涉及到两个dll库(zauxdll.dll和zmotion.dll)和一个Zmcaux.cs类文件,提前将这两个dll库复制到根目录下,然后手动将Zmcaux.cs类添加到你的项目中。

创建一个新的Zmotion.cs类,对Zmcaux.cs中的一些方法进行二次封装,便于后续项目的应用。

二次封装的方式每个人都会根据自己的编码习惯,进行不同程度的封装,下面我仅列举部分我的封装方法,仅供参考:

建立连接:EtherCAT连接之前需要执行一个bas文件,根据案例中的代码封装如下:

 /// <summary>
        /// 初始化卡
        /// </summary>
        /// <param name="ipAddress">IP地址</param>
        /// <param name="file">BAS文件</param>
        /// <param name="tempstatus">总线初始化完成状态</param>
        /// <param name="m_BusNodeNum">节点数</param>
        /// <returns>操作结果</returns>
        public OperationResult InitCard(string ipAddress, string file, ref float tempstatus, ref int m_BusNodeNum)
        {
            int error = 0;
            error = zmcaux.ZAux_OpenEth(ipAddress, out zhandle);
            if (error == 0)
            {
                error = zmcaux.ZAux_BasDown(zhandle, file, 1);
                if (error == 0)
                {
                    //执行初始化
                    StringBuilder buffer = new StringBuilder(10240);
                    //任务1重新运行BAS中的初始化函数
                    error = zmcaux.ZAux_Execute(zhandle, "RUNTASK 1,Ecat_Init", buffer, 0);
                    if (error != 0)
                    {
                        return new OperationResult()
                        {
                            IsSuccess = true,
                            ErrorMsg = "初始化失败"
                        };
                    }
                    IEC_Timer_TON ton = new IEC_Timer_TON(5000);
                    ton.Input = true;
                    while (true)
                    {
                        int ret = 0;
                        float Bus_type = 0.0f;
                        float m_BusAxisNum = 0.0f;
                        //读取BAS文件中的变量判断总线类型
                        ret += zmcaux.ZAux_Direct_GetUserVar(zhandle, "BUS_TYPE", ref Bus_type);
                        // 读取BAS文件中的变量判断总线初始化完成状态
                        ret += zmcaux.ZAux_Direct_GetUserVar(zhandle, "Bus_InitStatus", ref tempstatus);
                        ret += zmcaux.ZAux_BusCmd_GetNodeNum(zhandle, 0, ref m_BusNodeNum);
                        ret += zmcaux.ZAux_Direct_GetUserVar(zhandle, "Bus_TotalAxisnum", ref m_BusAxisNum);
                        bool completed = ret == 0;
                        completed &= tempstatus == 1;
                        completed &= m_BusNodeNum > 0;
                        bool output = ton.Output;
                        if (completed)
                        {
                            break;
                        }
                        else if (!output)
                        {
                            continue;
                        }
                        else
                        {
                            if (tempstatus == -1)
                            {
                                return new OperationResult()
                                {
                                    IsSuccess = false,
                                    ErrorMsg = "正在初始化"
                                };
                            }
                            else
                            {
                                return new OperationResult()
                                {
                                    IsSuccess = false,
                                    ErrorMsg = "初始化失败"
                                };
                            }
                        }
                    }
                    initedOK = true;
                    return OperationResult.CreateSuccessResult();
                }
                return new OperationResult()
                {
                    IsSuccess = true,
                    ErrorMsg = "文件下载失败"
                };
            }
            return new OperationResult()
            {
                IsSuccess = true,
                ErrorMsg = "以太网连接失败"
            };
        }

点位运动:点位运动主要就是根据轴号、速度、加速度、脉冲当量进行正转或反转,代码如下:

  public OperationResult Move(int axisNo, float scale, float vel, float acc, bool dir)
       {
           int error = 0;
           error += zmcaux.ZAux_Direct_SetUnits(zhandle, axisNo, scale);
           error += zmcaux.ZAux_Direct_SetSpeed(zhandle, axisNo, vel);
           error += zmcaux.ZAux_Direct_SetAccel(zhandle, axisNo, acc);
           error += zmcaux.ZAux_Direct_Single_Vmove(zhandle, axisNo, dir ? 1 : -1);

           if (error > 0)
           {
               return OperationResult.CreateFailResult();
           }
           else
           {
               return OperationResult.CreateSuccessResult();
           }
       }

停止运动:停止运动比较简单,调用ZAux_Direct_Single_Cancel指令即可。

public OperationResult Stop(int axisNo)
       {
           int error = 0;
           error = zmcaux.ZAux_Direct_Single_Cancel(zhandle, axisNo, 2);

           if (error > 0)
           {
               return OperationResult.CreateFailResult();
           }
           else
           {
               return OperationResult.CreateSuccessResult();
           }
       }

开发界面

这里做了一个简单的控制界面,实现了基本的板卡连接、点动、连续运动、伺服使能等基本控制功能。

 

 

posted @ 2021-04-23 11:22  常哥说编程  阅读(12)  评论(0编辑  收藏