C# 后台代码:
1、SoftModels类,SoftModels类代码内容(部分代码)如下
///开启膜厚检测线程
public void StarThreadMeasure()
{
if (!FlagThreadMeasureProcess)
{
lock (_flagAutoLock)
{
if (!FlagThreadMeasureProcess)
{
// 终止已有线程(如果存在)
if (ThreadMeasureProcess?.IsAlive == true)
{
ThreadMeasureProcess.Abort();
ThreadMeasureProcess.Join(500); // 等待线程退出
}
ThreadMeasureProcess = new Thread(MeasureThreadFunc)
{
IsBackground = true
};
ActionLog?.Invoke("启动按钮按下,开始膜厚检测的流程");
ActionRefreshStatus?.Invoke(PcbInPosition, true);
FlagThreadMeasureProcess = true;
ThreadMeasureProcess.Start();
}
}
;
}
}
///膜厚检测的流程
public void MeasureThreadFunc()
{
double AimZ = processParam.ProcessParamStr.adjDistanceZCoor;//测量位置Z坐标
double Blc = processParam.ProcessParamStr.adjDistanceBlc;
double AimDistance = processParam.ProcessParamStr.adjDistanceAim;
double BackPointZ = processParam.ProcessParamStr.adjDistanceBackPoint;//安全坐标
double refractiveIndex = processParam.ProcessParamStr.refractiveIndex;
int index;
if (NowSlectedSurface == 0)
{
index = processParam.PointDataManager.Count();
processParam.CMeasureData.Clear();
}
else
{
index = processParam.PointSDataManager.Count();
processParam.SMeasureData.Clear();
}
double PosX = 0;
double PosY = 0;
double difference = 0;
for (int num = 0; num < index; num++)
{
Thread.Sleep(1000);
Log.Information("膜厚测量第" + (num + 1) + "点开始");
ActionLog?.Invoke("测试点膜厚测量运行中");
if (!FlagThreadMeasureProcess)
break;
//DEto:新增代码 --12.02
ActionPointLocation(PosX, PosY, num, AimZ, Blc, AimDistance, BackPointZ, refractiveIndex, difference);
SaveSIT1000MeasureValue(SIT1000.ShowMeasureValue);
Log.Information("膜厚测量第" + (num + 1) + "点,结果:" + SIT1000.ShowMeasureValue + "");
}
}
///按点位进行运动
private void ActionPointLocation(double PosX, double PosY, int num, double AimZ, double Blc, double AimDistance, double BackPointZ, double refractiveIndex, double difference)
{
if (NowSlectedSurface == 0)
{
if (PosX == 0 && PosY == 0)
{
PosX = processParam.PointDataManager[num].X;
PosY = processParam.PointDataManager[num].Y;
}
}
else
{
if (PosX == 0 && PosY == 0)
{
PosX = processParam.PointSDataManager[num].X;
PosY = processParam.PointSDataManager[num].Y;
}
}
if (!motionManager.XYTablePmove(PosX, PosY))
{
Log.Information("膜厚测量-ActionPointLocation()-motionManager.XYTablePmove-2169");
FlagThreadMeasureProcess = false;
ThreadExitValue = 1;
return;
}
while (FlagThreadMeasureProcess)
{
Thread.Sleep(100);
if (!motionManager.IfXYTableMoving(out status))
{
Log.Information("膜厚测量-ActionPointLocation()-motionManager.IfXYTableMoving-2179");
FlagThreadMeasureProcess = false;
ThreadExitValue = 1;
return;
}
if (!status)
break;
Thread.Sleep(50);
}
if (!FlagThreadMeasureProcess)
{
ThreadExitValue = 0;
return;
}
Thread.Sleep(500);
//首先将Z轴运行至测量位置坐标
if (!motionManager.Z.MoveAbsTo(AimZ, out _))
{
Log.Information("膜厚测量-ActionPointLocation()-motionManager.Z.MoveAbsTo-2197");
FlagThreadMeasureProcess = false;
ThreadExitValue = 1;
return;
}
}
2、MotionManager 类,MotionManager 类代码内容如下:
public class MotionManager
{
string motionSettingsFilePath = System.AppDomain.CurrentDomain.BaseDirectory + "Config\\Motion_Settings.xml"; //motion参数设置文件路径
public List<MotionPara> AxisPara = new List<MotionPara>(); //轴参数定义
public IOlist iolist = new IOlist();
public List<int> IOOutListIndex = new List<int>();
public List<int> IOInListIndex = new List<int>();
public List<string> IOOutListDesc = new List<string>();
public List<string> IOInListDesc = new List<string>();
public InterfaceCommon MotionCard;
public InterfaceIO IO;
public InterfaceAxis X;
public InterfaceAxis Y;
public InterfaceAxis Z;
public InterfaceAxis A;
private Thread SystemHomeThread;
public int redport;
public int yellowport;
public int greenport;
public bool HomeThreadFlag;
public bool ControlFlag;
public MotionManager()
{
IOOutListIndex = Helper.GetAllEnumIntValue(typeof(IOOutList)); //获取每个IO的ID号
IOOutListDesc = Helper.GetAllEnumDescription(typeof(IOOutList));
IOInListIndex = Helper.GetAllEnumIntValue(typeof(IOInList)); //获取每个IO的ID号
IOInListDesc = Helper.GetAllEnumDescription(typeof(IOInList));
//三色灯 DETO:临时更改三色灯为同一状态,后续要根据实际IO口修改
//IO更改
redport = 1;//注意这里为扩展IO与主机IO的区别
greenport = 2;//主机IO
yellowport = 2;//注意这里为扩展IO与主机IO的区别
LoadMotionSettings(); //读取轴运动参数
ControlFlag = false;
}
~MotionManager()
{
SaveMotionSettings();
if (ControlFlag)
IO.WriteOut(iolist.IOOutPara[1].Port, false, out string message);
CloseMotion(out string info);
}
public void StopHomeThread()
{
HomeThreadFlag = false;
}
public void StartHomeThread()
{
if (null != SystemHomeThread)
{
if (SystemHomeThread.ThreadState == ThreadState.Running)
return;
SystemHomeThread.Abort();
}
SystemHomeThread = new Thread(HomeThreadFunc)
{
IsBackground = true
};
HomeThreadFlag = true;
SystemHomeThread.Start();
}
public void HomeThreadFunc()
{
if (!Z.HomeAxis())
{
Z.StopMotion(out _);
HomeThreadFlag = false;
return;
}
bool iErr, status, statusz;
do
{
if (!HomeThreadFlag)
{
Z.StopMotion(out _);
return;
}
iErr = Z.IfAxisHomeRuning(out statusz);
if (!iErr)
{
Z.StopMotion(out _);
HomeThreadFlag = false;
return;
}
}
while (statusz);
Z.ZeroPosition(out _);
if (!X.HomeAxis())
{
X.StopMotion(out _);
HomeThreadFlag = false;
return;
}
if (!Y.HomeAxis())
{
Y.StopMotion(out _);
HomeThreadFlag = false;
return;
}
if (!A.HomeAxis())
{
A.StopMotion(out _);
HomeThreadFlag = false;
return;
}
do
{
if (!HomeThreadFlag)
{
X.StopMotion(out _);
Y.StopMotion(out _);
A.StopMotion(out _);
return;
}
iErr = X.IfAxisHomeRuning(out bool statusx);
if (!iErr)
{
X.StopMotion(out _);
Y.StopMotion(out _);
A.StopMotion(out _);
HomeThreadFlag = false;
return;
}
iErr = Y.IfAxisHomeRuning(out bool statusy);
if (!iErr)
{
X.StopMotion(out _);
Y.StopMotion(out _);
A.StopMotion(out _);
HomeThreadFlag = false;
return;
}
iErr = A.IfAxisHomeRuning(out bool statusa);
if (!iErr)
{
X.StopMotion(out _);
Y.StopMotion(out _);
A.StopMotion(out _);
HomeThreadFlag = false;
return;
}
if (statusx || statusy || statusa)
status = true;
else
status = false;
}
while (status);
X.ZeroPosition(out _);
Y.ZeroPosition(out _);
A.ZeroPosition(out _);
HomeThreadFlag = false;
return;
}
/// <summary>
/// 设置三色灯状态
/// </summary>
/// <param name="index"></param>
public void SetRedYellowGreenLight(int index)
{
switch (index)
{
case 0:
{
IO.WriteOut(redport, true, out string message);
IO.WriteOut(yellowport, false, out string message1);
IO.WriteOut(greenport, false, out string message2);
}
break;
case 1://退出自动加工流程
{
IO.WriteOut(redport, false, out string message);
IO.WriteOut(yellowport, true, out string message1);
IO.WriteOut(greenport, false, out string message2);
}
break;
case 2://启动自动测量加工流程
{
IO.WriteOut(redport, false, out string message);
IO.WriteOut(yellowport, false, out string message1);
IO.WriteOut(greenport, true, out string message2);
}
break;
default:
break;
}
}
/// <summary>
/// 设置三色灯状态
/// </summary>
/// <param name="operState"></param>
public void SetRedYellowGreenLight(OperStateType operState)
{
switch (operState)
{
case OperStateType.StandBy://空闲待机
ExtendedIO.Oper_ExtendedIO(1, 1, 0);//红灯灭
IO.WriteOut(greenport, false, out string message);//绿灯灭
//黄灯常亮
ExtendedIO.Oper_ExtendedIO(1, 2, 1);//黄灯亮
break;
case OperStateType.RunStatus://运行
ExtendedIO.Oper_ExtendedIO(1, 2, 0);//黄灯灭
ExtendedIO.Oper_ExtendedIO(1, 1, 0);//红灯灭
//绿灯常亮
IO.WriteOut(greenport, true, out string message2);
break;
case OperStateType.AlarmStatus:
ExtendedIO.Oper_ExtendedIO(1, 2, 0);//黄灯灭
IO.WriteOut(greenport, false, out string message3);//绿灯灭
ExtendedIO.Oper_ExtendedIO(1, 1, 1);//红灯亮
break;
case OperStateType.ShieldAlarm://屏蔽报警
ExtendedIO.Oper_ExtendedIO(1, 1, 0);//红灯灭
//其他灯状态暂时不变
break;
case OperStateType.NormalStatus://正常
ExtendedIO.Oper_ExtendedIO(1, 1, 0);//红灯灭
ExtendedIO.Oper_ExtendedIO(1, 2, 0);//黄灯灭
IO.WriteOut(greenport, false, out string message4);//绿灯灭
break;
case OperStateType.StopStatus://停止
break;
case OperStateType.OtherStatus://其他
break;
}
}
/// <summary>
/// 初始化连接卡
/// </summary>
/// <param name="info"></param>
/// <returns></returns>
public bool Init(out string info) //初始化连接卡
{
bool ret = MotionCard.Init(out string message);
AssignAllAxis();
bool Newret = ExtendedIO.ExtModuleInitIO(1, 1);
if (!ret || !Newret)
{
info = message;
return false;
}
info = "运动控制器初始化成功";
return true;
}
public bool SetAllAxisServoOn(bool status, out string info)
{
if (X != null)
{
bool ret = X.SetServoOn(status, out string message);
if (!ret)
{
info = message;
return false;
}
}
if (Y != null)
{
bool ret = Y.SetServoOn(status, out string message);
if (!ret)
{
info = message;
return false;
}
}
if (Z != null)
{
bool ret = Z.SetServoOn(status, out string message);
if (!ret)
{
info = message;
return false;
}
}
if (A != null)
{
bool ret = A.SetServoOn(status, out string message);
info = message;
if (!ret)
return false;
info = message;
return true;
}
info = "";
return false;
}
public void CloseMotion(out string info) //关闭motion
{
if (MotionCard != null)
{
bool ret = SetAllAxisServoOn(false, out string message);
if (!ret)
info = message;
MotionCard.Close(out message);
info = message;
}
info = "运动控制卡未正常打开,无需关闭";
}
public void LoadMotionSettings() //加载读取轴参数
{
int AxisCount = 4;
string str = XmlSerializer.LoadXML<List<MotionPara>>(motionSettingsFilePath, ref AxisPara);
if (str != "")
{
AxisPara = new List<MotionPara>();
AxisPara.Clear();
for (int i = 0; i < AxisCount; i++)
{
MotionPara myPara = new MotionPara();
AxisPara.Add(myPara);
}
}
else
{
if (AxisPara.Count > AxisCount)
{
for (int i = AxisCount; i < AxisPara.Count; i++)
{
AxisPara.RemoveAt(i);
}
}
else if (AxisPara.Count < AxisCount)
{
for (int i = AxisPara.Count; i < AxisCount; i++)
{
MotionPara myPara = new MotionPara();
AxisPara.Add(myPara);
}
}
}
IO = new GTN.GTNIO();
iolist = new IOlist();
iolist.IOInPara.Clear();
iolist.IOOutPara.Clear();
// for (int i = 0; i < 12; i++)
for (int i = 0; i < 16; i++)
{
IOProperty IOpara = new IOProperty(IOInListDesc[i]);
IOpara.Port = IOInListIndex[i];
iolist.IOInPara.Add(IOpara);
}
for (int i = 0; i < 10; i++)
{
IOProperty IOpara = new IOProperty(IOOutListDesc[i]);
IOpara.Port = IOOutListIndex[i];
iolist.IOOutPara.Add(IOpara);
}
MotionCard = new GTN.GTNCard();
}
public void AssignAllAxis()
{
for (int i = 0; i < 4; i++)
{
InterfaceAxis axis = new GTN.Axis_GTN((short)(i + 1), AxisPara[i]);
switch (i)
{
case 0:
X = axis;
break;
case 1:
Y = axis;
break;
case 2:
Z = axis;
break;
case 3:
A = axis;
break;
default:
break;
}
}
}
public void SaveMotionSettings() //保存所有轴参数
{
XmlSerializer.SaveXML(motionSettingsFilePath, AxisPara);
}
public bool XYTablePmove(double PosX, double PosY)
{
bool ret = Y.MoveAbsTo(PosY, out string message);
if (!ret)
return false;
ret = X.MoveAbsTo(PosX, out message);
if (!ret)
return false;
return true;
}
public bool IfXYTableMoving(out bool flag)
{
bool ret = X.Busy(out bool statusx);
if (!ret)
{
flag = false;
return false;
}
ret = Y.Busy(out bool statusy);
if (!ret)
{
flag = false;
return false;
}
if (statusx && statusy)
flag = true;
else
flag = false;
return true;
}
public bool StopXYTableMove()
{
bool flag = X.StopMotion(out string message);
if (!flag)
return false;
flag = Y.StopMotion(out message);
if (!flag)
return false;
return true;
}
public bool StopALLTableMoving()
{
bool flag = X.StopMotion(out string message);
if (!flag)
return false;
flag = Y.StopMotion(out message);
if (!flag)
return false;
flag = Z.StopMotion(out message);
if (!flag)
return false;
flag = A.StopMotion(out message);
if (!flag)
return false;
return true;
}
}
3、Axis_GTN类,Axis_GTN代码内容如下:
class Axis_GTN : InterfaceAxis
{
public short axisID;
MotionPara AxisProfile;
public Axis_GTN(short axisid, MotionPara axispara)
{
axisID = axisid;
AxisProfile = axispara;
}
private bool IsHomed;
private bool IsHomeDone;
private string HomeError;
private Thread HomeThread;
public bool ALM(out bool status)
{
bool ret = GetMotionIO(mc.MC_ALARM, out bool rtnval);
status = rtnval;
return ret;
}
private bool GetMotionIO(short ioType, out bool status)
{
int iErr = mc.GTN_GetDi(1, ioType, out int byteResult);
if (iErr != 0)
{
status = false;
return false;
}
status = Convert.ToBoolean((byteResult & (0x01 << (axisID - 1))));
return true;
}
private bool GetMotionStatus(int axisID, short axisStatusType, out string info, out bool rtnval)
{
short iErr = mc.GTN_GetSts(1, (short)axisID, out int byteResult, 1, out _);
info = GtnInterFace.GetErrorString(iErr);
if (iErr != 0)
{
Log.Information("GTN Axis_GTN GetMotionStatus()-GTN_GetSts Error: {info}", info + "{iErr}:" + iErr + "");
rtnval = false;
return false;
}
rtnval = Convert.ToBoolean((byteResult & (0x01 << axisStatusType)));
return true;
}
public bool Busy(out bool status)
{
bool rtn = GetMotionStatus(axisID, (short)GTNAxisStauts.IsBusy, out string info, out bool rtnval);
status = rtnval;
return rtn;
}
public MotionPara GetMotionPara()
{
return AxisProfile;
}
public bool GetPosition(out double pos)
{
double scale = AxisProfile.MotorScale;
short iErr = mc.GTN_GetEncPos(1, axisID, out double postion, 1, out _);
if (iErr == 0)
{
pos = postion / scale;
return true;
}
pos = 0.0;
return false;
}
public bool HomeAxis()
{
mc.THomePrm homePrm = new mc.THomePrm()
{
acc = 10,
dec = 10,
moveDir = -1, //非正整数,负向回零
mode = 10, //限位回原点
edge = 0,
velHigh = (AxisProfile.HomeSpeed * AxisProfile.MotorScale) / 1000, //AxisProfile.HomeSpeed * (10000 / AxisProfile.MotorScale),
velLow = AxisProfile.HomeSpeed / 5.0,
searchHomeDistance = 100000000,
searchIndexDistance = 100000,
escapeStep = 100
};
short iErr = mc.GTN_GoHome(1, axisID, ref homePrm);
if (iErr != 0)
return false;
return true;
}
public bool IfAxisHomeRuning(out bool status)
{
short iErr = mc.GTN_GetHomeStatus(1, axisID, out mc.THomeStatus homeStatus);
if (iErr == 0)
{
if (homeStatus.run != 0)
status = true;
else
status = false;
return true;
}
status = false;
return false;
}
public string Homing()
{
if (HomeThread != null && HomeThread.IsAlive)
{
return "axis is homing";
}
HomeThread = new Thread(() =>
{
IsHomed = false;
HomeError = "";
HomeError = HomingThreadFunc();
IsHomed = true;
if (HomeError != "")
IsHomeDone = false;
else
IsHomeDone = true;
})
{
IsBackground = false,
Name = "GTN Homing"
};
HomeThread.Start();
Thread.Sleep(20);
return "";
}
string HomingThreadFunc()
{
IsHomeDone = false;
IsHomed = false;
int iErr;
mc.THomePrm homePrm = new mc.THomePrm()
{
acc = 10,
dec = 10,
moveDir = -1, //非正整数,负向回零
mode = 10, //限位回原点
edge = 0,
velHigh = (AxisProfile.HomeSpeed * AxisProfile.MotorScale) / 1000, //AxisProfile.HomeSpeed * (10000 / AxisProfile.MotorScale),
velLow = AxisProfile.HomeSpeed / 5.0,
searchHomeDistance = 100000000,
searchIndexDistance = 100000,
escapeStep = 100
};
iErr = mc.GTN_GoHome(1, axisID, ref homePrm);
if (iErr == 0)
{
mc.THomeStatus homeStatus;
do
{
mc.GTN_GetHomeStatus(1, axisID, out homeStatus);
}
while (homeStatus.run != 0);
iErr = mc.GTN_ZeroPos(1, axisID, 1);
if (iErr != 0)
return GtnInterFace.GetErrorString(iErr);
else return "";
}
else return GtnInterFace.GetErrorString(iErr);
}
public bool MoveAbsTo(double pos, out string info)
{
int scale = AxisProfile.MotorScale;
int pulseSpeed = (Int32)(AxisProfile.RunSpeed * AxisProfile.MotorScale);
double acc = (Int32)(AxisProfile.acc_dec * AxisProfile.MotorScale);
int pulsePos = (int)(pos * scale);
//short iErr = mc.GTN_Stop(1, axisID, 0);//停止运动
//info = GtnInterFace.GetErrorString(iErr);
//if (iErr != 0)
// return false;
// 1. 强制停止轴运动并验证状态
if (!StopMotion(out info)) return false;
// 2. 清除轴状态(原代码缺失此步骤)
short iErr = mc.GTN_ClrSts(1, axisID, 1);
info = GtnInterFace.GetErrorString(iErr);
if (iErr != 0)
{
Log.Information("GTN MoveAbsTo GTN_ClrSts Error: {info}", info + "{iErr}:" + iErr + "");
return false;
}
iErr = mc.GTN_PrfTrap(1, axisID);//设置为点位运动
info = GtnInterFace.GetErrorString(iErr);
if (iErr != 0)
{
Log.Information("GTN MoveAbsTo GTN_PrfTrap Error: {info}", info + "{iErr}:" + iErr + "");
return false;
}
iErr = mc.GTN_GetAxisPrfPos(1, axisID, out double curPulsePos, 1, out uint clock);
info = GtnInterFace.GetErrorString(iErr);
if (iErr != 0)
{
Log.Information("GTN MoveAbsTo GTN_GetAxisPrfPos Error: {info}", info + "{iErr}:" + iErr + "");
return false;
}
mc.TTrapPrm trap;
trap.acc = acc / 1000000;//单位:pulse/ms2
trap.dec = acc / 1000000;//单位:pulse/ms2
trap.velStart = 0;//起跳速度
trap.smoothTime = 50;//单位ms
//iErr = mc.GTN_SetTrapPrm(1, axisID, ref trap);//设置加减速
//info = GtnInterFace.GetErrorString(iErr);
//if (iErr != 0)
//{
// Log.Information("GTN MoveAbsTo GTN_SetTrapPrm Error: {info}", info + "{iErr}:" + iErr + "");
// return false;
//}
// 5. 核心参数设置(增加重试机制)
for (int i = 0; i < 3; i++)
{
short trapErr = mc.GTN_SetTrapPrm(1, axisID, ref trap);
info = GtnInterFace.GetErrorString(trapErr);
if (trapErr == 0) break;
Log.Warning($"SetTrapPrm retry {i + 1}: {info}");
Thread.Sleep(50);
}
iErr = mc.GTN_SetPos(1, axisID, pulsePos);//设置位置
info = GtnInterFace.GetErrorString(iErr);
if (iErr != 0)
{
Log.Information("GTN MoveAbsTo GTN_SetPos Error: {info}", info + "{iErr}:" + iErr + "");
return false;
}
iErr = mc.GTN_SetVel(1, axisID, pulseSpeed);//设置速度
info = GtnInterFace.GetErrorString(iErr);
if (iErr != 0)
{
Log.Information("GTN MoveAbsTo GTN_SetVel Error: {info}", info + "{iErr}:" + iErr + "");
return false;
}
// 7. 运动执行(增加状态验证)
mc.GTN_SetPos(1, axisID, pulsePos);
mc.GTN_SetVel(1, axisID, Convert.ToInt32(AxisProfile.RunSpeed * AxisProfile.MotorScale));
iErr = mc.GTN_Update(1, 1 << (axisID - 1));//启动轴
info = GtnInterFace.GetErrorString(iErr);
if (iErr != 0)
{
Log.Information("GTN MoveAbsTo GTN_Update Error: {info}", info + "{iErr}:" + iErr + "");
return false;
}
Thread.Sleep(10);
return true;
}
public bool NEL(out bool status)
{
if (!GetMotionIO(mc.MC_LIMIT_NEGATIVE, out bool value))
{
status = false;
return false;
}
status = value;
return true;
}
public bool ORG(out bool status)
{
if (!GetMotionIO(mc.MC_HOME, out bool value))//原点信号默认是1的,触碰是0
{
status = false;
return false;
}
status = !value;
return status;
}
public bool PEL(out bool status)
{
if (!GetMotionIO(mc.MC_LIMIT_POSITIVE, out bool value))
{
status = false;
return false;
}
status = value;
return true;
}
public bool ZeroPosition(out string info)
{
short iErr = mc.GTN_ZeroPos(1, axisID, 1);
info = GtnInterFace.GetErrorString(iErr);
if (iErr != 0)
return false;
return true;
}
//对指定电机轴进行使能或者断开使能操作
public bool SetServoOn(bool status, out string info)
{
//如果操作的是Y轴,则需要首先对抱闸进行操作。抱闸的IO端口号为2
short ret;
if (axisID == 2)
{
ret = mc.GTN_SetDoBit(1, mc.MC_GPO, 2, Convert.ToInt16(status));
info = GtnInterFace.GetErrorString(ret);
if (ret != 0)
return false;
}
if (status)
ret = mc.GTN_AxisOn(1, axisID);
else
ret = mc.GTN_AxisOff(1, axisID);
info = GtnInterFace.GetErrorString(ret);
if (ret != 0)
return false;
return true;
}
public bool StepMove(double distance, out string message)
{
int scale = AxisProfile.MotorScale;
int speed = (Int32)(AxisProfile.ManualSpeed * AxisProfile.MotorScale);
double acc = (double)(AxisProfile.acc_dec * AxisProfile.MotorScale);
int distancePulse = (int)(distance * scale);
int setPulsePos;
bool ret = StopMotion(out string info);
message = info;
if (!ret)
return false;
short iErr = mc.GTN_ClrSts(1, axisID, 1);
message = GtnInterFace.GetErrorString(iErr);
if (iErr != 0)
return false;
iErr = mc.GTN_PrfTrap(1, axisID);//设置为点位运动
message = GtnInterFace.GetErrorString(iErr);
if (iErr != 0)
return false;
iErr = mc.GTN_GetAxisPrfPos(1, axisID, out double curPulsePos, 1, out uint clock);
message = GtnInterFace.GetErrorString(iErr);
if (iErr != 0)
return false;
setPulsePos = (int)curPulsePos + distancePulse;
mc.TTrapPrm trap;
trap.acc = acc / 1000000;//单位:pulse/ms2
trap.dec = acc / 1000000;//单位:pulse/ms2
trap.velStart = 0;//起跳速度
trap.smoothTime = 50;//单位ms
// 设置点位运动参数
iErr = mc.GTN_SetTrapPrm(1, axisID, ref trap);//设置加减速
message = GtnInterFace.GetErrorString(iErr);
if (iErr != 0)
return false;
iErr = mc.GTN_SetPos(1, axisID, setPulsePos);//设置位置
message = GtnInterFace.GetErrorString(iErr);
if (iErr != 0)
return false;
iErr = mc.GTN_SetVel(1, axisID, speed);//设置速度
message = GtnInterFace.GetErrorString(iErr);
if (iErr != 0)
return false;
iErr = mc.GTN_Update(1, 1 << (axisID - 1));//启动轴
message = GtnInterFace.GetErrorString(iErr);
if (iErr != 0)
return false;
return true;
}
/// <summary>
/// jog运动
/// </summary>
/// <param name="distance"></param>
/// <param name="message"></param>
/// <returns></returns>
public bool StepJogMovee(double distance, JogMovType movType, out string message)
{
int scale = AxisProfile.MotorScale;
int speed = (Int32)(AxisProfile.ManualSpeed * AxisProfile.MotorScale);
double acc = (double)(AxisProfile.acc_dec * AxisProfile.MotorScale);//50000pulse/ms2
int distancePulse = (int)(distance * scale);
int setPulsePos;
// 1.停止当前运动
bool ret = StopMotion(out string info);
message = info;
if (!ret)
return false;
//2.清除轴状态
short iErr = mc.GTN_ClrSts(1, axisID, 1);
message = GtnInterFace.GetErrorString(iErr);
if (iErr != 0)
return false;
//3. 设置为Jog运动模式
iErr = mc.GTN_PrfJog(1, axisID);
message = GtnInterFace.GetErrorString(iErr);
if (iErr != 0)
return false;
mc.TJogPrm trap;
trap.acc = acc / 1000000;//单位:pulse/ms2
trap.dec = acc / 1000000;//单位:pulse/ms2
trap.smooth = 0.5; // 平滑系数 (0~1)
// 设置Jog运动参数
iErr = mc.GTN_SetJogPrm(1, axisID, ref trap);
message = GtnInterFace.GetErrorString(iErr);
if (iErr != 0)
return false;
switch (movType)
{
case JogMovType.MeditatePerly:
iErr = mc.GTN_SetVel(1, axisID, speed);//设置目标速度
break;
case JogMovType.Counterforce:
iErr = mc.GTN_SetVel(1, axisID, -speed);//设置目标速度
break;
}
message = GtnInterFace.GetErrorString(iErr);
if (iErr != 0)
return false;
iErr = mc.GTN_Update(1, 1 << (axisID - 1));//启动轴
message = GtnInterFace.GetErrorString(iErr);
if (iErr != 0)
return false;
return true;
}
public bool StopMotion(out string info)
{
int mask = 1 << (axisID - 1);
int option = 1 << (axisID - 1);//0表示平滑停止,1表示紧急停止
int iErr = mc.GTN_Stop(1, mask, 0); //mc.GTN_Stop(1, mask, option);
info = GtnInterFace.GetErrorString(iErr);
if (iErr != 0)
{
Log.Information("GTN Axis_GTN StopMotion()-GTN_Stop Error: {info}", info + "{iErr}:" + iErr + "");
return false;
}
return true;
}
public bool SVN(out bool status)
{
if (!GetMotionStatus(axisID, (short)GTNAxisStauts.Servo, out string info, out bool val))
{
status = false;
return false;
}
status = val;
return true;
}
public string WaitHomeDone()
{
Stopwatch watch = new Stopwatch();
watch.Start();
while (true)
{
if (IsHomed)
{
if (IsHomeDone)
return "";
else
return "Home Error:" + HomeError;
}
if (watch.ElapsedMilliseconds > 30000)
{
return "home timeout";
}
Application.DoEvents();
Thread.Sleep(15);
}
}
public bool WaitMoveDone()
{
bool status;
Stopwatch watch = new Stopwatch();
watch.Start();
bool ret = Busy(out status);
if (!ret)
return false;
while (status)
{
if (watch.ElapsedMilliseconds > 30000)
return false;
Application.DoEvents();
Thread.Sleep(15);
ret = Busy(out status);
if (!ret)
return false;
}
return true;
}
public bool WaitMovePos(double pos)
{
WaitMoveDone();
Stopwatch watch = new Stopwatch();
watch.Start();
while (true)
{
if (GetPosition(out double curPos))
{
if (Math.Abs(curPos - pos) < 0.005)
break;
}
if (watch.ElapsedMilliseconds > 3000)
return false;
Thread.Sleep(10);
}
return true;
}
}
背景:
1.已知用户启动程序后通过,点击按钮“自动加工”后会在SoftModels类开启执行StarThreadMeasure()方法,开启线程去执行膜厚检测的流程动作
2.已知代码MeasureThreadFunc()方法里面主要功能是:
2.1 提前设置好测试点的X/Y 具体的点位坐标值,并保存到processParam.PointDataManager列表。
例如:提前设置好12个坐标值(
528.655,300.885
397.071,300.885
210.737,336.92659
210.737,414.533
412.96,414.533
609.46,414.533
609.624,500.44
391.353,500.44
218.115,500.44
109.613,500.44
109.613,265.201752
109.613,247.143
)
2.2 再通过 for (int num = 0; num < index; num++)去控制设备去进行多少次的动作即执行ActionPointLocation()方法里面的代码
3.当执行ActionPointLocation()里面的代码时,需要先执行 if (!motionManager.XYTablePmove(PosX, PosY))处代码,即对X/Y轴去进行点位运动
3.1 再执行 while (FlagThreadMeasureProcess)- if (!motionManager.IfXYTableMoving(out status))
去执行固高GTN_GetSts函数(读取轴状态)
3.2 当前面操作执行完成后执行代码: if (!motionManager.Z.MoveAbsTo(AimZ, out _))即Z轴按位置进行点位运动,再触发执行GTN_GetSts函数(读取轴状态)
4.重复执行直到 for (int num = 0; num < index; num++)执行完成,即点位测量完成
5.GTN_SetTrapPrm,指令错误返回值:
若返回值为 1:
(1) 若当前轴在规划运动,请调用 GTN_Stop 停止运动再调用该指令。
(2) 请检查当前轴是否为 Trap 模式,若不是,请先调用 GTN_PrfTrap 将当前轴设置为
Trap 模式。
其他返回值:请参照指令返回值列表。
问题:
1.实际设备执行运动控制,即执行StarThreadMeasure()-MeasureThreadFunc()-ActionPointLocation()时总是会设备在某一个点位就停止动作
2.当1发生是通过断点及日志添加后,排查发现SetTrapPrm retry {3}: {1},即固高GTN_SetTrapPrm指令错误并返回值为:1
需求:
1.请你做为一名C# 软件工程师,对C#后台代码(SoftModels类、MotionManager类、Axis_GTN类)、背景1-5、对问题1-2进行分析与排查动作时停止动作
(即:固高GTN_SetTrapPrm指令错误)的原因
2..请你做为一名C# 软件工程师,在分析与排查到原因后对问题1-2进行优化与完善并输出完整的解决方案与示例代码
最新发布