运动控制卡应用开发教程之C++ 点击:167 | 回复:3



之卿 。 ❁҉҉҉҉҉҉҉

    
  • 精华:0帖
  • 求助:0帖
  • 帖子:34帖 | 73回
  • 年度积分:0
  • 历史总积分:243
  • 注册:2020年5月25日
发表于:2020-12-24 13:40:35
楼主

今天,正运动技术为大家分享一下应用C++开发一个多段连续插补的运动控制应用。

  我们主要从新建MFC项目,添加函数库讲起,再了解PC函数用法,最后通过项目实战——连续插补运动例程讲解,来让大家熟悉C++的项目开发。

  在正式学习之前,我们先了解一下正运动技术的运动控制卡ECI2418和ECI2618。这两款产品分别是4轴,6轴运动控制卡。

  

  1.jpg

  

  ECI2418支持4轴脉冲输入与编码器反馈,板载24点输入,16点输出,2AD,2DA,支持手轮接口,其中特定输出口支持高速PWM控制。

  

  2.jpg

  

  ECI2618支持6轴脉冲输入与编码器反馈,板载24点输入,16点输出,2AD,2DA,支持手轮接口,其中特定输出口支持高速PWM控制。

  

  3.jpg

  

  ECI2418,ECI2618均使用同一套API函数,均支持C、C++、C#、LabVIEW、Python、Delphi等开发语言,支持VC6.0、VB6.0、Qt、.Net等平台,支持Windows、Linux、WinCE、iMac等操作系统。

  以下是C++

  开发流程

   01 新建MFC项目,添加函数库。

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

  

  4.jpg

  

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

  

  5.jpg

  

   3、下一步即可。

  

  6.jpg

  

   4、选择类型为“基于对话框”,下一步或者完成。

  下一步则往后继续配置,完成就直接完成即可。这里就不需要再配置了,无关紧要的,只要这个类型选好就行,其他的可以在项目中编辑。

  

  7.jpg

  

   5、找到厂家提供的光盘资料,路径如下(64位库为例)。

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

  

  8.jpg

  

  2)选择函数库2.1。

  

  9.jpg

  

  3)Windows平台。

  

  10.jpg

  

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

  

  11.jpg

  

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

  

  12.jpg

  

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

  

  13.jpg

  

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

  

  14.jpg

  

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

  静态库:zauxdll.lib, zmotion.lib

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

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

  

  15.jpg

  

  

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

  

  16.jpg

  

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

  

  17.jpg

  

  至此项目新建完成。

  

   02 查看PC函数手册,了解其用法。

  

   1、PC函数手册也在光盘资料里面。

  具体路径如下:

  

  18.jpg

  

   2、PC编程

  先根据控制器连接方式选择对应的连接函数连接控制器,返回控制器句柄。接着用返回的控制器句柄,实现对控制器的控制。

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

  

  19.jpg

  

  通过获取到的控制器句柄handle,对控制器进行单轴运动控制。

  

  20.jpg

  

  通过获取到的控制器句柄handle,对控制器进行多轴运动控制。

  

  21.jpg

  

  //多轴运动

   intaxislist[ 4] = { 0, 1, 2, 3 };                                              //运动BASE轴列表

   floatdislist[ 4] = { 100,100,100,100};                            //运动距离列表

  ZAux_Direct_Move(g_handle, 4, axislist, dislist);           //多轴运动

  

   03 项目实战之连续插补运动例程讲解

  

   1、例程以建立板卡的连接,执行3段连续轨迹的加工为目标。

  

  22.jpg

  

   2、例程简易流程图。

  

  23.jpg

  

  // 相关函数

  ZAux_OpenEth(IP_buffer, &g_handle);                                            //连接控制器

  ZAux_Direct_GetAllAxisPara(g_handle, " DPOS", 4, showpos);        //获取当前轴位

  ZAux_Direct_GetAllAxisPara(g_handle, " MSPEED", 4, mspeed);     //更新轴速度

  ZAux_Direct_Single_Cancel(g_handle, 0, 2); //停止主轴运动

  ZAux_Direct_Move(g_handle, 4, axislist, dislist1);                            //第1段多轴插补指令

  ZAux_Direct_Move(g_handle, 4, axislist, dislist2);                            //第2段多轴插补指令

  ZAux_Direct_Move(g_handle, 4, axislist, dislist3);                            //第3段多轴插补指令

  ZAux_Close(g_handle);//断开连接

  

   3、通过网口连接控制器,获取控制器连接句柄。

  

  /li<x>nk按钮事件处理函数

   voidCMergeDlg::OnBnClickedButtonLink()

  {

       charbuffer[256];

      int32 iresult;

      //如果之前有连接控制器着先断开连接

       if(NULL != g_handle)

      {

      ZAux_Close(g_handle);

      g_handle = NULL;

      }

      //从IP下拉框中获取IP

      GetDlgItemText(IDC_COMBOX_IP, buffer, 255);

      buffer[255] = '\0';

      //通过PC函数库提供的连接控制器的函数接口(API),连接控制器

      iresult = ZAux_OpenEth(buffer, &g_handle);

       if(ERR_SUCCESS != iresult)

      {

      g_handle = NULL;

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

      SetWindowText(" 未链接");

       return;

  }

  SetWindowText(" 已链接");

  //启动定时器

  SetTimer(1, 100, NULL);

  SetTimer(2, 100, NULL);

  //初始化轴参数

   for( inti = 0; i<4; i++)

  {

      ZAux_Direct_SetAtype(g_handle, i, 1); //轴类型

      ZAux_Direct_SetUnits(g_handle, i, 1000); //脉冲当量

      ZAux_Direct_SetSpeed(g_handle, i, 100); //速度

      ZAux_Direct_SetAccel(g_handle, i, 1000); //加速度

      ZAux_Direct_SetDecel(g_handle, i, 1000); //减速度

  ZAux_Direct_SetSramp(g_handle, i, 100); //S曲线时间

      }

  }

  

   4、通过定时器1更新控制器轴0-3的位置信息和速度信息。

  

  //定时器

  void CMergeDlg::OnTimer(UINT_PTR nIDEvent)

  {

      if (NULL == g_handle)

      {

          MessageBox(_T(" 链接断开"));

          return;

      }

      switch (nIDEvent)

      {

      case 1: //更新控制器轴0-3的位置信息和速度信息

          CString Xpos, Xmspeed;

          CString Ypos, Ymspeed;

          CString Zpos, Zmspeed;

          CString Upos, Umspeed;

          float showpos[4] = { 0 };

          float mspeed[4] = { 0 };

  int         status = 0;

          //获取当前轴位置

          ZAux_Direct_GetAllAxisPara(g_handle, " DPOS", 4, showpos);

          Xpos.Format(" X: %.2f", showpos[0]);

          Ypos.Format(" Y: %.2f", showpos[1]);

          Zpos.Format(" Z: %.2f", showpos[2]);

          Upos.Format(" U: %.2f", showpos[3]);

          GetDlgItem(IDC_XPOS)->SetWindowText(Xpos);

          GetDlgItem(IDC_YPOS)->SetWindowText(Ypos);

          GetDlgItem(IDC_ZPOS)->SetWindowText(Zpos);

          GetDlgItem(IDC_UPOS)->SetWindowText(Upos);

          //判断主轴状态(即BASE的第一个轴)

          ZAux_Direct_GetIfIdle(g_handle, 0, &status);

          if (status == -1)

          {

              GetDlgItem(IDC_RUNSTATUS)->SetWindowText(" 运动状态:停止中");

          }

          else

          {

              GetDlgItem(IDC_RUNSTATUS)->SetWindowText(" 运动状态:运动中");

          }

          //更新轴速度

          ZAux_Direct_GetAllAxisPara(g_handle, " MSPEED", 4, mspeed);

          Xmspeed.Format(" X轴速度: %.2f", mspeed[0]);

          Ymspeed.Format(" Y轴速度: %.2f", mspeed[1]);

          Zmspeed.Format(" Z轴速度: %.2f", mspeed[2]);

          Umspeed.Format(" U轴速度: %.2f", mspeed[3]);

          GetDlgItem(IDC_SPEED_X)->SetWindowText(Xmspeed);

          GetDlgItem(IDC_SPEED_Y)->SetWindowText(Ymspeed);

          GetDlgItem(IDC_SPEED_Z)->SetWindowText(Zmspeed);

          GetDlgItem(IDC_SPEED_U)->SetWindowText(Umspeed);

          break;

      }

      CDialogEx::OnTimer(nIDEvent);

  }

  

   5、通过启动按钮的事件处理函数来启动连续插补运动。

  

  //启动按钮

  void CMergeDlg::OnBnClickedButtonRun()

  {

      if (NULL == g_handle)

      {

          MessageBox(_T( "链接断开"));

          return;

      }

      UpdateData(true);//刷新参数

      int corner_mode = 0;

      int axislist[4] = { 0,1,2,3 }; //运动BASE轴列表

      float dislist1[4] = { 0 }; //运动距离列表

      float dislist2[4] = { 0 };

      float dislist3[4] = { 0 };

      //选择参与运动的轴,第一个轴为主轴,插补参数全用主轴参数

      ZAux_Direct_SetSpeed(g_handle, axislist[0], M_Speed); //速度

      ZAux_Direct_SetAccel(g_handle, axislist[0], M_Accel); //加速度

      ZAux_Direct_SetDecel(g_handle, axislist[0], M_Decel); //减速度

  ZAux_Direct_SetSramp(g_handle, axislist[0], M_SRAMP); //S曲线时间

      //设置拐角模式

      if (m_mode1 == 1)

      {

          corner_mode = corner_mode + 2;

      }

      if (m_mode2 == 1)

      {

          corner_mode = corner_mode + 8;

      }

      if (m_mode3 == 1)

      {

          corner_mode = corner_mode + 32;

      }

      ZAux_Direct_SetCornerMode(g_handle, axislist[0], corner_mode);

      //设置连续插补

      ZAux_Direct_SetMerge(g_handle, axislist[0], m_mode);

      //设置SP速度

      ZAux_Direct_SetForceSpeed(g_handle, axislist[0], SP_Speed);

      //设置开始.结束减速角度,转换为弧度

      ZAux_Direct_SetDecelAngle(g_handle, axislist[0], StartAngle * 3.14 / 180);

      ZAux_Direct_SetStopAngle(g_handle, axislist[0], StopAngle * 3.14 / 180);

      //设置小圆限速半径

      ZAux_Direct_SetFullSpRadius(g_handle, axislist[0], SP_Radius);

      //设置拐角半径

      ZAux_Direct_SetZsmooth(g_handle, axislist[0], CornerRadius);

      //SP指令中自动拐角模式中设置一个较大的startmovespeed与endmovespeed

      ZAux_Direct_SetStartMoveSpeed(g_handle, axislist[0], 10000);

      ZAux_Direct_SetEndMoveSpeed(g_handle, axislist[0], 10000);

      //更新运动数据

      dislist1[0] = DPOS_X_1; dislist1[1] = DPOS_Y_1;

      dislist1[2] = DPOS_Z_1; dislist1[3] = DPOS_U_1;

      dislist2[0] = DPOS_X_2; dislist2[1] = DPOS_Y_2;

      dislist2[2] = DPOS_Z_2; dislist2[3] = DPOS_U_2;

      dislist3[0] = DPOS_X_3; dislist3[1] = DPOS_Y_3;

      dislist3[2] = DPOS_Z_3; dislist3[3] = DPOS_U_3;

      //开始运动

      ZAux_Direct_Move(g_handle, 4, axislist, dislist1);

      ZAux_Direct_Move(g_handle, 4, axislist, dislist2);

      ZAux_Direct_Move(g_handle, 4, axislist, dislist3);

  }

  

   6、通过停止按钮的事件处理函数来停止插补运动。

  

  //停止按钮

  void CMergeDlg::OnBnClickedButtonStop()

  {

      if (NULL == g_handle)

      {

          MessageBox(_T("链接断开"));

          return;

      }

      ZAux_Direct_Single_Cancel(g_handle, 0, 2); //停止主轴 BASE的一个轴

  }

  

  7、轴坐标清零。

  

  //坐标清零

  void CMergeDlg::OnBnClickedButtonClear()

  {

      if (NULL == g_handle)

      {

          MessageBox(_T("链接断开"));

          return;

      }

      for (int i = 0; i<4; i++)

      {

          ZAux_Direct_SetDpos(g_handle, i, 0); //DPOS设为零

      }

  }

  

   8、编译运行演示。

  

  1)编译运行示教例程。

  

  24.jpg

  

  2)同时通过ZDevelop软件连接同一个控制器,对运动控制的轴参数进行监控。

      A、连续插补加自动倒角的位置波形。

  

  25.jpg

  

      B、不开启连续插补的速度波形。

  

  26.jpg

  28.jpg

  

  

      C、连续插补加合适的拐角减速的速度波形。

  

  28.jpg

  29.jpg

  30.jpg

  


  正运动技术C++开发就讲到这里。更多学习视频及图文请关注我们的公众号“正运动小助手”。

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




楼主最近还看过



正运动技术

  • 精华:0帖
  • 求助:1帖
  • 帖子:267帖 | 328回
  • 年度积分:50
  • 历史总积分:918
  • 注册:2020年9月10日
发表于:2021-01-21 16:38:55
1楼

任何技术问题,请访问正运动官网

正运动技术

  • 精华:0帖
  • 求助:1帖
  • 帖子:267帖 | 328回
  • 年度积分:50
  • 历史总积分:918
  • 注册:2020年9月10日
发表于:2021-01-27 16:08:41
2楼

任何技术问题,请访问正运动技术官网

正运动技术

  • 精华:0帖
  • 求助:1帖
  • 帖子:267帖 | 328回
  • 年度积分:50
  • 历史总积分:918
  • 注册:2020年9月10日
发表于:2021-02-04 15:38:44
3楼

任何技术问题,请访问正运动技术官网


热门招聘
相关主题

官方公众号

智造工程师