当前位置: 首页 > news >正文

vbs获取程序窗体句柄_研华运动控制卡程序开发编写——板卡初始化

    本文主要介绍研华运动控制卡初始化和反初始化的程序编写,由于研华的脉冲型运动控制卡和EtherCAT总线运动控制卡共用同样的API接口,因此该程序适用于脉冲型和EtherCAT总线的板卡初始化程序编写,本文的编程以C#为例。

1. 准备工作

    1)为了方便,此次我们以虚拟卡代替实体卡进行编程,可以参考“

研华运动控制卡虚拟轴卡安装”一文进行虚拟卡安装,建议安装两张以上虚拟卡。

    2)新建一个C#的项目工程,可以参考“

研华运动控制卡C#项目开发”一文进行创建项目工程。

2. 板卡初始化流程

edced137901bb577b86e596d2e70c10d.png

    1)Acm_GetAvailableDevs  获取工控机中有用的运动控制卡信息,调用这个函数主要是获得板卡个数和每个板卡对应的DeviceNum。

函数原型:U32 Acm_GetAvailableDevs(DEVLIST *DeviceList, U32 MaxEntries,PU32 OutEntries)

DeviceList是指针指向返回可用设备信息列表,在C#表现就是返回可用设备的一维数组。

MaxEntries是指需要获取的最大设备个数,比如填10,就是最多可以获得10个板卡设备

OutEntries是指向实际返回的设备个数的指针,即工控机目前有的板卡设备个数

DEVLIST 为自定义结构体,定义如下:

typedef struct tagPT_DEVLIST

{

    DWORD   dwDeviceNum; // Acm_DevOpen 所需要的设备号

    char szDeviceName[50];    // 设备名

    SHORT   nNumOfSubdevices; // 用于AMONET板卡,对于Common Motion板卡

                                                     // 该值为0

} DEVLIST, *LPDEVLIST;

因此调用Acm_GetAvailableDevs()函数主要是获取板卡的DeviceNum设备个数

    2)Acm_DevOpen  打开板卡设备,并获取对应设备的句柄。

函数原型:U32 Acm_DevOpen (U32 DeviceNumber, PHAND DeviceHandle)

DeviceNumber打开设备需要用到的设备编号即DeviceNum,获取DeviceNum有三种方式:(1)从Acm_GetAvailableDevs中的DeviceList中获取到对应板卡的DeviceNum。(2)用Acm_GetDevNum 给定板卡类型和BoardID值也可以获得对应板卡的DeviceNum。(3)直接从Common Motion Utility中直接获得板卡的DeviceNum,如下图。

eccf7b1f4aaea0b9b07e8795e8c79cd8.png

    3)通过设备句柄读取设备的轴数特性FT_DevAxesCount,可以获得对应设备所具有的轴数,方便打开轴时直接用获得的轴数,循环打开所有轴。

Acm_GetU32Property(DeviceHandle, FT_DevAxesCount, ref AxesCount)

    4)Acm_AxOpen  根据Acm_DevOpen 获得的设备句柄,打开板卡设备指定轴,并获得轴对应的句柄

函数原型:U32 Acm_AxOpen (HAND DeviceHandle, U16 PhyAxis, PHAND

AxisHandle)

    5)Acm_DevLoadConfig 加载板卡的配置参数文件,切记加载配置参数时必须所有轴都打开,才能加载配置参数,不然会报错。

板卡的配置参数文件是用Common Motion Utility设置好各个轴的参数,然后保存出来的,如下图保存。

e0d010fa76c8c519f72a0fbeec270b0e.png

    6)Acm_AxGetState 获取轴当前的状态,若轴当前的状态是ErrorStop则需要调用Acm_AxResetError函数进行清除。切记,只有轴的状态是Ready时(即用Acm_AxGetState返回值是1)才能对轴下运动指令(如点到点运动或者回原点运动)。

    7)Acm_AxSetSvOn 用来打开或关闭伺服驱动器的使能。伺服电机只有上了使能才能正常运动,没有上使能是不能运动的。因此针对伺服驱动器需要进行打开使能操作,若是脉冲型的步进,可以不进行打开使能的操作。

