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

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

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

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

在这里插入图片描述

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#”和.NET Framework 4以及Windows 窗体应用程序。

5.jpg

3.找到厂家提供的光盘资料里面的C#函数库,路径如下(64位库为例):

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

6.jpg

2)选择函数库2.1。

7.jpg

3)Windows平台。

8.jpg

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

9.jpg

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

10.jpg

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

11.jpg

4.将厂商提供的C#的库文件以及相关文件复制到新建的项目里面。

1)将zmcaux.cs文件复制到新建的项目里面中。

12.jpg

2)将zaux.dll和zmotion.dll文件放入bin\debug文件夹中。

13.jpg

5.用vs打开新建的项目文件,在右边的解决方案资源管理器中点击显示所有,然后鼠标右键点击zmcaux.cs文件,点击包括在项目中。

14.jpg

15.jpg

6.双击Form1.cs里面的Form1,出现代码编辑界面,在文件开头写入 using cszmcaux,并声明控制器句柄g_handle。

16.jpg

至此项目新建完成。

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

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

17.jpg

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

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

18.jpg

19.jpg

项目应用截图

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

20.jpg

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

21.jpg

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

float[] destdis = { 100, 100, 200, 100 }; //运动距离列表

zmcaux.ZAux_Direct_MoveAbs(g_handle, 4, axislist, destdis);

6.通过获取到的控制器句柄handle,获取控制器缓冲区剩余的缓冲数量。

23.jpg

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

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

24.jpg

2.例程简易流程图。

25.jpg

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

//连接控制器

  private void button_link_Click(object sender, EventArgs e)

  {

          if (g_handle != (IntPtr)0)

          {

              zmcaux.ZAux_Close(g_handle);//断开连接

              g_handle = (IntPtr)0;

      }

      zmcaux.ZAux_OpenEth(comboBox_IpList.Text, out g_handle);//连接控制器

      if (g_handle != (IntPtr)0)

      {

          this.Text = "已连接";

          timer1.Enabled = true;

          //初始化轴参数

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

          {

              zmcaux.ZAux_Direct_SetAtype(g_handle, i, 1);//轴类型 脉冲轴

              zmcaux.ZAux_Direct_SetUnits(g_handle, i, 1);//脉冲当量

          }

      }

      else

      {

          MessageBox.Show("控制器链接失败,请检测IP地址!", "警告");

      }

  }

  

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

  

  //定时器刷新

  private void timer1_Tick(object sender, EventArgs e)

  {

      int runstate = 0;

      float[] curpos = new float[4];

      float vspeed = 0;

      int remin_buff = 0;

      int curmark = 0;

      //获取轴位置

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

      {

          zmcaux.ZAux_Direct_GetDpos(g_handle, i, ref curpos[i]);

      }

      //获取轴运动状态

      zmcaux.ZAux_Direct_GetIfIdle(g_handle, 0, ref runstate);

      //获取插补运动合速度

      zmcaux.ZAux_Direct_GetVpSpeed(g_handle, 0, ref vspeed);

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

      zmcaux.ZAux_Direct_GetRemain_LineBuffer(g_handle, 0, ref remin_buff);

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

      zmcaux.ZAux_Direct_GetMoveCurmark(g_handle, 0, ref curmark);


      label_pos.Text = "X:" + curpos[0] + " Y:" + curpos[1] + " Z:" + curpos[2] + " U:" + curpos[3];

      label_state.Text = Convert.ToString(runstate == 0 ? " 运行状态:运行中" : " 运行状态:停止中");

      label_vspeed.Text = "当前速度:" + vspeed;

      label_buff.Text = "剩余缓冲:" + remin_buff;

      label_mark.Text = "当前MARK:" + curmark;

  }

5.通过启动按钮的事件处理函数来启动插补运动

