The value of Zmotion is to bring customers more success!
今天,正运动小助手给大家分享一下EtherCAT运动控制卡之ECI2828如何使用C#进行实时性程序的运行和读写控制。
一 ECI2828运动控制卡硬件介绍
ECI2828系列运动控制卡支持多达 16 轴直线插补、任意圆弧插补、空间圆弧、螺旋插补、电子凸轮、电子齿轮、同步跟随、虚拟轴和机械手指令等;采用优化的网络通讯协议可以实现实时的运动控制。
ECI2828系列运动运动控制卡支持以太网,232 通讯接口和电脑相连,接收电脑的指令运行,可以通过EtherCAT总线和CAN总线去连接各个扩展模块,从而扩展输入输出点数或运动轴。
ECI2828系列运动控制卡的应用程序可以使用 VC,VB,VS,C++,C#等软件来开发,程序运行时需要动态库 zmotion.dll。调试时可以把ZDevelop软件同时连接到控制器,从而方便调试,方便观察。
二 C#语言进行运动控制开发
01 新建WinForm项目并添加函数库
1.在VS2015菜单“文件”→“新建”→ “项目”,启动创建项目向导。
2.选择开发语言为“Visual C#”和.NET Framework 4以及Windows 窗体应用程序。
3.找到厂家提供的光盘资料里面的C#函数库,路径如下(64位库为例):
A.进入厂商提供的光盘资料找到“8.PC函数”文件夹,并点击进入。
B.选择“函数库2.1”文件夹。
C.选择“Windows平台”文件夹。
D.根据需要选择对应的函数库这里选择64位库。
E.解压C#的压缩包,里面有C#对应的函数库。
F.函数库具体路径如下。
4.将厂商提供的C#的库文件以及相关文件复制到新建的项目中。
A.将zmcaux.cs文件复制到新建的项目里面中。
B.将zaux.dll和zmotion.dll文件放入bin\debug文件夹中。
5.用vs打开新建的项目文件,在右边的解决方案资源管理器中点击显示所有,然后鼠标右键点击zmcaux.cs文件,点击包括在项目中。
6.双击Form1.cs里面的Form1,出现代码编辑界面,在文件开头写入 using cszmcaux,并声明控制器句柄g_handle。
至此项目新建完成,可进行C#项目开发。
02 查看PC函数手册
A.PC函数手册也在光盘资料里面,具体路径如下:“光盘资料\8.PC函数\函数库2.1\ZMotion函数库编程手册 V2.1.pdf”。
B.PC编程,一般如果网口对控制器和工控机进行链接。网口链接函数接口是ZAux_OpenEth();如果链接成功,该接口会返回一个链接句柄。通过操作这个链接句柄可以实现对控制器的控制。
ZAux_OpenEth()接口说明:
C.使用对下位机寄存器操作的指令操作链接句柄“g_handle”,对控制器进行寄存器内容取值,实时控制下位机相关的指令如下。
实时全局变量指令:
ZAux_Direct_HwPswitch2硬件比较输出指令到位置后硬件自动触发op输出信号:
ZAux_Direct_HwTimer硬件定时器硬件比较输出后一段时见还原电平:
锁存相关指令:
ZAux_Direct_Regist接收到指定信号输入后立即锁存当前位置记录,R0,R1输入一般对应到输入口0和1:
ZAux_Direct_GetMark判断锁存mark是否产生:
ZAux_Direct_GetMarkB判断锁存markB是否产生:
ZAux_Direct_GetRegPos 锁存信号触发时反馈位置:
ZAux_Direct_GetRegPosB获取R1类型锁存反馈到的编码器位置位置:
硬件比较输出相关功能:
运动控制器内有位置比较单元,硬件比较输出是通过比较轴是否到达设定位置,来操作输出口动作,一般使用时将编码器位置与设定位置比较,当编码器的位置到达一个设定比较位置时,触发相应输出口电平翻转一次。
如下图所示,到达设置的位置1,电平翻转,到达位置2电平再次翻转,到达位置3电平再翻转,直达比较完所有的点后,电平维持最后一次翻转后的状态。
03 c#进行实时程序的运行和读写控制开发
1.实时程序的运行和读写控制开发人机交互界面如下。
2.例程功能介绍
位置比较输出功能实现:
使用以下数据传输到控制器的table表中,硬件比较输出功能到位置将会选择将对应信号进行翻转达到硬件比较输出的功能目的。
位置比较输出参数设置
通过进行设置比较的轴号,对应操作的输出口编号,进行动作,以起始点table寄存器编号内容数据到结束点的编号内容数据,运动到达每个对应的数据位置时将会进行翻转电平。
硬件定时器操作
在硬件比较输出功能操作后,可使用硬件定时器功能,进行对应设置周期时间内op口信号的还原,保证op口不存在长时间输出信号的情况。
状态显示
PC定时器进行刷新当前获取到控制器的坐标以及操作的op输出口的状态,显示在界面上,并记录锁存触发的次数。
运动部分
选定运动的距离,确保位置比较输出的坐标数据点在运动范围内,可以触发到对应的信号点并进行动作。
编码器锁存
指定锁存模式以及锁存轴,当运动到达比较输出位置时op输出信号到in口,触发对应的上升沿或者下降沿进行锁存当前位置,并将位置记录下来,显示在当前界面上。
3.例程简易流程图。
4.在Form1的构造函数中调用接口ZAux_OpenEth(),使在系统初始化的时候自动链接控制器。
private void C_Open_Eth_Click(object sender, EventArgs e) //以太网连接控制器
{
if (g_handle == (IntPtr)0)
{
C_Close_Card_Click(sender, e); //断开前面的连接
}
zmcaux.ZAux_OpenEth(C_Ip_Address.Text, out g_handle); //网口连接控制器
if (g_handle != (IntPtr)0)
{
this.Text = "已连接";
timer1.Enabled = true;
//C_Move_Axis_TextChanged(sender, e);
}
}
5.通过定时器更新控制器轴状态:当前坐标、OP输出状态等等。
private void timer1_Tick(object sender, EventArgs e) //刷新状态显示
{
float AxisDpos = 0;
int iret = 0;
UInt32 Op_status = 0;
updata_value();
if (RadioButton1.Checked == true) //位置比较是否开启
m_POS_IfOpen = false;
if (RadioButton2.Checked == true)
m_POS_IfOpen = true;
if (RadioButton4.Checked == true) //定时器输出反转是否开启
m_Timer_IfOpen = false;
if (RadioButton3.Checked == true)
m_Timer_IfOpen = true;
iret = zmcaux.ZAux_Direct_GetDpos(g_handle, m_AxisNum, ref AxisDpos);
iret = zmcaux.ZAux_Direct_GetOp(g_handle, m_POS_out, ref Op_status);
label_dpos.Text = "轴" + m_AxisNum.ToString() + "坐标: " + AxisDpos.ToString();
op.BackColor = Color.Red;
if (Op_status == 1)
op.BackColor = Color.LimeGreen;
}
6.设置比较点位置并选择启用硬件比较输出以及硬件定时器并开始进行运动:
private void Button2_Click(object sender, EventArgs e) //运动
{
if (g_handle == (IntPtr) 0)
{
MessageBox.Show( "未链接到控制器!", "提示");
return;
}
int iret = 0;
iret = zmcaux.ZAux_Direct_SetUnits(g_handle, m_AxisNum, 100);
iret = zmcaux.ZAux_Direct_SetSpeed(g_handle, m_AxisNum, 100);
iret = zmcaux.ZAux_Direct_SetAccel(g_handle, m_AxisNum, 2000);
iret = zmcaux.ZAux_Direct_HwPswitch2(g_handle, m_AxisNum, 2, 0, 0, 0, 0, 0, 0); //清除前面的比较输出指令
if (m_POS_IfOpen == false) //比较完成一次后需要重新调用HwPswitch
{
iret = zmcaux.ZAux_Direct_SetTable(g_handle, m_POS_StartTable, m_POS_EndTable, fPointPos); //将比较点填入TABLE
if (iret != 0)
{
string tempstr;
tempstr = "SetTable失败 返回值:" + iret.ToString();
MessageBox.Show(tempstr, "提示");
return;
}
iret = zmcaux.ZAux_Direct_HwPswitch2(g_handle, m_AxisNum, 1, m_POS_out, m_POS_OutStatus, m_POS_StartTable, m_POS_EndTable, m_PSO_dir, 0);
if (iret != 0)
{
string tempstr;
tempstr = "HwPswitch2失败 返回值:" + iret.ToString();
MessageBox.Show(tempstr, "提示");
return;
}
}
else
{
iret = 0;
iret = zmcaux.ZAux_Direct_HwPswitch2(g_handle, m_AxisNum, 2, 0, 0, 0, 0, 0, 0); //清除比较输出指令
if (iret != 0)
{
string tempstr;
tempstr = "HwPswitch2失败 返回值:" + iret.ToString();
MessageBox.Show(tempstr, "提示");
return;
}
}
int tempoutstatus = 0;
if (m_POS_OutStatus == 0)
tempoutstatus = 1;
else
tempoutstatus = 0;
if (m_Timer_IfOpen == false)
{
iret = zmcaux.ZAux_Direct_HwTimer(g_handle, 2, m_Timer_Cycle, m_Timer_Valid, m_Timer_Num, tempoutstatus, m_POS_out);
if (iret != 0)
{
string tempstr;
tempstr = "HwTimer失败 返回值:" + iret.ToString();
MessageBox.Show(tempstr, "提示");
//return;
}
}
else
{
iret = zmcaux.ZAux_Direct_HwTimer(g_handle, 0, m_Timer_Cycle, m_Timer_Valid, m_Timer_Num, tempoutstatus, m_POS_out);
if (iret != 0)
{
string tempstr;
tempstr = "HwTimer失败 返回值:" + iret.ToString();
MessageBox.Show(tempstr, "提示");
//return;
}
}
zmcaux.ZAux_Trigger(g_handle);
iret = zmcaux.ZAux_Direct_SetDpos(g_handle, m_AxisNum, 0);
iret = zmcaux.ZAux_Direct_Single_MoveAbs(g_handle, m_AxisNum, m_Start_Pos);
iret = zmcaux.ZAux_Direct_Single_MoveAbs(g_handle, m_AxisNum, m_End_Pos);
}
7.选择锁存模式以及锁存轴位置启用锁存。
private void Button1_Click(object sender, EventArgs e) //启动锁存
{
if (g_handle == (IntPtr) 0)
{
MessageBox.Show( "未链接到控制器!", "提示");
return;
}
int iret = 0;
if (m_Regist_IfOpen == false)
{
m_RegistCount = 0;
iret = zmcaux.ZAux_Direct_SetAtype(g_handle, m_RegistAxis, 4); //必须是编码器轴才可以
int ReglistListSel = ComboBox1.SelectedIndex;
if (ReglistListSel >= 0 && ReglistListSel <= 3)
{
RegistMode = ReglistListSel + 1;
}
else if (ReglistListSel == 4 || ReglistListSel == 5)
{
RegistMode = 10 + ReglistListSel;
}
else if (ReglistListSel > 5 || ReglistListSel < 9)
{
RegistMode = 12 + ReglistListSel;
}
iret = zmcaux.ZAux_Direct_Regist(g_handle, m_RegistAxis, RegistMode);
timer2.Start();
m_Regist_IfOpen = true;
ComboBox1.Enabled = false;
Button1.Text = "停止锁存";
}
else
{
timer2.Stop();
m_Regist_IfOpen = false;
ComboBox1.Enabled = true;
Button1.Text = "启动锁存";
DataGridView2.Rows.Clear();
}
}
8.定时器定时判断当前是否触发锁存状态,并将锁存位置读取出来并显示在界面上。
private void timer2_Tick(object sender, EventArgs e) //定时器刷新
{
int iret = 0;
int MarkStatus = 0;
float RegistPos= 0;
if(RegistMode >= 0 && RegistMode <= 4)
{
iret = zmcaux.ZAux_Direct_GetMark(g_handle,m_RegistAxis, ref MarkStatus);
}
else if(RegistMode >= 14 || RegistMode < 16)
{
iret = zmcaux.ZAux_Direct_GetMarkB(g_handle, m_RegistAxis, ref MarkStatus);
}
else if(RegistMode >= 18 || RegistMode < 20)
{
float tempc= 0;
iret = zmcaux.ZAux_Direct_GetParam(g_handle, "MARKC", m_RegistAxis, ref tempc);
MarkStatus = ( int)tempc;
}
else if(RegistMode >= 20 || RegistMode < 22)
{
float tempd= 0;
iret = zmcaux.ZAux_Direct_GetParam(g_handle, "MARKD", m_RegistAxis, ref tempd);
MarkStatus = ( int)tempd;
}
if (MarkStatus == -1)
{
if (RegistMode >= 0 && RegistMode <= 4)
{
iret = zmcaux.ZAux_Direct_GetRegPos(g_handle, m_RegistAxis, ref RegistPos); //获取锁存位置
}
else if (RegistMode >= 14 || RegistMode < 16)
{
iret = zmcaux.ZAux_Direct_GetRegPosB(g_handle, m_RegistAxis, ref RegistPos);
}
else if (RegistMode >= 18 || RegistMode < 20)
{
iret = zmcaux.ZAux_Direct_GetParam(g_handle, "REG_POSC", m_RegistAxis, ref RegistPos);
}
else if (RegistMode >= 20 || RegistMode < 22)
{
iret = zmcaux.ZAux_Direct_GetParam(g_handle, "REG_POSD", m_RegistAxis, ref RegistPos);
}
string[] tempstr = new string[ 2];
tempstr[ 0] = m_RegistCount.ToString();
tempstr[ 1] = RegistPos.ToString();
DataGridView2.Rows.Add(tempstr);
m_RegistCount = m_RegistCount + 1;
iret = zmcaux.ZAux_Direct_Regist(g_handle, m_RegistAxis, RegistMode); //重新触发锁存
}
string temps;
temps = "锁存触发状态:" + MarkStatus.ToString() + " 次数: " + m_RegistCount.ToString();
Label3.Text = temps;
}
}
04 调试与监控
编译运行例程,同时连接ZDevelop软件进行调试,对运动控制的轴参数和运动情况进行监控。
1.位置比较功能
通过界面上的位置比较输出功能以及对应的位置表,在指定位置将会对信号口电平进行翻转,如图示波器所示位置。
2.硬件定时器功能
硬件定时器主要是用于硬件比较输出后一段时间后还原电平,可以用于保证输出口的状态输出时间,控制输出时间长短。
3.编码器锁存功能
开启锁存功能,对应输入口接收到信号的同时将会锁存当前位置的mpos大小,并将读取到的对应内容显示到界面上。
锁存模式3:R0上升沿触发(默认RO信号口为in0)
如图:外部输入口IN由导通状态进入截止状态的一瞬间触发,位置进行记录显示在表格中。
锁存模式4:R0下降沿触发(默认RO信号口为in0)
如图:当外部输入口由截止状态进入导通状态的一瞬间触发,位置进行记录显示在表格中。
演示视频可点击→EtherCAT运动控制卡硬件比较输出以及编码器锁存查看。
本次,正运动技术EtherCAT运动控制卡的IO动作与运动控制的同步,就分享到这里。
更多精彩内容请关注“正运动小助手”公众号,需要相关开发环境与例程代码,请咨询正运动技术销售工程师:400-089-8936。
本文由正运动技术原创,欢迎大家转载,共同学习,一起提高中国智能制造水平。文章版权归正运动技术所有,如有转载请注明文章来源。