但是对于EtherCAT总线的驱动器,不管是伺服还是步进都需要进行打开使能才能正常驱动电机运动。

3. 板卡初始化流程

5a22fde76810677a93cb0106754b4188.png

    1)Acm_AxStopDec  让轴做减速停止。反初始化就是要将板卡关闭或者关闭程序,必须保证轴可靠停止才能将程序关闭。

函数原型:U32 Acm_AxStopDec (HAND AxisHandle))

    2)Acm_GpRemAxis 将指定轴将轴群移出。为了确保轴群正常关闭,需要将轴从轴群移出。

    3)Acm_GpClose 关闭轴群句柄。关闭程序需要将轴群关闭,确保轴句柄注销,不要滞留。

    4)Acm_AxClose 关闭已经打开的轴。关闭程序需要将轴关闭,确保轴句柄注销,避免影响下次使用。

    5)Acm_DevClose 关闭已经打开板卡设备。关闭程序需要将板卡设备关闭,确保设备句柄注销,避免影响下次开卡。

4. 代码实现板卡初始化和反初始化

    1)板卡初始化代码如下: 

全局变量

publicconstuint MAX_DEVICES =16;  //最多支持16张板卡 protectedDEV_LIST[] mCurAvailableDevs= newDEV_LIST[MAX_DEVICES];//定义获取工控机中板卡列表 IntPtr[]mDeviceHandle = newIntPtr[16];//设备句柄 IntPtr[]mAxisHand = newIntPtr[64];  //轴句柄 uint[]mAxisPerDev = newuint[64];//每个设备的轴数,放到对应的数组中 uint  uDeviceCount = 0; //板卡设备的个数 uint mAxisNum = 0;//总的轴数

初始化函数

