using Bro.Common.Base; using Bro.Common.Helper; using Bro.Common.Interface; using Bro.Common.Model; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Drawing; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using static Bro.Common.Helper.EnumHelper; namespace Bro.Device.GTSCard { [Device("GTSCard", "固高板卡", EnumHelper.DeviceAttributeType.Device)] public class GTSCardDriver : DeviceBase, IMonitor, IMotion { public event Action OnMonitorInvoke; public event Action OnMonitorAlarm; public delegate bool OnAxisStartToCheckDelegate(int axisIndex, int startPosition, int endPosition); // 异常事件 public Action OnExceptionRaised; public GTSCardInitialConfig IConfig { get { return InitialConfig as GTSCardInitialConfig; } } static object moveLock = new object(); /// /// 是否复位标志 /// bool _isResetting = false; public void SetResetFlag(bool isReset) { _isResetting = isReset; } public List GetCurrentAxisInfo(params string[] axisName) { throw new NotImplementedException(); } #region DeviceBase protected override void Init() { InitialMotionCard(); } protected override void Pause() { throw new NotImplementedException(); } protected override void Resume() { throw new NotImplementedException(); } protected override void Start() { throw new NotImplementedException(); } protected override void Stop() { throw new NotImplementedException(); } #endregion #region GTSCard /// /// Load Motion Card parameter from file /// /// Invalid Parameter /// public void InitialMotionCard() { var res = GTSCardAPI.GT_Open((short)IConfig.CardNum, 0, 1); //打开运动控制器。参数必须为(0,1),不能修改。 res += GTSCardAPI.GT_LoadConfig((short)IConfig.CardNum, IConfig.InitialConfigFilePath); res += GTSCardAPI.GT_ClrSts(0, 1, 8); if (res != (short)GTSRetCode.GRCRunOK) { throw new Exception("板卡载入配置文件异常,错误码:" + res); } } /// /// 点位到点位运动 /// /// 运动对象 /// 运动控制+停止判断 public bool MoveToPoint(IOperationConfig opConfig) { bool resultOK = false; var gtsOperationConfig = opConfig as GTSCardOperationConfig; foreach (var movingOp in gtsOperationConfig.MovingOps) { resultOK = SingleAxisMoving(movingOp); } return resultOK; } /// /// Set AxisParam /// /// 运动参数对象 /// private bool SetAxisParam(MovingOption optionPara) { List resultCode = new List() { 0 }; GTSCardAPI.TTrapPrm trapprm; resultCode.Add(GTSCardAPI.GT_PrfTrap((short)IConfig.CardNum, (short)optionPara.AxisIndex)); resultCode.Add(GTSCardAPI.GT_GetTrapPrm((short)IConfig.CardNum, (short)optionPara.AxisIndex, out trapprm)); trapprm.smoothTime = 1; trapprm.acc = optionPara.VelocityPara.Acc != 0 ? optionPara.VelocityPara.Acc : 1; trapprm.dec = optionPara.VelocityPara.Dec != 0 ? optionPara.VelocityPara.Dec : 1; resultCode.Add(GTSCardAPI.GT_SetTrapPrm((short)IConfig.CardNum, (short)optionPara.AxisIndex, ref trapprm)); resultCode.Add(GTSCardAPI.GT_SetVel((short)IConfig.CardNum, (short)optionPara.AxisIndex, optionPara.VelocityPara.Velocity * IConfig.AxisVelocityRatio)); var resultOK = resultCode.All(u => u == (short)GTSRetCode.GRCRunOK); if (!resultOK) { throw new Exception("轴" + optionPara.AxisIndex + "设置参数异常,错误码:" + string.Join(",", resultCode)); } return resultOK; } /// /// 单个轴 点位到点位运动 /// /// 运动参数对象 public bool SingleAxisMoving(MovingOption optionPara) { bool isSuccessAndStop = false; if (IConfig.AxisSettings.FirstOrDefault(a => a.AxisIndex == optionPara.AxisIndex)?.IsAxisEnabled ?? false) { string _position = ""; string motionType = optionPara.MoveMode == EnumHelper.MotorMoveMode.Normal ? (optionPara.IsAbsolute ? "Abs" : "Rel") : optionPara.MoveMode.ToString(); _position = $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")},{optionPara.AxisIndex},{motionType},{GetPosition(optionPara.AxisIndex).ToString()},{GetPrfPosition(optionPara.AxisIndex).ToString()},{optionPara.Destination},"; switch (optionPara.MoveMode) { case MotorMoveMode.Normal: { if (_isResetting) { LogAsync(DateTime.Now, "复位中启动运动异常", optionPara.AxisIndex + "启动运动异常"); return false; } //设置 运动参数 var isSuccess = SetAxisParam(optionPara); if (isSuccess) { if (optionPara.IsAbsolute) { isSuccessAndStop = MoveAbs(optionPara); } else { isSuccessAndStop = MoveRel(optionPara); } } } break; case MotorMoveMode.FindOri: { isSuccessAndStop = GoHome(optionPara); } break; } _position += $"{GetPosition(optionPara.AxisIndex)},"; _position += $"{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}"; LogAsync(DateTime.Now, "", _position); } return isSuccessAndStop; } /// /// 获取规划位置(要去的位置) /// /// Axis number /// public double GetPrfPosition(int axisNum) { lock (moveLock) { double position = 0; double prfpos = 0; uint pclock = 0; var ret = GTSCardAPI.GT_GetPrfPos((short)IConfig.CardNum, (short)axisNum, out prfpos, 1, out pclock); if (ret != (short)GTSRetCode.GRCRunOK) { throw new Exception("轴" + axisNum + "获取规划位置异常,错误码:" + ret); } position = prfpos / IConfig.AxisVelocityRatio; return position; } } /// /// 获取目前当前位置 /// /// Axis number /// public double GetPosition(int axisNum) { lock (moveLock) { double position = 0; int pPos = 0; var ret = GTSCardAPI.GT_GetPos((short)IConfig.CardNum, (short)axisNum, out pPos); if (ret != (short)GTSRetCode.GRCRunOK) { throw new Exception("轴" + axisNum + "获取目标位置异常,错误码:" + ret); } position = pPos / IConfig.AxisVelocityRatio; return position; } } /// /// Set Single Axis Do Jog Move /// /// AxisNo /// Motion Direction 0: Negative, 1: Positive /// max velocity /// public bool StartJog(int axisNum, int nDirection, int velocity) { GTSCardAPI.TJogPrm jogprm = new GTSCardAPI.TJogPrm(); short rtn = GTSCardAPI.GT_PrfJog((short)IConfig.CardNum, (short)axisNum); jogprm.acc = 1; jogprm.dec = 1; GTSCardAPI.GT_SetJogPrm((short)IConfig.CardNum, (short)axisNum, ref jogprm);//设置jog运动参数 GTSCardAPI.GT_SetVel((short)IConfig.CardNum, (short)axisNum, velocity);//设置目标速度 int ret = GTSCardAPI.GT_Update((short)IConfig.CardNum, 1 << (axisNum - 1));//更新轴运动 if (ret != (int)GTSRetCode.GRCRunOK) { return false; } return true; } /// /// Set Single Axis Do stop Jog Move /// /// AxisNo /// public bool StopJog(int axisNum) { //停止运动 MoveStop(axisNum, 0); //运动开始后 检查运动是否停止 bool isStop = false; int repeatTime = 1000; do { isStop = IsStop((short)IConfig.CardNum, (short)axisNum); Thread.Sleep(50); repeatTime--; } while (!isStop && repeatTime > 0); return isStop; } /// /// 相对位置运动 /// /// AxisNo /// run distance /// public bool MoveRel(MovingOption optionPara) { try { if (_isResetting) { LogAsync(DateTime.Now, "复位过程异常", "轴" + optionPara.AxisIndex + "试图在复位过程中运动"); throw new Exception("轴" + optionPara.AxisIndex + "试图在复位过程中运动"); } int repeatTime = 30; while (CurrentState != EnumHelper.DeviceState.DSOpen && repeatTime > 0) { Thread.Sleep(10); repeatTime--; } if (CurrentState == EnumHelper.DeviceState.DSExcept) { LogAsync(DateTime.Now, "板卡异常状态", "轴" + optionPara.AxisIndex + "试图异常状态运动"); return false; } if (CurrentState != EnumHelper.DeviceState.DSOpen) { LogAsync(DateTime.Now, "非正常状态异常", "轴" + optionPara.AxisIndex + "试图在非正常状态运动"); throw new Exception("轴" + optionPara.AxisIndex + "试图在非正常状态运动", null); } LogAsync(DateTime.Now, "轴" + optionPara.AxisIndex + "开始运动", "目标坐标:" + optionPara.Destination); short ret = 0; repeatTime = 1000; int currentPosition = (int)GetPosition(optionPara.AxisIndex); int dPosition = optionPara.Destination + currentPosition; do { ret = GTSCardAPI.GT_SetPrfPos((short)IConfig.CardNum, (short)optionPara.AxisIndex, (int)(dPosition * IConfig.AxisVelocityRatio));// 设置规划位置 ret = GTSCardAPI.GT_Update((short)IConfig.CardNum, 1 << (optionPara.AxisIndex - 1));//更新运动 if (ret != (short)GTSRetCode.GRCRunOK) { LogAsync(DateTime.Now, "轴" + optionPara.AxisIndex + "APS_absolute_move异常", "错误码:" + ret + ";" + "重试次数:" + repeatTime); Thread.Sleep(50); } repeatTime--; } while (ret != (short)GTSRetCode.GRCRunOK && repeatTime > 0); //运动开始后 检查运动是否停止 bool isStop = false; repeatTime = 1000; do { isStop = IsStop((short)IConfig.CardNum, (short)optionPara.AxisIndex); Thread.Sleep(50); repeatTime--; } while (!isStop && repeatTime > 0); return (ret == (short)GTSRetCode.GRCRunOK) && isStop; } catch (Exception ex) { AllMoveStop(true); OnExceptionRaised?.Invoke(ex); return false; } } /// /// 绝对位置运动 /// /// 运动参数对象 public bool MoveAbs(MovingOption optionPara) { try { if (_isResetting) { LogAsync(DateTime.Now, "复位过程异常", "轴" + optionPara.AxisIndex + "试图在复位过程中运动"); throw new Exception("轴" + optionPara.AxisIndex + "试图在复位过程中运动"); } int repeatTime = 30; while (CurrentState != EnumHelper.DeviceState.DSOpen && repeatTime > 0) { Thread.Sleep(10); repeatTime--; } if (CurrentState == EnumHelper.DeviceState.DSExcept) { LogAsync(DateTime.Now, "板卡异常状态", "轴" + optionPara.AxisIndex + "试图异常状态运动"); return false; } if (CurrentState != EnumHelper.DeviceState.DSOpen) { LogAsync(DateTime.Now, "非正常状态异常", "轴" + optionPara.AxisIndex + "试图在非正常状态运动"); throw new Exception("轴" + optionPara.AxisIndex + "试图在非正常状态运动", null); } LogAsync(DateTime.Now, "轴" + optionPara.AxisIndex + "开始运动", "目标坐标:" + optionPara.Destination); short ret = 0; repeatTime = 1000; do { ret = GTSCardAPI.GT_SetPrfPos((short)IConfig.CardNum, (short)optionPara.AxisIndex, (int)(optionPara.Destination * IConfig.AxisVelocityRatio));// 设置规划位置 ret = GTSCardAPI.GT_Update((short)IConfig.CardNum, 1 << (optionPara.AxisIndex - 1));//更新运动 if (ret != (short)GTSRetCode.GRCRunOK) { LogAsync(DateTime.Now, "轴" + optionPara.AxisIndex + "APS_absolute_move异常", "错误码:" + ret + ";" + "重试次数:" + repeatTime); Thread.Sleep(50); } repeatTime--; } while (ret != (short)GTSRetCode.GRCRunOK && repeatTime > 0); bool isStop = false; repeatTime = 1000; do { isStop = IsStop((short)IConfig.CardNum, (short)optionPara.AxisIndex); Thread.Sleep(50); repeatTime--; } while (!isStop && repeatTime > 0); return (ret == (short)GTSRetCode.GRCRunOK) && isStop; } catch (Exception ex) { AllMoveStop(true); OnExceptionRaised?.Invoke(ex); return false; } } /// /// 运动停止 /// /// axisNo /// 0表示平滑停止,1表示紧急停止 /// public void MoveStop(int axisNum, int option) { if (option == 1) { StateChange(EnumHelper.DeviceState.DSExcept); } var ret = GTSCardAPI.GT_Stop((short)IConfig.CardNum, 1 << (axisNum - 1), option); if (ret != (short)GTSRetCode.GRCRunOK) { LogAsync(DateTime.Now, "轴" + axisNum + "运动停止异常", "错误码:" + ret); throw new Exception("轴" + axisNum + "运动停止异常,错误码:" + ret); } else { LogAsync(DateTime.Now, "轴" + axisNum + "运动停止", ""); } } /// /// 所有开启的轴关闭 /// /// public void AllMoveStop(bool emergencyStop = false) { int option = emergencyStop ? 1 : 0; IConfig.AxisSettings.Where(a => a.IsAxisEnabled).ToList().ForEach(axisNum => { MoveStop(axisNum.AxisIndex, option); }); } /// /// 回原点 /// /// 卡号 /// 轴号 /// 轴回原点状态 public bool GoHome(MovingOption movingOption) { try { GTSCardAPI.GT_ZeroPos((short)IConfig.CardNum, (short)movingOption.AxisIndex, 1); GTSCardAPI.THomePrm thomeprm; GTSCardAPI.THomeStatus homests; short rtn = GTSCardAPI.GT_GetHomePrm((short)IConfig.CardNum, (short)movingOption.AxisIndex, out thomeprm); thomeprm.mode = movingOption.GoHomePara.HomeMode;//回零方式 thomeprm.moveDir = movingOption.GoHomePara.HomeDir;//回零方向 thomeprm.edge = movingOption.GoHomePara.Edge; thomeprm.velHigh = movingOption.GoHomePara.HighVelocity; thomeprm.velLow = movingOption.GoHomePara.LowVelocity; thomeprm.acc = movingOption.VelocityPara.Acc; thomeprm.dec = movingOption.VelocityPara.Dec; thomeprm.searchHomeDistance = movingOption.GoHomePara.SearchHomeDistance;//搜搜距离 thomeprm.homeOffset = movingOption.GoHomePara.HomeOffset; //偏移距离 thomeprm.escapeStep = movingOption.GoHomePara.EscapeStep; rtn = GTSCardAPI.GT_GoHome((short)IConfig.CardNum, (short)movingOption.AxisIndex, ref thomeprm); //启动回零 bool isStop = false; int repeatTime = 1000; do { Thread.Sleep(10); GTSCardAPI.GT_GetHomeStatus((short)IConfig.CardNum, (short)movingOption.AxisIndex, out homests); isStop = homests.run == 0; if (isStop && homests.error == 0) { Thread.Sleep(200); GTSCardAPI.GT_ZeroPos((short)IConfig.CardNum, (short)movingOption.AxisIndex, 1); } repeatTime--; } while (!isStop && repeatTime > 0); return isStop; } catch (Exception ex) { AllMoveStop(true); OnExceptionRaised?.Invoke(ex); return false; } } /// /// 读取输入 /// /// 卡号 /// 输入口 /// 有输入返回true,无输入返回false public bool GetDi(short cardNum, short index) { int value; GTSCardAPI.GT_GetDi(cardNum, GTSCardAPI.MC_GPI, out value); if ((value & 1 << index) == 0) return true;//有输入返回true else return false; //无输入返回false } /// /// 输出 /// /// 卡号 /// 输出口,返回1-16 /// false表示输出,true表示关闭 public void WriteOut(short cardNum, short index, bool value) { short outNum = (short)(index % 100 + 1); if (value) { GTSCardAPI.GT_SetDoBit(cardNum, GTSCardAPI.MC_GPO, outNum, 0); } else { GTSCardAPI.GT_SetDoBit(cardNum, GTSCardAPI.MC_GPO, outNum, 1); } } /// /// 停止 某个轴 /// /// /// 轴号 /// 停止方式,false表示平滑停止,true表示紧急停止 public void Stop(short cardNum, short axisNum, bool emergencyStop) { if (emergencyStop) { GTSCardAPI.GT_Stop(cardNum, 1 << (axisNum - 1), 1 << (axisNum - 1)); } else { GTSCardAPI.GT_Stop(cardNum, 1 << (axisNum - 1), 0); } } /// /// IO输出 /// /// 卡号 /// 模块号 /// IO输出 /// true表示输出,false表示无输出 public void MC_WriteDigitalOutput(short cardNum, short mdl, short index, bool value) { if (value) { GTSCardAPI.GT_SetExtIoBit(cardNum, mdl, index, 0); } else { GTSCardAPI.GT_SetExtIoBit(cardNum, mdl, index, 1); } } /// /// 读取IO输出状态 /// /// /// /// public bool GetDoSts(short cardNum, short index) { short outNum = 0; int outSts; outNum = (short)(index % 100); GTSCardAPI.GT_GetDo(cardNum, GTSCardAPI.MC_GPO, out outSts); if ((outSts & (1 << outNum)) == 0) return true; else return false; } /// /// 读取轴状态,判断电机是否停止 /// /// 板卡号 /// 轴号 /// public bool IsStop(short cardNum, short axisNum) { lock (moveLock) { int sts = 0; uint pclock = 0; GTSCardAPI.GT_GetSts(cardNum, axisNum, out sts, 1, out pclock); if ((sts & 0x400) == 0) return true;//停止返回true else return false; //运行中返回false } } #endregion public void Monitor() { throw new NotImplementedException(); } public void ResetAlarm() { throw new NotImplementedException(); } } }