今天郑运动助手给大家分享一下如何使用C++开发硬件对比输出例程。
我们主要从新建MFC工程并添加函数库开始,然后了解PC机功能的使用,最后讲解实际工程——硬件对比输出例程,让大家熟悉运动控制卡的PC机开发。
在正式学习之前,我们先来了解一下正运动科技的运动控制卡ECI2828。本产品为8轴运动控制卡。
正动科技ECI2828 EtherCAT总线型运动控制卡,与之前发布的ECI2618相比,新增了EtherCAT总线接口,电机轴数增加到8个,板载24+16个输入点,16+16个输出点(每个轴接口包含2路通用输入和2路通用输出,可用于伺服使能、报警清除、到位信号、报警信号等);各轴输出脉冲频率可达10MHz;通过CAN总线,可扩展至512个隔离输入或输出端口。 ECI2828支持硬件比较输出、精准输出、飞行拍摄等功能。
运动控制卡ECI2828支持C++、C#、LabVIEW、VB、Delphi、Linux、Net平台、iMac、Python、Matlab等,具有统一的上位机API函数接口,开放、兼容、简单、易于使用使用。
1、新建MFC工程,添加函数库
1、在VS2015菜单“文件”“新建”“项目”中,启动创建项目向导。
2. 选择开发语言为“Visual C++”,程序类型为“MFC Application”。
3. 进行下一步即可。
4. 选择类型“基于对话框”、“下一步”或“完成”。接下来继续配置,直接完成。这里不需要配置,没关系,只要选择这个类型,其他的都可以在项目中编辑。
5、找到正动科技厂家提供的光盘信息,路径如下(以64位库为例):
(1) 输入CD数据并找到PC功能文件夹。
(2) 选择函数库2.1。
(3)Windows平台。
(4) 根据需要选择相应的函数库。在这里,选择64 位库。
(5)解压C++压缩包,其中包含C++对应的函数库。
(6)函数库的具体路径如下。
6、将厂家提供的C++库文件和相关头文件复制到新创建的工程中。
7. 在工程中添加静态库和相关头文件。
静态库:zauxdll.lib、zmotion.lib
相关头文件:zauxdll2.h、zmotion.h
(1) 首先右键单击头文件,然后选择:“添加”“现有项”。
(2) 在弹出的窗口中依次添加静态库及相关头文件。
8. 声明所使用的头文件并定义控制器连接句柄。
至此,新项目就完成了。
2.查看PC功能手册,了解PC功能的使用方法。
1. CD-ROM 中还包含PC 功能手册。具体路径如下:
2、上位机编程,一般先根据控制器连接方式选择对应的连接函数连接到控制器,并返回控制器句柄。然后使用返回的控制器句柄来控制控制器。
3、例如通过网口连接控制器,首先使用ZAux_OpenEth()连接控制器并获取控制器句柄。
4. 使用ZAux_Direct_SetTable通过获取的控制器句柄设置控制器TABLE寄存器的值。
5、使用ZAux_Direct_HwPswitch2通过获取控制器句柄来启动并设置控制器的硬件比较输出模式。
6. 使用ZAux_Direct_Regist()启动并通过获得的控制器句柄设置控制器的锁存模式。
3、实际项目中硬件比较输出例程说明
1. 硬件比较输出
运动控制器中有一个位置比较单元。硬件比较输出是通过比较轴是否到达设定位置来操作输出端口。一般使用时,将编码器位置与设定位置进行比较。当编码器位置到达设定位置时进行位置比较时,触发对应输出端口的电平翻转一次。
如下图所示,当到达设定位置1时,电平翻转。当到达位置2 时,液位再次翻转。当到达位置3 时,液位再次翻转。所有点比较后,级别保持上次翻转后的状态。
2、例程是建立板子的连接,然后设置并打开硬件比较输出,连接硬件比较输出的输出口和锁存器的输入口,从而记录硬件比较的位置通过锁存器输出。
(1)为了实验室测试方便,采用自发脉冲,同轴编码器接收脉冲方式测试。同DB26轴接口的脉冲轴和编码器轴的连接方法(用于锁存硬件比较输出的位置),PUL+接EA+,PUL-接EA-,DIR+接EB+, DIR- 连接到EB-。 (或者直接通过脉冲伺服电机进行位置反馈。)
(2)常规接口。
3、简单的例程流程图。
4. 通过网口连接控制器,获取控制器连接句柄。
//连接控制器
无效Ctest_PswitchDlg:OnBnClickedOpen()
{
字符缓冲区[256];
int32 结果;
//从下拉框中获取IP地址
GetDlgItemText(IDC_IPLIST,缓冲区,255);
缓冲区[255]='\0';
//通过网口连接控制器
iresult=ZAux_OpenEth(缓冲区, g_handle);
if(ERR_SUCCESS !=i结果)
{
g_handle=NULL;
MessageBox(_T('链接失败'));
SetWindowText('未链接');
返回;
}
SetWindowText('链接');
SetTimer(0,100,NULL);
}
5. 使用运动按钮的事件处理功能设置硬件比较输出模式并启动轴运动。
(1)通过在UI界面的控件中添加相应的变量,实现硬件比较输出方式的参数输入。
(2)运动按钮事件处理函数。
//运动的
无效Ctest_PswitchDlg:OnBnClickedStartmove()
{
m_RegistCount=0;
显示注册列表();
更新数据(真);
//设置轴参数
ZAux_Direct_SetAtype(g_handle, m_AxisNum, 1);
ZAux_Direct_SetUnits(g_handle, m_AxisNum, 1000);
ZAux_Direct_SetSpeed(g_handle, m_AxisNum, 200);
ZAux_Direct_SetAccel(g_handle, m_AxisNum, 2000);
ZAux_Direct_SetDecel(g_handle, m_AxisNum, 2000);
//关闭硬件比较输出(停止并删除未完成的比较点)
ZAux_Direct_HwPswitch2(g_handle, m_AxisNum, 2, 0, 0, 0, 0, 0, 0);
//启用硬件比较输出MODE:1
if (m_POS_IfOpen==false) //比较完成一次后需要再次调用HwPswitch
{
//将比较点填充到TABLE中
ZAux_Direct_SetTable(g_handle, m_POS_StartTable, m_POS_EndTable- m_POS_StartTable+1, fPointPos);
//使能硬件比较输出
ZAux_Direct_HwPswitch2(g_handle, m_AxisNum, 1, m_POS_out, m_POS_OutStatus, m_POS_StartTable, m_POS_EndTable, m_POS_dir, 0);
}
别的
{
//关闭硬件比较输出
ZAux_Direct_HwPswitch2(g_handle, m_AxisNum, 2, 0, 0, 0, 0, 0, 0);
}
//打开示波器
ZAux_Trigger(g_handle);
ZAux_Direct_SetDpos(g_handle, m_AxisNum, 0);
//开始轴运动(绝对位置)
ZAux_Direct_Single_MoveAbs(g_handle, m_AxisNum, m_Start_Pos);
ZAux_Direct_Single_MoveAbs(g_handle, m_AxisNum, m_End_Pos);
}
6、根据设置情况确定是否开启锁存,并设置锁存模式。
//开始或停止锁存
无效Ctest_PswitchDlg:OnBnClickedRegistStart()
{
int iret=0;
更新数据(真);
if(m_Regist_IfOpen==FALSE)
{
m_RegistCount=0;
//必须是编码器轴才可以锁存
iret=ZAux_Direct_SetAtype(g_handle,m_RegistAxis,6);
//设置锁存模式
int ReglistListSel=((CComboBox *) GetDlgItem(IDC_REGIST_MODE))-GetCurSel();
if(ReglistListSel=0 ReglistListSel=3)
{
RegistMode=ReglistListSel +1;
}
否则if(ReglistListSel==4 || ReglistListSel==5)
{
注册模式=10 + 注册列表选择;
}
else if(ReglistListSel 5 || ReglistListSel 9)
{
注册模式=12 + 注册列表选择;
}
//打开锁存器
iret=ZAux_Direct_Regist(g_handle,m_RegistAxis,RegistMode);
SetTimer(1,5,NULL);
m_Regist_IfOpen=TRUE;
SetDlgItemTextA(IDC_REGIST_START,_T('停止锁存'));
((CComboBox *)GetDlgItem(IDC_REGIST_MODE))-EnableWindow(FALSE);
显示注册列表();
}
别的
{
终止定时器(1);
m_Regist_IfOpen=FALSE;
SetDlgItemTextA(IDC_REGIST_START,_T('启动锁存器'));
((CComboBox *)GetDlgItem(IDC_REGIST_MODE))-EnableWindow(TRUE);
}
}
7. 通过定时器1更新锁存器信息。
void Ctest_PswitchDlg:OnTimer(UINT_PTR nIDEvent) //定时器刷新
{
if(NULL!=g_handle)
{
CString 字符串;
if(nIDEvent==1)
{
int iret=0;
int 标记状态=0;
浮动注册位置;
//判断latch是否被触发
if(注册模式=0 注册模式4)
{
iret=ZAux_Direct_GetMark(g_handle,m_RegistAxis,MarkStatus);
}
否则if(注册模式=14 || 注册模式16)
{
iret=ZAux_Direct_GetMarkB(g_handle,m_RegistAxis,MarkStatus);
}
否则if(注册模式=18 || 注册模式20)
{
浮点温度;
iret=ZAux_Direct_GetParam(g_handle,'MARKC',m_RegistAxis,tempc);
标记状态=(int)tempc;
}
否则if(注册模式=20 || 注册模式22)
{
浮点温度;
iret=ZAux_Direct_GetParam(g_handle,'MARKD',m_RegistAxis,tempd);
标记状态=(int)tempd;
}
//读取锁存位置
if(标记状态==-1)
{
if(注册模式=0 注册模式=4)
{
iret=ZAux_Direct_GetRegPos(g_handle,m_RegistAxis,RegistPos);
}
否则if(注册模式=14 || 注册模式16)
{
iret=ZAux_Direct_GetRegPosB(g_handle,m_RegistAxis,RegistPos);
}
否则if(注册模式=18 || 注册模式20)
{
iret=ZAux_Direct_GetParam(g_handle,'REG_POSC',m_RegistAxis,RegistPos);
}
否则if(注册模式=20 || 注册模式22)
{
iret=ZAux_Direct_GetParam(g_handle,'REG_POSD',m_RegistAxis,RegistPos); }
m_RegistList.InsertItem(m_RegistCount,'');
str.Format(_T('%d'), m_RegistCount);
m_RegistList.SetItemText(m_RegistCount,0,str);
str.Format(_T('%.3f'), RegistPos);
m_RegistList.SetItemText(m_RegistCount,1,str);
m_RegistCount++;
//重新触发锁存器
iret=ZAux_Direct_Regist(g_handle,m_RegistAxis,RegistMode);
}
str.Format(_T('锁存触发状态:%d次:%d'), MarkStatus,m_RegistCount);
SetDlgItemTextA(IDC_STATUS_REGIST,str);
}
}
CDialogEx:OnTimer(nIDEvent);
}
8. 通过停止按钮的事件处理程序停止运动。
//停止
无效Ctest_PswitchDlg:OnBnClickedStopmove()
{
int iret=ZAux_Direct_Single_Cancel(g_handle, m_AxisNum, 2);
}
9. 编译并运行demo。
(1) 用导线连接硬件比较输出的输出端口(out0)和锁存输入端口(in0),并在0 轴的DB26 接口上连接脉冲轴和编码器轴。
(2) 编译并运行例程。
(3) 同时通过ZDevelop软件连接到同一个控制器,通过示波器监控运动过程。