privateuint AdvInitMotionCard()//板卡初始化程序 {   Int32 iResult= 0;//定义接收函数调用返回码   

  uint uDeviceNum = 0;//设备的DeviceNum 

  uint uResult;//定义接收函数调用返回码

  uint uRetry = 0;//开卡失败重新开卡次数

  bool bRescan = false;//是否进行重新开卡

  string mConfigDir =System.IO.Directory.GetCurrentDirectory();//获得工程bin//Debug路径

  string mConfigFile = ""; //板卡配置文件名

  uDeviceCount = 0;//设备个数

  mAxisNum = 0;//先轴总数变量清零

  iResult = Motion.mAcm_GetAvailableDevs(mCurAvailableDevs,Motion.MAX_DEVICES, ref uDeviceCount);//获取有用设备列表及个数

  if(iResult != (int)ErrorCode.SUCCESS)

  {

    return (uint)iResult;

  }

  if(uDeviceCount> 0)//当有设备时才进行开卡

  {

    for (int i = 0; i //循环打开各个板卡

     {

        uDeviceNum =mCurAvailableDevs[i].DeviceNum;//从列表中获取板卡对应的设备号

       do//为了程序适用EtherCAT板卡,可以在开卡阶段增加报错重新开卡处理,防止由于对DC时间导致开卡不成功

        {

        uResult = Motion.mAcm_DevOpen(uDeviceNum,ref mDeviceHandle[i]);//打开板卡

        if (uResult != (uint)ErrorCode.SUCCESS)

          {

            uRetry++;

             bRescan = true;

          if (uRetry > 10)

             {

               return uResult;

             }

             else

             {

               System.Threading.Thread.Sleep(1000);//主要是EtherCAT有可能开卡失败,需要进行延时等待从站就绪

          }

        }

        else

        {

          bRescan = false;

        }

      } while (bRescan);

      uResult = Motion.mAcm_GetU32Property(mDeviceHandle[i],(uint)PropertyID.FT_DevAxesCount, ref mAxisPerDev[i]);//获取设备的轴数

      if (uResult != (uint)ErrorCode.SUCCESS)

      {

        return uResult;

      }

      for (int j = (int)mAxisNum; j < mAxisNum + mAxisPerDev[i]; j++)

      {

        uResult = Motion.mAcm_AxOpen(mDeviceHandle[i], (UInt16)(j - mAxisNum), ref mAxisHand[j]);//打开每个板卡的每个轴

          if (uResult != (UInt32)Advantech.Motion.ErrorCode.SUCCESS)

         {

          return uResult;

        }

        }

      mConfigFile = mConfigDir + "\\Card_" +i.ToString() + ".cfg";//要求每张板卡的配置文件名字按顺序保存“Card_*.cfg”格式,*表示每个卡的顺序值,如Card_0.cfg

      uResult = Motion.mAcm_DevLoadConfig(mDeviceHandle[i],mConfigFile);//每个设备加载配置参数

      if (uResult != (UInt32)Advantech.Motion.ErrorCode.SUCCESS)

      {

        return uResult;

      }

      mAxisNum = mAxisNum +mAxisPerDev[i];//获取总的轴数

    }

    UInt16 uAxState = 0;//用于存放轴状态的变量

    for(int k = 0; k < mAxisNum; k++)

    {

      uResult = Motion.mAcm_AxGetState(mAxisHand[k],ref uAxState);//获取每个轴的状态

      if (uResult != (UInt32)Advantech.Motion.ErrorCode.SUCCESS)

      {

        return uResult;

      }

      else

      {

        if(uAxState == (UInt16)AxisState.STA_AX_ERROR_STOP)//若轴报"ErrorStop",则进行错误清除

        {

          uResult = Motion.mAcm_AxResetError(mAxisHand[k]);//对轴报"ErrorStop"的状态,进行错误清除

          if (uResult != (UInt32)Advantech.Motion.ErrorCode.SUCCESS)

          {

            return uResult;

          }

        }

      }

    }

  }

 else

 {

   MessageBox.Show("获取有用板卡数等于0,请检查!", "AdvMotionContriol", MessageBoxButtons.OK, MessageBoxIcon.Error);

   return0xFFFFFFFF;

  }

  return (uint)ErrorCode.SUCCESS;//运行没错误,则返回0,表示初始化成功

}

反初始化函数

privateuintAdvUnInitMotionCard()//板卡反初始化程序

