XPCIE1032H功能简介
XPCIE1032H是一款基于PCI Express的EtherCAT总线运动控制卡,可选6-64轴运动控制,支持多路高速数字输入输出,可轻松实现多轴同步控制和高速数据传输。
XPCIE1032H集成了强大的运动控制功能,结合MotionRT7运动控制实时软核,解决了高速高精应用中,PC Windows开发的非实时痛点,指令交互速度比传统的PCI/PCIe快10倍。
XPCIE1032H支持PWM,PSO功能,板载16进16出通用IO口,其中输出口全部为高速输出口,可配置为4路PWM输出口或者16路高速PSO硬件比较输出口。输入口含有8路高速输入口,可配置为4路高速色标锁存或两路编码器输入。
XPCIE1032H搭配MotionRT7实时内核,使用本地LOCAL接口连接,通过高速的核内交互,可以做到更快速的指令交互,单条指令与多条指令一次性交互时间可以达到3-5us左右。
➜XPCIE1032H与MotionRT7实时内核的配合具有以下优势:
1.支持多种上位机语言开发,所有系列产品均可调用同一套API函数库;
2.借助核内交互,可以快速调用运动指令,响应时间快至微秒级,比传统PCI/PCIe快10倍;
3.解决传统PCI/PCIe运动控制卡在Windows环境下控制系统的非实时性问题;
4.支持一维/二维/三维PSO(高速硬件位置比较输出),适用于视觉飞拍、精密点胶和激光能量控制等应用;
5.提供高速输入接口,便于实现位置锁存;
6.支持EtherCAT总线和脉冲输出混合联动、混合插补。
➜使用XPCIE1032H和MotionRT7进行项目开发时,通常需要进行以下步骤:
1.安装驱动程序,识别XPCIE1032H;
2.打开并执行文件“MotionRT710.exe”,配置参数和运行运动控制实时内核;
3.使用ZDevelop软件连接到控制器,进行参数监控。连接时请使用PCI/LOCAL方式,并确保ZDevelop软件版本在3.10以上;
4.完成控制程序开发,通过LOCAL链接方式连接到运动控制卡,实现实时运动控制。
➜与传统PCI/PCIe卡和PLC的测试数据结果对比:
平均值 | C++ LOCAL | C# LOCAL | 传统PCI/PCIe卡接口交互 | PLC网口通讯交互 |
1w次单条读取交互周期 | 4.70us | 5.3us | 64us | 500us-10ms |
10w次单条读取交互周期 | 3.90us | 5.7us | 65us | 500us-10ms |
1w次多条读取交互周期 | 6.20us | 8.85us | 472us | 500us-10ms |
10w次多条读取交互周期 | 5.50us | 8.37us | 471us | 500us-10ms |
我们可以从测试对比结果看出,XPCIE1032H运动控制卡配合实时运动控制内核MotionRT7,在LOCAL链接(核内交互)的方式下,指令交互的效率是非常稳定,当测试数量从1w增加到10w时,单条指令交互时间与多条指令交互时间波动不大,非常适用于高速高精的应用。 XPCIE1032H卡安装
关闭计算机电源。
打开计算机机箱,选择一条空闲的XPCIE卡槽,用螺丝刀卸下相应的挡板条。
将运动控制卡插入该槽,拧紧挡板条上的固定螺丝。
XPCIE1032H驱动安装与建立连接参考往期文章EtherCAT超高速实时运动控制卡XPCIE1032H上位机C#开发(一):驱动安装与建立连接。
一、新建C#项目(VS2022)
到正运动技术官网的下载中心选择需要的平台库文件。
解压下载的安装包找到 “Zmcaux.cs” , “zauxdll.dll” , “zmotion.dll” 放入到项目文件中。
1、“Zmcaux.cs”放在项目根目录文件中,与bin目录同级。
2、“zauxdll.dll”,“zmotion.dll”放在bin -> Debug。
用vs打开新建的项目文件,在右边的解决方案资源管理器中点击显示所有,选中项目,右键“添加”->“现有项”,选中zmcaux.cs文件添加进在项目中。
双击Form1.cs里面的Form1,出现代码编辑界面,在文件开头写入using cszmcaux,并声明控制器句柄g_handle。
二、相关PC函数介绍
相关PC函数介绍详情可参考“ZMotion PC函数库编程手册 V2.1.1”。
指令11 | ZAux_FastOpen | ||||||||
指令原型 | int32 __stdcall ZAux_FastOpen(int type, char *pconnectstring, uint32 uims ,ZMC_HANDLE * phandle) | ||||||||
指令说明 | 与控制器建立连接, 可以指定连接的等待时间 | ||||||||
输入参数 |
|
||||||||
输出参数 |
|
||||||||
返回值 | 成功返回值为0,非0详见错误码说明。 | ||||||||
指令示例 |
串口连接: ZMC_HANDLE phandle;//控制器连接句柄 Char comID[32]= "Com0";//串口ID,不能直接写串口号,需要在串口号前加个Com ZAux_FastOpen(1, comID,1000s ,&phandle); 网口连接例子: ZMC_HANDLE phandle;//控制器连接句柄 Char EthID[32]= "192.168.0.11";//网口ID ZAux_FastOpen(2, EthID,1000s ,&phandle); MotionRT7连接例子: ZMC_HANDLE phandle;//控制器连接句柄 ZAux_FastOpen(5, "LOCAL1",3000,&g_handle); |
||||||||
详细说明 | type设置为5,zmotion.dll版本要在3.8.8.50以上。 |
指令47 | ZAux_Direct_SetAxisEnable |
指令原型 | int32 __stdcall ZAux_Direct_SetAxisEnable(ZMC_HANDLE handle, int iaxis, int iValue); |
指令说明 | 设置轴的使能。 |
输入参数 | 共有2个输入参数,见下方说明。 |
handle | 连接句柄。 |
axis | 槽位号 |
iValue | 状态:0-关闭,1-打开 |
输出参数 | 一个参数 |
返回值 | 成功返回值为0,非0详见错误码说明。 |
指令示例 | EthrCat总线轴的使能 |
指令92 | ZAux_Direct_Single_Move | ||||||||
指令原型 | int32 __stdcall ZAux_Direct_Single_Move(ZMC_HANDLE handle, int iaxis, float fdistance) | ||||||||
指令说明 | 单轴相对运动。 | ||||||||
输入参数 |
|
||||||||
输出参数 | / | ||||||||
返回值 | 成功返回值为0,非0详见错误码说明。 | ||||||||
指令示例 | 单轴点位运动 | ||||||||
详细说明 | / |
指令93 | ZAux_Direct_Single_MoveAbs | ||||||||
指令原型 | int32 __stdcall ZAux_Direct_Single_MoveAbs(ZMC_HANDLE handle, int iaxis, float fdistance) | ||||||||
指令说明 | 单轴绝对运动。 | ||||||||
输入参数 |
|
||||||||
输出参数 | / | ||||||||
返回值 | 成功返回值为0,非0详见错误码说明。 | ||||||||
指令示例 | 单轴点位运动 | ||||||||
详细说明 | / |
指令94 | ZAux_Direct_Single_Vmove | ||||||||
指令原型 | int32 __stdcall ZAux_Direct_Single_Vmove(ZMC_HANDLE handle, int iaxis, int idir) | ||||||||
指令说明 | 单轴连续运动指令,连续往一个方向运动。 | ||||||||
输入参数 |
|
||||||||
输出参数 | / | ||||||||
返回值 | 成功返回值为0,非0详见错误码说明。 | ||||||||
指令示例 | 单轴持续运动 | ||||||||
详细说明 | 当前面的VMOVE运动没有停止时,此VMOVE指令会自动替换前面的VMOVE指令并修改方向,因此无需CANCEL前面的VMOVE指令。 |
指令186 | ZAux_Direct_Rapidstop | ||||||
指令原型 | int32 __stdcall ZAux_Direct_Rapidstop(ZMC_HANDLE handle, int imode) | ||||||
指令说明 | 所有轴列表立即停止,如果轴参与插补,也停止插补运动。 | ||||||
输入参数 |
|
||||||
输出参数 | / | ||||||
返回值 | 成功返回值为0,非0详见错误码说明。 | ||||||
指令示例 | / | ||||||
详细说明 |
Mode0~2减速度按FASTDEC和DECEL中最大的值。 RAPIDSTOP后要调用绝对位置运动,必须先WAIT IDLE等待停止完成。 |
指令189 | ZAux_Direct_Single_Cancel | ||||||||
指令原型 | int32 __stdcall ZAux_Direct_Single_Cancel (ZMC_HANDLE handle, int iaxis, int imode); | ||||||||
指令说明 | 单轴运动停止。 | ||||||||
输入参数 |
|
||||||||
输出参数 | / | ||||||||
返回值 | 成功返回值为0,非0详见错误码说明。 | ||||||||
指令示例 | 单轴持续运动 | ||||||||
详细说明 |
如果指定轴在插补运动轴列表中,无论主轴或者其他轴,都停止轴组的插补运动 MODE0~2减速度按FASTDEC和DECEL中最大的值。 CANCEL后要调用绝对位置运动,必须先等待停止完成。 |
指令205 | ZAux_Direct_SetInvertIn | ||||||||
指令原型 | int32 __stdcall ZAux_Direct_SetInvertIn(ZMC_HANDLE handle, int ionum, int bifInvert) | ||||||||
指令说明 | 设置反转输入状态,参见软件手册里面的“ INVERT_IN”指令。 | ||||||||
输入参数 |
|
||||||||
输出参数 | / | ||||||||
返回值 | 成功返回值为0,非0详见错误码说明。 | ||||||||
指令示例 | 正负硬限位设置 | ||||||||
详细说明 | ZMC系列控制器输入OFF时认为有信号输入(ECI系列控制器与之相反) |
指令214 | ZAux_Direct_SetFsLimit | ||||||||
指令原型 | int32 __stdcall ZAux_Direct_SetFsLimit(ZMC_HANDLE handle, int iaxis, float fValue) | ||||||||
指令说明 | 设置轴正向软限位,取消软限位时设置一个较大的值即可。单位units。 | ||||||||
输入参数 |
|
||||||||
输出参数 | / | ||||||||
返回值 | 成功返回值为0,非0详见错误码说明。 | ||||||||
指令示例 | 正负软限位设置 | ||||||||
详细说明 |
当FS_LIMIT大于REP_DIST时,参数不起作用,正向软限位被禁止。 取消软限位时,建议不要去修改REP_DIST的值,将FS_LIMIT设置一个较大值即可。FS_LIMIT的值默认为200000000。 软限位无法作为DATUM回零时的限位信号参考。 注:设置限位前需检查有无设置对应的加减速度,以及快减减速度,若无设置,碰到限位无法停止 |
指令216 | ZAux_Direct_SetRsLimit | ||||||||
指令原型 | int32 __stdcall ZAux_Direct_SetRsLimit(ZMC_HANDLE handle, int iaxis, float fValue) | ||||||||
指令说明 | 设置轴负向软限位,取消软限位时设置一个较大的值即可。单位units。 | ||||||||
输入参数 |
|
||||||||
输出参数 | / | ||||||||
返回值 | 成功返回值为0,非0详见错误码说明。 | ||||||||
指令示例 | 正负软限位设置 | ||||||||
详细说明 |
当RS_LIMIT大于REP_DIST时,参数不起作用,负向软限位被禁止。 取消软限位时,建议不要去修改REP_DIST的值,将RS_LIMIT设置一个较大值即可。RS_LIMIT的值默认为-200000000。 软限位无法作为DATUM回零时的限位信号参考。 注:设置限位前需检查有无设置对应的加减速度,以及快减减速度,若无设置,碰到限位无法停止 |
指令218 | ZAux_Direct_SetFwdIn | ||||||||
指令原型 | int32 __stdcall ZAux_Direct_SetFwdIn(ZMC_HANDLE handle, int iaxis,int iValue) | ||||||||
指令说明 | 设置正向限位信号,-1表示取消,参见软件手册里面的“FWD_IN”指令。注:设置限位前需检查有无设置对应的加减速度,以及快减减速度,若无设置,碰到限位无法停止 | ||||||||
输入参数 |
|
||||||||
输出参数 | / | ||||||||
返回值 | 成功返回值为0,非0详见错误码说明。 | ||||||||
指令示例 | 正负硬限位设置 | ||||||||
详细说明 |
1设置限位前需检查有无设置对应的加减速度,以及快减减速度,若无设置,碰到限位无法停止 2输入OFF时,认为有信号输入,要相反效果可以用INVERT_IN反转电平(ECI系列控制器相反)。 3正负限位切记勿要设置反,否则碰到限位还是会继续运动。 |
指令220 | ZAux_Direct_SetRevIn | ||||||||
指令原型 | int32 __stdcall ZAux_Direct_SetRevIn(ZMC_HANDLE handle, int iaxis,int iValue); | ||||||||
指令说明 | 设置负向限位信号,-1表示取消,参见软件手册里面的“REV_IN”指令。注:设置限位前需检查有无设置对应的加减速度,以及快减减速度,若无设置,碰到限位无法停止 | ||||||||
输入参数 |
|
||||||||
输出参数 | / | ||||||||
返回值 | 成功返回值为0,非0详见错误码说明。 | ||||||||
指令示例 | 正负硬限位设置 | ||||||||
详细说明 |
1设置限位前需检查有无设置对应的加减速度,以及快减减速度,若无设置,碰到限位无法停止 2输入OFF时,认为有信号输入,要相反效果可以用INVERT_IN反转电平(ECI系列控制器相反)。 3正负限位切记勿要设置反,否则碰到限位还是会继续运动。 |
指令264 | ZAux_Execute | ||||||||
指令原型 | int32 __stdcall ZAux_Execute(ZMC_HANDLE handle, const char *pszCommand, char *psResponse, uint32 uiResponseLength) | ||||||||
指令说明 | 发送字符串命令到控制器,缓存方式(当控制器没有缓冲时自动阻塞)。 | ||||||||
输入参数 |
|
||||||||
输出参数 |
|
||||||||
返回值 | 成功返回值为0,非0详见错误码说明。 | ||||||||
指令示例 | 在线命令函数的使用 | ||||||||
详细说明 | 上位机调用上位机未封装的Basic指令功能 |
其他基本轴参数指令:
ZAux_Direct_SetUnits | 设置脉冲当量(units) |
ZAux_Direct_GetUnits | 读取脉冲当量(units) |
ZAux Direct SetAccel | 设置加速度,单位为 units /s/s |
ZAux Direct GetAccel | 读取加速度,单位为 units/s/s |
ZAux Direct SetDecel | 设置减速度,单位为 units/s/s |
ZAux Direct GetDecel | 读取减速度,单位为 units/s/s |
ZAux Direct SetSpeed | 设置轴速度,单位为 units/s |
ZAux Direct GetSpeed | 读取轴速度,单位为 units/s |
ZAux Direct SetDpos | 设置轴的规划位置,单位为 units |
ZAux Direct GetDpos | 读取轴的规划位置,单位为 units |
ZAux Direct SetMpos | 设置反馈位置,单位为 units |
ZAux Direct GetMpos | 读取反馈位置,单位为 units |
在form设计界面找到需要用到的控件拖拽到窗体中进行UI界面设计,设计效果图如下。
三、相关程序以及设计思路
1、通过LOCAL链接方式,按钮控件的的click事件触发链接控制卡。
private void Local_Connect_Button_Click(object sender, EventArgs e) { if (g_handle == (IntPtr)0) { Local_DisConnect_Button_Click(sender, e); } zmcaux.ZAux_FastOpen(5, "local", 1000, out g_handle); if (g_handle != (IntPtr)0) { this.Text = "已链接"; timer1.Enabled = true; Local_Connect_Button.BackColor = Color.Green; MessageBox.Show("链接成功"); } else { MessageBox.Show("链接失败,请选择正确的LOCAL!"); } }
2、选择总线初始化的bas脚本文件下载到控制器rom里面掉电保存。
提前在zdevelop软件根据需求修改总线初始化的basic程序,映射轴,节点IO等初始化内容。 这里以节点0(汇川驱动器-0轴)、节点1(EIO16084)的1-4轴映射为总线轴为例,将节点之间通过ETHERCAT口连接起来。如下图:
相关初始化basic程序(其中红色为指令,可以到正运动官网查阅其使用场景以及方法)。
相关配置如下:
'ECAT总线初始化 GLOBAL CONST BUS_TYPE = 0 '总线类型。可用于上位机区分当前总线类型 GLOBAL CONST Bus_Slot = 0 '槽位号0(单总线控制器缺省0) GLOBAL CONST PUL_AxisStart = 0 '本地脉冲轴起始轴号 GLOBAL CONST PUL_AxisNum = 0 '本地脉冲轴轴数量 GLOBAL CONST Bus_AxisStart = 0 '总线轴起始轴号 GLOBAL CONST Bus_NodeNum = 1 '总线配置节点数量,用于判断实际检测到的从站数量是否一致 GLOBAL MAX_AXISNUM '最大轴数 MAX_AXISNUM = SYS_ZFEATURE(0) GLOBAL Bus_InitStatus '总线初始化完成状态 Bus_InitStatus = -1 GLOBAL Bus_TotalAxisnum '检查扫描的总轴数 DELAY(3000) '延时3S等待驱动器上电,不同驱动器自身上电时间不同,具体根据驱动器调整延时 ?"总线通讯周期:",SERVO_PERIOD,"us" Ecat_Init() '初始化ECAT总线 END GLOBAL SUB Ecat_Init() local Node_Num,Temp_Axis,Drive_Vender,Drive_Device,Drive_Alias RAPIDSTOP(2) for i = 0 to SYS_ZFEATURE(0) - 1 '初始化还原轴类型 AXIS_ENABLE(i) = 0 ATYPE(i) = 0 DELAY(20) next Bus_InitStatus = -1 Bus_TotalAxisnum = 0 SLOT_STOP(Bus_Slot) DELAY(200) SLOT_SCAN(Bus_Slot) '扫描总线 if return then ?"总线扫描成功","连接从站设备数:"NODE_COUNT(Bus_Slot) if NODE_COUNT(Bus_Slot) <> Bus_NodeNum then '判断总线检测数量是否为实际接线数量 ?"" ?"扫描节点数量与程序配置数量不一致!" ,"配置数量:"Bus_NodeNum,"检测数量:"NODE_COUNT(Bus_Slot) Bus_InitStatus = 0 '初始化失败。报警提示 endif '"开始映射轴号" for Node_Num = 0 to NODE_COUNT(Bus_Slot)-1 '遍历扫描到的所有从站节点 Drive_Vender = NODE_INFO(Bus_Slot,Node_Num,0) '读取驱动器厂商 Drive_Device = NODE_INFO(Bus_Slot,Node_Num,1) '读取设备编号 Drive_Alias = NODE_INFO(Bus_Slot,Node_Num,3) '读取设备拨码ID if NODE_AXIS_COUNT(Bus_Slot,Node_Num) <> 0 then '判断当前节点是否有电机 for j=0 to NODE_AXIS_COUNT(Bus_Slot,Node_Num)-1 '根据节点带的电机数量循环配置轴参数(针对一拖多驱动器) Temp_Axis = Bus_AxisStart + Bus_TotalAxisnum '轴号按NODE顺序分配 BASE(Temp_Axis) AXIS_ADDRESS = Bus_TotalAxisnum+1 '映射轴号 ATYPE = 65 '设置控制模式 65-位置 66-速度 67-转矩 DRIVE_PROFILE = 18 Sub_SetDriverIo(Temp_Axis,Drive_Vender,48 + 48*Temp_Axis) '映射驱动器IO IO映射到控制器IO32-以后每个驱动器间隔32点 DISABLE_GROUP(Temp_Axis) '每轴单独分组 Bus_TotalAxisnum = Bus_TotalAxisnum+1 '总轴数+1 next endif next ?"轴号映射完成","连接总轴数:"Bus_TotalAxisnum WA 200 SLOT_START(Bus_Slot) '启动总线 if return then WDOG = 1 '使能总开关 for i = Bus_AxisStart to Bus_AxisStart + Bus_TotalAxisnum - 1 BASE(i) DELAY 50 AXIS_ENABLE = 1 next Bus_InitStatus = 1 ?"轴使能完成" ?"总线开启成功" else ?"总线开启失败" Bus_InitStatus = 0 endif else ?"总线扫描失败" Bus_InitStatus = 0 endif ENDSUB '总线驱动IO映射 'iAxis - 轴号 iVender - 驱动器类型 i_IoNum - 输入输出起始编号 GLOBAL SUB Sub_SetDriverIo(iAxis,iVender,i_IoNum) DRIVE_IO(Iaxis) = i_IoNum FWD_IN(Iaxis) = i_IoNum REV_IN(Iaxis) = i_IoNum + 1 DATUM_IN(Iaxis) = i_IoNum + 2 INVERT_IN(i_IoNum,ON) INVERT_IN(i_IoNum + 1,ON) INVERT_IN(i_IoNum + 2,ON) ENDSUB利用按钮的click事件,浏览选择编辑好的bas文件下载掉电保存,并弹出反馈下载是否成功的提示。
private void BasFileDownLoad_Btn_Click(object sender, EventArgs e) { if (g_handle == (IntPtr)0) { MessageBox.Show("未链接到控制器!", "提示"); } else { int tmpret = 0; string strFilePath; OpenFileDialog openFileDialog1 = new OpenFileDialog(); openFileDialog1.InitialDirectory = "\"; openFileDialog1.Filter = "配置文件(*.bas)|*.bas"; openFileDialog1.RestoreDirectory = true; openFileDialog1.FilterIndex = 1; if (openFileDialog1.ShowDialog() == DialogResult.OK) { //打开配置文件 strFilePath = openFileDialog1.FileName; //下载到ROM tmpret = zmcaux.ZAux_BasDown(g_handle, strFilePath, 1); if (tmpret != 0) { MessageBox.Show("文件下载失败!", "提示"); } else { MessageBox.Show("文件下载成功!", "提示"); } } } }3、通过按钮控件的click事件触发初始化。
调用函数库的ZAux_Execute函数(在线命令),通过在线命令调用basic脚本里面的总线初始化函数--Ecat_Init()进行总线初始化。
private void EcatInitStart_Btn_Click(object sender, EventArgs e) { if (g_handle == (IntPtr)0) { MessageBox.Show("未链接到控制器!", "提示"); } else { int tmpret; //-1可能正在执行初始化 if ((BasFlag == true) && (InitStatus != -1)) { InitStatus = -1; StringBuilder buffer = new StringBuilder(10240); tmpret = zmcaux.ZAux_Execute(g_handle, "RUNTASK 1,Ecat_Init", buffer, 0); //任务1重新运行BAS中的初始化函数 if (tmpret != 0) { MessageBox.Show("总线初始化失败!", "提示"); return; } else { MessageBox.Show("总线初始化成功!", "提示"); } } else { MessageBox.Show("Bas文件未加载"); return; } } }
4、以汇川驱动器为例,驱动器IO映射的起始地址为DI1,也就是正向超程开关(正硬限位),若要设置负向超程开关,将起始地址加1。
可以通过按钮控件的click事件,触发设置轴的软限位,以及原点、正负硬限位。驱动器IO映射的basic指令是DRIVE_IO。在这里调用在线命令的PC函数去实现驱动器IO映射。 Basic指令说明见下图:
DRIVE_IO -- 驱动器IO:
类型 | 轴参数 | ||||||||||||||||||||||||||
描述 |
直接配置DRIVE的IO的起始编号,输入输出都是同样的编号。 DRIVE_PROFILE支持读取驱动器IO时起作用。 |
||||||||||||||||||||||||||
语法 |
可读:var=DRIVE_IO (axis) 可写:DRIVE_IO (axis)=value axis:轴号 EtherCAT总线伺服的输入输出点功能及地址参考数据字典60FD,60FE(某些厂家不是按照标准协议地址,请查看对应驱动器手册) Rtex总线伺服的输入输出点功能对应控制器的地址=DRIVE_IO+编号
|
||||||||||||||||||||||||||
适用控制器 | 带EtherCAT接口或RTEX接口 |
通过按钮控件的click事件,配置轴的正负软限位和驱动器IO起始地址(正负硬限位IO映射)。
private void Configure_OK_Button_Click(object sender, EventArgs e) { StringBuilder buffer = new StringBuilder(10240); //正向软限位设置 zmcaux.ZAux_Direct_SetFsLimit(g_handle, MoveAxis, Convert.ToSingle(FSLimit_Value.Text)); //负向软限位设置 zmcaux.ZAux_Direct_SetRsLimit(g_handle, MoveAxis, Convert.ToSingle(RSLimit_Value.Text)); //驱动器IO起始地址 zmcaux.ZAux_Execute(g_handle, "DRIVE_IO(" + MoveAxis.ToString() + ") = " +DriveStart_IO_Value.Value.ToString(), buffer, 0); //正硬限位设置 zmcaux.ZAux_Direct_SetFwdIn(g_handle, MoveAxis, DRIVE_Start_IO); zmcaux.ZAux_Direct_SetInvertIn(g_handle, DRIVE_Start_IO, 1); //负硬限位设置 zmcaux.ZAux_Direct_SetRevIn(g_handle, MoveAxis, DRIVE_Start_IO + 1); zmcaux.ZAux_Direct_SetInvertIn(g_handle, DRIVE_Start_IO + 1, 1); MessageBox.Show("当前轴配置成功!", "提示"); }5、通过按钮控件的MouseDown(鼠标在组件上方并按下时发生)事件来触发单轴持续运动;MouseUp(鼠标在组件上方并松开时发生)事件来触发单轴运动的停止。模拟手动运动的调试过程。
//正向 private void Fwd_Button_MouseDown(object sender, MouseEventArgs e) { zmcaux.ZAux_Direct_Single_Vmove(g_handle, MoveAxis, 1); } private void Fwd_Button_MouseUp(object sender, MouseEventArgs e) { zmcaux.ZAux_Direct_Single_Cancel(g_handle, MoveAxis, 2); } //负向 private void Rev_Button_MouseDown(object sender, MouseEventArgs e) { zmcaux.ZAux_Direct_Single_Vmove(g_handle, MoveAxis, -1); } private void Rev_Button_MouseUp(object sender, MouseEventArgs e) { zmcaux.ZAux_Direct_Single_Cancel(g_handle, MoveAxis, 2); }6、通过textbook控件的TextChanged(空间上text属性更改时发生)事件来修改运动过程中轴的基本参数,定时器会获取接收。
//脉冲当量变化 private void Units_Value_TextChanged(object sender, EventArgs e) { zmcaux.ZAux_Direct_SetUnits(g_handle, MoveAxis, Convert.ToSingle(Units_Value.Text)); } //轴速度变化 private void Speed_Value_TextChanged(object sender, EventArgs e) { zmcaux.ZAux_Direct_SetSpeed(g_handle, MoveAxis, Convert.ToSingle(Speed_Value.Text)); } //加速度变化 private void Accel_Value_TextChanged(object sender, EventArgs e) { zmcaux.ZAux_Direct_SetAccel(g_handle, MoveAxis, Convert.ToSingle(Accel_Value.Text)); } //减速度变化 private void Decel_Value_TextChanged(object sender, EventArgs e) { zmcaux.ZAux_Direct_SetDecel(g_handle, MoveAxis, Convert.ToSingle(Decel_Value.Text)); }7、通过按钮控件,与文本信息比对,触发总线轴的使能切换功能。
private void Enable_Button_Click(object sender, EventArgs e) { if (g_handle == (IntPtr)0) { MessageBox.Show("未链接到控制器!", "提示"); return; } int ret = 0; if (Enable_Value.Text == "ON") { ret = zmcaux.ZAux_Direct_SetAxisEnable(g_handle, MoveAxis, 0); } else { ret = zmcaux.ZAux_Direct_SetAxisEnable(g_handle, MoveAxis, 1); } }8、通过复选框的切换、单选框的选择实现寸动运动调试的功能。
//寸动方向选择 private void MoveDirection_CheckedChanged(object sender, EventArgs e) { if (MoveDirection.Checked == false) { MoveDirection.Text = "运动方向: 正"; dir = 1; } else { MoveDirection.Text = "运动方向: 负"; dir = -1; } } //寸动启动 private void InchStart_Button_Click(object sender, EventArgs e) { if (g_handle == (IntPtr)0) { MessageBox.Show("未链接到控制器!", "提示"); } else { //绝对运动 if (MoveAbs_RadBtn.Checked == true) { zmcaux.ZAux_Direct_Single_MoveAbs(g_handle, MoveAxis, dir * Convert.ToSingle(InchDistance_Value.Text)); } //相对运动 if (MoveOpp_RadBtn.Checked == true) { zmcaux.ZAux_Direct_Single_Move(g_handle, MoveAxis, dir * Convert.ToSingle(InchDistance_Value.Text)); } } }9、通过定时器的刷新,对轴参数的接收,初始化信息,IO监控等信息进行实时的反馈。
//轴参数更新 private void Update_AxisPara() { int CurAxisAtype = 0; int CurAxisIdle = 0; int CurAxisStatus = 0; double CurAxisFSLimit = 0; double CurAxisRSLimit = 0; double CurAxisDpos = 0; double CurAxisMpos = 0; Axis_Para[0] = Convert.ToSingle(Units_Value.Text); Axis_Para[1] = Convert.ToSingle(Speed_Value.Text); Axis_Para[2] = Convert.ToSingle(Accel_Value.Text); Axis_Para[3] = Convert.ToSingle(Decel_Value.Text); MoveAxis = Convert.ToInt32(AxisNum_Value.Text); zmcaux.ZAux_Direct_GetAtype(g_handle, MoveAxis, ref CurAxisAtype); zmcaux.ZAux_Direct_GetDpos(g_handle, MoveAxis, ref CurAxisDpos); zmcaux.ZAux_Direct_GetMpos(g_handle, MoveAxis, ref CurAxisMpos); zmcaux.ZAux_Direct_GetIfIdle(g_handle, MoveAxis, ref CurAxisIdle); zmcaux.ZAux_Direct_GetAxisStatus(g_handle, MoveAxis, ref CurAxisStatus); zmcaux.ZAux_Direct_GetUnits(g_handle, MoveAxis, ref Axis_Para[0]); zmcaux.ZAux_Direct_GetSpeed(g_handle, MoveAxis, ref Axis_Para[1]); zmcaux.ZAux_Direct_GetAccel(g_handle, MoveAxis, ref Axis_Para[2]); zmcaux.ZAux_Direct_GetDecel(g_handle, MoveAxis, ref Axis_Para[3]); zmcaux.ZAux_Direct_GetFsLimit(g_handle, MoveAxis, ref CurAxisFSLimit); zmcaux.ZAux_Direct_GetRsLimit(g_handle, MoveAxis, ref CurAxisRSLimit); if (EcatInitFlag == true) //总线初始化完成后实时显示状态信息 { AxisAtype_Label.Text = "轴 类 型: " + CurAxisAtype; AxisDpos_Label.Text = "DPOS位置: " + CurAxisDpos; AxisMpos_Label.Text = "MPOS位置: " + CurAxisMpos; AxisIdle_Label.Text = "运动状态: " + CurAxisIdle; AxisStatus_Label.Text = "轴 状 态: " + CurAxisStatus; } }10、通过按钮控件的的click事件触发断开链接。
private void Local_DisConnect_Button_Click(object sender, EventArgs e) { timer1.Enabled = false; zmcaux.ZAux_Close(g_handle); g_handle = (IntPtr)0; Local_DisConnect_Button.BackColor = Color.White; this.Text = "未连接"; }
四、运行效果
运行主界面如下:
附录:basic初始化程序通用模板
global CONST BUS_TYPE = 0 '总线类型。用于上位机区分当前模式 global CONST MAX_AXISNUM = 32 '最大轴数 global CONST Bus_Slot = 0 '槽位号0 global CONST Bus_AxisStart = 0 '总线轴起始轴号 global Bus_InitStatus '总线初始化完成状态 Bus_InitStatus = -1 global Bus_TotalAxisnum '检查扫描的总轴数 delay(3000) '延时3S等待驱动器上电 '**********************初始化ECAT总线********************** Ecat_Init() global sub Ecat_Init() for i=0 to MAX_AXISNUM - 1 '初始化还原轴类型 AXIS_ENABLE(i) = 0 atype(i)=0 next Bus_InitStatus = -1 Bus_TotalAxisnum = 0 SLOT_STOP(Bus_Slot) delay(200) slot_scan(Bus_Slot) '开始扫描 if return then ?"总线扫描成功","连接设备数:"NODE_COUNT(Bus_Slot) ?"开始映射轴号" endif for i=0 to NODE_COUNT(Bus_Slot)-1 '遍历总线下所有从站节点 if NODE_AXIS_COUNT(Bus_Slot,i) <>0 then '判断当前节点是否有电机 for j=0 to NODE_AXIS_COUNT(Bus_Slot,i)-1 AXIS_ADDRESS(Bus_AxisStart+i)=Bus_TotalAxisnum+1 '映射轴号 ATYPE(Bus_AxisStart+i)=65 '设置控制模式 DRIVE_PROFILE(Bus_AxisStart+i)= 4 '设置PROFILE功能 disable_group(Bus_AxisStart+i) '每轴单独分组 DRIVE_IO(Bus_AxisStart+i) = 128 + (Bus_AxisStart+i)*16 REV_IN(Bus_AxisStart+i) = 128 + (Bus_AxisStart+i)*16 FWD_IN(Bus_AxisStart+i) = 129 + (Bus_AxisStart+i)*16 DATUM_IN(Bus_AxisStart+i) = 130 + (Bus_AxisStart+i)*16 INVERT_IN(128 + (Bus_AxisStart+i)*16,ON) INVERT_IN(129 + (Bus_AxisStart+i)*16,ON) INVERT_IN(130 + (Bus_AxisStart+i)*16,ON) Bus_TotalAxisnum=Bus_TotalAxisnum+1 '总轴数+1 next endif next ?"轴号映射完成","连接总轴数:"Bus_TotalAxisnum wa 2000 SLOT_START(Bus_Slot) '启动总线 if return then ?"总线开启成功" ?"开始清除驱动器错误(根据驱动器数据字典设置)" for i= Bus_AxisStart to Bus_AxisStart + Bus_TotalAxisnum - 1 DRIVE_CONTROLWORD(i)=128 '根据驱动器数据字典 wa 100 DRIVE_CONTROLWORD(i)=6 wa 100 DRIVE_CONTROLWORD(i)=15 wa 100 next ?"驱动器错误清除完成" wa 100 ?"清除控制器错误" datum(0) DRIVE_CLEAR(0) ?"控制器错误清除完成" wa 100 ?"轴使能准备" for i= Bus_AxisStart to Bus_AxisStart + Bus_TotalAxisnum - 1 base(i) AXIS_ENABLE=1 next wdog=1 '使能总开关 Bus_InitStatus = 1 ?"轴使能完成" else ?"总线开启失败" Bus_InitStatus = 0 endif ?"总线扫描失败" Bus_InitStatus = 0 end sub
全部0条评论
快来发表一下你的评论吧 !