运动控制卡初学(二)

运动控制卡初学(二)

一、引言:

插补(Interpolation),即机床数控系统依照一定方法确定刀具运动轨迹的过程。也可以说,已知曲线上的某些数据,按照某种算法计算已知点之间的中间点的方法,也称为“数据点的密化”;数控装置根据输入的零件程序的信息,将程序段所描述的曲线的起点、终点之间的空间进行数据密化,从而形成要求的轮廓轨迹,这种“数据密化”机能就称为“插补”。

插补(Interpolation)在数控机床中,刀具不能严格地按照要求加工的曲线运动,只能用折线轨迹逼近所要加工的曲线。

运动控制卡涉及到到的插补主要分为两种:直线插补和圆弧插补。

直线插补:为了生成一条直线轨迹的算法。具体信息,可以参考一个B站视频,里面讲解的非常清楚,我自己了解的不是十分的透彻就不瞎说了。

[直线插补算法讲解](https://www.bilibili.com/video/BV1P5411Y7oa/?vd_source=e8855b8e314cdd528d36827fb0e1dd8b)

圆弧插补:为了生成一条带有弧度曲线痕迹的算法。具体信息也请参考如下链接

二、直线插补

这里我们着重讲解下多轴绝对直线插补

第一步:先看官方的例程和手册(模仿写不容易踩坑)

  1. 先看例程,发现有写好的直线插补。那么我们观察代码的逻辑信息

image-20230309171619931

点击启动后查看代码如下:

        private void Button_start_Click(object sender, EventArgs e)
        {
            if (g_handle == (IntPtr)0)
            {
                MessageBox.Show("未链接到控制器!", "提示");
            }
            else
            {
                int[] axislist  = {0,1,2,3};
                float[] poslist = { Convert.ToSingle(destpos1.Text), Convert.ToSingle(destpos2.Text), Convert.ToSingle(destpos3.Text), Convert.ToSingle(destpos4.Text)};
                float[] midlist = { Convert.ToSingle(midpos1.Text), Convert.ToSingle(midpos2.Text), Convert.ToSingle(midpos3.Text), Convert.ToSingle(midpos4.Text) };
                float[] endmove = { 0,0,0,0 };              //相当绝对转换

                zmcaux.ZAux_Direct_Base(g_handle, 4, axislist); //选择运动轴列表

                //插补运动使用的是主轴参数,及BASE的第一个轴
                zmcaux.ZAux_Direct_SetSpeed(g_handle, axislist[0],Convert.ToSingle(textBox_speed.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));

                if (run_mode == 1)          //绝对
                {
                    switch (move_mode)
                    { 
                        case 1:     //XY直线
                            zmcaux.ZAux_Direct_MoveAbs(g_handle, 2, axislist, poslist);
                            break;
                        case 2:     //XY圆弧
                            zmcaux.ZAux_Direct_MoveCirc2Abs(g_handle,2,axislist, midlist[0], midlist[1],poslist[0], poslist[1]);
                            break;
                        case 3:     //XYZU直线
                            zmcaux.ZAux_Direct_MoveAbs(g_handle, 4,axislist, poslist);
                            break;
                        case 4:      //空间圆弧 	XYZ空间圆弧插补U螺旋 没有绝对指令,需要用ENDMOVE_BUFF转相对
                            for (int i = 0; i < 4; i++)
                            {
                                zmcaux.ZAux_Direct_GetEndMoveBuffer(g_handle, i, ref endmove[i]);	//计算相对位移
                                poslist[i] = poslist[i] - endmove[i];
                                midlist[i] = midlist[i] - endmove[i];
                            }

                            zmcaux.ZAux_Direct_MSpherical(g_handle, 4,axislist, poslist[0], poslist[1], poslist[2], midlist[0], midlist[1], midlist[2], 0, poslist[3], 0);
                            break;
                        default:
                            break;
                    }

                }
                else
                {
                    switch (move_mode)
                    {
                        case 1:
                            zmcaux.ZAux_Direct_Move(g_handle, 2, axislist, poslist);
                            break;
                        case 2:
                            zmcaux.ZAux_Direct_MoveCirc2(g_handle, 2, axislist, midlist[0], midlist[1], poslist[0], poslist[1]);
                            break;
                        case 3:
                            zmcaux.ZAux_Direct_Move(g_handle, 4, axislist, poslist);
                            break;
                        case 4:
                            zmcaux.ZAux_Direct_MSpherical(g_handle, 4, axislist, poslist[0], poslist[1], poslist[2], midlist[0], midlist[1], midlist[2], 0, poslist[3], 0);	
                            break;
                        default:
                            break;
                    }        
                }
            }
        }

仅仅看XY直线在绝对运动下的功能函数这段代码的工作如下:

  1. 存储了目的坐标信息到poslist。设置了base主轴的参数信息(速度,加速度,减速带)

  2. 调用了 ZAux_Direct_MoveAbs功能函数执行运动。很简单就能实现

    image-20230309173333804

那么分析代码,发现如果需要三轴运动,仅仅需要修改:poslist中的目的点个数。ZAux_Direct_Move中的参与运动轴个数即可。

二、圆弧插补(绝对3点定圆弧插补运动)

image-20230309175027463

看例程以后,发现圆弧中间点信息存储在 float[] midlist中,目的点信息仍旧存储在float[] poslist中。代码中调用了

zmcaux.ZAux_Direct_MoveCirc2Abs()功能函数。

该函数在手册里是这么写的

image-20230309173302383

三、圆弧定位法(圆心定位)

image-20230309172945252

image-20230309175051076

四、编写代码如下:

含有以下6个功能函数:

多轴相对直线插补、多轴绝对直线插补

XY圆弧相对插补(圆心定位)、XY圆弧绝对插补(圆心定位)

XY圆弧相对插补(中点定位)、XY圆弧绝对插补(中点定位)

        /// <summary>
        /// 多轴相对直线插补
        /// </summary>
        /// <param name="axis"></param>
        /// <param name="distance"></param>
        /// <param name="vel"></param>
        /// <param name="acc"></param>
        /// <param name="dec"></param>
        /// <returns></returns>
        public OperationResult MoveLineRelative(int[] axis, float[] distance, float vel, float acc, float dec)
        {

            if (axis.Length >= 2 && axis.Length == distance.Length)
            {
                OperationResult result = new OperationResult();

                //判断每个轴是否满足要求
                foreach (var item in axis)
                {
                    result = CommonMotionValidate((short)item);
                    if (!result.IsSuccess) return result;
                }

                int error = 0;
                try
                {
                    //选择 BASE 轴列表
                    error = zmcaux.ZAux_Direct_Base(Handle, axis.Length, axis);
                    ErrorHandler("ZAux_Direct_Base", error);

                    error = zmcaux.ZAux_Direct_SetSpeed(Handle, axis[0], vel);
                    ErrorHandler("ZAux_Direct_SetSpeed", error);

                    error = zmcaux.ZAux_Direct_SetAccel(Handle, axis[0], acc);
                    ErrorHandler("ZAux_Direct_SetAccel", error);

                    error = zmcaux.ZAux_Direct_SetDecel(Handle, axis[0], dec);
                    ErrorHandler("ZAux_Direct_SetDecel", error);

                    error = zmcaux.ZAux_Direct_Move(Handle, axis.Length, axis, distance);
                    ErrorHandler("ZAux_Direct_Move", error);

                    return OperationResult.CreateSuccessResult();
                }
                catch (Exception ex)
                {
                    result.IsSuccess = false;
                    result.ErrorMsg = ex.Message;
                    return result;
                }

            }

            return new OperationResult()
            {
                IsSuccess = false,
                ErrorMsg = "传递参数不正确"
            };
        }

        /// <summary>
        /// 多轴绝对直线插补
        /// </summary>
        /// <param name="axis"></param>
        /// <param name="distance"></param>
        /// <param name="vel"></param>
        /// <param name="acc"></param>
        /// <param name="dec"></param>
        /// <returns></returns>
        public OperationResult MoveLineAbs(int[] axis, float[] pos, float vel, float acc, float dec)
        {

            if (axis.Length >= 2 && axis.Length == pos.Length)
            {
                OperationResult result = new OperationResult();

                //判断每个轴是否满足要求
                foreach (var item in axis)
                {
                    result = CommonMotionValidate((short)item);
                    if (!result.IsSuccess) return result;
                }

                int error = 0;
                try
                {
                    //选择 BASE 轴列表
                    error = zmcaux.ZAux_Direct_Base(Handle, axis.Length, axis);
                    ErrorHandler("ZAux_Direct_Base", error);

                    error = zmcaux.ZAux_Direct_SetSpeed(Handle, axis[0], vel);
                    ErrorHandler("ZAux_Direct_SetSpeed", error);

                    error = zmcaux.ZAux_Direct_SetAccel(Handle, axis[0], acc);
                    ErrorHandler("ZAux_Direct_SetAccel", error);

                    error = zmcaux.ZAux_Direct_SetDecel(Handle, axis[0], dec);
                    ErrorHandler("ZAux_Direct_SetDecel", error);

                    error = zmcaux.ZAux_Direct_MoveAbs(Handle, axis.Length, axis, pos);
                    ErrorHandler("ZAux_Direct_Move", error);

                    return OperationResult.CreateSuccessResult();
                }
                catch (Exception ex)
                {
                    result.IsSuccess = false;
                    result.ErrorMsg = ex.Message;
                    return result;
                }

            }

            return new OperationResult()
            {
                IsSuccess = false,
                ErrorMsg = "传递参数不正确"
            };
        }

        /// <summary>
        /// XY圆弧相对插补(圆心定位)
        /// </summary>
        /// <param name="axis"></param>
        /// <param name="distance"></param>
        /// <param name="circlecenter"></param>
        /// <param name="vel"></param>
        /// <param name="acc"></param>
        /// <param name="dec"></param>
        /// <param name="dir"></param>
        /// <returns></returns>
        public OperationResult MoveCircleRelative(int[] axis, float[] distance, float[] circlecenter,  float vel, float acc, float dec,int dir)
        {

            if (axis.Length == 2 && axis.Length == distance.Length)
            {
                OperationResult result = new OperationResult();

                //判断每个轴是否满足要求
                foreach (var item in axis)
                {
                    result = CommonMotionValidate((short)item);
                    if (!result.IsSuccess) return result;
                }

                int error = 0;
                try
                {
                    //选择 BASE 轴列表
                    error = zmcaux.ZAux_Direct_Base(Handle, axis.Length, axis);
                    ErrorHandler("ZAux_Direct_Base", error);

                    error = zmcaux.ZAux_Direct_SetSpeed(Handle, axis[0], vel);
                    ErrorHandler("ZAux_Direct_SetSpeed", error);

                    error = zmcaux.ZAux_Direct_SetAccel(Handle, axis[0], acc);
                    ErrorHandler("ZAux_Direct_SetAccel", error);

                    error = zmcaux.ZAux_Direct_SetDecel(Handle, axis[0], dec);
                    ErrorHandler("ZAux_Direct_SetDecel", error);

                    error = zmcaux.ZAux_Direct_MoveCirc(Handle, axis.Length, axis, distance[0], distance[1],circlecenter[0],circlecenter[1],dir);
                    ErrorHandler("ZAux_Direct_MoveCirc", error);

                    return OperationResult.CreateSuccessResult();
                }
                catch (Exception ex)
                {
                    result.IsSuccess = false;
                    result.ErrorMsg = ex.Message;
                    return result;
                }

            }

            return new OperationResult()
            {
                IsSuccess = false,
                ErrorMsg = "传递参数不正确"
            };
        }


        /// <summary>
        /// XY圆弧绝对插补(圆心定位)
        /// </summary>
        /// <param name="axis"></param>
        /// <param name="distance"></param>
        /// <param name="circlecenter"></param>
        /// <param name="vel"></param>
        /// <param name="acc"></param>
        /// <param name="dec"></param>
        /// <param name="dir"></param>
        /// <returns></returns>
        public OperationResult MoveCircleAbs(int[] axis, float[] distance, float[] circlecenter, float vel, float acc, float dec, int dir)
        {

            if (axis.Length == 2 && axis.Length == distance.Length)
            {
                OperationResult result = new OperationResult();

                //判断每个轴是否满足要求
                foreach (var item in axis)
                {
                    result = CommonMotionValidate((short)item);
                    if (!result.IsSuccess) return result;
                }

                int error = 0;
                try
                {
                    //选择 BASE 轴列表
                    error = zmcaux.ZAux_Direct_Base(Handle, axis.Length, axis);
                    ErrorHandler("ZAux_Direct_Base", error);

                    error = zmcaux.ZAux_Direct_SetSpeed(Handle, axis[0], vel);
                    ErrorHandler("ZAux_Direct_SetSpeed", error);

                    error = zmcaux.ZAux_Direct_SetAccel(Handle, axis[0], acc);
                    ErrorHandler("ZAux_Direct_SetAccel", error);

                    error = zmcaux.ZAux_Direct_SetDecel(Handle, axis[0], dec);
                    ErrorHandler("ZAux_Direct_SetDecel", error);

                    error = zmcaux.ZAux_Direct_MoveCircAbs(Handle, axis.Length, axis, distance[0], distance[1], circlecenter[0], circlecenter[1], dir);
                    ErrorHandler("ZAux_Direct_MoveCircAbs", error);

                    return OperationResult.CreateSuccessResult();
                }
                catch (Exception ex)
                {
                    result.IsSuccess = false;
                    result.ErrorMsg = ex.Message;
                    return result;
                }

            }

            return new OperationResult()
            {
                IsSuccess = false,
                ErrorMsg = "传递参数不正确"
            };
        }


        /// <summary>
        /// XY圆弧相对插补(中点定位)
        /// </summary>
        /// <param name="axis"></param>
        /// <param name="distance"></param>
        /// <param name="midpos"></param>
        /// <param name="vel"></param>
        /// <param name="acc"></param>
        /// <param name="dec"></param>
        /// <returns></returns>
        public OperationResult MoveCircle2Relative(int[] axis, float[] distance, float[] midpos, float vel, float acc, float dec)
        {

            if (axis.Length == 2 && axis.Length == distance.Length)
            {
                OperationResult result = new OperationResult();

                //判断每个轴是否满足要求
                foreach (var item in axis)
                {
                    result = CommonMotionValidate((short)item);
                    if (!result.IsSuccess) return result;
                }

                int error = 0;
                try
                {
                    //选择 BASE 轴列表
                    error = zmcaux.ZAux_Direct_Base(Handle, axis.Length, axis);
                    ErrorHandler("ZAux_Direct_Base", error);

                    error = zmcaux.ZAux_Direct_SetSpeed(Handle, axis[0], vel);
                    ErrorHandler("ZAux_Direct_SetSpeed", error);

                    error = zmcaux.ZAux_Direct_SetAccel(Handle, axis[0], acc);
                    ErrorHandler("ZAux_Direct_SetAccel", error);

                    error = zmcaux.ZAux_Direct_SetDecel(Handle, axis[0], dec);
                    ErrorHandler("ZAux_Direct_SetDecel", error);

                    error = zmcaux.ZAux_Direct_MoveCirc2(Handle, axis.Length, axis, midpos[0], midpos[1], distance[0], distance[1]);
                    ErrorHandler("ZAux_Direct_MoveCirc", error);

                    return OperationResult.CreateSuccessResult();
                }
                catch (Exception ex)
                {
                    result.IsSuccess = false;
                    result.ErrorMsg = ex.Message;
                    return result;
                }

            }

            return new OperationResult()
            {
                IsSuccess = false,
                ErrorMsg = "传递参数不正确"
            };
        }


        /// <summary>
        /// XY圆弧绝对插补(中点定位)
        /// </summary>
        /// <param name="axis"></param>
        /// <param name="distance"></param>
        /// <param name="midpos"></param>
        /// <param name="vel"></param>
        /// <param name="acc"></param>
        /// <param name="dec"></param>
        /// <returns></returns>
        public OperationResult MoveCircle2Abs(int[] axis, float[] distance, float[] midpos, float vel, float acc, float dec)
        {

            if (axis.Length == 2 && axis.Length == distance.Length)
            {
                OperationResult result = new OperationResult();

                //判断每个轴是否满足要求
                foreach (var item in axis)
                {
                    result = CommonMotionValidate((short)item);
                    if (!result.IsSuccess) return result;
                }

                int error = 0;
                try
                {
                    //选择 BASE 轴列表
                    error = zmcaux.ZAux_Direct_Base(Handle, axis.Length, axis);
                    ErrorHandler("ZAux_Direct_Base", error);

                    error = zmcaux.ZAux_Direct_SetSpeed(Handle, axis[0], vel);
                    ErrorHandler("ZAux_Direct_SetSpeed", error);

                    error = zmcaux.ZAux_Direct_SetAccel(Handle, axis[0], acc);
                    ErrorHandler("ZAux_Direct_SetAccel", error);

                    error = zmcaux.ZAux_Direct_SetDecel(Handle, axis[0], dec);
                    ErrorHandler("ZAux_Direct_SetDecel", error);

                    error = zmcaux.ZAux_Direct_MoveCirc2Abs(Handle, axis.Length, axis, midpos[0], midpos[1],distance[0], distance[1] );
                    ErrorHandler("ZAux_Direct_MoveCirc2Abs", error);

                    return OperationResult.CreateSuccessResult();
                }
                catch (Exception ex)
                {
                    result.IsSuccess = false;
                    result.ErrorMsg = ex.Message;
                    return result;
                }

            }

            return new OperationResult()
            {
                IsSuccess = false,
                ErrorMsg = "传递参数不正确"
            };
        }
posted @ 2023-03-09 17:53  聆听微风  阅读(778)  评论(0编辑  收藏  举报