//启动按钮

  private void button_start_Click(object sender, EventArgs e)

  {

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

          float[] destdis = { 0, 0, 0, 0 }; //运动距离列表

          int corner_mode = 0; //拐角模式

          int merge_flag = 0; //连续插补

          int iresult = 0; //PC函数返回值

          int remin_buff = 0; //剩余直线缓冲数

          if (checkBox1.Checked)

          {

              corner_mode = corner_mode + 2;

          }

          if(checkBox2.Checked)

          {

              corner_mode = corner_mode + 8;

          }

          if(checkBox3.Checked)

  {

              corner_mode = corner_mode + 32;

          }

          if (checkBox4.Checked)

          {

              merge_flag = 1;

          }

          //设置插补速度

          zmcaux.ZAux_Direct_SetSpeed(g_handle, axislist[0], Convert.ToSingle(textBox_sp.Text));

          //设置插补加速度

          zmcaux.ZAux_Direct_SetAccel(g_handle, axislist[0], Convert.ToSingle(textBox_acc.Text));

          //设置插补减速度

          zmcaux.ZAux_Direct_SetDecel(g_handle, axislist[0], Convert.ToSingle(textBox_dec.Text));

          //设置连续插补

          zmcaux.ZAux_Direct_SetMerge(g_handle, axislist[0], merge_flag);

          //S曲线时间

          zmcaux.ZAux_Direct_SetSramp(g_handle, axislist[0], Convert.ToSingle(SRAMP.Text));

          //设置SP速度

          zmcaux.ZAux_Direct_SetForceSpeed(g_handle, axislist[0], Convert.ToSingle(textBox_for_sp.Text));

          //设置拐角模式

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

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

          zmcaux.ZAux_Direct_SetDecelAngle(g_handle, axislist[0], (float)(Convert.ToSingle(textBox_ang1.Text) * 3.14 / 180));

          //停止减速角度,转换为弧度

          zmcaux.ZAux_Direct_SetStopAngle(g_handle, axislist[0], (float)(Convert.ToSingle(textBox_ang2.Text) * 3.14 / 180));

          //小圆半径

          zmcaux.ZAux_Direct_SetFullSpRadius(g_handle, axislist[0], Convert.ToSingle(textBox_radio.Text));

          //倒角

          zmcaux.ZAux_Direct_SetZsmooth(g_handle, axislist[0], Convert.ToSingle(textBox_zsmooth.Text));

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

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

          //选择base轴

          zmcaux.ZAux_Direct_Base(g_handle, 4, axislist);

          zmcaux.ZAux_Trigger(g_handle);

          //计算剩余直线缓冲数量

          zmcaux.ZAux_Direct_GetRemain_LineBuffer(g_handle, 0, ref remin_buff);

          while(remin_buff<4)

          {

              zmcaux.ZAux_Direct_GetRemain_LineBuffer(g_handle, 0, ref remin_buff);

              System.Threading.Thread.Sleep(1); //1毫秒

          }

          //第一段插补运动

          destdis[0] = Convert.ToSingle(destdis1_X.Text);

          destdis[1] = Convert.ToSingle(destdis1_Y.Text);

          destdis[2] = Convert.ToSingle(destdis1_Z.Text);

          destdis[3] = Convert.ToSingle(destdis1_U.Text);

          iresult = zmcaux.ZAux_Direct_MoveAbs(g_handle, 4, axislist, destdis);//4轴插补指令

          //函数返回非0 则表示发送不成功,缓冲区可能满了,重新发送

          while (iresult != 0)

          {

              iresult = zmcaux.ZAux_Direct_MoveAbs(g_handle, 4, axislist, destdis);

              System.Threading.Thread.Sleep(1); //1毫秒

          }

          //第二段插补运动

          destdis[0] = Convert.ToSingle(destdis2_X.Text);

          destdis[1] = Convert.ToSingle(destdis2_Y.Text);

          destdis[2] = Convert.ToSingle(destdis2_Z.Text);

          destdis[3] = Convert.ToSingle(destdis2_U.Text);

          iresult = zmcaux.ZAux_Direct_MoveAbs(g_handle, 4, axislist, destdis);//4轴插补指令

          //函数返回非0 则表示发送不成功,缓冲区可能满了,重新发送

  while (iresult != 0)

          {

              iresult = zmcaux.ZAux_Direct_MoveAbs(g_handle, 4, axislist, destdis);

              System.Threading.Thread.Sleep(1); //1毫秒

          }

          //第三段插补运动

          destdis[0] = Convert.ToSingle(destdis3_X.Text);

          destdis[1] = Convert.ToSingle(destdis3_Y.Text);

          destdis[2] = Convert.ToSingle(destdis3_Z.Text);

          destdis[3] = Convert.ToSingle(destdis3_U.Text);

          iresult = zmcaux.ZAux_Direct_MoveAbs(g_handle, 4, axislist, destdis);//4轴插补指令

          //函数返回非0 则表示发送不成功,缓冲区可能满了,重新发送

          while (iresult != 0)

          {

              iresult = zmcaux.ZAux_Direct_MoveAbs(g_handle, 4, axislist, destdis);

              System.Threading.Thread.Sleep(1); //1毫秒

          }

          //第四段插补运动

          destdis[0] = Convert.ToSingle(destdis4_X.Text);

          destdis[1] = Convert.ToSingle(destdis4_Y.Text);

          destdis[2] = Convert.ToSingle(destdis4_Z.Text);

          destdis[3] = Convert.ToSingle(destdis4_U.Text);

          iresult = zmcaux.ZAux_Direct_MoveAbs(g_handle, 4, axislist, destdis);//4轴插补指令

          //函数返回非0 则表示发送不成功,缓冲区可能满了,重新发送

          while (iresult != 0)

          {

              iresult = zmcaux.ZAux_Direct_MoveAbs(g_handle, 4, axislist, destdis);

              System.Threading.Thread.Sleep(1); //1毫秒

          }

      }

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

