首页 新闻 工控搜 论坛 厂商论坛 产品 方案 厂商 人才 文摘 下载 展览
中华工控网首页
  P L C | 变频器与传动 | 传感器 | 现场检测仪表 | 工控软件 | 人机界面 | 运动控制
  D C S | 工业以太网 | 现场总线 | 显示调节仪表 | 数据采集 | 数传测控 | 工业安全
  电 源 | 嵌入式系统 | PC based | 机柜箱体壳体 | 低压电器 | 机器视觉
C#运动控制开源(三): CAD导图和小线段速度前瞻优化的软件框架
深圳市正运动技术有限公司
收藏本文     查看收藏

01 ZMC432-V2运动控制器介绍

ZMC432-V2高性能多轴运动控制器是一款兼容EtherCAT总线和脉冲型的独立式运动控制器,自带6轴本地差分脉冲轴,最多可扩展至32轴,能实现总线轴+脉冲轴混合插补的多轴运动控制场合。同时支持正运动远程显示功能,能提供网络组态显示,可实时监控和调整参数配置。

正运动ZMC432-V2高性能多轴运动控制器.png

ZMC432-V2硬件功能特性:

(1)支持32轴运动控制(脉冲+EtherCAT总线),EtherCAT最小通讯周期可达125us。

(2)24路通用输入、12路通用输出,2路模拟量输出(DA),其中包括2路高速输入和2路高速输出。

(3)6路差分脉冲轴输出,总线轴、脉冲轴可混合插补。

(4)内置多项实时性运动控制功能,例如视觉飞拍、多维PSO、高速位置锁存,多轴同步运行等。

(5)可通过EtherCAT扩展模块进行IO硬件资源扩展,可扩展至4096个隔离输入口和4096个隔离输出口。

(6)具备丰富的运动控制功能,如点位运动、电子凸轮、直线插补、圆弧插补、连续轨迹加工。

(7)支持掉电检测、掉电存储,多种程序加密方式,能够有效防止系统故障,保护项目工程文件数据,并提高系统的可靠性。

(8)通过纯国产IDE开发环境RTSys进行项目开发,可实时仿真、在线跟踪以及诊断与调试,简便易用,支持多种高级上位机语言联合编程进行二次开发。

正运动ZMC432-V2高性能多轴运动控制器架构图.webp

02 内容回顾

回顾上两期推文,我们对CAD导图和小线段速度前瞻的C#DEMO中的主要两个功能:CAD导图和运动前瞻设置做了详细的介绍。这次我们回归推文本身,对DEMO软件框架进行介绍。

往期内容详情点击下方链接:

C#运动控制开源(一):CAD导图和小线段速度前瞻的优化之CAD导图

C#运动控制开源(二): CAD导图和小线段速度前瞻优化

03 开发环境

?适用场景:需要CAD导图给XY机台做轨迹运动的场合都可以使用本DEMO测试。

?软件平台:使用Visual Studio C#(即Visual C#)开发。‌

04 DEMO界面和操作步骤介绍

一、软件框架流程图

软件框架流程图.webp

二、主界面

打开软件后首先显示的是主界面,主要分为3个部分:

①工具栏提供控制器连接复位,CAD图纸导入及编辑,参数界面跳转等按钮。

②中间部分用于显示导入CAD文件后轨迹的显示。

③右侧操作界面则是用来操作各轴移动以及启动加工,切换到BASIC或者G代码标签则会显示轨迹对应的相关代码。

1.webp

2.webp

三、工具栏

①连接控制器:点击控制器→连接控制器弹出控制器连接界面,手动输入控制器IP或者下拉框搜索,点击连接即可连接对应IP控制器,连接成功软件标题会显示连接成功。

3.webp

4.webp

②导入CAD图纸:点击文件→打开弹出文件选择界面,选择对应格式的CAD文件,成功导入后会将轨迹显示出来。

5.webp

6.webp

7.webp

