(1)关于固高运动控制卡《编程手册-基本功能》上第12章 smart home的解释。
1,限位回原点(用于装有限位开关而未装有零点开关,精度要求不高的场景)
a,调用回原点指令
b,电机以较高速度运动到限位,
c,碰到限位后反向运动,
d,脱离限位后再以较低速度往限位方向动,
e,再次碰到限位时停止运动,所听位置即为我们要找的原点。
此种方式用的最多,很多模组类型的运控系统都是x,y,z轴,且都是只装上下限位开关而不装零点开关的。
2,限位加Home回原点
a,调用回原点指令
b,电机以较高速度运动到限位,
c,碰到限位后反向运动,开启高速硬件捕获,
d,在设定范围内搜索Home位置
e,触发Home开关,电机以较低速度运动到Home处,此即原点处。(这里触发Home开关后还是会运动一定位置,这个距离很小,我们感觉不到,但实际是运动了一段距离的)
第二种回零方式使用于既装了限位开关,又方便安装Home开关且精度要求较高的情形。
例如z轴的上下限位都安装了,但是回零时不希望轴停在限位开关处,可用这种方式进行回零操作。
3,Home回原点
a,调用回原点指令
b,电机以较高速度运动并开启告诉硬件捕获,
c,在设搜索范围内搜索home,
d,触发home开关,电机以较低速度运动到捕获的位置,此即我们要找的零点位置。
d段这里会返回去可能是因为b段这里开始是高速运动的,捕获到Home开关后可能速度过大来不及刹车,所以又要以较低速度返回去找零点,暂时这么理解吧!!!
第三种回零方式主要在转盘的运动控制上应用,比如一个水平圆盘的运动可以在360度范围内走动,圆盘上又方便安装Home开关,就用这种回零方式。
(4)index回原点
a,调用回原点指令
b,电以较高速度运动并开启高速硬件捕获,
c,捕获到index信号,
d,电机以较低速度运动到index处停止,此即我们需要找的原点位置。
第四种回原点方式主要应用在转盘的运动控制,并且不方便安装原点和限位的情形下,这种回零方式要求在硬件上把z相信号接上,这样才能捕获到index信号,不然控制器会一直转动找不到index信号。
以上四种回零方式是较常用的,其他的参考固高的编程手册,我也没有在实际项目上应用过,就不再一一说明了,以免误人子弟。
下面是限位回零方式的代码(主体是moveHomeInner 这个函数),具体内容看代码注释信息。
从LimitHome函数-》HomeInner函数
#pragma once
#include "gts.h"
#include <vector>
//这里用的是4轴卡
//为方便记录,用枚举的方式把轴与实际的连接轴关联起来,
//不然到后面自己都不知道那个轴对应的是第几轴了
enum Axis
{
Axis_U = 1,
Axis_V = 2,
Axis_X = 3,
Axis_Z = 4,
};
#define escape_distance 1000
class Motion
{
public:
Motion();
~Motion();
//定义静态函数,
static short init();
//运动控制卡关闭
static short close();
//先写几个回零函数种会用到的函数
//轴状态获取函数,在回零过程种会用到读取轴的状态信息,比如是否触发限位,是否处于零点位置等信息
static short axisStatus(Axis axis,long *sts);//第一个参数是需要获取状态的轴号,第二个参数是状态信息,每个为对应不同信息,后面会具体解析出来
static short isMoving(Axis axis,bool *isMoving);//判断某个轴当前是否在移动
static short stop(const std::vector<Axis>& axes);//停止轴运动,入口参数是轴数组,如果是4个全停止,数组就有4个数
//轴移动函数,这里只需要知道这个函数是控制轴移动的就可以了,后续会讲解这个函数的具体含义及实现具体实现方法
static short moveTo(Axis axis, long pos, double vel);
//限位回零方式
static short LimitHome(Axis axis);
private:
//内部调用的回零函数
static short moveHomeInner(Axis axis);
};
#include "Motion.h"
Motion::Motion()
{
}
Motion::~Motion()
{
}
//运动控制卡初始化函数,后面在打开程序的时候把运动控制卡初始化后就可以对运控卡进行控制了
short Motion::init()
{
//打开运动控制卡,确保运控卡已经插在电脑上
short ret = GT_Open();
if (ret != 0)
{
return ret;
}
//运控卡复位
ret = GT_Reset(); //这中带有GT_开头的函数都是固高提供的编程函数,直接调用即可
if (ret != 0)
{
return ret;
}
//加载配置文件,由固高的demo软件生成的,主要配置一些急停端口,限位端口之类的东西
ret = GT_LoadConfig("GTS800.cfg");
if (ret != 0)
{
return ret;
}
//清除运动报警状态,1-4代表4个轴都清楚报警状态,如果是8轴卡,则是ret = GT_ClrSts(1, 8);
ret = GT_ClrSts(1, 4);
if (ret != 0)
{
return ret;
}
//清除轴的输出参数,让各轴的当前位置为0
ret = GT_ZeroPos(1, 4);
if (ret != 0)
{
return ret;
}
//使能x轴
ret = GT_AxisOn(short(Axis::Axis_X));
if (ret != 0)
{
return ret;
}
//使能z轴
ret = GT_AxisOn(short(Axis::Axis_Z));
if (ret != 0)
{
return ret;
}
//使能u轴
ret = GT_AxisOn(short(Axis::Axis_U));
if (ret != 0)
{
return ret;
}
//使能v轴
ret = GT_AxisOn(short(Axis::Axis_V));
if (ret != 0)
{
return ret;
}
return 0;
}
//当用玩运控后需要把运控卡关掉,不然其他程序不能调用运控卡
short Motion::close()
{
return GT_Close();
}
short Motion::axisStatus(Axis axis,long *sts)
{
return GT_GetSts(short(axis), sts);
}
short Motion::isMoving(Axis axis, bool * isMoving)
{
long sts = 0;
short ret = GT_GetSts(short(axis), &sts);//用状态位来判断
if (ret != 0)
{
return ret;
}
*isMoving = sts & long(1L << 10);
return ret;
}
short Motion::stop(const std::vector<Axis>& axes)
{
long mask = 0, option = 0;
for (auto axis : axes)
{
mask |= 1 << (short(axis) - 1);
option |= 1 << (short(axis) - 1);
}
short ret = GT_Stop(mask, option);
if (ret != 0)
return ret;
else
return 0;
}
short Motion::moveTo(Axis axis, long pos, double vel)
{
bool moving = false;
short ret = isMoving(axis, &moving);
if (ret != 0)
return ret;
if (moving)
{
ret = stop({ axis });
if (ret != 0)
return ret;
}
return 0;
}
short Motion::LimitHome(Axis axis)
{
short ret;
ret = moveHomeInner(axis); //直接调用限位回零函数执行操作
if (ret != 0)
{
return ret;
}
return ret;
}
short Motion::moveHomeInner(Axis axis)
{
short ret = GT_ClrSts(short(axis));
if (ret != 0)
{
return ret;
}
//当前位置信息清零
ret = GT_ZeroPos(short(axis));
if (ret != 0)
{
return ret;
}
long sts = 0;
//获取轴状态信息
ret = axisStatus(axis, &sts);
if (ret != 0)
{
return ret;
}
//解析轴状态信息,每个bit对应的信息
//从后往前数是第六位,第六位对应负限位,下面这个if语句即是判断第六位是否为1,为1则说明触发了负限位
if (sts & 0x40)//负限位触发信号0000 0000 0000 0000 0000 0000 0100 0000
{
ret = moveTo(axis, escape_distance, 10);
if (ret != 0)
{
return ret;
}
ret = GT_ClrSts(short(axis));
if (ret != 0)
{
return ret;
}
}
if (sts & 0x20)//判断是否在正限位位置上,因为如果是在正限位位置上,是不能直接调用回零函数回零的。
{
ret = moveTo(axis, -escape_distance, 10);//先移动一小段距离后再回零
if (ret != 0)
{
return ret;
}
ret = GT_ClrSts(short(axis));
if (ret != 0)
{
return ret;
}
}
THomePrm thomePrm;//回零参数结构体
ret = GT_GetHomePrm(short(axis), &thomePrm);//获取回零参数
if (ret != 0)
{
return ret;
}
//对回零参数进行设置
thomePrm.mode = HOME_MODE_LIMIT; //回零模式,即上文提到的集中回零模式,这里是限位模式回零
thomePrm.moveDir = -1; //回零的方向,1:正方向,即往正限位方向找零点。-1:负方向
thomePrm.triggerIndex = -1;
thomePrm.velHigh = 50;//回零过程中的速度,分别对应高速和低速
thomePrm.velLow = 20;
thomePrm.acc = 5;//回零过程中的加速度,减速度
thomePrm.dec = 5;
thomePrm.smoothTime = 0; // 0-50
thomePrm.homeOffset = 10000;
thomePrm.searchHomeDistance = 0;//一直搜索,如果不为0,即为设置的搜索距离
thomePrm.escapeStep = escape_distance;
ret = GT_ClearCaptureStatus(short(axis));
if (ret != 0)
{
return ret;
}
GT_PrfTrap(short(axis));//设置为点位运动模式
if (ret != 0)
{
return ret;
}
THomeStatus thomeSts;//回零状态参数结构体
ret = GT_GoHome(short(axis), &thomePrm);
//一直在执行回零操作,直到找到零点位置才停止,这个找到零点了的话它是会自动停止的,否则一直执行找零点,直到出错
do {
ret = GT_GetHomeStatus(short(axis), &thomeSts);
ret = GT_ClrSts(short(axis));//清除正限位触发状态用的
if (ret)
{
return ret;
}
} while (thomeSts.run);
if (ret != 0)
{
return ret;
}
//清楚所有的报警状态信息
ret = GT_ClrSts(short(axis));
if (ret != 0)
{
return ret;
}
//将当前位置清零
ret = GT_ZeroPos(axis, 1);
if (ret != 0)
{
return ret;
}
//回零函数执行结束
return 0;
}