运动控制卡应用开发教程之硬件比较输出

供稿:深圳市正运动技术有限公司

  • 关键词:正运动技术,运动控制卡
  • 摘要:今天,正运动小助手为大家分享一下应用C++开发一个硬件比较输出例程。


今天,正运动小助手为大家分享一下应用C++开发一个硬件比较输出例程。


我们主要从新建MFC项目,添加函数库讲起,再了解PC函数用,最后通过项目实战——硬件比较输出例程讲解,来让大家熟悉运动控制卡的PC开发。


image.png

image.png


在正式学习之前,我们先了解一下正运动技术的运动控制卡ECI2828。这款产品是8轴运动控制卡。


正运动技术ECI2828 EtherCAT总线型运动控制卡,相对之前发布的ECI2618,新增了EtherCAT总线接口,电机轴数增加到8个,板载24+16点输入,16+16点输出(每个轴接口含2路通用输入和2路通用输出,可以做伺服使能、报警清除、到位信号、报警信号等控制);每轴输出脉冲频率可达10MHz;通过 CAN 总线,可扩展到512 个隔离输入或输出口。ECI2828支持硬件比较输出、精准输出、飞拍等功能。


image.png


image.png


运动控制卡ECI2828,支持C++、C#、LabVIEW、VB、Delphi、Linux、.Net平台、iMac、Python、Matlab等,统一的上位机API函数接口,具有开放、兼容、简单、易用等功能特性。


一新建MFC项目 添加函数库


1.在VS2015菜单“文件”→“新建”→ “项目”,启动创建项目向导。


image.png


2.选择开发语言为“Visual C++”和程序类型“MFC应用程序”。


image.png


3.下一步即可。


image.png


4.选择类型为“基于对话框”,下一步或者完成。下一步则往后继续配置,完成就直接完成即可。这里就不需要再配置了,无关紧要的,只要这个类型选好就行,其他的可以在项目中编辑。


image.png


5.找到正运动技术厂家提供的光盘资料,路径如下(64位库为例):

(1)进入光盘资料找到PC函数文件夹。


(2)选择函数库2.1。


(3)Windows平台。


image.png


(4)根据需要选择对应的函数库这里选择64位库。


image.png


(5)解压C++的压缩包,里面有C++对应的函数库。


image.png


(6)函数库具体路径如下。


image.png


6.将厂商提供的C++的库文件和相关头文件复制到新建的项目里面。


image.png


7.在项目中添加静态库和相关头文件。

静态库:zauxdll.lib, zmotion.lib


相关头文件:zauxdll2.h, zmotion.h


(1)先右击头文件,接着依次选择:“添加”→“现有项”。


image.png


(2)在弹出的窗口中依次添加静态库和相关头文件。


image.png


8.声明用到的头文件和定义控制器连接句柄。


image.png


至此项目新建完成。


二查看PC函数手册 了解PC函数用法


1.PC函数手册也在光盘资料里面,具体路径如下:


image.png


2.PC编程,一般先根据控制器连接方式选择对应的连接函数连接控制器,返回控制器句柄。接着用返回的控制器句柄,实现对控制器的控制。


3.比如通过网口连接控制器,先使用ZAux_OpenEth()链接控制器,获取控制器句柄handle。


image.png


4.通过获取到的控制器句柄,使用ZAux_Direct_SetTable,来设置控制器的TABLE寄存器的数值。

image.png


5.通过获取到的控制器句柄,使用ZAux_Direct_HwPswitch2,来启动并设置控制器的硬件比较输出的模式。

image.png

image.png


6.通过获取到的控制器句柄,使用ZAux_Direct_Regist()来启动并设置控制器的锁存方式。

image.png


三项目实战之硬件比较输出例程讲解


1.硬件比较输出


运动控制器内有位置比较单元,硬件比较输出是通过比较轴是否到达设定位置,来操作输出口动作,一般使用时将编码器位置与设定位置比较,当编码器的位置到达一个设定比较位置时,触发相应输出口电平翻转一次。


如下图所示,到达设置的位置1,电平翻转,到达位置2电平再次翻转,到达位置3电平再翻转,直达比较完所有的点后,电平维持最后一次翻转后的状态。


image.png


2.例程以建立板卡的连接,然后设置并开启硬件比较输出,将硬件比较输出的输出口和锁存的输入口进行连接,从而通过锁存记录硬件比较输出的位置。

(1)为了实验室测试方便,采用自发脉冲,同一轴编码器接收脉冲模式测试。同一个DB26轴接口的脉冲轴和编码器轴的连接方式(用于锁存硬件比较输出的位置),PUL+接EA+、PUL-接EA-、DIR+接EB+、DIR-接EB-。(或者直接通过脉冲型伺服电机进行位置反馈。)