③轨迹操作和优化:CAD图纸轨迹显示后,可以进行一些编辑操作。通过左键选取操作对应的轨迹,右键进行画面移动。对应编辑视图中进行轨迹优化以及排序。对应视图中进行显示元素的选择。

8.webp

9.webp

10.webp

四、参数设置

①打开参数界面:点击视图→参数设置可以打开参数设置界面。

11.webp

12.webp

②设置轴参数和测试:可以在此页面设置XYZU轴各轴参数,以及进行简单的手动运动测试,确保轴运动没有问题。

③前瞻参数设置:点击前瞻参数标签页,可以进行前瞻参数的设置。

13.webp

④加工参数设置:点击加工参数标签页,可以进行加工参数的设置。

14.webp

⑤保存参数设置:点击参数保存按钮,会将所有的设置保存到对应exe所在目录的para文件夹下,下次打开软件会自动读取参数并设置上去。

15.webp

五、加工操作面板

①开启加工:设置完参数后,可以在操作面板点击启动开始加工,同时记录加工时间和目前状态。对应各轴坐标和速度也会显示出来,轨迹显示视图中也会把当前末端加工位置显示出来,方便观察目前位置。如果加工中需要暂停和停止,点击对应按钮即可。

16.webp

②显示生成代码:点击BASIC或者G代码标签可以显示当前轨迹对应的运行代码,可以用来排查问题,或者复制到其它软件中直接运行。

17.webp

18.webp

05

DEMO程序介绍

DEMO中把主要用到的重要程序分别放在了:

ZCadFn.cs,ZGCode.cs,ZmotionCard.cs

依次对应CAD导图,轨迹解析,运动控制三部分,方便大家使用学习。

ZCadFn.cs(CAD导图解析与绘制)

19.webp

该部分主要提供CAD导图初始化与导入CAD图纸获取轨迹数据,然后进行图形绘制的函数。

form1.cs中按照:初始化CAD→导入CAD文件→获得轨迹数组→绘制轨迹的顺序进行调用。比如下方程序:

//导入CAD文件
if (!m_GloFn.m_ZCad.ZcadReadFile(strFilePath))
{
    MessageBox.Show("导入文件失败");
    return;
}
//计算比例
if (!m_GloFn.m_ZCad.ZcadPicBoxMath(CadShow.Width, CadShow.Height))
{
    MessageBox.Show("导入文件失败");
    return;
}
//获取轨迹数组
if (!m_GloFn.m_ZCad.ZcadArrayGet())
{
    MessageBox.Show("获取轨迹失败");
    return;
}
//绘制一遍CAD
if (!m_GloFn.m_ZCad.ZcadShowPic(CadShow.Width, CadShow.Height, 坐标系ToolStripMenuItem.Checked, 顺序ToolStripMenuItem.Checked, 空移ToolStripMenuItem.Checked, 起点ToolStripMenuItem.Checked, 方向ToolStripMenuItem.Checked,XCurDpos,YCurDpos, UCurDpos))
{
    MessageBox.Show("绘制失败");
    return;
}

ZGCode.cs.cs(数据转化为G代码或者BASIC代码)

该部分主要提供将轨迹数据转化成G代码或者BASIC代码格式的函数。

20.webp

主界面上的代码显示就是通过该部分转话后显示到textbox控件中。

if (m_GloFn.m_ZmotionCard.m_bInited && m_GloFn.m_ZCad.m_bInited)
{
    string basicCode = "";
    string gcode = "";
    ZGCode.CadArraytoCode(m_GloFn.m_ZCad.m_ZCad_ArrayInfo, ref basicCode, ref gcode, 仅处理选中图形toolStripMenuItem.Checked,true, CadShow.Width, CadShow.Height);
    txt_Basic.Text = basicCode;
    txt_GCode.Text = gcode;
}

ZmotionCard.cs(运动控制测试和前瞻下发)

