C#编写运动控制:自定义回原(一) 5种轴位置下的回原

勇哥注:
设备的动作可以是plc,或者是运动控制来完成。
后者是一台工业电脑配上运动板卡来完成。
在有些工厂里,可能由客户喜好更喜欢用运动控制(比如富士康的苹果客户,
因为PC机和工厂的生产系统进行通讯要更方便一些,并且对视觉的配合要更好些)。
基于IPC和windows的运动控制,可靠性是没有plc好的。
因为plc相当于是一个专用小系统,并且是实时扫描的。可靠性是相当高。
但是PC有自己的优势,比如复杂和精密的视觉处理的设备都是离不开运动控制的,
因为运动卡能提供更复杂的运动能力和精度保证,plc只能做一些简单的ptp运动。


系列贴子导航:

C#编写运动控制:自定义回原(五) 验证自定义回原精度,并提出解决方案

C#编写运动控制:自定义回原(四) 完善回原功能

C#编写运动控制:自定义回原(三) 回原时为什么会出现运动指令无效跳过的现象

C#编写运动控制:自定义回原(二) 限位做为回原、限位反找回原

C#编写运动控制:自定义回原(一) 5种轴位置下的回原



运动控制之自定义回原(一)


回原是运动控制最重要的技术之一。

好的回原功能要考虑两个方面:

 一是保证精度要求,二是无论轴在哪个位置均能保证回原成功。

对于第一点,主要看设备的要求,精度要求不高可以选择原点信号回原,要求高一些可以选择原点信号+Z向信号回原。

对于第二点,是因为客户可能在断电状态下或者单动状态下让轴处于任何位置,再启动设备。


下图是运动卡常见的回原配置:

正限位+负限位+原点感应器


image.png


勇哥在下面的演示中要实现下面的能力:


  1.   轴在正限位到原点之间的时候回原

  2.   轴在原点上回原

  3.   轴在正限位上回原

  4.   轴在负限位上回原

  5.   轴在负限位和原点之间回原



其它更多的回原情况在后面的贴子中继续讨论。

例如: 仅使用限位回原, 高精度回原, 找限位后反找原点, 等等。


为什么要自定义回原呢?

这是因为除了总线运动控制卡的回原方法是工业标准定义的,普通的脉冲运动控制卡的回原api属于各个品牌自由发挥的。

这种情况下自己的通用回原就能适应不同的品牌运动控制卡。



程序及测试环境如下图:

image.png



测试代码:

        /// <summary>
        /// 回原时在原点上,先往前走一定距离,再回原
        /// </summary>
        private int inOriMoveDist { get; set; } =200;
        /// <summary>
        /// 回原时在负限位上,先往正方向走一定距离,再回原
        /// </summary>
        private int inPelMoveDist { get; set; } = 200;
        /// <summary>
        /// 回原时在正限位上,先往负方向走一定距离,再回原
        /// </summary>
        private int inMelMoveDist { get; set; } = -200;

        /// <summary>
        /// 最大回原重试次数
        /// </summary>
        private int maxHomeCount { get; set; } = 3;


        private int homecount = 0;
        public void home(HomeModeEnum type,ushort homeMode = 2, ushort homeSpeedMode = 0)
        {
            Home2(0, type,homeMode,homeSpeedMode);
            Dmc2210.d2210_set_position(0, 0);
            homecount = 0;
        }

        /*
         home_mode:回原点的方法,
        1—正方向回原点
        2—负方向回原点
        vel_mode:选择回原点的速度方式,
        0—低速回原点
        1—高速回原点,遇原点信号,减速后停止
             */
        public bool Home2(ushort axisID, HomeModeEnum type,ushort homeMode=2,ushort homeSpeedMode=0)
        {
            ++homecount;
            if (homecount > maxHomeCount) return false;
            //回原时已经在原点上
            if (AxisORG==1)
            {
                outmsg($"回原时已经在原点上,向前冲[{inOriMoveDist}]");
                waitPTP(axisID, inOriMoveDist);
                return Home2(axisID, type, homeMode, homeSpeedMode);
            }
            //回原时已经在正限位
            if (AxisPEL==1)
            {
                outmsg($"回原时已经在正限位,向负方向冲[{inPelMoveDist}]");
                waitPTP(axisID, inPelMoveDist );
                return Home2(axisID, type, homeMode, homeSpeedMode);
            }
            //回原时已经在负限位
            if (AxisMEL==1)
            {
                outmsg($"回原时已经在负限位,向正方向冲[{inMelMoveDist}]");
                waitPTP(axisID, inPelMoveDist);
                return Home2(axisID, type, homeMode, homeSpeedMode);
            }

            if(type== HomeModeEnum.MODE1_Abs)
            {
                outmsg($"开始回原运动");
                //Dmc2210.d2210_home_move(axisID, homeMode, homeSpeedMode);
                homeMove(axisID, type, homeMode, homeSpeedMode);
                WaitMotorDone(0, 10);
                outmsg($"回原完成");
            }

           
            return true;

        }

        /// <summary>
        /// 回原最大距离
        /// </summary>
        private int homeMaxDistance { get; set; } = 10000;

        //homeMode = 2 负方向    
        //homeSpeedMode = 0 低速回原
        private void homeMove(ushort axisID, HomeModeEnum type, ushort homeMode = 2, ushort homeSpeedMode = 0)
        {
            switch(type)
            {
                case HomeModeEnum.MODE1_Abs:
                    PTP(axisID, homeMaxDistance* (homeMode==2?-1:1));
                    waitHomeDone(axisID);
                    break;
            }
        }

        public void waitHomeDone(ushort axisid)
        {
            while (true)
            {
                if (AxisORG == 1)
                {
                    StopMove(axisid);
                    break;
                }
                Delay(1);
            }
        }


示例程序的原理请参考后面的视频讲解,勇哥在这里省略了。

示例程序虽然基于雷塞运动卡,但是其回原原理对任何运动卡都是通用的。



本文视频讲解如下:




本文源码资料下载:


扫码收费2元,勇哥用以支付本站服务器费用。


支付2元或购买VIP会员后,才能查看本内容!立即支付升级会员查询订单



--------------------- 

作者:hackpig

来源:www.skcircle.com

版权声明:本文为博主原创文章,转载请附上博文链接!



本文出自勇哥的网站《少有人走的路》wwww.skcircle.com,转载请注明出处!讨论可扫码加群:

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

会员中心
搜索
«    2025年4月    »
123456
78910111213
14151617181920
21222324252627
282930
网站分类
标签列表
最新留言
    热门文章 | 热评文章 | 随机文章
文章归档
友情链接
  • 订阅本站的 RSS 2.0 新闻聚合
  • 扫描加本站机器视觉QQ群,验证答案为:halcon勇哥的机器视觉
  • 点击查阅微信群二维码
  • 扫描加勇哥的非标自动化群,验证答案:C#/C++/VB勇哥的非标自动化群
  • 扫描加站长微信:站长微信:abc496103864
  • 扫描加站长QQ:
  • 扫描赞赏本站:
  • 留言板:

Powered By Z-BlogPHP 1.7.2

Copyright Your skcircle.com Rights Reserved.

鄂ICP备18008319号


站长QQ:496103864 微信:abc496103864