//停止运动

  private void button_stop_Click(object sender, EventArgs e)

  {

          //取消主轴运动

          zmcaux.ZAux_Direct_Single_Cancel(g_handle, 0, 2);

  }

7.轴坐标清零。

//坐标清零

  private void button_zero_Click(object sender, EventArgs e)

  {

          if (g_handle == (IntPtr)0)

          {

              MessageBox.Show("未链接到控制器!", "提示");

          }

          else

          {

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

          {

          zmcaux.ZAux_Direct_SetDpos(g_handle, i, 0);

          }

      }

  }

8. 编译运行演示。

编译运行示教例程,同时通过ZDevelop软件连接控制器,对运动控制的轴参数进行监控。

9.连续插补加自动倒角的位置波形。

26.jpg

10.不开启连续插补的速度波形。

27.jpg

28.jpg

29.jpg

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

30.jpg

31.jpg

正运动技术《运动控制卡应用开发教程之C#》就讲到这里。更多学习视频及图文,请关注我们的公众号“正运动小助手”。
  
  更多精彩内容请关注“正运动小助手”公众号,需要相关开发环境与例程代码,请咨询正运动技术销售工程师:400-089-8936。

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

在这里插入图片描述

  • 9
    点赞
  • 85
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
固高运动控制卡提供了基于C#的开发接口,您可以使用Visual Studio等开发工具进行开发。首先,您需要安装固高运动控制卡的开发包和控制卡驱动程序,然后在Visual Studio中创建一个C#项目,并将固高运动控制卡的开发包引用到项目中。 接下来,您可以使用固高运动控制卡提供的C#类库来编写控制程序,包括连接控制卡、设置控制卡参数、控制运动等。 以下是一个简单的示例代码,演示了如何连接控制卡并控制一个步进电机运动: ```csharp using GTS; using GTS.LoadConfig; using GTS.Command; using GTS.Clock; using System.Threading; namespace MotionControl { class Program { static void Main(string[] args) { // 初始化运动控制卡 GTSMC.InitMotionCard(); // 连接控制卡 int cardId = 0; int ret = GTSMC.Open(cardId); if(ret != 0) { // 连接失败 return; } // 设置步进电机参数 int axis = 0; // 轴号 int pulsePerRev = 200; // 每转脉冲数 int gearRatio = 1; // 减速比 GTSMC.SetMotorParam(axis, pulsePerRev, gearRatio); // 使能轴 GTSMC.AxisOn(axis); // 设置运动速度 int speed = 10000; // 10mm/s GTSMC.SetVel(axis, speed); // 启动连续运动 GTSMC.ContinuousMove(axis, 1); // 等待一段时间后停止运动 Thread.Sleep(5000); GTSMC.Stop(axis, StopType.Immediately); // 关闭轴 GTSMC.AxisOff(axis); // 断开连接 GTSMC.Close(); } } } ``` 当然,这只是一个简单的示例,实际的控制程序会更加复杂,需要根据具体的应用场景进行开发。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

正运动技术

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值