该部分主要提供一些封装好的轴运动控制函数,以及以三次文件形式或者批量函数形式下发轨迹。

21.webp

单轴控制界面时就是通过按钮调用对应的轴控制函数来实现JOG,定位,回原等测试功能。

22.webp

按钮调用代码如下:

?回原:

private void btn_X_SingleHome_Click(object sender, EventArgs e)
{
    SetAxisParaByCtr(); //先控件参数设置到实际轴参数
    m_GloFn.m_ZmotionCard.AxisParaSet();    //读取参数出来之后设置一遍到轴参数上
    int axisnum = m_GloFn.m_ZmotionCard.m_nAxis_X;
    int datumtype = m_GloFn.m_ZmotionCard.m_nAxis_X_DatumType;
    float homespeed = (float)m_GloFn.m_ZmotionCard.m_dAxis_X_DatumSpeed;
    float creep = (float)m_GloFn.m_ZmotionCard.m_dAxis_X_Creep;
    bool ifbushome = m_GloFn.m_ZmotionCard.m_bAxis_X_BusDatum;
    float homeoffset = (float)m_GloFn.m_ZmotionCard.m_dAxis_X_DatumOffset;
    m_GloFn.m_ZmotionCard.AxisHome(axisnum,datumtype,homespeed,creep,ifbushome,homeoffset);
}

?定位:

private void btn_X_Move_Click(object sender, EventArgs e)
{
    SetAxisParaByCtr(); //先控件参数设置到实际轴参数
    m_GloFn.m_ZmotionCard.AxisParaSet();    //读取参数出来之后设置一遍到轴参数上
    int axisnum = m_GloFn.m_ZmotionCard.m_nAxis_X;
    float movesp = 0;
    if (radio_X_LowSp.Checked) movesp = (float)m_GloFn.m_ZmotionCard.m_dAxis_X_LowSpeed;
    if (radio_X_NomalSp.Checked) movesp = (float)m_GloFn.m_ZmotionCard.m_dAxis_X_NormalSpeed;
    if (radio_X_HighSp.Checked) movesp = (float)m_GloFn.m_ZmotionCard.m_dAxis_X_HighSpeed;
    float movedis = Convert.ToSingle(tb_X_MoveDis.Text);
    bool ifabsmove = cb_X_IfAbs.Checked;
    if(ifabsmove) m_GloFn.m_ZmotionCard.AxisMoveAbs(axisnum,movesp,movedis);
    else m_GloFn.m_ZmotionCard.AxisMove(axisnum, movesp, movedis);
}

?点动:

private void btn_X_RVmove_MouseDown(object sender, MouseEventArgs e)
{
    SetAxisParaByCtr(); //先控件参数设置到实际轴参数
    m_GloFn.m_ZmotionCard.AxisParaSet();    //读取参数出来之后设置一遍到轴参数上
    int axisnum = m_GloFn.m_ZmotionCard.m_nAxis_X;    float movesp = 0;
    if (radio_X_LowSp.Checked) movesp = (float)m_GloFn.m_ZmotionCard.m_dAxis_X_LowSpeed;
    if (radio_X_NomalSp.Checked) movesp = (float)m_GloFn.m_ZmotionCard.m_dAxis_X_NormalSpeed;
    if (radio_X_HighSp.Checked) movesp = (float)m_GloFn.m_ZmotionCard.m_dAxis_X_HighSpeed;
    m_GloFn.m_ZmotionCard.AxisVmove(axisnum, false, movesp);
}
private void btn_X_RVmove_MouseUp(object sender, MouseEventArgs e)
{
    int axisnum = m_GloFn.m_ZmotionCard.m_nAxis_X;
    m_GloFn.m_ZmotionCard.AxisCancel(axisnum);
}

前瞻功能则是调用控制器前瞻初始化函数设置参数到控制器中,或者使用平滑函数前瞻将轨迹数据处理成平滑好的数据。

?控制器前瞻设置:

