勇哥注: 设备的动作可以是plc,或者是运动控制来完成。 后者是一台工业电脑配上运动板卡来完成。 在有些工厂里,可能由客户喜好更喜欢用运动控制(比如富士康的苹果客户, 因为PC机和工厂的生产系统进行通讯要更方便一些,并且对视觉的配合要更好些)。 基于IPC和windows的运动控制,可靠性是没有plc好的。 因为plc相当于是一个专用小系统,并且是实时扫描的。可靠性是相当高。 但是PC有自己的优势,比如复杂和精密的视觉处理的设备都是离不开运动控制的, 因为运动卡能提供更复杂的运动能力和精度保证,plc只能做一些简单的ptp运动。
系列贴子导航:
C#编写运动控制:自定义回原(五) 验证自定义回原精度,并提出解决方案
C#编写运动控制:自定义回原(三) 回原时为什么会出现运动指令无效跳过的现象
C#编写运动控制:自定义回原(二) 限位做为回原、限位反找回原
运动控制之自定义回原(一)
回原是运动控制最重要的技术之一。
好的回原功能要考虑两个方面:
一是保证精度要求,二是无论轴在哪个位置均能保证回原成功。
对于第一点,主要看设备的要求,精度要求不高可以选择原点信号回原,要求高一些可以选择原点信号+Z向信号回原。
对于第二点,是因为客户可能在断电状态下或者单动状态下让轴处于任何位置,再启动设备。
下图是运动卡常见的回原配置:
正限位+负限位+原点感应器
勇哥在下面的演示中要实现下面的能力:
轴在正限位到原点之间的时候回原
轴在原点上回原
轴在正限位上回原
轴在负限位上回原
轴在负限位和原点之间回原
其它更多的回原情况在后面的贴子中继续讨论。
例如: 仅使用限位回原, 高精度回原, 找限位后反找原点, 等等。
为什么要自定义回原呢?
这是因为除了总线运动控制卡的回原方法是工业标准定义的,普通的脉冲运动控制卡的回原api属于各个品牌自由发挥的。
这种情况下自己的通用回原就能适应不同的品牌运动控制卡。
程序及测试环境如下图:
测试代码:
/// <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元,勇哥用以支付本站服务器费用。
---------------------
作者:hackpig
来源:www.skcircle.com
版权声明:本文为博主原创文章,转载请附上博文链接!

