摘要:PCIE464运动控制卡是正运动推出的一款EtherCAT总线+脉冲型、PCIE接口式的运动控制卡,可选6-64轴运动控制,支持多路高速数字输入输出,可轻松实现多轴同步控制和高速数据传输。
一.硬件介绍
PCIE464运动控制卡是正运动推出的一款EtherCAT总线+脉冲型、PCIE接口式的运动控制卡,可选6-64轴运动控制,支持多路高速数字输入输出,可轻松实现多轴同步控制和高速数据传输。
PCIE464运动控制卡适合于多轴点位运动、插补运动、轨迹规划、手轮控制、编码器位置检测、IO控制、位置锁存等功能的应用。PCIE464运动控制卡适用于3C电子加工、检测设备、半导体设备、SMT加工、激光加工、光通讯设备、锂电及光伏设备、以及非标自动化设备等高速高精应用场合。
PCIE4系列控制卡的应用程序可以使用VC,VB,VS,C++,C#等软件开发,程序运行时需要动态库zmotion.dll,调试时可以将RTSys软件同时连接控制器,从而方便调试、方便观察。
更多关于PCIE464的详情介绍,点击“PCIE464 — 高速高精,超高实时性的PCIe EtherCAT实时运动控制卡”查看。
二.接线参考
1.IN数字量输入接口
数字输入分布在J400(IN0-IN7)和X400(IN8-IN39)信号接口中。
2.OUT数字量输出接口
数字输出分布在J400(OUT0-7)和X400(OUT8-OUT39)信号接口中。
3.单端编码器及单端脉冲接线
注:PCIE464的J400接口中有一个差分脉冲轴接口和三个单端脉冲轴接口,两个差分编码器接口(其中一个与差分脉冲轴接口复用,取决于固件设定)和两个单端编码器接口,具体引脚定义参见PCIE464硬件手册。
三.同步指令解析及技巧解释
1.同步过程
同步跟随过程分为三部分:加速追赶、同步加工、结束归位。
(1)加速追赶:动作机构加速追上产品位置,并保持追赶末端速度与产品速度一致的过程。
(2)同步加工:动作机构加速追赶上之后,继续保持与产品同样的速度运动的过程,即两者相对静止的过程;加工动作常在此过程中进行。
(3)结束归位:加工完成后,打断跟随过程,回归待机位的过程。
▶ 正运动技术提供了成熟的同步跟随执行指令MOVESYNC完成上述过程。
2.同步指令
MOVESYNC -- 同步运动,皮带上物体跟随
语法:
MOVESYNC(mode,synctime,syncposition,syncaxis,pos1[,pos2, pos3…])
参数解释:
(1)mode:mode=0 + angle,angle:皮带旋转角度,角度=皮带轴dpos正向与BASE轴正向的夹角。使用时需要将角度转换为弧度(0~2PI)。
(2)synctime:同步时间,ms单位。
(3)syncposition:皮带轴物体被感应到时皮带轴的位置。
(4)syncaxis:皮带轴轴号,-1表示没有皮带轴。
(5)pos1:皮带轴物体被感应到时的BASE第1个轴绝对位置。
(6)posn:皮带轴物体被感应到时的BASE第n个轴绝对位置。
上位机指令参数排列一样。
3.使用疑难点解析
(1)如何获知syncposition:皮带轴物体被感应到时皮带轴的位置?
首先,我们先了解跟随的完整实现流程,如下:
光电传感器产生信号→控制器收到信号,锁存获取跟随坐标→产品流到到位,跟随触发→追赶产品,进入同步加工,走轨迹→进入下一次跟随。
那么按照流程看,物体被感应到时的位置就由锁存产生并记录,我们只需要将锁存数据记录就获取到了参数syncposition的值。
(2)如何获知同步跟随所需的POSN:皮带轴物体被感应到时跟随轴的位置?
syncposition与POSN都是在物体被感应到时的位置,两者的关系是同时相对静止的;所以此处的POSN:皮带轴物体被感应到时跟随轴的位置并不是感应到产品时跟随轴所处的位置,而是感应到产品时跟随轴应该走到的位置,也就是我们想要的产品同步跟随位置点。
在上一步,我们获知了皮带轴的感应位置是在锁存的时候获取到,那么可以在程序中设计,产品经过传感器后停下来,获取当前皮带轴位置,用锁存到的值-皮带轴当前位置=跟随方向的位移量→移动归零后的跟随轴组到产品上标记的需要加工的起点位置,记录下轴组位置数据→将轴组中跟随方向轴的坐标-计算出来的跟随方向的位移量=锁存时跟随轴组中跟随方向的轴位置→记录下数据就得到了皮带轴物体被感应到时跟随轴的位置POSN。
(3)跟随三个过程中的数据怎么填?是否需要重新计算?
跟随三个过程中的参数数据不需要重新计算;三个过程中唯一需要变化的参数是synctime,其他的参数保持不变;而synctime参数根据实际加工需要设定即可,一般会将同步加工时间设置大。
(4)在同步加工段中,怎么去走加工轨迹?能直接控制跟随轴组走轨迹吗?
在同步过程中一般是不能直接使用运动指令去操控跟随轴组走轨迹的,不然会打断跟随的状态;可以使用叠加运动的方式间接走轨迹;通过addax指令将几个没有用到的虚拟轴,叠加到跟随轴组上,使用运动指令控制虚拟轴执行加工轨迹,就能实现在保持跟随状态下走加工轨迹。
(5)不同产品轨迹所需时间不一样,同步加工段的时间怎么计算?
其实在实际应用中,同步加工段的时间通常会设置一个很大很大的时间值确保加工完成,加工完成后,用MOVESYNC的-2模式强制结束即可。
(6)加工中产品不断进来,怎么实现跟随轴组不回待机,连续跟随加工产品?
只需要注意不要在程序中每一段的跟随加工返回待机位的后面加入等待或者其他进运动缓冲的指令即可;因为复位用-1模式时,其会被后面的缓冲MOVESYNC覆盖,也就是当下一个产品的MOVESYNC跟随指令已经压进运动缓冲之后,当前产品加工完的复位MOVESYNC就会被覆盖,无效。
4.扩展用法
MOVE_ADDAX运动缓冲叠加
使用MOVESYNC+MOVE_ADDAX,可以实现在保持跟随状态下直接操作跟随轴组走轨迹。
四.C#语言进行项目开发
1.在VS2010菜单“文件”→“新建”→“项目”,启动创建项目向导。
2.选择开发语言为“Visual C#”和.NET Framework 4以及Windows窗体应用程序。
3.找到厂家提供的光盘资料里面的C#函数库,路径如下(32位库为例)。
1)进入厂商提供的光盘资料找到“04PC函数”文件夹,并点击进入。
2)选择“01PC函数库V2.1”文件夹。
3)选择“Windows平台”文件夹。
4)选择“C#”文件夹。
5)根据需要选择对应的函数库,这里选择32位库。
4.将厂商提供的C#的库文件以及相关文件复制到新建的项目中。
1)将zmcaux.cs文件复制到新建的项目里面中。
2)将zauxdll.dll和zmotion.dll文件放入bin\debug文件夹中。
5.双击Form1.cs里面的Form1,出现代码编辑界面,在文件开头写入using cszmcaux,并声明控制器句柄g_handle。
6.至此,项目新建完成,可进行C#项目开发。
C#跟随主体代码:
public void SubMoveSync
{
int iret = 0;
int iAxisList = new int[2]{0,1} ;
int iTime = new int[3];
iTime[0] = Convert.ToInt32(TextAccTime.Text);
iTime[1] = Convert.ToInt32(TextSyncTime.Text);
iTime[2] = Convert.ToInt32(TextBackTime.Text);
float fWaitPos = new float[2];
fWaitPos[0] = Convert.ToSingle (TextXpos.Text);
fWaitPos[1] = Convert.ToSingle(TextYpos.Text);
float fOffPos= Convert.ToSingle(TextOffpos.Text);
float fPdAxisPos = 0; //当前皮带轴位置
float fMakrPos = new float[2]; //当前加工产品锁存编码器的位置
int iMaxNum = Convert.ToInt32(Text_TabNum.Text);
float imode = 0;
imode = 0 ; //X方向跟随
if (m_SyncMode == 1) //同步轨迹运动
{
iret = zmcaux.ZAux_Direct_SetMerge(G_CardHandle, 4, 1); //打开虚拟X轴连续插补
iret = zmcaux.ZAux_Direct_Single_Addax(G_CardHandle,0,4); //虚拟4号轴X轴的运动叠加到实际X轴
iret = zmcaux.ZAux_Direct_Single_Addax(G_CardHandle, 1, 5); //虚拟5号轴Y轴的运动叠加到实际Y轴
}
float Units = new float[2];
zmcaux.ZAux_Direct_GetUnits(G_CardHandle, 2, ref Units[0]);
zmcaux.ZAux_Direct_GetUnits(G_CardHandle, 0, ref Units[1]);
float ratio = new float[1] { Units[0] / Units[1] };
int scraxis = new int[1] { 2 };
while(true)
{
if( (m_RegistCount != 0) && (iWorkCount
{
iret = zmcaux.ZAux_Direct_GetTable(G_CardHandle, Convert.ToInt32(Text_TabStart.Text) + 1 + iWorkCount, 1, fMakrPos); //获取当前准备加工的锁存位置
}
else if (iWorkCount > iMaxNum) //锁存坐标已经溢出,数据保存在锁存前面
{
iWorkCount = iWorkCount - m_RegistCount; //从下个循环开始取值
if (iWorkCount
{
iret = zmcaux.ZAux_Direct_GetTable(G_CardHandle, Convert.ToInt32(Text_TabStart.Text) + 1 + iWorkCount, 1, fMakrPos); //获取当前准备加工的锁存位置
}
else
{
continue;
}
}
//锁存事件未触发
if (m_RegistCount == 0 || m_RegistCount == iWorkCount)
{
continue;
}
//等待传送带位置运动超过开始跟随位置
do
{
iret = zmcaux.ZAux_Direct_GetMpos(G_CardHandle, 2, ref fPdAxisPos); //获取当前编码轴位置
} while (fPdAxisPos
iret = zmcaux.ZAux_Direct_MoveSync(G_CardHandle, imode, iTime[0], fMakrPos[0] + fOffPos, 2, 2, iAxisList, fWaitPos); //同步启动加速段,
if (Sync_Mode == 0)
{
if (m_SyncMode == 1) //同步轨迹运动
{
SubVirAxisMove; //调用虚拟轴轨迹
iret = zmcaux.ZAux_Direct_MoveTable(G_CardHandle, (uint)iAxisList[0], 0, (float)1); //写TABLE数据到实际轴缓冲区,速度同步后修改TABLE触发虚拟轴
if (iret != 0)
{
MessageBox.Show("ZAux_Direct_MoveTable失败 错误码:" + iret.ToString);
continue;
}
iret = zmcaux.ZAux_Direct_MoveSync(G_CardHandle, imode, iTime[1], fMakrPos[0] + fOffPos, 2, 2, iAxisList, fWaitPos); //同步启动匀速速段,匀速时间
//同步结束
iret = zmcaux.ZAux_Direct_MoveTable(G_CardHandle, (uint)iAxisList[0], 0, (float)0); //写TABLE数据到实际轴缓冲区,速度同步后修改TABLE触发虚拟轴
//iret = zmcaux.ZAux_Direct_MoveCancel(G_CardHandle, iAxisList[0], 4, 2); //运动完成强制停止未完成的虚拟轴运动
}
else
{
iret = zmcaux.ZAux_Direct_MoveSync(G_CardHandle, imode, iTime[1], fMakrPos[0] + fOffPos, 2, 2, iAxisList, fWaitPos); //同步启动匀速速段,匀速时间
}
}
else if(Sync_Mode == 1)
{
if (m_SyncMode == 1) //同步轨迹运动
{
iret = Motion_MoveAddax(G_CardHandle, iAxisList[0], iAxisList, 2, ratio, scraxis); //建立叠加关系
SubVirAxisMove_Dirct; //直接控制实际轴走轨迹
//同步结束
iret = zmcaux.ZAux_Direct_MoveTable(G_CardHandle, (uint)iAxisList[0], 0, (float)0); //写TABLE数据到实际轴缓冲区,速度同步后修改TABLE触发虚拟轴
iret = Motion_MoveAddax(G_CardHandle, iAxisList[0], iAxisList, 0, ratio, scraxis);
}
else
{
iret = Motion_MoveAddax(G_CardHandle, iAxisList[0], iAxisList, 2, ratio, scraxis); //建立叠加关系
iret = zmcaux.ZAux_Direct_MoveDelay(G_CardHandle, iAxisList[0], iTime[1]); //运行延时时间
iret = Motion_MoveAddax(G_CardHandle, iAxisList[0], iAxisList, 0, ratio, scraxis); //取消叠加
}
}
iret = zmcaux.ZAux_Direct_MoveSync(G_CardHandle, imode, iTime[2], 0, -1, 2, iAxisList, fWaitPos); //结束同步走到待机位置
int Axisidle = 0;
//此处判断并实现是否每次都强制回待机位之后再执行下一次跟随动作,由于MOVESYNC在-1模式下的特殊性,会被紧接的MOVESYNC取代,不需要其他逻辑,即可以实现连续跟随
if (Force_Back_Flag == 1)
{
do
{
iret = zmcaux.ZAux_Direct_GetIfIdle(G_CardHandle, iAxisList[0], ref Axisidle); //等待主轴跟随完毕
} while (Axisidle == 0);
}
iWorkCount++;
}
}
五.Basic编程进行项目开发
1.在电脑里新建一个文件夹用来保存即将要建立的工程。打开RTSys编程软件。
2.新建项目:菜单栏“文件”→“新建工程”。
3.点击“新建工程”后弹出“另存为”界面,选择一个文件夹打开,输入文件名后保存项目,后缀为“.zpj”。
4.新建文件:点击菜单栏“文件”→“新建”,新建弹出窗口支持Basic/Plc/Hmi混合编程,这里选择新建的文件类型为Basic后确认。
5.设置文件自动运行:如下图,双击文件右边自动运行的位置,输入任务号“0”。
Basic跟随主体代码:
global sub reg_Task '//锁存线程
REG_INPUTS(belt) = $0000 '//指定皮带轴的锁存输入口,这里R3 R2 R1 R0都用0号输入口的信号
Reg_Count = 0 '// 清零锁存计数循环量
WHILE 1
REGIST(4)axis(belt) '//开启轴锁存
wait until(MARK(belt)) '//等待轴锁存触发
Reg_Array(Reg_Count) = REG_POS(belt) '//将锁存到的轴位置存放到锁存数组中
reg_Flag(Reg_Count) = 1 '//标记触发
if(Reg_Count >= Reg_Space - 1) then '//判断锁存缓存数组是否满,满了重新开始计数
Reg_Count = 0
else
Reg_Count = Reg_Count + 1
endif
Reg_Count_All = Reg_Count_All + 1
WEND
endsub
global sub movesync_Task(Mode) '//mode 0- 三段式跟随 1- 直接跟随
Sync_Count = 0 '// 清零 跟随标志
Over_Max_Count = 0
Sync_Count_All = 0
base(X_sync,Y_sync,Z_sync)
moveabs(X_Wait,Y_Wait,Z_Wait) '//移动到待机位
WHILE 1
if(reg_Flag(Sync_Count) = 1) then
reg_Flag(Sync_Count) = -1 '//复位标志
wait until(MPOS(belt) > Reg_Array(Sync_Count) + Diff_Pos) '//等待满足触发跟随距离
if(MPOS(belt)
if(Mode = 0) then
base(X_sync,Y_sync,Z_sync)
MOVESYNC(0,catch_time,Reg_Array(Sync_Count),belt,X_POS,Y_POS,Z_POS)axis(X_sync) '// 同步追赶段 由于MOVESYNC指令会根据跟随轴位置控制跟随从轴,此处填入锁存时刻的位置即可
MOVE_TASK(10,rectangel)AXIS(X_sync) '//开启异步线程10,执行加工动作
MOVESYNC(0,work_time,Reg_Array(Sync_Count),belt,X_POS,Y_POS,Z_POS)axis(X_sync) '//保持跟随状态
wait until(PROC_STATUS(10) = 1) wait until(PROC_STATUS(10) = 0)
MOVESYNC(-1,back_time,Reg_Array(Sync_Count),-1, X_Wait,Y_Wait,Z_Wait)AXIS(X_sync)
Sync_Count_All = Sync_Count_All + 1
elseif(mode = 1) then
base(X_sync,Y_sync,Z_sync)
MOVESYNC(0,catch_time,Reg_Array(Sync_Count),belt,X_POS,Y_POS,Z_POS)axis(X_sync) '// 同步追赶段 由于MOVESYNC指令会根据跟随轴位置控制跟随从轴,此处填入锁存时刻的位置即可
MOVE_ADDAX(belt, 1, UNITS(belt) / UNITS(X_sync))axis(X_sync) '//使用move_addax替代MOVESYNC,使得跟随动作保持,将皮带轴的运动叠加到跟随轴上
rectangel2 '//加工
MOVESYNC(-1,back_time,Reg_Array(Sync_Count),-1, X_Wait,Y_Wait,Z_Wait)AXIS(X_sync)
Sync_Count_All = Sync_Count_All + 1
endif
else
?"位置超出最大触发距离" '//此处简单做打印输出提示,可以根据自己需求扩展
Over_Max_Count = Over_Max_Count + 1
endif
if(Sync_Count >= Reg_Space - 1) then '//判断跟随触发是否读取完了全部数据,满了重新开始计数
Sync_Count = 0
else
Sync_Count = Sync_Count + 1
endif
endif
endsub
六.效果演示
下面以C#代码跑测试和RTSys示波器抓取波形分析。
视频讲解:
完整代码获取地址
▼
本次,正运动技术PCIe EtherCAT实时运动控制卡PCIE464同步跟随/皮带跟随加工应用,就分享到这里。
本文由正运动技术原创,欢迎大家转载,共同学习,一起提高中国智能制造水平。文章版权归正运动技术所有,如有转载请注明文章来源。
来源:正运动技术