#region
控制器前瞻参数初始化
public bool RunParaIni()
{
    //判断控制卡是否初始化成功
    if (!m_bInited)
        return false;  //-1代表初始化未成功
    int iret = 0;
    //控制器前瞻参数设置到主轴上
    iret += zmcaux.ZAux_Direct_SetCornerMode(g_handle, m_nAxis_X, m_nCornerMode); CommandHandler("ZAux_Direct_SetCornerMode", iret);   //Corner_Mode
    iret += zmcaux.ZAux_Direct_SetMerge(g_handle, m_nAxis_X, 1); CommandHandler("ZAux_Direct_SetMerge", iret);       //打开连续插补
    iret += zmcaux.ZAux_Direct_SetFullSpRadius(g_handle, m_nAxis_X, m_fLimitR); CommandHandler("ZAux_Direct_SetFullSpRadius", iret);    //设置小圆限速半径
    StringBuilder cmdbuffack = new StringBuilder(2048);
    iret += zmcaux.ZAux_Execute(g_handle, "SPLIMIT_RADIUS(" + m_nAxis_X.ToString() + ") = " + m_fLimitRMinSp.ToString(), cmdbuffack, 2048);  CommandHandler("ZAux_Execute", iret);//小圆限速最小限速
    iret += zmcaux.ZAux_Direct_SetZsmooth(g_handle, m_nAxis_X, m_fZsmooth); CommandHandler("ZAux_Direct_SetZsmooth", iret); //倒角半径
    iret += zmcaux.ZAux_Direct_SetDecelAngle(g_handle, m_nAxis_X, (float)((m_fDecelAngle / 180) * Math.PI)); CommandHandler("ZAux_Direct_SetDecelAngle", iret);      //减速角
    iret += zmcaux.ZAux_Direct_SetStopAngle(g_handle, m_nAxis_X, (float)((m_fStopAngle / 180) * Math.PI)); CommandHandler("ZAux_Direct_SetStopAngle", iret);    //停止角
    iret += zmcaux.ZAux_Direct_SetStartMoveSpeed(g_handle, m_nAxis_X, m_fXYSpeed); CommandHandler("ZAux_Direct_SetStartMoveSpeed", iret);     //起始速度设置成加工速度
    iret += zmcaux.ZAux_Direct_SetEndMoveSpeed(g_handle, m_nAxis_X, m_fXYSpeed); CommandHandler("ZAux_Direct_SetEndMoveSpeed", iret);    //结束速度设置成加工速度
    if (iret != 0) return false;
    return true;
}
#endregion

?平滑前瞻函数处理:

