src/Bro.Common.Model/Helper/EnumHelper.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/Bro.Device.GTSCard/Bro.Device.GTSCard.csproj | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/Bro.Device.GTSCard/GTS800.cfg | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/Bro.Device.GTSCard/GTSCardAPI.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/Bro.Device.GTSCard/GTSCardConfig.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/Bro.Device.GTSCard/GTSCardDriver.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/Bro.Device.GTSCard/gts.dll | 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/Bro.Device.GTSCard/packages.config | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
src/Bro.Common.Model/Helper/EnumHelper.cs
@@ -443,5 +443,145 @@ [Description("相机坐标系相对运动")] CameraRelativeMove = 12, } /// <summary> /// 马达/运动板卡运行模式 /// </summary> public enum MotorMoveMode { /// <summary> /// 普通点位运动 /// </summary> [Description("普通点位运动")] Normal = 1, ///// <summary> ///// 高速等距运动 ///// </summary> //[Description("高速等距运动")] //HighSpeedStep = 2, ///// <summary> ///// 高速不等距运动 ///// </summary> //[Description("高速不等距运动")] //HighSpeed = 3, /// <summary> /// 找正限位运动 /// </summary> [Description("找正限位运动")] FindPositive = 4, /// <summary> /// 离开正限位 /// </summary> [Description("离开正限位")] LeavePositive = 5, /// <summary> /// 找负限位运动 /// </summary> [Description("找负限位运动")] FindNegative = 6, /// <summary> /// 离开负限位 /// </summary> [Description("离开负限位")] LeaveNegative = 7, /// <summary> /// 找原点运动 /// </summary> [Description("找原点运动")] FindOri = 8, /// <summary> /// Jog模式 /// </summary> [Description("Jog模式")] Jog = 9, /// <summary> /// 读数头找原点方式 /// </summary> [Description("读数头找原点方式")] FindOriIndex = 10, /// <summary> /// 插补模式 /// </summary> [Description("插补模式")] Coordinate = 11, ///// <summary> ///// 刀向更随功能 ///// </summary> //[Description("刀向更随功能")] //BufMove = 12, } /// <summary> /// 马达IO定义类型 /// </summary> public enum MotorIODefine { Nothing, InputStartLeft, InputStartRight, InputCurtainLeft, InputCurtainRight, InputSafeDoor, InputEmergency, InputReset, InputScrew1, InputScrew2, InputSuckLeft, InputSuckRight, InputSuckXYZ, InputCylinderLeftLimitFront, InputCylinderLeftLimitBack, InputCylinderRightLimitFront, InputCylinderRightLimitBack, OutputYellow, OutputGreen, OutputRed, OutputBeep, OutputLight, OutputMotorPower, OutputInitOK, OutputZLock, OutputLeftCylinder, OutputRightCylinder, OutputLeftSuck, OutputRightSuck, OutputScrewBlow, OutputCamera, OutputScrewSuck, } /// <summary> /// GTS运动板卡控制返回控制码 /// </summary> public enum GTSRetCode { [Description("指令执行成功")] GRCRunOK = 0, // 指令执行成功 [Description("指令执行错误")] GRCRunErr = 1, // 指令执行错误 [Description("icense不支持")] GRCNotSupport = 2, // icense不支持 [Description("指令参数错误")] GRCInvalidParam = 7, // 指令参数错误 [Description("主机和运动控制器通讯失败")] GRCCommErr = -1, // 主机和运动控制器通讯失败 [Description("打开控制器失败")] GRCOpenErr = -6, // 打开控制器失败 [Description("运动控制器没有响应")] GRCNotAck = -7 // 运动控制器没有响应 } } } src/Bro.Device.GTSCard/Bro.Device.GTSCard.csproj
@@ -31,6 +31,9 @@ <WarningLevel>4</WarningLevel> </PropertyGroup> <ItemGroup> <Reference Include="Newtonsoft.Json, Version=11.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> <HintPath>..\..\packages\Newtonsoft.Json.11.0.2\lib\net45\Newtonsoft.Json.dll</HintPath> </Reference> <Reference Include="System" /> <Reference Include="System.Configuration" /> <Reference Include="System.Core" /> @@ -63,5 +66,12 @@ <Name>Bro.Common.Model</Name> </ProjectReference> </ItemGroup> <ItemGroup> <Content Include="gts.dll" /> </ItemGroup> <ItemGroup> <None Include="GTS800.cfg" /> <None Include="packages.config" /> </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> </Project> src/Bro.Device.GTSCard/GTS800.cfg
New file @@ -0,0 +1,793 @@ [profile1] active=1 decSmoothStop=1.000000 decAbruptStop=1000.000000 [profile2] active=1 decSmoothStop=1.000000 decAbruptStop=1000.000000 [profile3] active=1 decSmoothStop=1.000000 decAbruptStop=1000.000000 [profile4] active=1 decSmoothStop=1.000000 decAbruptStop=1000.000000 [profile5] active=1 decSmoothStop=1.000000 decAbruptStop=1000.000000 [profile6] active=1 decSmoothStop=1.000000 decAbruptStop=1000.000000 [profile7] active=1 decSmoothStop=1.000000 decAbruptStop=1000.000000 [profile8] active=1 decSmoothStop=1.000000 decAbruptStop=1000.000000 [axis1] active=1 alarmType=2 alarmIndex=1 limitPositiveType=0 limitPositiveIndex=1 limitNegativeType=1 limitNegativeIndex=1 smoothStopType=4 smoothStopIndex=-1 abruptStopType=4 abruptStopIndex=5 prfMap=0x1 encMap=0x1 prfMapAlpha1=1 prfMapBeta1=1 prfMapAlpha2=1 prfMapBeta2=1 encMapAlpha1=1 encMapBeta1=1 encMapAlpha2=1 encMapBeta2=1 [axis2] active=1 alarmType=2 alarmIndex=2 limitPositiveType=0 limitPositiveIndex=2 limitNegativeType=1 limitNegativeIndex=2 smoothStopType=4 smoothStopIndex=-1 abruptStopType=4 abruptStopIndex=5 prfMap=0x2 encMap=0x2 prfMapAlpha1=1 prfMapBeta1=1 prfMapAlpha2=1 prfMapBeta2=1 encMapAlpha1=1 encMapBeta1=1 encMapAlpha2=1 encMapBeta2=1 [axis3] active=1 alarmType=2 alarmIndex=3 limitPositiveType=0 limitPositiveIndex=3 limitNegativeType=1 limitNegativeIndex=3 smoothStopType=4 smoothStopIndex=-1 abruptStopType=4 abruptStopIndex=5 prfMap=0x4 encMap=0x4 prfMapAlpha1=1 prfMapBeta1=1 prfMapAlpha2=1 prfMapBeta2=1 encMapAlpha1=1 encMapBeta1=1 encMapAlpha2=1 encMapBeta2=1 [axis4] active=1 alarmType=2 alarmIndex=4 limitPositiveType=0 limitPositiveIndex=4 limitNegativeType=1 limitNegativeIndex=4 smoothStopType=4 smoothStopIndex=-1 abruptStopType=4 abruptStopIndex=5 prfMap=0x8 encMap=0x8 prfMapAlpha1=1 prfMapBeta1=1 prfMapAlpha2=1 prfMapBeta2=1 encMapAlpha1=1 encMapBeta1=1 encMapAlpha2=1 encMapBeta2=1 [axis5] active=1 alarmType=2 alarmIndex=5 limitPositiveType=0 limitPositiveIndex=5 limitNegativeType=1 limitNegativeIndex=5 smoothStopType=4 smoothStopIndex=-1 abruptStopType=4 abruptStopIndex=-1 prfMap=0x10 encMap=0x10 prfMapAlpha1=1 prfMapBeta1=1 prfMapAlpha2=1 prfMapBeta2=1 encMapAlpha1=1 encMapBeta1=1 encMapAlpha2=1 encMapBeta2=1 [axis6] active=1 alarmType=2 alarmIndex=6 limitPositiveType=0 limitPositiveIndex=6 limitNegativeType=1 limitNegativeIndex=6 smoothStopType=4 smoothStopIndex=-1 abruptStopType=4 abruptStopIndex=-1 prfMap=0x20 encMap=0x20 prfMapAlpha1=1 prfMapBeta1=1 prfMapAlpha2=1 prfMapBeta2=1 encMapAlpha1=1 encMapBeta1=1 encMapAlpha2=1 encMapBeta2=1 [axis7] active=1 alarmType=2 alarmIndex=7 limitPositiveType=0 limitPositiveIndex=7 limitNegativeType=1 limitNegativeIndex=7 smoothStopType=4 smoothStopIndex=-1 abruptStopType=4 abruptStopIndex=-1 prfMap=0x40 encMap=0x40 prfMapAlpha1=1 prfMapBeta1=1 prfMapAlpha2=1 prfMapBeta2=1 encMapAlpha1=1 encMapBeta1=1 encMapAlpha2=1 encMapBeta2=1 [axis8] active=1 alarmType=2 alarmIndex=8 limitPositiveType=0 limitPositiveIndex=8 limitNegativeType=1 limitNegativeIndex=8 smoothStopType=4 smoothStopIndex=-1 abruptStopType=4 abruptStopIndex=-1 prfMap=0x80 encMap=0x80 prfMapAlpha1=1 prfMapBeta1=1 prfMapAlpha2=1 prfMapBeta2=1 encMapAlpha1=1 encMapBeta1=1 encMapAlpha2=1 encMapBeta2=1 [dac1] active=1 control=-1 reverse=0 bias=0 limit=32767 [dac2] active=1 control=-1 reverse=0 bias=0 limit=32767 [dac3] active=1 control=-1 reverse=0 bias=0 limit=32767 [dac4] active=1 control=-1 reverse=0 bias=0 limit=32767 [dac5] active=1 control=-1 reverse=0 bias=0 limit=32767 [dac6] active=1 control=-1 reverse=0 bias=0 limit=32767 [dac7] active=1 control=-1 reverse=0 bias=0 limit=32767 [dac8] active=1 control=-1 reverse=0 bias=0 limit=32767 [dac9] active=1 control=-1 reverse=0 bias=0 limit=32767 [dac10] active=1 control=-1 reverse=0 bias=0 limit=32767 [dac11] active=1 control=-1 reverse=0 bias=0 limit=32767 [dac12] active=1 control=-1 reverse=0 bias=0 limit=32767 [step1] active=1 axis=1 mode=0 parameter=0 reverse=0 [step2] active=1 axis=2 mode=0 parameter=0 reverse=0 [step3] active=1 axis=3 mode=0 parameter=0 reverse=0 [step4] active=1 axis=4 mode=0 parameter=0 reverse=0 [encoder1] active=1 reverse=1 filterType=0 captureSource=0 captureHomeSense=0 captureIndexSense=0 [encoder2] active=1 reverse=1 filterType=0 captureSource=0 captureHomeSense=0 captureIndexSense=0 [encoder3] active=1 reverse=1 filterType=0 captureSource=0 captureHomeSense=0 captureIndexSense=0 [encoder4] active=1 reverse=1 filterType=0 captureSource=0 captureHomeSense=0 captureIndexSense=0 [encoder5] active=1 reverse=1 filterType=0 captureSource=0 captureHomeSense=0 captureIndexSense=0 [encoder6] active=1 reverse=1 filterType=0 captureSource=0 captureHomeSense=0 captureIndexSense=0 [encoder7] active=1 reverse=1 filterType=0 captureSource=0 captureHomeSense=0 captureIndexSense=0 [encoder8] active=1 reverse=1 filterType=0 captureSource=0 captureHomeSense=0 captureIndexSense=0 [encoder9] active=1 reverse=1 filterType=0 captureSource=0 captureHomeSense=0 captureIndexSense=0 [encoder10] active=1 reverse=1 filterType=0 captureSource=0 captureHomeSense=0 captureIndexSense=0 [encoder11] active=1 reverse=1 filterType=0 captureSource=0 captureHomeSense=0 captureIndexSense=0 [enable1] active=1 axis=1 axisItem=-1 reverse=1 [enable2] active=1 axis=2 axisItem=-1 reverse=1 [enable3] active=1 axis=3 axisItem=-1 reverse=1 [enable4] active=1 axis=4 axisItem=-1 reverse=1 [enable5] active=1 axis=5 axisItem=-1 reverse=1 [enable6] active=1 axis=6 axisItem=-1 reverse=1 [enable7] active=1 axis=7 axisItem=-1 reverse=1 [enable8] active=1 axis=8 axisItem=-1 reverse=1 [clear1] active=1 axis=-1 axisItem=-1 reverse=0 [clear2] active=1 axis=-1 axisItem=-1 reverse=0 [clear3] active=1 axis=-1 axisItem=-1 reverse=0 [clear4] active=1 axis=-1 axisItem=-1 reverse=0 [clear5] active=1 axis=-1 axisItem=-1 reverse=0 [clear6] active=1 axis=-1 axisItem=-1 reverse=0 [clear7] active=1 axis=-1 axisItem=-1 reverse=0 [clear8] active=1 axis=-1 axisItem=-1 reverse=0 [gpo1] active=1 axis=-1 axisItem=-1 reverse=0 [gpo2] active=1 axis=-1 axisItem=-1 reverse=1 [gpo3] active=1 axis=-1 axisItem=-1 reverse=0 [gpo4] active=1 axis=-1 axisItem=-1 reverse=0 [gpo5] active=1 axis=-1 axisItem=-1 reverse=0 [gpo6] active=1 axis=-1 axisItem=-1 reverse=0 [gpo7] active=1 axis=-1 axisItem=-1 reverse=0 [gpo8] active=1 axis=-1 axisItem=-1 reverse=0 [gpo9] active=1 axis=-1 axisItem=-1 reverse=0 [gpo10] active=1 axis=-1 axisItem=-1 reverse=0 [gpo11] active=1 axis=-1 axisItem=-1 reverse=0 [gpo12] active=1 axis=-1 axisItem=-1 reverse=0 [gpo13] active=1 axis=-1 axisItem=-1 reverse=0 [gpo14] active=1 axis=-1 axisItem=-1 reverse=0 [gpo15] active=1 axis=-1 axisItem=-1 reverse=0 [gpo16] active=1 axis=-1 axisItem=-1 reverse=0 [limitPositive1] active=1 reverse=0 filterTime=3 [limitPositive2] active=1 reverse=0 filterTime=3 [limitPositive3] active=1 reverse=0 filterTime=3 [limitPositive4] active=1 reverse=0 filterTime=3 [limitPositive5] active=1 reverse=0 filterTime=3 [limitPositive6] active=1 reverse=0 filterTime=3 [limitPositive7] active=1 reverse=0 filterTime=3 [limitPositive8] active=1 reverse=0 filterTime=3 [limitNegative1] active=1 reverse=0 filterTime=3 [limitNegative2] active=1 reverse=0 filterTime=3 [limitNegative3] active=1 reverse=0 filterTime=3 [limitNegative4] active=1 reverse=0 filterTime=3 [limitNegative5] active=1 reverse=0 filterTime=3 [limitNegative6] active=1 reverse=0 filterTime=3 [limitNegative7] active=1 reverse=0 filterTime=3 [limitNegative8] active=1 reverse=0 filterTime=3 [alarm1] active=1 reverse=0 filterTime=3 [alarm2] active=1 reverse=0 filterTime=3 [alarm3] active=1 reverse=0 filterTime=3 [alarm4] active=1 reverse=0 filterTime=3 [alarm5] active=1 reverse=0 filterTime=3 [alarm6] active=1 reverse=0 filterTime=3 [alarm7] active=1 reverse=0 filterTime=3 [alarm8] active=1 reverse=0 filterTime=3 [home1] active=1 reverse=0 filterTime=3 [home2] active=1 reverse=0 filterTime=3 [home3] active=1 reverse=0 filterTime=3 [home4] active=1 reverse=0 filterTime=3 [home5] active=1 reverse=0 filterTime=3 [home6] active=1 reverse=0 filterTime=3 [home7] active=1 reverse=0 filterTime=3 [home8] active=1 reverse=0 filterTime=3 [gpi1] active=1 reverse=0 filterTime=3 [gpi2] active=1 reverse=0 filterTime=3 [gpi3] active=1 reverse=0 filterTime=3 [gpi4] active=1 reverse=0 filterTime=3 [gpi5] active=1 reverse=0 filterTime=3 [gpi6] active=1 reverse=0 filterTime=3 [gpi7] active=1 reverse=0 filterTime=3 [gpi8] active=1 reverse=0 filterTime=3 [gpi9] active=1 reverse=0 filterTime=3 [gpi10] active=1 reverse=0 filterTime=3 [gpi11] active=1 reverse=0 filterTime=3 [gpi12] active=1 reverse=0 filterTime=3 [gpi13] active=1 reverse=0 filterTime=3 [gpi14] active=1 reverse=0 filterTime=3 [gpi15] active=1 reverse=0 filterTime=3 [gpi16] active=1 reverse=0 filterTime=3 [arrive1] active=1 reverse=0 filterTime=3 [arrive2] active=1 reverse=0 filterTime=3 [arrive3] active=1 reverse=0 filterTime=3 [arrive4] active=1 reverse=0 filterTime=3 [arrive5] active=1 reverse=0 filterTime=3 [arrive6] active=1 reverse=0 filterTime=3 [arrive7] active=1 reverse=0 filterTime=3 [arrive8] active=1 reverse=0 filterTime=3 [mpg1] active=1 reverse=0 filterTime=3 [mpg2] active=1 reverse=0 filterTime=3 [mpg3] active=1 reverse=0 filterTime=3 [mpg4] active=1 reverse=0 filterTime=3 [mpg5] active=1 reverse=0 filterTime=3 [mpg6] active=1 reverse=0 filterTime=3 [mpg7] active=1 reverse=0 filterTime=3 src/Bro.Device.GTSCard/GTSCardAPI.cs
@@ -143,6 +143,16 @@ public const short LASER_CTRL_VOLTAGE = 2; public const short LASER_CTRL_MODE_PWM2 = 3; //指令返回值 public const short ResultSuccess = 0; public const short ResultError = 1; public const short ResultNotSupported = 2; public const short ParameterError = 7; public const short CommunicationFailed = -1; public const short OpenFailed = -6; public const short NoResponse = -7; public struct TTrapPrm { public double acc; src/Bro.Device.GTSCard/GTSCardConfig.cs
@@ -1,247 +1,675 @@ using Bro.Common.Base; using Bro.Common.Helper; using Bro.Common.Interface; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Configuration; using System.Drawing.Design; using System.Linq; using System.Threading; using static Bro.Common.Helper.EnumHelper; namespace Bro.Device.GTSCard { public abstract class GTSCardOperationConfigBase : OperationConfigBase [Device("GTSCard", "固高板卡", EnumHelper.DeviceAttributeType.OperationConfig)] public class GTSCardOperationConfig : OperationConfigBase, IComplexDisplay { ///// <summary> ///// 需要操作的PLC项 ///// </summary> //public List<PLCItem> Items { get; set; } = new List<PLCItem>(); [Category("板卡运动配置")] [DisplayName("运动配置集合")] [Description("MovingOps:运动配置集合")] [TypeConverter(typeof(CollectionCountConvert))] [Editor(typeof(ComplexCollectionEditor<MovingOption>), typeof(UITypeEditor))] public ObservableCollection<MovingOption> MovingOps { get; set; } = new ObservableCollection<MovingOption>(); public string GetDisplayText() { return MovingOps.Count() == 0 ? "--" : string.Join(";", MovingOps.Select(m => m.GetDisplayText())); } } //public class GTSCardInitialConfigBase : InitialConfigBase, IMonitorConfig //{ // [Category("驱动类型")] // [Description("驱动类型")] // [DisplayName("驱动类型")] // [TypeConverter(typeof(PLCTypeConverter))] // public override string DriverType { get; set; } [Device("GTSCard", "固高板卡", EnumHelper.DeviceAttributeType.OperationConfig)] public class GTSCardInitialConfig : InitialConfigBase, IMonitorConfig { [Category("板卡配置")] [DisplayName("卡号")] [Description("CardNum:卡号")] public int CardNum { get; set; } // [Category("警报配置")] // [Description("警报配置列表")] // [DisplayName("警报配置")] // [TypeConverter(typeof(CollectionCountConvert))] // [Editor(typeof(WarningSetsEditor), typeof(UITypeEditor))] // public List<WarningSet> WarningSetCollection { get; set; } = new List<WarningSet>(); //[Category("板卡配置")] //[Description("IO卡号")] //public int IOCardNum { get; set; } // #region IMonitorConfig // [Category("监听设置")] // [Description("监听操作配置集合")] // [DisplayName("监听配置")] // [TypeConverter(typeof(CollectionCountConvert))] // [Editor(typeof(ComplexCollectionEditor<MonitorSet>), typeof(UITypeEditor))] // public List<IMonitorSet> MonitorSetCollection { get; set; } = new List<IMonitorSet>(); [Category("板卡配置")] [DisplayName("初始配置文件路径")] [Description("InitialConfigFilePath:初始配置文件路径")] [Editor(typeof(FileDialogEditor), typeof(UITypeEditor))] public string InitialConfigFilePath { get; set; } // [Category("监听设置")] // [Description("true:启动监听 false:关闭监听")] // [DisplayName("监听启用")] // public bool IsEnableMonitor { get; set; } = true; [Category("IO扫描配置")] [DisplayName("扫描间隔")] [Description("ScanInterval:扫描间隔,以毫秒为单位")] public int ScanInterval { get; set; } = 100; // [Category("监听设置")] // [Description("扫描间隔时间,单位:ms")] // [DisplayName("扫描间隔")] // public int MonitorInterval { get; set; } = 100; [Category("轴配置")] [DisplayName("轴数量")] [Description("AxisNum:轴数量")] public int AxisNum { get; set; } = 2; // [Category("监听设置")] // [Description("超时设置,单位:ms")] // [DisplayName("监听超时")] // public int MonitorTimeout { get; set; } = 500; [Category("轴配置")] [DisplayName("轴配置信息集合")] [Description("AxisSettings:轴配置信息集合")] [TypeConverter(typeof(CollectionCountConvert))] [Editor(typeof(ComplexCollectionEditor<AxisSetting>), typeof(UITypeEditor))] public List<AxisSetting> AxisSettings { get; set; } = new List<AxisSetting>(); // [Category("事件地址设置")] // [Description("事件开始地址,PLC的实际寄存器地址。十进制,不包含功能码。")] // [DisplayName("监听开始地址")] // public int EventStartAddress { get; set; } = 8000; [Category("轴配置")] [DisplayName("轴速度比率")] [Description("AxisVelocityRatio:轴速度比率")] public double AxisVelocityRatio { get; set; } = 1; // [Category("事件地址设置")] // [Description("事件地址长度,最大长度128")] // [DisplayName("监听长度")] // public int EventLength { get; set; } = 120; [Category("延时配置")] [DisplayName("动作完成后延迟")] [Description("ActionAfterDelay:动作完成后延迟")] public int ActionAfterDelay { get; set; } = 100; // public List<IMonitorSet> GetAllMonitorSet() // { // WarningSetCollection.ForEach(m => m.Source = this.Name); public bool IsEnableMonitor { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } public int MonitorInterval { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } public int MonitorTimeout { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } public List<IMonitorSet> MonitorSetCollection { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } // MonitorSetCollection.ForEach(m => m.SourceDevice = this.Id); // return MonitorSetCollection; // } // #endregion // #region IMotion Related // [Category("运动配置")] // [Description("运动轴状态集合")] // [DisplayName("运动轴状态集合")] // [TypeConverter(typeof(CollectionCountConvert))] // [Editor(typeof(ComplexCollectionEditor<PLCMotionDefinition_State>), typeof(UITypeEditor))] // public List<PLCMotionDefinition_State> MotionStateCollection { get; set; } = new List<PLCMotionDefinition_State>(); // #endregion //} public List<IMonitorSet> GetAllMonitorSet() { throw new NotImplementedException(); } } /// <summary> /// 点位类型 /// 轴配置 /// </summary> public enum PosType public class AxisSetting : IComplexDisplay { /// <summary> /// 直线插补 /// </summary> Line = 1, /// <summary> /// 圆弧插补(半径) /// </summary> CircleRadius, /// <summary> /// 圆弧插补(圆心) /// </summary> CircleCenter [Category("轴配置")] [DisplayName("轴号索引")] [Description("AxisIndex:轴号索引")] public int AxisIndex { get; set; } [Category("轴配置")] [DisplayName("轴名称")] [Description("AxisName:轴名称")] public string AxisName { get; set; } [Category("轴配置")] [DisplayName("轴是否启用")] [Description("IsAxisEnabled:轴是否启用")] public bool IsAxisEnabled { get; set; } = false; [Category("换算配置")] [DisplayName("脉冲数换算比例")] [Description("脉冲数和其他计量单位的换算比例,例如设置为1000,表示1000个脉冲等于1uint")] public int PulseRatio { get; set; } = 1; [Category("速度配置")] [DisplayName("默认速度参数")] [Description("VelocityPara:默认速度参数")] [TypeConverter(typeof(ComplexObjectConvert))] [Editor(typeof(PropertyObjectEditor), typeof(UITypeEditor))] public VelocityPara VelocityPara { get; set; } = new VelocityPara(); [Category("回原点设置")] [DisplayName("回原点模式")] [Description("HomeMode:回原点模式。0:一般模式 1:极限限位模式 2:外部触发模式")] public int HomeMode { get; set; } = 0; [Category("回原点设置")] [DisplayName("回原点方向")] [Description("IsHomePositive:回原点方向。 true:正方向开始 false:负方向开始")] public bool IsHomePositive { get; set; } = true; [Category("回原点设置")] [DisplayName("是否自动回原点")] [Description("IsAutoGoHome:是否自动回原点。 true:是 false:否")] public bool IsAutoGoHome { get; set; } = false; [Category("超时设置")] [DisplayName("回原点超时")] [Description("TimeOutHome:回原点超时,单位毫秒")] public int TimeOutHome { get; set; } = 30000; [Category("超时设置")] [DisplayName("运动超时")] [Description("TimeOutMove:运动超时,单位毫秒")] public int TimeOutMove { get; set; } = 10000; [Category("开闭环设置")] [DisplayName("是否使用Cmmd回馈")] [Description("IsUseCmmdPosition:是否使用Cmmd回馈")] public bool IsUseCmmdPosition { get; set; } = false; [Category("开闭环设置")] [DisplayName("是否使用板卡反馈停止信号")] [Description("IsUseMDNStopSignal:是否使用板卡反馈停止信号")] public bool IsUseMDNStopSignal { get; set; } = false; [Category("开闭环设置")] [DisplayName("是否启用报警")] [Description("IsUseWarning:是否启用报警")] public bool IsUseWarning { get; set; } = false; [Category("暂停配置")] [DisplayName("是否启用立即暂停")] [Description("IsImmediatePause:是否启用立即暂停")] public bool IsImmediatePause { get; set; } = false; [Category("暂停配置")] [DisplayName("轴位置处于区间内时适用的暂停操作")] [Description("ImmediatePauseSections:当轴位置处于区间内时适用的暂停操作")] [TypeConverter(typeof(CollectionCountConvert))] [Editor(typeof(ComplexCollectionEditor<Section>), typeof(UITypeEditor))] public List<Section> ImmediatePauseSections { get; set; } = new List<Section>(); public string GetDisplayText() { return AxisIndex + "-" + AxisName + "-" + (IsAxisEnabled ? "启用" : "禁用"); } } public static class GTSCardParameter /// <summary> /// 位置对象 /// </summary> public class Section : IComplexDisplay { #region 运动参数 public static int Dangliang = 1; public static int AxisCount = 2;//运动轴数量 public static short CardNum = Convert.ToInt16(ConfigurationManager.AppSettings["cardNum"]); public static short fifo = Convert.ToInt16(ConfigurationManager.AppSettings["fifo"]); public static int FlySpeed = Convert.ToInt32(ConfigurationManager.AppSettings["flySpeed"]); public static double FlyAcc = Convert.ToDouble(ConfigurationManager.AppSettings["flyAcc"]); public static int P2PSpeed = Convert.ToInt32(ConfigurationManager.AppSettings["p2pSpeed"]); public static double P2PAcc = Convert.ToDouble(ConfigurationManager.AppSettings["p2pAcc"]); public static double P2PDec = Convert.ToDouble(ConfigurationManager.AppSettings["p2pDec"]); public static int FreeSpeed = Convert.ToInt32(ConfigurationManager.AppSettings["freeSpeed"]); public static int VelEnd = Convert.ToInt32(ConfigurationManager.AppSettings["velEnd"]);//飞拍结束速度 public static int HomeSpeed = Convert.ToInt32(ConfigurationManager.AppSettings["homeSpeed"]); public static int Loading = Convert.ToInt32(ConfigurationManager.AppSettings["loading"]); //public const short cardn = 0;//运动控制器卡号 默认为:0 //public const short crdn = 1;//坐标系号 取值范围:[1, 2] //public const short fifo = 0;//插补缓存区号 取值范围:[0, 1],默认值为:0 //public const int flySpeed = 250;//飞拍速度 //public const double flyAcc = 0.5;//飞拍加速度 //public const int gocatorSpeed = 150;//3D检测轴运动速度 //public const int p2pSpeed = 250;//P2P速度 //public const double p2pAcc = 1;//P2P加速度 //public const double p2pDec = 1;//P2P减速度 //public const int calibrationSpeed = 10;//标定速度 //public const int calibrationZ = 19336;//标定Z轴高度 //public const int barcodeSpeed = 250;//条码检测轴运动速度 //public const int freeSpeed = 250;//非检测时轴运动速度 //public const int velEnd = 0;//飞拍结束速度 //public const int homeSpeed = 50;//回零速度 //public const int loading = 80000;//上料位置 #endregion [Category("暂停区间")] [DisplayName("起始位置")] [Description("StartPosition:起始位置")] public int StartPosition { get; set; } #region IO /// <summary> /// 输入IO默认值 /// </summary> public const int InDefaultValue = 0xFFDA; /// <summary> /// 夹紧气缸 /// </summary> public const short EXO_1 = 100;//夹紧气缸 /// <summary> /// 日光灯 /// </summary> public const short EXO_2 = 101;//日光灯 /// <summary> /// 光源切换 /// </summary> public const short EXO_3 = 102;//光源切换 /// <summary> /// 红灯 /// </summary> public const short EXO_4 = 103;//红灯 /// <summary> /// 黄灯 /// </summary> public const short EXO_5 = 104;//黄灯 /// <summary> /// 绿灯 /// </summary> public const short EXO_6 = 105;//绿灯 /// <summary> /// 蜂鸣器 /// </summary> public const short EXO_7 = 106;//蜂鸣器 /// <summary> /// Gocator X /// </summary> public const short EXO_8 = 107;//Gocator X [Category("暂停区间")] [DisplayName("结束位置")] [Description("EndPosition:结束位置")] public int EndPosition { get; set; } /// <summary> /// 正面光(左) /// </summary> public const short EXO_9 = 108;//正面光(左) /// <summary> /// 正面光(后) /// </summary> public const short EXO_10 = 109;//正面光(后) /// <summary> /// 正面光(右) /// </summary> public const short EXO_11 = 110;//正面光(右) /// <summary> /// 正面光(前) /// </summary> public const short EXO_12 = 111;//正面光(前) /// <summary> /// Gocator Y /// </summary> public const short EXO_16 = 115;//Gocator Y /// <summary> /// 输出IO默认值 /// </summary> public const int OutDefaultValue = 0xFFF; /// <summary> /// 左启动 /// </summary> public const short EXI0 = 0;//左起动 /// <summary> /// 右启动 /// </summary> public const short EXI1 = 1;//右起动 /// <summary> /// 停止 /// </summary> public const short EXI2 = 2;//停止 /// <summary> /// 复位 /// </summary> public const short EXI3 = 3;//复位 /// <summary> /// 急停 /// </summary> public const short EXI4 = 4;//急停 /// <summary> /// 门开关 /// </summary> public const short EXI5 = 5;//门开关 /// <summary> /// 安全光幕 /// </summary> public const short EXI6 = 6;//安全光幕 public const short EXI7 = 7;// /// <summary> /// 夹紧气缸原位 /// </summary> public const short EXI8 = 8;//夹紧气缸原位 /// <summary> /// 夹紧气缸到位 /// </summary> public const short EXI9 = 9;//夹紧气缸到位 #endregion public string GetDisplayText() { return $"{StartPosition}--{EndPosition}"; } } /// <summary> /// 速度参数对象 /// </summary> public class VelocityPara { [Category("速度配置")] [DisplayName("速度")] [Description("Velocity:速度,为0时表示不修改当前设置")] public double Velocity { get; set; } = 0; [Category("速度配置")] [DisplayName("加速度")] [Description("Acc:加速度,为0时表示不修改当前设置")] public double Acc { get; set; } = 0; [Category("速度配置")] [DisplayName("减速度")] [Description("减速度,为0时表示不修改当前设置。回原点模式时设置为曲线参数")] public double Dec { get; set; } = 0; } /// <summary> /// 运动对象 /// </summary> public class MovingOption : INotifyPropertyChanged, IComplexDisplay { private int axisIndex = 0; [Category("运动配置")] [DisplayName("运动轴索引")] [Description("AxisIndex:运动轴索引")] [TypeConverter(typeof(AxisIndexConvert))] public int AxisIndex { get => axisIndex; set { if (axisIndex != value) { axisIndex = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("AxisIndex")); } axisIndex = value; } } private MotorMoveMode moveMode = MotorMoveMode.Normal; [Category("运动配置")] [DisplayName("运动模式")] [Description("MoveMode:运动模式")] public MotorMoveMode MoveMode { get => moveMode; set { if (moveMode != value) { moveMode = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("MoveMode")); } moveMode = value; } } private bool isAbsolute = true; [Category("运动配置")] [DisplayName("是否绝对运动")] [Description("IsAbsolute:是否绝对运动")] public bool IsAbsolute { get => isAbsolute; set { if (isAbsolute != value) { isAbsolute = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("IsAbsolute")); } isAbsolute = value; } } private int destination = 0; [Category("运动配置")] [DisplayName("目的地")] [Description("Destination:目的地")] public int Destination { get => destination; set { if (destination != value) { destination = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Destination")); } destination = value; } } private VelocityPara velocityPara = new VelocityPara(); [Category("运动配置")] [DisplayName("速度参数")] [Description("VelocityPara:速度参数")] [TypeConverter(typeof(ComplexObjectConvert))] [Editor(typeof(PropertyObjectEditor), typeof(UITypeEditor))] public VelocityPara VelocityPara { get => velocityPara; set { velocityPara = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("VelocityPara")); } } internal List<AxisSetting> _axisSettingList = new List<AxisSetting>(); public void SetAxisSetting(List<AxisSetting> settings) { if (settings != null) _axisSettingList = settings; } public string GetDisplayText() { string axisName = AxisIndex.ToString(); var axisSet = _axisSettingList.FirstOrDefault(a => a.AxisIndex == AxisIndex); if (axisSet != null) { axisName += ("-" + axisSet.AxisName); } return axisName + "," + MoveMode.ToString() + "," + (IsAbsolute ? "Abs" : "Rel") + "," + Destination; } public event PropertyChangedEventHandler PropertyChanged; } public class AxisIndexConvert : TypeConverter { Dictionary<int, string> _indexNameDict = new Dictionary<int, string>(); public override bool GetStandardValuesSupported(ITypeDescriptorContext context) { return true; } public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context) { MovingOption mo = context.Instance as MovingOption; _indexNameDict = mo._axisSettingList.ToDictionary(a => a.AxisIndex, a => a.AxisIndex + "-" + a.AxisName); return new StandardValuesCollection(_indexNameDict.Keys); } public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) { if (sourceType == typeof(string)) { return true; } return base.CanConvertFrom(context, sourceType); } public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object v) { if (v is string) { foreach (var indexName in _indexNameDict) { if (indexName.Value == v.ToString()) { return indexName.Key; } } return Convert.ToInt32(v); } return base.ConvertFrom(context, culture, v); } public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object v, Type destinationType) { if (destinationType == typeof(string)) { if (_indexNameDict.ContainsKey(Convert.ToInt32(v))) { return _indexNameDict[Convert.ToInt32(v)]; } } return base.ConvertTo(context, culture, v, destinationType); } public override bool GetStandardValuesExclusive(ITypeDescriptorContext context) { return false; } } public class AxisConflictSet : IComplexDisplay { [Category("1.轴冲突条件")] [Description("轴冲突条件,满足全部条件时轴运动需要检查冲突")] [TypeConverter(typeof(CollectionCountConvert))] [Editor(typeof(ComplexCollectionEditor<AxisLimit>), typeof(UITypeEditor))] public List<AxisLimit> AxisOptions { get; set; } = new List<AxisLimit>(); [Category("1.轴冲突条件")] [Description("IO冲突条件,满足全部条件时轴运动需要检查冲突")] [TypeConverter(typeof(CollectionCountConvert))] [Editor(typeof(ComplexCollectionEditor<IOLimit>), typeof(UITypeEditor))] public List<IOLimit> IOOptions { get; set; } = new List<IOLimit>(); [Category("2.轴冲突限制")] [Description("轴冲突限制,轴运动允许区间")] [TypeConverter(typeof(CollectionCountConvert))] [Editor(typeof(ComplexCollectionEditor<AxisLimit>), typeof(UITypeEditor))] public List<AxisLimit> AxisLimits { get; set; } = new List<AxisLimit>(); [Category("2.轴冲突限制")] [Description("IO允许条件,允许输出的IO")] [TypeConverter(typeof(CollectionCountConvert))] [Editor(typeof(ComplexCollectionEditor<IOLimit>), typeof(UITypeEditor))] public List<IOLimit> IOOutputs { get; set; } = new List<IOLimit>(); [Category("3.轴冲突启用")] [Description("true:启用轴冲突限制 false:不启用轴冲突限制")] public bool IsEnabled { get; set; } = true; public string GetDisplayText() { string optionStr = "Options:" + String.Join(";", AxisOptions.Select(a => a.GetDisplayText())); string limitStr = "Limits:" + String.Join(";", AxisLimits.Select(a => a.GetDisplayText())); return optionStr + "|" + limitStr; } } public class AxisLimit : IComplexDisplay { [Category("1.轴号")] [Description("1.轴号")] public int AxisIndex { get; set; } [Category("2.轴最小限制")] [Description("2.轴最小限制")] public int LimitMin { get; set; } [Category("3.轴最大限制")] [Description("3.轴最大限制")] public int LimitMax { get; set; } private int currentPosition = 0; [Browsable(false)] [JsonIgnore] public int CurrentPosition { get => currentPosition; set { if (currentPosition != value) { if (value >= LimitMin && value <= LimitMax) { IsInLimit = true; } else { IsInLimit = false; } } currentPosition = value; } } [Browsable(false)] [JsonIgnore] public bool IsInLimit { get; set; } public string GetDisplayText() { return String.Format("Index:{0},{1}->{2}", AxisIndex, LimitMin, LimitMax); } } public class IOLimit : IComplexDisplay { [Category("1.IO限制")] [Description("IO索引")] public int IOIndex { get; set; } [Category("1.IO限制")] [Description("IO限制值。输入判断时该值作为启用判断值,输出判断时该值作为允许输出值")] public bool IOSignal { get; set; } public string GetDisplayText() { return IOIndex + "--" + IOSignal.ToString(); } } public class AxisMovingStay { public int Position { get; set; } public int Velocity { get; set; } public AutoResetEvent MoveHandle { get; set; } = new AutoResetEvent(false); public AutoResetEvent MoveSendHandle { get; set; } = new AutoResetEvent(false); } ///// <summary> ///// 点位类型 ///// </summary> //public enum PosType //{ // /// <summary> // /// 直线插补 // /// </summary> // Line = 1, // /// <summary> // /// 圆弧插补(半径) // /// </summary> // CircleRadius, // /// <summary> // /// 圆弧插补(圆心) // /// </summary> // CircleCenter //} //public static class GTSCardParameter //{ // #region 运动参数 // public static int Dangliang = 1; // public static int AxisCount = 2;//运动轴数量 // public static short CardNum = Convert.ToInt16(ConfigurationManager.AppSettings["cardNum"]); // public static short fifo = Convert.ToInt16(ConfigurationManager.AppSettings["fifo"]); // public static int FlySpeed = Convert.ToInt32(ConfigurationManager.AppSettings["flySpeed"]); // public static double FlyAcc = Convert.ToDouble(ConfigurationManager.AppSettings["flyAcc"]); // public static int P2PSpeed = Convert.ToInt32(ConfigurationManager.AppSettings["p2pSpeed"]); // public static double P2PAcc = Convert.ToDouble(ConfigurationManager.AppSettings["p2pAcc"]); // public static double P2PDec = Convert.ToDouble(ConfigurationManager.AppSettings["p2pDec"]); // public static int FreeSpeed = Convert.ToInt32(ConfigurationManager.AppSettings["freeSpeed"]); // public static int VelEnd = Convert.ToInt32(ConfigurationManager.AppSettings["velEnd"]);//飞拍结束速度 // public static int HomeSpeed = Convert.ToInt32(ConfigurationManager.AppSettings["homeSpeed"]); // public static int Loading = Convert.ToInt32(ConfigurationManager.AppSettings["loading"]); // //public const short cardn = 0;//运动控制器卡号 默认为:0 // //public const short crdn = 1;//坐标系号 取值范围:[1, 2] // //public const short fifo = 0;//插补缓存区号 取值范围:[0, 1],默认值为:0 // //public const int flySpeed = 250;//飞拍速度 // //public const double flyAcc = 0.5;//飞拍加速度 // //public const int gocatorSpeed = 150;//3D检测轴运动速度 // //public const int p2pSpeed = 250;//P2P速度 // //public const double p2pAcc = 1;//P2P加速度 // //public const double p2pDec = 1;//P2P减速度 // //public const int calibrationSpeed = 10;//标定速度 // //public const int calibrationZ = 19336;//标定Z轴高度 // //public const int barcodeSpeed = 250;//条码检测轴运动速度 // //public const int freeSpeed = 250;//非检测时轴运动速度 // //public const int velEnd = 0;//飞拍结束速度 // //public const int homeSpeed = 50;//回零速度 // //public const int loading = 80000;//上料位置 // #endregion // #region IO // /// <summary> // /// 输入IO默认值 // /// </summary> // public const int InDefaultValue = 0xFFDA; // /// <summary> // /// 夹紧气缸 // /// </summary> // public const short EXO_1 = 100;//夹紧气缸 // /// <summary> // /// 日光灯 // /// </summary> // public const short EXO_2 = 101;//日光灯 // /// <summary> // /// 光源切换 // /// </summary> // public const short EXO_3 = 102;//光源切换 // /// <summary> // /// 红灯 // /// </summary> // public const short EXO_4 = 103;//红灯 // /// <summary> // /// 黄灯 // /// </summary> // public const short EXO_5 = 104;//黄灯 // /// <summary> // /// 绿灯 // /// </summary> // public const short EXO_6 = 105;//绿灯 // /// <summary> // /// 蜂鸣器 // /// </summary> // public const short EXO_7 = 106;//蜂鸣器 // /// <summary> // /// Gocator X // /// </summary> // public const short EXO_8 = 107;//Gocator X // /// <summary> // /// 正面光(左) // /// </summary> // public const short EXO_9 = 108;//正面光(左) // /// <summary> // /// 正面光(后) // /// </summary> // public const short EXO_10 = 109;//正面光(后) // /// <summary> // /// 正面光(右) // /// </summary> // public const short EXO_11 = 110;//正面光(右) // /// <summary> // /// 正面光(前) // /// </summary> // public const short EXO_12 = 111;//正面光(前) // /// <summary> // /// Gocator Y // /// </summary> // public const short EXO_16 = 115;//Gocator Y // /// <summary> // /// 输出IO默认值 // /// </summary> // public const int OutDefaultValue = 0xFFF; // /// <summary> // /// 左启动 // /// </summary> // public const short EXI0 = 0;//左起动 // /// <summary> // /// 右启动 // /// </summary> // public const short EXI1 = 1;//右起动 // /// <summary> // /// 停止 // /// </summary> // public const short EXI2 = 2;//停止 // /// <summary> // /// 复位 // /// </summary> // public const short EXI3 = 3;//复位 // /// <summary> // /// 急停 // /// </summary> // public const short EXI4 = 4;//急停 // /// <summary> // /// 门开关 // /// </summary> // public const short EXI5 = 5;//门开关 // /// <summary> // /// 安全光幕 // /// </summary> // public const short EXI6 = 6;//安全光幕 // public const short EXI7 = 7;// // /// <summary> // /// 夹紧气缸原位 // /// </summary> // public const short EXI8 = 8;//夹紧气缸原位 // /// <summary> // /// 夹紧气缸到位 // /// </summary> // public const short EXI9 = 9;//夹紧气缸到位 // #endregion //} } src/Bro.Device.GTSCard/GTSCardDriver.cs
@@ -1,27 +1,101 @@ 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; namespace Bro.Device.GTSCard { public class GTSCardDriver : DeviceBase,IMonitor, IMotion [Device("GTSCard", "固高板卡", EnumHelper.DeviceAttributeType.Device)] public class GTSCardDriver : DeviceBase, IMonitor, IMotion { public event Action<DateTime, string, IDevice, MonitorSet> OnMonitorInvoke; public event Action<DateTime, IDevice, WarningSet> OnMonitorAlarm; public delegate bool OnAxisStartToCheckDelegate(int axisIndex, int startPosition, int endPosition); // 异常事件 public Action<Exception> OnExceptionRaised; public GTSCardInitialConfig IConfig { get { return InitialConfig as GTSCardInitialConfig; } } static Dictionary<int, object> axisMoveLockDict = new Dictionary<int, object>(); /// <summary> /// 轴运动开始时的检测,true:有冲突 不可继续执行 false:无冲突,可继续执行 /// </summary> public event OnAxisStartToCheckDelegate OnAxisStartToCheckConfliction; /// <summary> /// 暂停(线程同步事件) /// </summary> Dictionary<int, ManualResetEvent> axisImmediatePauseHandleDict = new Dictionary<int, ManualResetEvent>(); Dictionary<int, CancellationTokenSource> axisMoveCancelDict = new Dictionary<int, CancellationTokenSource>(); /// <summary> /// 运行过程中的线程等待 /// </summary> private Dictionary<int, ManualResetEvent> runningEventDic = new Dictionary<int, ManualResetEvent>(); private Dictionary<int, AutoResetEvent> axisMovingHandleDict = new Dictionary<int, AutoResetEvent>(); private ConcurrentDictionary<int, int> axisDestination = new ConcurrentDictionary<int, int>(); private ObservableCollection<int> _commandAxisList = new ObservableCollection<int>(); public Action<bool> CommandAxisCountChangedAction = null; private Dictionary<int, VelocityPara> velIndexDict = new Dictionary<int, VelocityPara>(); ManualResetEvent _pauseHandle = new ManualResetEvent(true); static object lockObj = new object(); static object _commandAxisLock = new object(); /// <summary> /// 是否复位标志 /// </summary> bool _isResetting = false; public void SetResetFlag(bool isReset) { _isResetting = isReset; } public List<AxisInfo> GetCurrentAxisInfo(params string[] axisName) { throw new NotImplementedException(); } #region DeviceBase protected override void Init() { throw new NotImplementedException(); InitialMotionCard((short)IConfig.CardNum, IConfig.InitialConfigFilePath); axisMoveLockDict = IConfig.AxisSettings.ToDictionary(a => a.AxisIndex, a => new object()); runningEventDic = IConfig.AxisSettings.ToDictionary(a => a.AxisIndex, a => new ManualResetEvent(false)); axisMovingHandleDict = IConfig.AxisSettings.ToDictionary(a => a.AxisIndex, a => new AutoResetEvent(true)); axisImmediatePauseHandleDict = IConfig.AxisSettings.ToDictionary(a => a.AxisIndex, a => new ManualResetEvent(true)); axisMoveCancelDict = IConfig.AxisSettings.ToDictionary(a => a.AxisIndex, a => new CancellationTokenSource()); axisMoveCancelDict.Values.ToList().ForEach(c => { c = new CancellationTokenSource(); }); _commandAxisList.CollectionChanged -= CommandAxisList_CollectionChanged; _commandAxisList.CollectionChanged += CommandAxisList_CollectionChanged; } private void CommandAxisList_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) { CommandAxisCountChangedAction?.Invoke(_commandAxisList.Count > 0); } protected override void Pause() @@ -43,43 +117,874 @@ { throw new NotImplementedException(); } #endregion /// <summary> /// 点位到点位 运动 /// </summary> /// <param name="cardNum">卡号</param> /// <param name="axisNum">轴号</param> /// <param name="prfPosition">规划位置,单位毫米</param> /// <param name="prfVelocity">规划速度,单位米每秒</param> public void P2P(short cardNum, short axisNum, int prfPosition, int prfVelocity) #region GTSCard public void ClearPosition(short cardNum, short axisNum) { GTSCardAPI.TTrapPrm trapprm; GTSCardAPI.GT_PrfTrap(cardNum, axisNum); GTSCardAPI.GT_GetTrapPrm(cardNum, axisNum, out trapprm); trapprm.acc = GTSCardParameter.P2PAcc; trapprm.dec = GTSCardParameter.P2PDec; trapprm.smoothTime = 1; GTSCardAPI.GT_SetTrapPrm(cardNum, axisNum, ref trapprm); GTSCardAPI.GT_SetPos(cardNum, axisNum, prfPosition * GTSCardParameter.Dangliang); GTSCardAPI.GT_SetVel(cardNum, axisNum, prfVelocity * GTSCardParameter.Dangliang); GTSCardAPI.GT_Update(cardNum, 1 << (axisNum - 1)); int ret = GTSCardAPI.GT_SetPos(cardNum, axisNum, 0); } /// <summary> /// Jog运动 /// Load Motion Card parameter from file /// </summary> /// <param name="cardNum"></param> /// <param name="axisNum"></param> /// <param name="velocity">规划速度,单位米每秒</param> public void Jog(short cardNum, short axisNum, double velocity) /// <param name="fileName">Invalid Parameter</param> /// <returns></returns> public void InitialMotionCard(short cardNum, string fileName) { var res = GTSCardAPI.GT_LoadConfig(cardNum, fileName); if (res != GTSCardAPI.ResultSuccess) { throw new Exception("板卡载入配置文件异常,错误码:" + res); } } /// <summary> /// 单个轴 点位到点位运动(异步) /// </summary> /// <param name="item">运动对象</param> /// <returns></returns> public async Task SingleAxisMovingAsync(MovingOption item) { await Task.Run(() => { SingleAxisMoving(item); }); } /// <summary> /// 单个轴 点位到点位运动(异步) /// </summary> /// <param name="item">运动对象</param> public void SingleAxisMoving(MovingOption item) { if (IConfig.AxisSettings.FirstOrDefault(a => a.AxisIndex == item.AxisIndex)?.IsAxisEnabled ?? false) { axisImmediatePauseHandleDict[item.AxisIndex].WaitOne(); VelocityPara vel = new VelocityPara(); if (item.VelocityPara.Velocity != 0) { velIndexDict[item.AxisIndex] = vel = item.VelocityPara; } else { vel = velIndexDict[item.AxisIndex]; } string _position = ""; string motionType = item.MoveMode == EnumHelper.MotorMoveMode.Normal ? (item.IsAbsolute ? "Abs" : "Rel") : item.MoveMode.ToString(); _position = $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")},{item.AxisIndex},{motionType},{GetCmdOrPosition(item.AxisIndex, 0).ToString()},{GetCmdOrPosition(item.AxisIndex, 1).ToString()},{item.Destination},"; lock (axisMoveLockDict[item.AxisIndex]) { Task.Run(() => { lock (_commandAxisLock) { try { if (!_commandAxisList.Contains(item.AxisIndex)) { _commandAxisList.Add(item.AxisIndex); } } catch (Exception) { } } }); switch (item.MoveMode) { case EnumHelper.MotorMoveMode.Normal: { if (_isResetting) { LogAsync(DateTime.Now, "复位中启动运动异常", item.AxisIndex + "启动运动异常"); return; } SetAxisParam(item.AxisIndex, vel); if (item.IsAbsolute) { MoveAbs(item.AxisIndex, item.Destination, (int)(vel.Velocity * IConfig.AxisVelocityRatio)); } else { MoveRel(item.AxisIndex, item.Destination, (int)(vel.Velocity * IConfig.AxisVelocityRatio)); } } break; case EnumHelper.MotorMoveMode.FindOri: { AxisSetting setting = IConfig.AxisSettings.FirstOrDefault(u => u.AxisIndex == item.AxisIndex); StartHoming(item.AxisIndex, setting.HomeMode, setting.IsHomePositive ? 1 : 0, item.VelocityPara.Dec, item.VelocityPara.Acc, item.VelocityPara.Velocity); } break; } Task.Run(() => { lock (_commandAxisLock) { try { _commandAxisList.Remove(item.AxisIndex); } catch (Exception) { } } }); } _position += $"{GetCmdOrPosition(item.AxisIndex, 0).ToString()},"; _position += $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}"; LogAsync(DateTime.Now, "", _position); } } public int GetCmdOrPosition(int axisNum, int flag = 0) { int position = 0; if (flag == 0) { GetPosition(axisNum, ref position); } else { GetCmdPosition(axisNum, ref position); } return position; } /// <summary> ///Get single Axis Feedback position /// </summary> /// <param name="axisNum">Axis number</param> /// <param name="nPosition">Feedback/Encorde position </param> /// <returns></returns> public void GetPosition(int axisNum, ref int nPosition) { lock (lockObj) { double prfpos = 0; uint pclock = 0; var ret = GTSCardAPI.GT_GetPrfPos((short)IConfig.CardNum, (short)axisNum, out prfpos, 1, out pclock); if (ret != GTSCardAPI.ResultSuccess) { throw new Exception("轴" + axisNum + "获取当前位置异常,错误码:" + ret); } nPosition = prfpos / IConfig.AxisVelocityRatio; } } public int GetPosition(int axisNum) { int position = 0; if (!IConfig.AxisSettings.FirstOrDefault(u => u.AxisIndex == axisNum).IsUseCmmdPosition) { GetPosition(axisNum, ref position); } else { GetCmdPosition(axisNum, ref position); } return position; } /// <summary> ///Get single Axis Command position /// </summary> /// <param name="axisNum">Axis number</param> /// <param name="nPosition">Command position </param> /// <returns></returns> public void GetCmdPosition(int axisNum, ref int nPosition) { var ret = GTSCardAPI.APS_get_command(axisNum, ref nPosition); if (ret != (Int32)GTSCardParameter.ResultSuccess) { throw new Exception("轴" + axisNum + "获取当前位置异常,错误码:" + ret); } nPosition = prfpos / IConfig.AxisVelocityRatio; } /// <summary> /// Set AxisParam /// </summary> /// <param name="axisNo"></param> /// <param name="param"></param> /// <returns></returns> public void SetAxisParam(int axisNum, VelocityPara param) { int ret = 0; GTSCardAPI.TTrapPrm trapprm; GTSCardAPI.GT_PrfTrap((short)IConfig.CardNum, (short)axisNum); GTSCardAPI.GT_GetTrapPrm((short)IConfig.CardNum, (short)axisNum, out trapprm); trapprm.smoothTime = 1; if (param.Acc != 0) { trapprm.acc = param.Acc; } if (param.Dec != 0) { trapprm.dec = param.Dec; } ret += GTSCardAPI.GT_SetTrapPrm((short)IConfig.CardNum, (short)axisNum, ref trapprm); ret += GTSCardAPI.GT_SetVel((short)IConfig.CardNum, (short)axisNum, param.Velocity * IConfig.AxisVelocityRatio); if (ret != (int)APS_Define.ResultSuccess) { throw new Exception("轴" + axisNum + "设置参数异常,错误码:" + ret); } } /// <summary> /// Set Single Axis Do Jog Move /// </summary> /// <param name="axisNum">AxisNo</param> /// <param name="nDirection">Motion Direction 0: Negative, 1: Positive</param> /// <param name="nMaxVel">max velocity</param> /// <returns></returns> public bool StartJog(int axisNum, int nDirection, int velocity) { GTSCardAPI.TJogPrm jogprm = new GTSCardAPI.TJogPrm(); short rtn = GTSCardAPI.GT_PrfJog(cardNum, axisNum); short rtn = GTSCardAPI.GT_PrfJog((short)IConfig.CardNum, (short)axisNum); jogprm.acc = 1; jogprm.dec = 1; GTSCardAPI.GT_SetJogPrm(cardNum, axisNum, ref jogprm);//设置jog运动参数 GTSCardAPI.GT_SetVel(cardNum, axisNum, velocity);//设置目标速度 GTSCardAPI.GT_Update(cardNum, 1 << (axisNum - 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)APS_Define.ResultSuccess) { return false; } return true; } /// <summary> /// Set Single Axis Do stop Jog Move /// </summary> /// <param name="axisNum">AxisNo</param> /// <returns></returns> public bool StopJog(int axisNum) { MoveStop(); return IsStop((short)IConfig.CardNum, (short)axisNum); } /// <summary> /// Set Single Axis Do Rel Move /// </summary> /// <param name="axisNum">AxisNo</param> /// <param name="nDistance">run distance</param> /// <returns></returns> public void MoveRel(int axisNum, int nDistance, int nMaxVel) { try { if (CurrentState == EnumHelper.DeviceState.DSExcept) { LogAsync(DateTime.Now, "板卡异常状态", "轴" + axisNum + "试图异常状态运动"); return; } if (CurrentState != EnumHelper.DeviceState.DSOpen) { return; } int currentPosition = GetPosition(axisNum); if (OnAxisStartToCheckConfliction != null && OnAxisStartToCheckConfliction.Invoke(axisNum, currentPosition, currentPosition + nDistance)) { return; } int ret = GTSCardAPI.GT_SetPos((short)IConfig.CardNum, (short)axisNum, nDistance * IConfig.AxisVelocityRatio); ret += GTSCardAPI.GT_Update((short)IConfig.CardNum, 1 << (axisNum - 1)); if (ret != (Int32)APS_Define.ResultSuccess) { throw new Exception("轴" + axisNum + "启动相对运动异常,错误码:" + ret); } RunFinish(axisNum, false); } catch (Exception ex) { MoveStop(); OnExceptionRaised?.Invoke(ex); } } /// <summary> /// Set Single Axis Do Absolute Move /// </summary> /// <param name="axisNum">AxisNo</param> /// <param name="nDistance">run distance</param> /// <param name="nMaxVel">max velocity</param> /// <returns></returns> public void MoveAbs(int axisNum, int nPosition, int nMaxVel) { try { ReMove: MoveAbsAsync(axisNum, nPosition); var runFinish = Task.Run(() => RunFinish(axisNum), axisMoveCancelDict[axisNum].Token); try { runFinish.Wait(axisMoveCancelDict[axisNum].Token); } catch (OperationCanceledException ex) { goto ReMove; } //// 删除记录 //if (currentCommandDic.ContainsKey(axisNum)) //{ // currentCommandDic.TryRemove(axisNum, out int[] temp); //} } catch (Exception ex) { MoveStop(); OnExceptionRaised?.Invoke(ex); } } static object moveLock = new object(); /// <summary> /// 绝对运动(异步) /// </summary> /// <param name="axisNum"></param> /// <param name="nPosition"></param> public void MoveAbsAsync(int axisNum, int nPosition) { try { lock (moveLock) { axisImmediatePauseHandleDict[axisNum].WaitOne(); _pauseHandle.WaitOne(); int currentPosition = GetPosition(axisNum); if (OnAxisStartToCheckConfliction != null && OnAxisStartToCheckConfliction.Invoke(axisNum, currentPosition, nPosition)) { return; } if (_isResetting) { LogAsync(DateTime.Now, "复位过程异常", "轴" + axisNum + "试图在复位过程中运动"); throw new Exception("轴" + axisNum + "试图在复位过程中运动"); } int repeatTime = 30; while (CurrentState != EnumHelper.DeviceState.DSOpen && repeatTime > 0) { Thread.Sleep(10); repeatTime--; } if (CurrentState == EnumHelper.DeviceState.DSExcept) { LogAsync(DateTime.Now, "板卡异常状态", "轴" + axisNum + "试图异常状态运动"); return; } if (CurrentState != EnumHelper.DeviceState.DSOpen) { LogAsync(DateTime.Now, "非正常状态异常", "轴" + axisNum + "试图在非正常状态运动"); throw new Exception("轴" + axisNum + "试图在非正常状态运动", null); } int ret = 0; repeatTime = 50; do { LogAsync(DateTime.Now, "轴" + axisNum + "启动运动", "目标坐标:" + nPosition); ret = GTSCardAPI.GT_SetPos((short)IConfig.CardNum, (short)axisNum, nPosition * IConfig.AxisVelocityRatio); ret += GTSCardAPI.GT_Update((short)IConfig.CardNum, 1 << (axisNum - 1)); if (ret != (Int32)APS_Define.ResultSuccess) { LogAsync(DateTime.Now, "轴" + axisNum + "APS_absolute_move异常", "返回值:" + ret + ";重试次数:" + repeatTime); Thread.Sleep(50); } repeatTime--; } while (ret != (Int32)APS_Define.ResultSuccess && repeatTime > 0); if (ret != (Int32)APS_Define.ResultSuccess) { LogAsync(DateTime.Now, "轴" + axisNum + "启动绝对运动异常", "错误码:" + ret); throw new Exception("轴" + axisNum + "启动绝对运动异常,错误码:" + ret); } } } catch (Exception ex) { MoveStop(); OnExceptionRaised?.Invoke(ex); } } Dictionary<int, AxisMovingStay> _axisStayDict = new Dictionary<int, AxisMovingStay>(); private async void MoveAbsStay(int axisNum) { await Task.Run(() => { while (CurrentState != EnumHelper.DeviceState.DSClose) { if (!_axisStayDict.ContainsKey(axisNum)) { _axisStayDict[axisNum] = new AxisMovingStay(); } _axisStayDict[axisNum].MoveHandle.WaitOne(); MoveAbsAsync(axisNum, _axisStayDict[axisNum].Position); _axisStayDict[axisNum].MoveSendHandle.Set(); } }); } /// <summary> /// 动作结束 /// </summary> /// <param name="axisNum"></param> /// <returns></returns> public void RunFinish(int axisNum, bool isAbs = true) { MOTION_IO_STATUS MotionIoSts = new MOTION_IO_STATUS(); MOTION_BOOL_STATUS MotionSts = new MOTION_BOOL_STATUS(); var axisSetting = IConfig.AxisSettings.FirstOrDefault(a => a.AxisIndex == axisNum); int startTime = System.Environment.TickCount; //MDN信号 if (axisSetting.IsUseMDNStopSignal) { while (GetMotionIoStatus(axisNum, ref MotionIoSts) && GetMotionStatus(axisNum, ref MotionSts)) { if (MotionIoSts.EMG) { LogAsync(DateTime.Now, "轴" + axisNum + "急停", ""); throw new Exception("轴" + axisNum + "急停"); } if (MotionSts.MDN) { int stopCode = -1; APS168.APS_get_stop_code(axisNum, ref stopCode); LogAsync(DateTime.Now, "轴" + axisNum + "StopCode:", stopCode.ToString()); //0 正常停止 4 正极限 5 负极限 if (new List<int>() { 0, 4, 5 }.Contains(stopCode)) { if (new List<int>() { 4, 5 }.Contains(stopCode) && axisSetting.IsUseWarning) { MoveStop(true); OnExceptionRaised?.Invoke(new Exception("轴" + axisNum + "运动至极限位置,stopCode:" + stopCode.ToString(), null)); return; } if (IConfig.ActionAfterDelay > 0) { Thread.Sleep(IConfig.ActionAfterDelay); } int feedBack = 0; GetPosition(axisNum, ref feedBack); LogAsync(DateTime.Now, "轴" + axisNum + "运动结束", "当前位置:" + feedBack); break; } } } } else //INP信号 { while (GetMotionIoStatus(axisNum, ref MotionIoSts) && GetMotionStatus(axisNum, ref MotionSts)) { if (MotionIoSts.EMG) { LogAsync(DateTime.Now, "轴" + axisNum + "急停", ""); throw new Exception("轴" + axisNum + "急停"); } if (MotionSts.MDN && MotionIoSts.INP) { int stopCode = -1; APS168.APS_get_stop_code(axisNum, ref stopCode); LogAsync(DateTime.Now, "轴" + axisNum + "StopCode:", stopCode.ToString()); //0 正常停止 4 正极限 5 负极限 if (new List<int>() { 0, 4, 5 }.Contains(stopCode)) { if (new List<int>() { 4, 5 }.Contains(stopCode) && axisSetting.IsUseWarning) { MoveStop(true); OnExceptionRaised?.Invoke(new AMPRunException("轴" + axisNum + "运动至极限位置,stopCode:" + stopCode.ToString(), null)); return; } if (IConfig.ActionAfterDelay > 0) { Thread.Sleep(IConfig.ActionAfterDelay); } int feedBack = 0; GetPosition(axisNum, ref feedBack); LogAsync(DateTime.Now, "轴" + axisNum + "运动结束", "当前位置:" + feedBack); break; } } } } } /// <summary> /// Stop single axis move /// </summary> /// <param name="axisNum">axisNo</param> /// <param name="option">0表示平滑停止,1表示紧急停止</param> /// <returns></returns> public void MoveStop(int axisNum, int option) { int ret = GTSCardAPI.GT_Stop((short)IConfig.CardNum, 1 << (axisNum - 1), option); if (ret != (Int32)APS_Define.ResultSuccess) { LogAsync(DateTime.Now, "轴" + axisNum + "运动停止异常", "错误码:" + ret); throw new Exception("轴" + axisNum + "运动停止异常,错误码:" + ret); } else { LogAsync(DateTime.Now, "轴" + axisNum + "运动停止", ""); } } static object motionIOLock = new object(); /// <summary> /// Get single Axis Motion_Io status and motion status /// </summary> /// <param name="nAxis"></param> /// <param name="nMotionSts"></param> /// <returns></returns> public bool GetMotionStatus(int nAxis, ref MOTION_BOOL_STATUS strcMotionSts) { lock (motionIOLock) { int nMotionSts = 0; nMotionSts = APS168.APS_motion_status(nAxis); if (nMotionSts < 0) { return false; } strcMotionSts.ASTP = Convert.ToBoolean(nMotionSts & (1 << (int)MOTION_STATUS.ASTP)); strcMotionSts.HMV = Convert.ToBoolean(nMotionSts & (1 << (int)MOTION_STATUS.HMV)); strcMotionSts.MDN = Convert.ToBoolean(nMotionSts & (1 << (int)MOTION_STATUS.MDN)); strcMotionSts.DIR = Convert.ToBoolean(nMotionSts & (1 << (int)MOTION_STATUS.DIR)); } return true; } /// <summary> /// Get single Axis Motion_Io status and motion status /// </summary> /// <param name="nAxis"></param> /// <param name="nMotionIoSts"></param> /// <returns></returns> public bool GetMotionIoStatus(int nAxis, ref MOTION_IO_STATUS strcMotionIoSts) { lock (motionIOLock) { //Thread.Sleep(15); int nMotionIoSts = 0; nMotionIoSts = APS168.APS_motion_io_status(nAxis); if (nMotionIoSts < 0) { return false; } bool isAlarm = Convert.ToBoolean(nMotionIoSts & (1 << (int)MOTION_IOSTATUS.ALM)); if (strcMotionIoSts.ALM != isAlarm) { strcMotionIoSts.ALM = isAlarm; OnMotionAlarm?.Invoke(nAxis, isAlarm); } strcMotionIoSts.PEL = Convert.ToBoolean(nMotionIoSts & (1 << (int)MOTION_IOSTATUS.PEL)); strcMotionIoSts.MEL = Convert.ToBoolean(nMotionIoSts & (1 << (int)MOTION_IOSTATUS.MEL)); strcMotionIoSts.ORG = Convert.ToBoolean(nMotionIoSts & (1 << (int)MOTION_IOSTATUS.ORG)); strcMotionIoSts.EMG = Convert.ToBoolean(nMotionIoSts & (1 << (int)MOTION_IOSTATUS.EMG)); strcMotionIoSts.INP = Convert.ToBoolean(nMotionIoSts & (1 << (int)MOTION_IOSTATUS.INP)); strcMotionIoSts.SVON = Convert.ToBoolean(nMotionIoSts & (1 << (int)MOTION_IOSTATUS.SVON)); } return true; } public void MoveStop(bool emergencyStop = false) { int option = 0; if (emergencyStop) { option = 1; StateChange(EnumHelper.DeviceState.DSExcept); } IConfig.AxisSettings.Where(a => a.IsAxisEnabled).ToList().ForEach(axisNum => { MoveStop(axisNum.AxisIndex, option); }); } /// <summary> /// 回原点 /// </summary> /// <param name="cardn">卡号</param> /// <param name="axisn">轴号</param> /// <param name="homests">轴回原点状态</param> public bool GoHome(short cardn, short axisn, short home_mode, short home_dir, int homeoffset) { try { GTSCardAPI.GT_ZeroPos(cardn, axisn, 1); GTSCardAPI.THomePrm thomeprm; GTSCardAPI.THomeStatus homests; short rtn = GTSCardAPI.GT_GetHomePrm(cardn, axisn, out thomeprm); thomeprm.mode = home_mode;//回零方式 thomeprm.moveDir = home_dir;//回零方向 thomeprm.edge = 0; thomeprm.velHigh = 50; thomeprm.velLow = 50; thomeprm.acc = 50; thomeprm.dec = 50; thomeprm.searchHomeDistance = 9999999;//搜搜距离 thomeprm.homeOffset = 0; //偏移距离 thomeprm.escapeStep = 1000; rtn = GTSCardAPI.GT_GoHome(cardn, axisn, ref thomeprm); //启动回零 while (true) { Thread.Sleep(5); GTSCardAPI.GT_GetHomeStatus(cardn, axisn, out homests); if (homests.run == 0) { if (homests.error == 0) { Thread.Sleep(200); GTSCardAPI.GT_ZeroPos(cardn, axisn, 1); } return true; } } } catch (Exception ex) { MoveStop(); OnExceptionRaised?.Invoke(ex); return false; } } /// <summary> /// 回原点 /// </summary> /// <param name="axisId"></param> public void StartHoming(int axisId) { try { //servo on APS168.APS_set_servo_on(axisId, 1); Thread.Sleep(500); // Wait stable. // 2. Start home move APS168.APS_home_move(axisId); WaitHomeFinish(axisId); axisDestination[axisId] = 0; } catch (Exception ex) { MoveStop(); OnExceptionRaised?.Invoke(ex); } } /// <summary> /// 回原点 /// </summary> /// <param name="axisId"></param> /// <param name="homeMode"></param> /// <param name="homeDir"></param> /// <param name="praCurve"></param> /// <param name="praAcc"></param> /// <param name="praVm"></param> public void StartHoming(int axisId, int homeMode, int homeDir, double praCurve, double praAcc, double praVm) { // 1. Select home mode and config home parameters APS168.APS_set_axis_param(axisId, (Int32)APS_Define.PRA_HOME_MODE, homeMode); // Set home mode APS168.APS_set_axis_param(axisId, (Int32)APS_Define.PRA_HOME_DIR, homeDir); // Set home direction APS168.APS_set_axis_param_f(axisId, (Int32)APS_Define.PRA_HOME_CURVE, praCurve); // Set acceleration paten (T-curve) APS168.APS_set_axis_param_f(axisId, (Int32)APS_Define.PRA_HOME_ACC, praAcc); // Set homing acceleration rate APS168.APS_set_axis_param_f(axisId, (Int32)APS_Define.PRA_HOME_VM, praVm); // Set homing maximum velocity. APS168.APS_set_axis_param_f(axisId, (Int32)APS_Define.PRA_HOME_VO, praVm / 5); // Set homing VO speed APS168.APS_set_axis_param_f(axisId, (Int32)APS_Define.PRA_HOME_EZA, 0); // Set EZ signal alignment (yes or no) APS168.APS_set_axis_param_f(axisId, (Int32)APS_Define.PRA_HOME_SHIFT, 0); // Set home position shfit distance. APS168.APS_set_axis_param_f(axisId, (Int32)APS_Define.PRA_HOME_POS, 0); // Set final home position. StartHoming(axisId); } /// <summary> /// 回原点结束 /// </summary> /// <param name="axisNum"></param> /// <returns></returns> public void WaitHomeFinish(int axisNum) { MOTION_IO_STATUS MotionIoSts = new MOTION_IO_STATUS(); MOTION_BOOL_STATUS MotionSts = new MOTION_BOOL_STATUS(); var axisSetting = IConfig.AxisSettings.FirstOrDefault(a => a.AxisIndex == axisNum); int startTime = System.Environment.TickCount; while ((GetMotionIoStatus(axisNum, ref MotionIoSts)) && (GetMotionStatus(axisNum, ref MotionSts))) { if (MotionIoSts.EMG) { LogAsync(DateTime.Now, "轴复位中" + axisNum + "急停", ""); throw new Exception("轴复位中" + axisNum + "急停"); } if (axisSetting.HomeMode == 0) { if (!MotionSts.HMV && MotionIoSts.ORG) break; } else { if (!MotionSts.HMV) break; } if (axisSetting.TimeOutHome < System.Environment.TickCount - startTime) { LogAsync(DateTime.Now, "轴复位中" + axisNum + "回原点超时", ""); MoveStop(axisNum); throw new Exception("轴复位中" + axisNum + "回原点超时"); } } //ClearPosition(axisNum); } static object _ioLock = new object(); /// <summary> /// 设置IO卡输出 /// </summary> /// <param name="DINo">IO端口序号</param> /// <param name="Value">设置值(true:高电平, false:低电平)</param> /// <returns></returns> public bool SetOutput(int DINo, bool Value) { if (OnCheckOutputAllowed?.Invoke(DINo, Value, new Dictionary<int, int>(axisDestination.ToDictionary(u => u.Key, u => u.Value))) ?? false) { OnExceptionRaised?.Invoke(new AMPRunException(DINo + "输出" + Value.ToString() + "不被允许", null)); return false; } int ret = -1; lock (_ioLock) { ret = APS168.APS_write_d_channel_output(0, 0, DINo, Value ? 1 : 0); } if (ret < 0) { return false; } return true; } /// <summary> /// 获取输入信号 /// </summary> /// <param name="stateType"></param> /// <returns></returns> public bool[] GetInputState() { int diVaule = 0; lock (_ioLock) { APS168.APS_read_d_input(0, 0, ref diVaule); } return GetBoolSig(diVaule); //return new bool[16]; } /// <summary> /// 获取输出信号 /// </summary> /// <param name="stateType"></param> /// <returns></returns> public bool[] GetOutputState() { int doVaule = 0; lock (_ioLock) { APS168.APS_read_d_output(0, 0, ref doVaule); } return GetBoolSig(doVaule); } /// <summary> /// 将无符号整型转换为Bool型数组 /// </summary> /// <param name="sigStr"></param> /// <returns></returns> private bool[] GetBoolSig(int sigStr) { bool[] state = new bool[32]; for (int i = 0; i < 32; i++) { state[i] = (sigStr & (1 << i)) != 0; } return state; } /// <summary> /// 将bool数组转换成无符号整型 /// </summary> /// <param name="sigArray"></param> /// <returns></returns> private int GetintSig(bool[] sigArray) { int state = -1; for (int i = 31; i > -1; i--) { state = (state << 1) + (sigArray[i] ? 1 : 0); } return state; } /// <summary> @@ -99,36 +1004,45 @@ /// <summary> /// 输出 /// </summary> /// <param name="cardNumo">卡号</param> /// <param name="cardNum">卡号</param> /// <param name="index">输出口,返回1-16</param> /// <param name="value">0表示输出,1表示关闭</param> public void WriteOut(short cardNumo, short index, bool value) /// <param name="value">false表示输出,true表示关闭</param> public void WriteOut(short cardNum, short index, bool value) { short outNum = (short)(index % 100 + 1); switch (value) if (value) { case true: { GTSCardAPI.GT_SetDoBit(cardNumo, GTSCardAPI.MC_GPO, outNum, 0);//按位输出,0表示输出,1表示关闭 } break; case false: { GTSCardAPI.GT_SetDoBit(cardNumo, GTSCardAPI.MC_GPO, outNum, 1);//按位输出,0表示输出,1表示关闭 } break; GTSCardAPI.GT_SetDoBit(cardNum, GTSCardAPI.MC_GPO, outNum, 0); } else { GTSCardAPI.GT_SetDoBit(cardNum, GTSCardAPI.MC_GPO, outNum, 1); } } /// <summary> /// 停止 某个轴 /// </summary> /// <param name="cardNum"></param> /// <param name="axisNum"></param> /// <param name="cardNum">卡号</param> /// <param name="axisNum">轴号</param> /// <param name="option">0表示平滑停止,1表示紧急停止</param> public void Stop(short cardNum, short axisNum, short option) { GTSCardAPI.GT_Stop(cardNum, 1 << (axisNum - 1), option); } /// <summary> /// 停止 某个轴(异步) /// </summary> /// <param name="cardNum">卡号</param> /// <param name="axisNum">轴号</param> /// <param name="option">0表示平滑停止,1表示紧急停止</param> public async Task StopAsync(short cardNum, short axisNum, short option) { await Task.Run(() => { GTSCardAPI.GT_Stop(cardNum, 1 << (axisNum - 1), option); }); } /// <summary> @@ -137,21 +1051,15 @@ /// <param name="cardNum"></param> /// <param name="axisNum">轴号</param> /// <param name="value">停止方式,false表示平滑停止,true表示紧急停止</param> public void Stop(short cardNum, short axisNum, bool value) public void Stop(short cardNum, short axisNum, bool emergencyStop) { switch (value) if (emergencyStop) { case false: { GTSCardAPI.GT_Stop(cardNum, 1 << (axisNum - 1), 0); } break; case true: { GTSCardAPI.GT_Stop(cardNum, 1 << (axisNum - 1), 1 << (axisNum - 1)); } break; GTSCardAPI.GT_Stop(cardNum, 1 << (axisNum - 1), 1 << (axisNum - 1)); } else { GTSCardAPI.GT_Stop(cardNum, 1 << (axisNum - 1), 0); } } @@ -190,21 +1098,21 @@ /// <summary> /// 读取IO输出状态 /// </summary> /// <param name="cardNumo"></param> /// <param name="cardNum"></param> /// <param name="index"></param> /// <returns></returns> public bool GetDoSts(short cardNumo, short index) public bool GetDoSts(short cardNum, short index) { short outNum = 0; int outSts; outNum = (short)(index % 100); GTSCardAPI.GT_GetDo(cardNumo, GTSCardAPI.MC_GPO, out outSts); GTSCardAPI.GT_GetDo(cardNum, GTSCardAPI.MC_GPO, out outSts); if ((outSts & (1 << outNum)) == 0) return true; else return false; } static object lockObj = new object(); /// <summary> /// 读取当前值 @@ -218,7 +1126,7 @@ { double prfpos = 0; uint pclock = 0; GTSCardAPI.GT_GetPrfPos(cardNum, axisNum, out prfpos, 1, out pclock); return prfpos / GTSCardParameter.Dangliang; return prfpos / IConfig.AxisVelocityRatio; } } @@ -239,6 +1147,7 @@ else return false; //运行中返回false } } #endregion public void Monitor() { src/Bro.Device.GTSCard/gts.dllBinary files differ
src/Bro.Device.GTSCard/packages.config
New file @@ -0,0 +1,4 @@ <?xml version="1.0" encoding="utf-8"?> <packages> <package id="Newtonsoft.Json" version="11.0.2" targetFramework="net452" /> </packages>