勇哥注:
设备的动作可以是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
版权声明:本文为博主原创文章,转载请附上博文链接!