#region
ZTrackSmooth函数平滑下发
public int SmoothByZTrackDown(double[] originalPos,ref float StartRDpos)
 //public int SmoothByZTrackDown(ref float StartRDpos)
{
    //判断控制卡是否初始化成功
    if (!m_bInited)
        return -1;  //-1代表初始化未成功
    int iret = 0;
    UInt32 pSmoothPointsNum = 0;
    IntPtr pSmoothPoints = (IntPtr)0;
    IntPtr parryLine = (IntPtr)0;
    IntPtr parryForceSp = (IntPtr)0;
    IntPtr parryLmtSp = (IntPtr)0;
    IntPtr parryR = (IntPtr)0;
    ZTrackSmooth.ZTS_Delete(pSmoothPoints);
    ZTrackSmooth.ZTS_Delete(parryLine);
    ZTrackSmooth.ZTS_Delete(parryForceSp);
    ZTrackSmooth.ZTS_Delete(parryLmtSp);
    ZTrackSmooth.ZTS_Delete(parryR);
    //提出平滑后的轨迹
    double[] SmoothPos = { };
    double[] SmoothSpeed = { };
    double[] SmoothLimSp = { };
    double[] SmoothR = { };
    if (m_dDiserr 0)      //有设置非线性小圆限速
            iret = ZTrackSmooth.ZTS_ContinueSmoothAndSpeed2(g_handle, originalPos, Convert.ToUInt16(originalPos.Length / 2), 2, m_dDiserr, m_dSplineDis, m_dCornerAccel, m_fXYSpeed, m_dLimitRArray, m_dLimitRSpArray, (uint)m_dLimitRArray.Length, out pSmoothPoints, out parryLine, out parryForceSp, out parryLmtSp, out parryR, ref pSmoothPointsNum);
        else
            iret = ZTrackSmooth.ZTS_ContinueSmoothAndSpeed2(g_handle, originalPos, Convert.ToUInt16(originalPos.Length / 2), 2, m_dDiserr, m_dSplineDis, m_dCornerAccel, m_fXYSpeed, new double[] { 0.1, m_fLimitR }, new double[] { m_fXYSpeed, m_fXYSpeed }, 2, out pSmoothPoints, out parryLine, out parryForceSp, out parryLmtSp, out parryR, ref pSmoothPointsNum);
        //提出平滑后的轨迹
        SmoothPos = new double[pSmoothPointsNum * 2];
        SmoothSpeed = new double[pSmoothPointsNum];
        SmoothLimSp = new double[pSmoothPointsNum];
        SmoothR = new double[pSmoothPointsNum];
        Marshal.Copy(pSmoothPoints, SmoothPos, 0, (int)(pSmoothPointsNum * 2));
        Marshal.Copy(parryForceSp, SmoothSpeed, 0, (int)(pSmoothPointsNum));
        Marshal.Copy(parryLmtSp, SmoothLimSp, 0, (int)(pSmoothPointsNum));
        Marshal.Copy(parryR, SmoothR, 0, (int)(pSmoothPointsNum));
    }
    StringBuilder cmdbuffack = new StringBuilder(2048);
    double rdpos = StartRDpos;
    //下发平滑轨迹
    for (uint i = 0; i < pSmoothPointsNum; i++)
    {
        float[] targetpos = new float[2];
        targetpos[0] = (float)SmoothPos[i * 2 + 0];
        targetpos[1] = (float)SmoothPos[i * 2 + 1];
        float runspeed = m_fXYSpeed;
        float limitspeed = m_fXYSpeed;
        if (m_dDiserr >= 0)
        {
            runspeed = (float)SmoothSpeed[i];
            limitspeed = (float)SmoothLimSp[i];
        }
        //计算该点需要转的角度值
        if (i < pSmoothPointsNum - 2 && i >= 0)
        {
            double moveangle = CalculateAngleWithX((float)SmoothPos[(i) * 2 + 0], (float)SmoothPos[(i) * 2 + 1], (float)SmoothPos[(i + 1) * 2 + 0], (float)SmoothPos[(i + 1) * 2 + 1]);
            rdpos = MoveR(moveangle, StartRDpos);
        }
        StartRDpos = (float)rdpos;
        if (m_b3FileDown) Z3pFile_LineString(targetpos[0], targetpos[1], rdpos, runspeed, limitspeed, i);
        else Command_LineString(targetpos[0], targetpos[1], rdpos, runspeed, limitspeed, i);
    } 
   ZTrackSmooth.ZTS_Delete(pSmoothPoints);
    ZTrackSmooth.ZTS_Delete(parryLine); 
   ZTrackSmooth.ZTS_Delete(parryForceSp);
    ZTrackSmooth.ZTS_Delete(parryLmtSp);
    ZTrackSmooth.ZTS_Delete(parryR);
    return iret;
}
#endregion

前瞻处理好后按照一定格式用三次文件或者批量函数下发到控制器中运行,流程可以直接参考自动线程的程序处理。