{

  uint uResult;//定义接收函数调用返回码

  UInt16 uAxState = 0;//用于存放轴状态的变量

  for (int i = 0; i

  {

     uResult = Motion.mAcm_AxGetState(mAxisHand[i], ref uAxState);//获取每个轴的状态

     if (uResult != (UInt32)Advantech.Motion.ErrorCode.SUCCESS)

     {

        return uResult;

     }

    else

     {

       if (uAxState == (UInt16)AxisState.STA_AX_ERROR_STOP)//若轴报"ErrorStop",则进行错误清除

       {

          uResult = Motion.mAcm_AxResetError(mAxisHand[i]);//对轴报"ErrorStop"的状态,进行错误清除

            if (uResult != (UInt32)Advantech.Motion.ErrorCode.SUCCESS)

          {

            return uResult;

          }

       }

     }

     uResult = Motion.mAcm_AxStopDec(mAxisHand[i]);//轴做减速停止

     if(uResult != (UInt32)Advantech.Motion.ErrorCode.SUCCESS)

     {

       return uResult;

     }

    }

   for (int j = 0; j

   {            

     uResult = Motion.mAcm_AxClose(ref mAxisHand[j]);//关闭每个轴

     if (uResult != (UInt32)Advantech.Motion.ErrorCode.SUCCESS)

     {

       return uResult;

     }

    }

    for (int k = 0; k < uDeviceCount; k++)

    {

     uResult = Motion.mAcm_DevClose(ref mDeviceHandle[k]);//关闭每个板卡设备

      if (uResult != (UInt32)Advantech.Motion.ErrorCode.SUCCESS)

     {

       return uResult;

     }

    }

    return (uint)ErrorCode.SUCCESS;//运行没错误,则返回0,表示初始化成功

}

相关文章:

  • fputs会覆盖吗_为什么越来越多家庭选择分布式无线覆盖方案?
  • navicat连接批量删除_vnc批量登录,vnc批量登录的具体操作方法
  • ethercat转profinet网关_HK50CCEN 网关操作指南
  • 正则表达式 逗号分隔_linux正则表达式详解(一) -通配符与基本正则表达式
  • 加到service中无效_Dataway让Spring Boot不在需要Controller、Service、DAO、Mapper
  • aac蓝牙编解码协议_国庆耳机选购盘点,适合假期使用的平价蓝牙耳机推荐
  • kafka 不同分区文件存储_消息系统Kafka笔试题:Kafka 底层的文件存储结构
  • kafka怎么查看消息堆积_Kafka 线上问题: 消息堆积一直不消费, 重启服务后开始消费...
  • 豪沃轻abs12v电是什么系统_小汽车显示abs是什么问题,ABS系统介绍
  • python列表删重_python列表删除和多重循环退出原理详解
  • redis集群如果保证数据一致性_从CAP理论到分布式一致性协议
  • 影像科dsa为什么必须买维修保险_为什么大家对影像科了解得那么少呢?
  • netcore权限控制_lin-cms-dotnetcore.是如何方法级别的权限控制的?
  • 文本框 清空_只需5步,Unity中创建自滚动聊天室文本框
  • java判断是否运行在windows terminal_判断制冷空调系统是否运行正常的5个参数
  • 【MySQL经典案例分析】 Waiting for table metadata lock
  • Android单元测试 - 几个重要问题
  • Apache Zeppelin在Apache Trafodion上的可视化
  • Eureka 2.0 开源流产,真的对你影响很大吗?
  • javascript 哈希表
  • JavaScript/HTML5图表开发工具JavaScript Charts v3.19.6发布【附下载】
  • maya建模与骨骼动画快速实现人工鱼
  • Spring Boot快速入门(一):Hello Spring Boot
  • Synchronized 关键字使用、底层原理、JDK1.6 之后的底层优化以及 和ReenTrantLock 的对比...
  • 阿里研究院入选中国企业智库系统影响力榜
  • 半理解系列--Promise的进化史
  • 从 Android Sample ApiDemos 中学习 android.animation API 的用法
  • 从输入URL到页面加载发生了什么
  • 关于 Cirru Editor 存储格式
  • 猴子数据域名防封接口降低小说被封的风险
  • 解决iview多表头动态更改列元素发生的错误
  • 模型微调
  • 如何打造100亿SDK累计覆盖量的大数据系统
  • 世界上最简单的无等待算法(getAndIncrement)
  • 项目管理碎碎念系列之一:干系人管理
  • 一文看透浏览器架构
  • 用Visual Studio开发以太坊智能合约
  • Oracle Portal 11g Diagnostics using Remote Diagnostic Agent (RDA) [ID 1059805.
  • elasticsearch-head插件安装
  • SAP CRM里Lead通过工作流自动创建Opportunity的原理讲解 ...
  • !$boo在php中什么意思,php前戏
  • $.each()与$(selector).each()
  • (3)llvm ir转换过程
  • (zt)最盛行的警世狂言(爆笑)
  • (超简单)构建高可用网络应用:使用Nginx进行负载均衡与健康检查
  • (附源码)springboot 智能停车场系统 毕业设计065415
  • (附源码)计算机毕业设计高校学生选课系统
  • (力扣题库)跳跃游戏II(c++)
  • (六)Hibernate的二级缓存
  • (论文阅读22/100)Learning a Deep Compact Image Representation for Visual Tracking
  • (源码版)2024美国大学生数学建模E题财产保险的可持续模型详解思路+具体代码季节性时序预测SARIMA天气预测建模
  • (转)ABI是什么
  • (转)Groupon前传:从10个月的失败作品修改,1个月找到成功
  • ***检测工具之RKHunter AIDE
  • .java 9 找不到符号_java找不到符号