(2)例程界面。


image.png


3.例程简易流程图。


image.png


4.通过网口连接控制器,获取控制器连接句柄。

//连接控制器

void Ctest_PswitchDlg::OnBnClickedOpen()

{

  char   buffer[256]; 

  int32 iresult;

  //从下拉框中获取IP地址

  GetDlgItemText(IDC_IPLIST,buffer,255);

  buffer[255] = '\0';

  //通过网口连接控制器

  iresult = ZAux_OpenEth(buffer, &g_handle);

  if(ERR_SUCCESS != iresult)

  {

    g_handle = NULL;

    MessageBox(_T("链接失败"));

    SetWindowText("未链接");

    return;

  }

  SetWindowText("已链接");

  SetTimer(0,100,NULL);

}

5.通过运动按钮的事件处理函数去设置硬件比较输出的模式,并开始轴运动。

(1)通过对UI界面的控件添加对应的变量,实现硬件比较输出的模式的参数输入。


image.png


(2)运动按钮事件处理函数。

//运动

void Ctest_PswitchDlg::OnBnClickedStartmove()      

{

  m_RegistCount = 0;

  ShowRegistList();

  UpdateData(TRUE);

//设置轴参数

  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);

  }

  else

  {

    //关闭硬件比较输出

    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.根据设置情况判断是否开启锁存,并设置锁存模式。

//启动或停止锁存

void Ctest_PswitchDlg::OnBnClickedRegistStart()    

{

  int iret = 0;

  UpdateData(TRUE);

  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;

    }

    else if(ReglistListSel == 4 || ReglistListSel ==5)

    {

      RegistMode = 10 + ReglistListSel;

    }

    else if(ReglistListSel > 5 || ReglistListSel < 9)

    {

      RegistMode = 12 + ReglistListSel;    

    }

    //开启锁存

    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);

    ShowRegistList();

  }

  else

  {

    KillTimer(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 str;

    if(nIDEvent == 1)

    {

      int iret = 0;

      int MarkStatus = 0;

      float RegistPos;

      //判断锁存是否触发

      if(RegistMode >= 0 && RegistMode < 4)

      {

        iret = ZAux_Direct_GetMark(g_handle,m_RegistAxis,&MarkStatus);  

      }

      else if(RegistMode >= 14 || RegistMode < 16)

      {

        iret = ZAux_Direct_GetMarkB(g_handle,m_RegistAxis,&MarkStatus);  

      }

      else if(RegistMode >= 18 || RegistMode < 20)

      {  

        float tempc;

        iret = ZAux_Direct_GetParam(g_handle,"MARKC",m_RegistAxis,&tempc);  

        MarkStatus = (int)tempc;

      }

      else if(RegistMode >= 20 || RegistMode < 22)

      {

        float tempd;

        iret = ZAux_Direct_GetParam(g_handle,"MARKD",m_RegistAxis,&tempd);  

        MarkStatus = (int)tempd;

      }

      //读取锁存的位置

      if(MarkStatus == -1)

      {

        if(RegistMode >= 0 && RegistMode < =4)

        {

          iret = ZAux_Direct_GetRegPos(g_handle,m_RegistAxis,&RegistPos);        

        }

        else if(RegistMode >= 14 || RegistMode < 16)

        {

          iret = ZAux_Direct_GetRegPosB(g_handle,m_RegistAxis,&RegistPos);  

        }

        else if(RegistMode >= 18 || RegistMode < 20)

        {  

      iret = ZAux_Direct_GetParam(g_handle,"REG_POSC",m_RegistAxis,&RegistPos);

        }

        else if(RegistMode >= 20 || RegistMode < 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.通过停止按钮的事件处理函数来停止运动。


//停止

void Ctest_PswitchDlg::OnBnClickedStopmove()      

{

int iret = ZAux_Direct_Single_Cancel(g_handle, m_AxisNum, 2);  

}         

9.编译运行演示。


(1)将硬件比较输出的输出口(out0)和锁存的输入口(in0)用导线进行连接,将轴0的DB26接口上的脉冲轴和编码器轴进行连接。


(2)编译并运行例程。


image.png


(3)同时通过ZDevelop软件连接同一个控制器,通过示波器对运动过程进行监控。


image.png


本次,正运动技术的C++开发之硬件比较输出就分享到这里,更多精彩内容请关注“正运动小助手”公众号。


本文由正运动技术原创,欢迎大家转载,共同学习,一起提高中国智能制造水平。文章版权归正运动技术所有,如有转载请注明文章来源。


发布时间:2021年8月19日 13:19  人气:   审核编辑(王静 )
更多内容请访问(深圳市正运动技术有限公司
相关链接

我有需求