#region线程
public void Thread_Run()
{
    WorkStart = DateTime.Now;
    RunStatus = "自动运行中";
    m_GloFn.m_ZmotionCard.AxisParaSet();
    //读取参数出来之后设置一遍到轴参数上
    if (!m_GloFn.m_ZmotionCard.RunParaIni())
    {
        MessageBox.Show("前瞻参数设置失败");
        return;
    }
    //获取轨迹数组
    if (!m_GloFn.m_ZCad.ZcadArrayGet())
    {
        MessageBox.Show("获取轨迹失败");
        return;
    }
    //如果皮带跟随
    if (m_GloFn.m_ZmotionCard.m_bSync)
     //开启皮带跟随
    {
        if (m_GloFn.m_ZmotionCard.AxisBeltSync() != 0)
        {
            MessageBox.Show("皮带跟随失败");
            return; 
       }
    }
    //取消U轴插补速度计算
    int iret = 0;
    iret = zmcaux.ZAux_Direct_SetInterpFactor(m_GloFn.m_ZmotionCard.g_handle, m_GloFn.m_ZmotionCard.m_nAxis_VU, 0); m_GloFn.m_ZmotionCard.CommandHandler("ZAux_Direct_SetInterpFactor", iret);
    //记录U轴坐标    float RDpos = 0;
    iret = zmcaux.ZAux_Direct_GetDpos(m_GloFn.m_ZmotionCard.g_handle, m_GloFn.m_ZmotionCard.m_nAxis_U,ref RDpos); m_GloFn.m_ZmotionCard.CommandHandler("ZAux_Direct_GetDpos", iret);
    //解析轨迹下发
    if (m_GloFn.m_ZmotionCard.m_b3FileDown) m_GloFn.m_ZmotionCard.Z3pFile_Init(); //三次文件初始化
    else m_GloFn.m_ZmotionCard.CommandIni();
    List OriginalPos = new List();    double Pos_x1, Pos_x2, Pos_z1, Pos_y1, Pos_y2, Pos_z2;
    double Pos_x1_2, Pos_x2_2, Pos_z1_2, Pos_y1_2, Pos_y2_2, Pos_z2_2;
    bool ifsplit = false;
    bool ifdownZ = false;
    for (int i = 0; i < m_GloFn.m_ZCad.m_nZCad_ArrayLen; i++)                //遍历数组
    {
        Pos_x1 = m_GloFn.m_ZCad.m_ZCad_ArrayInfo[i].x1;
        Pos_x2 = m_GloFn.m_ZCad.m_ZCad_ArrayInfo[i].x2;
        Pos_z1 = m_GloFn.m_ZCad.m_ZCad_ArrayInfo[i].z1;
        Pos_y1 = m_GloFn.m_ZCad.m_ZCad_ArrayInfo[i].y1;
        Pos_y2 = m_GloFn.m_ZCad.m_ZCad_ArrayInfo[i].y2;
        Pos_z2 = m_GloFn.m_ZCad.m_ZCad_ArrayInfo[i].z2;
        ifsplit = false;
        if ((仅处理选中图形toolStripMenuItem.Checked == true) && (m_GloFn.m_ZCad.m_ZCad_ArrayInfo[i].m_nChoose == 0)) continue;
        switch (m_GloFn.m_ZCad.m_ZCad_ArrayInfo[i].m_nItemtype)
        {
            case ZmotionCad.ZCAD_ITEMTYPE_VECTLine:    //线型
                if ((m_GloFn.m_ZCad.m_ZCad_ArrayInfo[i].m_nInVectFrist == 1) || (ifdownZ))              //是否轨迹起点起始
                {
                    ifdownZ = false;
                    double StartAngle = m_GloFn.m_ZmotionCard.CalculateAngleWithX(Pos_x1, Pos_y1, Pos_x2, Pos_y2);
                    //下发空移落刀指令
                    if (m_GloFn.m_ZmotionCard.m_b3FileDown) m_GloFn.m_ZmotionCard.Z3pFile_StartString(Pos_x1, Pos_y1, StartAngle, ref RDpos);
                    else m_GloFn.m_ZmotionCard.Command_StartString(Pos_x1, Pos_y1, StartAngle, ref RDpos);
                    OriginalPos.Clear();
                    //把起点存下来
                    OriginalPos.Add(Pos_x1);
                    OriginalPos.Add(Pos_y1);
                }
                OriginalPos.Add(Pos_x2); //记录过程点
                OriginalPos.Add(Pos_y2);
                if (i + 1 < m_GloFn.m_ZCad.m_nZCad_ArrayLen)
                {
                    Pos_x1_2 = m_GloFn.m_ZCad.m_ZCad_ArrayInfo[i + 1].x1;
                    Pos_x2_2 = m_GloFn.m_ZCad.m_ZCad_ArrayInfo[i + 1].x2;
                    Pos_z1_2 = m_GloFn.m_ZCad.m_ZCad_ArrayInfo[i + 1].z1;
                    Pos_y1_2 = m_GloFn.m_ZCad.m_ZCad_ArrayInfo[i + 1].y1;
                    Pos_y2_2 = m_GloFn.m_ZCad.m_ZCad_ArrayInfo[i + 1].y2;
                    Pos_z2_2 = m_GloFn.m_ZCad.m_ZCad_ArrayInfo[i + 1].z2;
                    //大于停止角就抬刀
                    if (Math.Abs(m_GloFn.m_ZmotionCard.CalculateAngle(Pos_x1, Pos_y1, Pos_x2, Pos_y2, Pos_x1_2, Pos_y1_2, Pos_x2_2, Pos_y2_2)) > m_GloFn.m_ZmotionCard.m_fStopAngle) ifsplit = true;
                    //判断下个点是否空移点
                    if ((m_GloFn.m_ZCad.m_ZCad_ArrayInfo[i + 1].m_nInVectFrist == 1) || (ifsplit))             //下条运动为空移点,需要抬刀
                    {
                        if (ifsplit == false)
                        {
                            OriginalPos.Add(Pos_x2); //记录过程点
                            OriginalPos.Add(Pos_y2);
                        }
                        //下发加工轨迹
                        m_GloFn.m_ZmotionCard.SmoothByZTrackDown(OriginalPos.ToArray(), ref RDpos);
                        //m_GloFn.m_ZmotionCard.SmoothByZTrackDown( ref RDpos);
                        //下发抬刀动作
                        if (m_GloFn.m_ZmotionCard.m_b3FileDown) m_GloFn.m_ZmotionCard.Z3pFile_EndString(Pos_x2, Pos_y2);
                        else m_GloFn.m_ZmotionCard.Command_EndString(Pos_x2, Pos_y2);
                        if (ifsplit)
                        {
                            ifdownZ = true;
                            ifsplit = false;
                        }
                    }
                }
                if (i == m_GloFn.m_ZCad.m_nZCad_ArrayLen - 1)
                {
                    //下发加工轨迹
                    m_GloFn.m_ZmotionCard.SmoothByZTrackDown(OriginalPos.ToArray(), ref RDpos);
                    //m_GloFn.m_ZmotionCard.SmoothByZTrackDown(ref RDpos); 
                   //下发抬刀动作
                    if (m_GloFn.m_ZmotionCard.m_b3FileDown) m_GloFn.m_ZmotionCard.Z3pFile_EndString(Pos_x2, Pos_y2);
                    else m_GloFn.m_ZmotionCard.Command_EndString(Pos_x2, Pos_y2);
                    if (ifsplit)
                    {
                        ifdownZ = true;
                        ifsplit = false;
                    }
                }
                break;
            default:
                break;
        }
    }
    if (m_GloFn.m_ZmotionCard.m_b3FileDown) m_GloFn.m_ZmotionCard.Z3pFile_End(); //三次文件结束
    //等待3次文件结束
    while (true)
    {
        int runstatus = 0;
        StringBuilder cmdbuffack = new StringBuilder(2048);
        iret = zmcaux.ZAux_DirectCommand(m_GloFn.m_ZmotionCard.g_handle,$"?PROC_STATUS({m_GloFn.m_ZmotionCard.Z3P_FILE_TASK})", cmdbuffack,2048); m_GloFn.m_ZmotionCard.CommandHandler("ZAux_DirectCommand", iret);
        runstatus = Convert.ToInt16(cmdbuffack.ToString());
        if (runstatus == 0) break;
    }
    //等待运动结束
    while (true)
    {
        int idle = 0;
        iret = zmcaux.ZAux_Direct_GetIfIdle(m_GloFn.m_ZmotionCard.g_handle, m_GloFn.m_ZmotionCard.m_nAxis_X, ref idle); m_GloFn.m_ZmotionCard.CommandHandler("ZAux_Direct_GetIfIdle", iret);
        if (idle != 0) break;
    }
    //如果皮带跟随
    if (m_GloFn.m_ZmotionCard.m_bSync)   //取消皮带跟随绑定
    {
        m_GloFn.m_ZmotionCard.beltsyncend();
    }
    //恢复U轴插补速度计算
    iret = zmcaux.ZAux_Direct_SetInterpFactor(m_GloFn.m_ZmotionCard.g_handle, m_GloFn.m_ZmotionCard.m_nAxis_VU, 1); m_GloFn.m_ZmotionCard.CommandHandler("ZAux_Direct_SetInterpFactor", iret);
    RunStatus = "待机";
}

