正运动技术

协助伙伴成功,是我们的价值所在

The value of Zmotion is to bring customers more success!

首页 / 支持与服务 / 技术分享

Technical support

技术分享

运动控制卡应用开发教程之Linux

  今天,正运动技术为大家分享一下运动控制卡应用开发教程之Linux。我们将从新建Qt项目,添加函数库讲起,再详细讲解函数的用法,最后通过一个连续插补例程讲解来了解项目实操。

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

  

  图片0_1.png

  

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

  

  图片0_2.png

  

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

  

  图片0_3.png

  

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

  以下是Linux

  开发流程

  一 新建Qt项目 添加函数库

  

  1.新建Qt项目:点击“New Project”→“Qt Widgets Application”→“Choose”。

  

  图片1.png

  

  图1 新建Qt项目

  2.找到正运动技术光盘资料里面的Linux系统的函数库

  

  图片2.png

  

  图2 Linux系统64位库路径

  3.将上面路径下的所有文件通过共享文件夹复制到刚刚新建的Qt项目中。

  

  图片3.png

  

  图3 复制函数库相关文件

  4.在Qt项目中添加函数库。

  A.右键项目,接着点击添加库。

  

  图片4.png

  

  图4 添加库1

  B.选择外部库,接着点击下一步。

  

 图片5.png 

  

  图5 添加库2

  C.点击浏览,找到刚刚复制到项目中的库文件libzmotio.so,然后点击下一步直到完成。

  

  图片6.png

  

  图6 添加库3

  5.在Qt项目中添加相关头文件和源文件(zmotion.h、zaux.cpp、zaux.h)。

  A.右键Headers/Sources文件夹,点击添加现有文件。

  

  图片7.png

  

  图7 添加头文件

  B.在弹出的界面中找到相关文件,并依次添加。

  

  图片8.png

  

  图8 选择文件

  6.在mainwindow.h中添加 #includezmotion.h”、 #include “zmcux.h”和定义控制器的连接句柄g_handle,至此,项目新进完成。

  

  图片9.png

  

  图9 声明头文件

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

  

  我们在PC项目开发的过程中,经常用到PC函数库,因此,需要查看PC函数手册来了解新函数的用法。

  比如在接下来的项目实战中,会用到一些新的函数接口。我们先来看一下这些函数接口的用法。

  1.连续连续插补指令的用法。

  

  图片10.png

  

  图10 连续插补指令用法

  2.拐角模式设置指令的用法。

  注意:这里的拐角模式设置,只是设置了一个模式。像拐角减速设置,还需要设置开始减速角度和结束减速角度等具体使用方法请参考下面的例程讲解。

  

  图片11.png

  

  图11 拐角模式设置指令用法

  3.获取控制器缓冲区剩余的缓冲数量指令的用法。

  注意:在发送插补指令前,需要先判断缓冲区是否有剩余,这样才能保证运动指令发送成功。

  

  图片12.png

  

  图12 拐角模式设置指令用法

  三 项目实操连续插补例程

  

  1.例程以建立板卡的连接,执行运动距离数组“destdis[120][5]”里面的120段点位运动为加工目标。

  

  图片13.png

  

  图13 连续插补例程

  

  图片14.png

  

  图14 destdis数组

  2.例程流程图。

  

  图片15.png

  

  图15 例程流程图

  3.通过连接按钮的槽函数去调用“ZAux_OpenEth()”连接控制器,获取控制器连接句柄,连接成功后并对轴参数初始化。

  //链接按钮槽函数

  void MainWindow::on_Open_clicked()

  {

      int32 iresult;

      char * tmp_buff = new char[16];

      QString str;

      QString str_title;

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

      str = ui->comboBox_IP->currentText();

      QByteArray ba = str.toLatin1();

      tmp_buff = ba.data();

      //链接控制器

      iresult = ZAux_OpenEth(tmp_buff,&g_handle);

      if(0 == iresult)

      {

          str_title += tmp_buff;

          setWindowTitle(str_title);

      }

      else

      {

          setWindowTitle("no link!");

          return ;

      }

      //开起定时器

      id1=startTimer(100);

      id2=startTimer(50);

      //初始化轴参数

      for(int i=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); //减速度

      }

  }

  4.通过定时器1和2更新控制器轴信息和运动状态。

  //定时器

  void MainWindow::timerEvent(QTimerEvent *event)

  {

      //定时器1:获取并更新轴位置信息

      if(event->timerId() == id1)

      {

          QString Xpos1,Ypos1,Zpos1,Upos1;

          QString Curspeed;

          float showpos[4] ={0};

          float curspeed =0;

          ZAux_Direct_GetDpos( g_handle,0,&showpos[0]);

          ZAux_Direct_GetDpos( g_handle,1,&showpos[1]);

          ZAux_Direct_GetDpos( g_handle,2,&showpos[2]);

          ZAux_Direct_GetDpos( g_handle,3,&showpos[3]);

          ZAux_Direct_GetVpSpeed( g_handle,0,&curspeed);

          Xpos1=Xpos1.sprintf("X:%.2f",showpos[0]);

          Ypos1=Ypos1.sprintf("Y:%.2f",showpos[1]);

          Zpos1=Zpos1.sprintf("Z:%.2f",showpos[2]);

          Upos1=Upos1.sprintf("U:%.2f",showpos[3]);

          Curspeed=Curspeed.sprintf("%.2f",curspeed);

          ui->Xpos->setText(Xpos1);

          ui->Ypos->setText(Ypos1);

          ui->Zpos->setText(Zpos1);

          ui->Upos->setText(Upos1);

          ui->Curspeed->setText(Curspeed);

      }

      //定时器2:获取并更新轴运动信息

      if(event->timerId() == id2)

      {

          int status=0, rembuff=0, curmark=0;

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

          ZAux_Direct_GetIfIdle(g_handle,0,&status);

          if (status == -1)

          {

              ui->motion_state->setText("停止中" );

          }

          else

          {

              ui->motion_state->setText("运动中" );

          }

          QString str="";

          //判断存放直线的剩余缓冲

          ZAux_Direct_GetRemain_LineBuffer(g_handle,0,&rembuff);

          str=str.sprintf("%d",rembuff);

          ui->rem_buff->setText(str);

          //判断当前运动到第几条运动,

          ZAux_Direct_GetMoveCurmark(g_handle,0,&curmark);

          str=str.sprintf("%d",curmark);

          ui->current_mark->setText(str);

      }

  }

  5.通过启动按钮的槽函数来设置拐角模式及拐角参数,设置插补运动参数,并启动定时器3来发送连续插补指令。

  //启动按钮槽函数

  void MainWindow::on_Onstart_clicked()

  {

          int corner_mode = 0;

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

          QString str;

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

          ZAux_Direct_Base(g_handle,4,axislist);

          str = ui->m_speed->text();

          m_speed = str.toFloat();

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

          str = ui->m_acc->text();

          m_acc = str.toFloat();

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

          str = ui->m_dec->text();

          m_dec = str.toFloat();

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

          //拐角模式设置

          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],1);

          //设置起始速度 ,拐角减速由 运动速度-起始速度 线性减速的

          str = ui->m_lspeed->text();

          m_lspeed = str.toFloat();

          ZAux_Direct_SetLspeed(g_handle,axislist[0],m_lspeed);

          //开始减速角度和结束减速角度,转换为弧度

          str = ui->m_startang->text();

          m_startang = str.toFloat();

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

          str = ui->m_stopang->text();

          m_stopang = str.toFloat();

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

          //设置小圆限速最小半径

          str = ui->m_fullradius->text();

          m_fullradius = str.toFloat();

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

          //设置拐角半径

          str = ui->m_zsmooth->text();

          m_zsmooth = str.toFloat();

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

          //设置MARK = 0 ,来通过读取CURMARK实现判断当前执行到那里

          ZAux_Direct_SetMovemark(g_handle,axislist[0],0);

          g_curseges = 0;

          //打开示波器

          ZAux_Trigger(g_handle);

          id3=startTimer(100);

  }

  6.通过定时器3发送连续插补指令

  //定时器3

  void MainWindow::timerEvent(QTimerEvent *event)

  {

      if(event->timerId() == id3)

      {

              int iresult = 0;

              int iremain = 2;

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

              {

                  if(g_curseges >= LEGS_MAX) //是否发送完所有指令

                  {

                      killTimer(id3);

                      return;

                  }

                  iresult = ZAux_Direct_GetRemain_LineBuffer(g_handle, 0, &iremain);

                  if(iremain > 2)

                  {

                      //加入一段,每段可以有自己的ForceSpeed

                      ZAux_Direct_SetForceSpeed(g_handle, 0, destdis[g_curseges][4]);

                      ZAux_Direct_MoveAbsSp(g_handle, 4, destdis[g_curseges]);

                      g_curseges++;

                  }

              }

          }

  }

  7.通过停止按钮的槽函数来停止轴运动,并停止定时器3

  //停止按钮插函数

  void MainWindow::on_stop_clicked()

      {

          if(NULL == g_handle)

          {

                  setWindowTitle("链接断开");

                  return ;

          }

          killTimer(id3);

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

  }

  8.通过清零按钮的槽函数来对各个轴的坐标进行清零

  //清零按钮槽函数

  void MainWindow::on_pushButton_5_clicked()

  {

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

      {

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

      }

  }

  9.最后编译运行查看效果

  A.修改运动距离数组“destdis[120][5]”的前面4段运动参数,打开自动倒角,通过ZDevelop软件的示波器查看效果。

  

  图片16.png

  

  图16 destdis数组

  

  图片17.png

  

  图17 例程运行截图

  

  图片18.png

  

  图18 自动倒角位置波形图

  B.修改运动距离数组“destdis[120][5]”的前面4段运动参数,通过示波器查看连续插补加合适的拐角减速的速度波形。

  

  图片19.png

  

  图19 destdis数组

  

  图片20.png

  

  图20 例程运行截图

  

  图片21.png

  

  图21 拐角减速的速度波形图

  本次,正运动技术运动控制卡应用开发教程之Linux就分享到这里,更多精彩内容请关注“正运动小助手”公众号。

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

  

  图片22.png

  

邮箱留言

Copyright © 2013 正运动技术有限公司 Design by Zmotion 版权所有   粤ICP备13037187号    Powered by www.zmotion.com.cn 运动控制器-运动控制卡

在线咨询