教学视频请点击→C#运动控制开源(三): CAD导图和小线段速度前瞻优化的软件框架

完整代码获取地址

正运动技术C#运动控制开源(三)例程二维码.jpg

本次,正运动技术C#运动控制开源(三): CAD导图和小线段速度前瞻优化的软件框架,就分享到这里。

更多精彩内容请关注“正运动小助手”公众号,需要相关开发环境与例程代码,请咨询正运动技术销售工程师:400-089-8936。

二维码.webp

正运动技术专注于运动控制技术研究和通用运动控制软硬件产品的研发,是国家级高新技术企业。正运动技术汇集了来自华为、中兴等公司的优秀人才,在坚持自主创新的同时,积极联合各大高校协同运动控制基础技术的研究。主要业务有:运动控制卡_运动控制器_EtherCAT运动控制卡_EtherCAT控制器_运动控制系统_视觉控制器__运动控制PLC_运动控制_机器人控制器_视觉定位_XPCIe/XPCI系列运动控制卡等等。


 

状 态: 离线

公司简介
产品目录

公司名称: 深圳市正运动技术有限公司
联 系 人: 戴德弟
电  话: 0755-32976042
传  真: 0755-2606 6955
地  址: 深圳市宝安区西乡洲石路阳光工业园A1栋5楼
邮  编: 518100
主  页:
 
该厂商相关技术文摘:
正运动在AOI光学检测设备上的运动控制解决方案
正运动通用机械手柔性供料解决方案
正运动磁驱多动子柔性产线解决方案API接口(二):组态配置
开放式激光振镜运动控制器在圆柱电池飞行焊接的应用
全闭环EtherCAT运动控制器运动到位判断方式详解
正运动在线式自动上下料视觉点胶解决方案
手持HMI的简易CAD图形导图与加工
全国产自主可控运动控制器邀您相约2026北京国防展
深圳工博会:深耕自主技术,正运动技术助力智能制造
强实时运动控制卡XPCIE1032H在FPC补强机上的应用解决方案
正运动磁驱多动子柔性产线解决方案API接口(一):ZTS环境的创建和函数库的使用
更多文摘...
立即发送询问信息在线联系该技术文摘厂商:
用户名: 密码: 免费注册为中华工控网会员
请留下您的有效联系方式,以方便我们及时与您联络

关于我们 | 联系我们 | 广告服务 | 本站动态 | 友情链接 | 法律声明 | 不良信息举报
工控网客服热线:0755-86369299
版权所有 中华工控网 Copyright©2022 Gkong.com, All Rights Reserved