JetAxisBase.cs 55 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475
  1. using Aitex.Core.RT.DataCenter;
  2. using Aitex.Core.RT.Device;
  3. using Aitex.Core.RT.Event;
  4. using Aitex.Core.RT.Log;
  5. using Aitex.Core.RT.OperationCenter;
  6. using Aitex.Core.RT.Routine;
  7. using Aitex.Core.RT.SCCore;
  8. using Aitex.Core.Util;
  9. using MECF.Framework.Common.Beckhoff.AxisProvider;
  10. using MECF.Framework.Common.Beckhoff.IOAxis;
  11. using MECF.Framework.Common.Beckhoff.Station;
  12. using MECF.Framework.Common.CommonData.PUF;
  13. using MECF.Framework.Common.TwinCat;
  14. using MECF.Framework.Common.Utilities;
  15. using CyberX8_Core;
  16. using System;
  17. using System.Collections.Generic;
  18. using System.Linq;
  19. using System.Reflection;
  20. using System.Text;
  21. using System.Threading;
  22. using System.Threading.Tasks;
  23. using System.Timers;
  24. using CommunityToolkit.HighPerformance.Buffers;
  25. using System.Windows.Documents;
  26. using MECF.Framework.Common.Device.Galil;
  27. namespace CyberX8_RT.Devices.AXIS
  28. {
  29. public abstract class JetAxisBase : BaseDevice, IDevice
  30. {
  31. #region 常量
  32. private const string STATUS_WORD = "StatusWord";
  33. private const string DIGITAL_INPUTS="DigitalInputs";
  34. private const string CONTROL_WORD = "ControlWord";
  35. private const string MODE_OF_OPERATION = "ModeOfOperation";
  36. protected const string PROFILE_VELOCITY = "ProfileVelocity";
  37. protected const string PROFILE_ACCEL = "ProfileAccel";
  38. protected const string PROFILE_DECEL = "ProfileDecel";
  39. private const string TARGET_POSITION = "TargetPosition";
  40. private const string MOTOR_POSITION = "MotorPosition";
  41. private const string ACTUAL_VELOCITY = "ActualVelocity";
  42. private const string ACTUAL_TORQUE = "ActualTorque";
  43. private const string POSITION_ERROR = "PositionError";
  44. private const string MOTION_DATA = "MotionData";
  45. private const string CURRENT_STATION = "CurrentStation";
  46. protected const string CURRENT_STATION_LIST = "CurrentStationList";
  47. private const string IS_SWITCH_ON = "IsSwitchOn";
  48. private const string HOME_OFFSET = "HomeOffset";
  49. private const string HOMING_METHOD = "HomingMethod";
  50. protected const string HOMING_VELOCITY = "HomingVelocity";
  51. protected const string HOMING_VELOCITY_SLOW = "HomingVelocitySlow";
  52. protected const string HOMING_ACCEL = "HomingAccel";
  53. private const string NEGATIVE_TORQUE_LIMIT="NegativeTorqueLimit";
  54. private const string POSITIVE_TORQUE_LIMIT = "PositiveTorqueLimit";
  55. private const string MANUF_STATUS="ManufStatus";
  56. private const string SOFTWARE_LIMIT_MINUS= "SoftwareLimitMinus";
  57. private const string SOFTWARE_LIMIT_PLUS = "SoftwareLimitPlus";
  58. private const string STOP_CODE = "StopCode";
  59. #endregion
  60. #region 内部变量
  61. /// <summary>
  62. /// 比例因子
  63. /// </summary>
  64. private double _scaleFactor = 0;
  65. /// <summary>
  66. /// jog限制
  67. /// </summary>
  68. private double _jogLimit = 0;
  69. /// <summary>
  70. /// 当前位置数值(用于判定是否正在运动)
  71. /// </summary>
  72. private int _currentLocation = 0;
  73. /// <summary>
  74. /// 是否运动
  75. /// </summary>
  76. private bool _isRun = false;
  77. /// <summary>
  78. /// 当前位置
  79. /// </summary>
  80. private string _currentStation = "";
  81. /// <summary>
  82. /// 当前位置集合(多个位置共用一个数值)
  83. /// </summary>
  84. private List<string> _currentStationList = new List<string>();
  85. /// <summary>
  86. /// 当前位置锁
  87. /// </summary>
  88. private object _locationLocker = new object();
  89. /// <summary>
  90. /// 工位位置对象
  91. /// </summary>
  92. private BeckhoffStationAxis _stationAxis;
  93. /// <summary>
  94. /// 运动时间
  95. /// </summary>
  96. private DateTime _runTime = DateTime.Now;
  97. /// <summary>
  98. /// 尺寸
  99. /// </summary>
  100. private int _waferSize = 0;
  101. /// <summary>
  102. /// inter lock
  103. /// </summary>
  104. private IAxisInterLock _interLock;
  105. /// <summary>
  106. /// 是否存在Rev Sensor Limit
  107. /// </summary>
  108. private bool _isRevSensorLimit = false;
  109. /// <summary>
  110. /// 是否存在Forward Limit
  111. /// </summary>
  112. private bool _isForwardSensorLimit = false;
  113. /// <summary>
  114. /// Home Switched是否触发
  115. /// </summary>
  116. private bool _isHomeSwitchedTrigger = false;
  117. /// <summary>
  118. /// 变量是否初始化字典
  119. /// </summary>
  120. private Dictionary<string, bool> _variableInitializeDic = new Dictionary<string, bool>();
  121. #endregion
  122. #region protected 字段
  123. /// <summary>
  124. /// 轴参数对象
  125. /// </summary>
  126. protected GalilAxisConfig _galilAxisConfig = null;
  127. /// <summary>
  128. /// 状态
  129. /// </summary>
  130. protected RState _status;
  131. /// <summary>
  132. /// 当前操作
  133. /// </summary>
  134. protected MotionOperation _currentOperation = MotionOperation.None;
  135. /// <summary>
  136. /// 模式
  137. /// </summary>
  138. protected byte _modeOfOperation;
  139. /// <summary>
  140. /// 状态字
  141. /// </summary>
  142. protected ushort _statusWord;
  143. /// <summary>
  144. /// 控制字
  145. /// </summary>
  146. protected ushort _controlWord;
  147. /// <summary>
  148. /// 运动数据对象
  149. /// </summary>
  150. protected CommandMotionData _commandMotionData = new CommandMotionData();
  151. /// <summary>
  152. /// Home状态
  153. /// </summary>
  154. protected bool _isHomed;
  155. /// <summary>
  156. /// SwitchOn状态
  157. /// </summary>
  158. protected bool _isSwitchOn;
  159. /// <summary>
  160. /// 是否错误
  161. /// </summary>
  162. protected bool _isError;
  163. /// <summary>
  164. /// 是否到达目标位置
  165. /// </summary>
  166. protected bool _inTargetPosition = false;
  167. /// <summary>
  168. /// 初始化的速度
  169. /// </summary>
  170. protected int _initialVelocity = 0;
  171. /// <summary>
  172. /// 初始化的加速度
  173. /// </summary>
  174. protected int _initialAcceleration = 0;
  175. /// <summary>
  176. /// 初始化的减速度
  177. /// </summary>
  178. protected int _initialDeceleration = 0;
  179. /// <summary>
  180. /// 运动速度
  181. /// </summary>
  182. protected int _profileVelocity = 0;
  183. /// <summary>
  184. /// 运动加速度
  185. /// </summary>
  186. protected int _profileAcceleration = 0;
  187. /// <summary>
  188. /// 运动减速度
  189. /// </summary>
  190. protected int _profileDeceleration = 0;
  191. /// <summary>
  192. /// 负向Torque限制
  193. /// </summary>
  194. protected int _profileNegativeTorqueLimit = 0;
  195. /// <summary>
  196. /// 正向Torque限制
  197. /// </summary>
  198. protected int _profilePositiveTorqueLimit = 0;
  199. /// <summary>
  200. /// Homing 速度
  201. /// </summary>
  202. protected int _profileHomingVelocity = 0;
  203. /// <summary>
  204. /// Homing 速度Slow
  205. /// </summary>
  206. protected int _profileHomingVelocitySlow = 0;
  207. /// <summary>
  208. /// Homing加速度
  209. /// </summary>
  210. protected int _profileHomingAccel = 0;
  211. /// <summary>
  212. /// <summary>
  213. /// 目标位置
  214. /// </summary>
  215. protected double _targetPosition = 0.0;
  216. /// <summary>
  217. /// home超时时长
  218. /// </summary>
  219. protected int _homeTimeout = 5000;
  220. /// <summary>
  221. /// coe输出变量集合
  222. /// </summary>
  223. protected List<string> _coeOutputs = new List<string>();
  224. /// <summary>
  225. /// 速度比例
  226. /// </summary>
  227. protected int _speedRatio = 1;
  228. /// <summary>
  229. /// 加速度的比例
  230. /// </summary>
  231. protected int _accelerationRatio = 1;
  232. /// <summary>
  233. /// torque比例
  234. /// </summary>
  235. protected int _torqueRatio = 1000;
  236. #endregion
  237. #region 属性
  238. /// <summary>
  239. /// 状态
  240. /// </summary>
  241. public RState Status { get { return _status; } }
  242. /// <summary>
  243. /// Home状态
  244. /// </summary>
  245. public bool IsHomed { get { return _isHomed; } set { _isHomed = value; } }
  246. /// <summary>
  247. /// SwitchOn状态
  248. /// </summary>
  249. public bool IsSwitchOn { get { return _isSwitchOn; } }
  250. /// <summary>
  251. /// 模式
  252. /// </summary>
  253. public byte ModeOfOperation { get { return _modeOfOperation; } }
  254. /// <summary>
  255. /// 控制字
  256. /// </summary>
  257. public ushort ControlWord { get { return _controlWord; } }
  258. /// <summary>
  259. /// 是否运动中
  260. /// </summary>
  261. public bool IsRun { get { return _isRun; } }
  262. /// <summary>
  263. /// 当前位置
  264. /// </summary>
  265. public string CurrentStation { get { return _currentStation; } }
  266. /// <summary>
  267. /// 是否到达目标位置
  268. /// </summary>
  269. public bool InTargetPosition { get { return _inTargetPosition; } }
  270. /// <summary>
  271. /// 运动数据对象
  272. /// </summary>
  273. public CommandMotionData MotionData { get { return _commandMotionData; } }
  274. /// <summary>
  275. /// 负向Torque限制数值
  276. /// </summary>
  277. public int NegativeTorqueLimit { get { return _profileNegativeTorqueLimit; } }
  278. /// <summary>
  279. /// 正向Torque限制数值
  280. /// </summary>
  281. public int PositiveTorqueLimit { get { return _profilePositiveTorqueLimit; } }
  282. /// <summary>
  283. /// 是否错误
  284. /// </summary>
  285. public bool IsError { get { return _isError; } }
  286. /// <summary>
  287. /// 目标位置
  288. /// </summary>
  289. public double TargetPosition { get { return _targetPosition; } }
  290. /// <summary>
  291. /// 加速度
  292. /// </summary>
  293. public double ProfileAcceleration { get { return _profileAcceleration; } }
  294. /// <summary>
  295. /// 减速度
  296. /// </summary>
  297. public double ProfileDeceleration { get { return _profileDeceleration; } }
  298. /// <summary>
  299. /// inter lock接口对象
  300. /// </summary>
  301. public IAxisInterLock InterLock { set { _interLock= value; } }
  302. /// <summary>
  303. /// 是否存在Sensor Limit
  304. /// </summary>
  305. public bool IsRevSensorLimit { set { _isRevSensorLimit = value; } }
  306. /// <summary>
  307. /// 是否存在正向Sensor Limit
  308. /// </summary>
  309. public bool IsForwardSensorLimit { set { _isForwardSensorLimit = value; } }
  310. /// <summary>
  311. /// Home Switch是否触发
  312. /// </summary>
  313. public bool IsHomeSwitchedTriggered { get { return _isHomeSwitchedTrigger; } set { _isHomeSwitchedTrigger = value; } }
  314. /// <summary>
  315. /// 所有io变量是否初始化
  316. /// </summary>
  317. public bool IOInitialized { get { return AllIoVariableInitialized(); } }
  318. #endregion
  319. /// <summary>
  320. /// 构造函数
  321. /// </summary>
  322. /// <param name="moduleName"></param>
  323. /// <param name="name"></param>
  324. public JetAxisBase(string moduleName,string name) : base(moduleName, name,name,name)
  325. {
  326. InitializeParameter();
  327. LoadStation();
  328. InitializeRoutine();
  329. SubscribeData();
  330. InitializeOperation();
  331. }
  332. #region private方法
  333. /// <summary>
  334. /// 加载Station位置
  335. /// </summary>
  336. private void LoadStation()
  337. {
  338. _waferSize = SC.GetValue<int>("System.WaferSize");
  339. _stationAxis = BeckhoffStationLocationManager.Instance.GetStationAxis(Module, Name, _waferSize);
  340. }
  341. /// <summary>
  342. /// 订阅数据
  343. /// </summary>
  344. private void SubscribeData()
  345. {
  346. BeckhoffProviderAxis beckhoffProviderAxis = BeckhoffAxisProviderManager.Instance.GetAxisProvider($"{Module}.{Name}");
  347. if (beckhoffProviderAxis != null)
  348. {
  349. _scaleFactor = beckhoffProviderAxis.ScaleFactor;
  350. _jogLimit = beckhoffProviderAxis.JogLimit;
  351. }
  352. _galilAxisConfig = GalilControllerCfgManager.Instance.GetGalilAxisConfig(Module.ToString(),Name);
  353. if (_galilAxisConfig != null)
  354. {
  355. _profileVelocity =CalculateMultiplySpeedRatio(_galilAxisConfig.Speed);
  356. _initialVelocity = _profileVelocity;
  357. _profileAcceleration = CalculateDivideAccelerationRatio(_galilAxisConfig.Acceleration);
  358. _initialAcceleration = _profileAcceleration;
  359. _profileDeceleration = CalculateDivideAccelerationRatio(_galilAxisConfig.Deceleration);
  360. _initialDeceleration = _profileDeceleration;
  361. _profileNegativeTorqueLimit = _galilAxisConfig.NegativeTorqueLimit;
  362. _profilePositiveTorqueLimit = _galilAxisConfig.PositiveTorqueLimit;
  363. _commandMotionData.FileAcceleration = CalculateValueAfterScale(_galilAxisConfig.Acceleration);
  364. _commandMotionData.FileDeceleration = CalculateValueAfterScale(_galilAxisConfig.Deceleration);
  365. _commandMotionData.HomeOffset = CalculateValueAfterScale(_galilAxisConfig.HomingOffset);
  366. _commandMotionData.FileHomingAccel = CalculateValueAfterScale(_galilAxisConfig.HomingAcceleration);
  367. _commandMotionData.FileHomingVelocitySlow = CalculateValueAfterScale(_galilAxisConfig.HomingSpeed);
  368. _commandMotionData.FileHomingVelocity = CalculateValueAfterScale(_galilAxisConfig.HomingSpeed);
  369. _commandMotionData.FileProfileVelocity = CalculateValueAfterScale(_galilAxisConfig.Speed);
  370. _commandMotionData.FwdSoftLimit = CalculateValueAfterScale(_galilAxisConfig.ForwardSoftwareLimit)-_commandMotionData.HomeOffset;
  371. _commandMotionData.RevSoftLimit = CalculateValueAfterScale(_galilAxisConfig.ReverseSoftwareLimit)-_commandMotionData.HomeOffset;
  372. _commandMotionData.NegativeTorqueLimit = _galilAxisConfig.NegativeTorqueLimit;
  373. _commandMotionData.PositiveTorqueLimit = _galilAxisConfig.PositiveTorqueLimit;
  374. if (_galilAxisConfig.NegativeTorqueLimit != 0 || _galilAxisConfig.PositiveTorqueLimit != 0)
  375. {
  376. _commandMotionData.TorqueLimit = $"-{_galilAxisConfig.NegativeTorqueLimit}/+{_galilAxisConfig.PositiveTorqueLimit}";
  377. }
  378. if(_galilAxisConfig.HomingTimeOut!=0)
  379. {
  380. _homeTimeout = _galilAxisConfig.HomingTimeOut;
  381. }
  382. }
  383. DATA.Subscribe($"{Module}.{Name}.{MOTION_DATA}", () => _commandMotionData,SubscriptionAttribute.FLAG.IgnoreSaveDB);
  384. DATA.Subscribe($"{Module}.{Name}.{MOTOR_POSITION}", () => _commandMotionData.MotorPosition,SubscriptionAttribute.FLAG.IgnoreSaveDB);
  385. DATA.Subscribe($"{Module}.{Name}.ProfileVelocity", () => _commandMotionData.ProfileVelocity, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  386. DATA.Subscribe($"{Module}.{Name}.Acceleration",()=>_commandMotionData.FileAcceleration,SubscriptionAttribute.FLAG.IgnoreSaveDB);
  387. DATA.Subscribe($"{Module}.{Name}.Deceleration",()=>_commandMotionData.FileDeceleration,SubscriptionAttribute.FLAG.IgnoreSaveDB);
  388. DATA.Subscribe($"{Module}.{Name}.ActualTorque",()=>_commandMotionData.ActualTorque,SubscriptionAttribute.FLAG.IgnoreSaveDB);
  389. DATA.Subscribe($"{Module}.{Name}.{CURRENT_STATION}", () => _currentStation,SubscriptionAttribute.FLAG.IgnoreSaveDB);
  390. DATA.Subscribe($"{Module}.{Name}.{CURRENT_STATION_LIST}", () => _currentStationList, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  391. DATA.Subscribe($"{Module}.{Name}.{IS_SWITCH_ON}", () => IsSwitchOn, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  392. DATA.Subscribe($"{Module}.{Name}.IsHomed", () => IsHomed, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  393. DATA.Subscribe($"{Module}.{Name}.IsError",()=>IsError, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  394. DATA.Subscribe($"{Module}.{Name}.IsMoving", () => _isRun, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  395. DATA.Subscribe($"{Module}.{Name}.IsRun", () => _isRun, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  396. }
  397. /// <summary>
  398. /// 初始化操作
  399. /// </summary>
  400. private void InitializeOperation()
  401. {
  402. OP.Subscribe($"{Module}.{Name}.{MotionOperation.SwitchOn}", (cmd, args) => { SwitchOn(); return true; });
  403. OP.Subscribe($"{Module}.{Name}.{MotionOperation.SwitchOff}", (cmd, args) => { SwitchOff(); return true; });
  404. OP.Subscribe($"{Module}.{Name}.{MotionOperation.Home}", (cmd, args) => { Home(); return true; });
  405. OP.Subscribe($"{Module}.{Name}.JogUp", JogUpPosition);
  406. OP.Subscribe($"{Module}.{Name}.JogDown", JogDownPosition);
  407. OP.Subscribe($"{Module}.{Name}.{MotionOperation.KeyDown}", KeyDownOperation);
  408. OP.Subscribe($"{Module}.{Name}.{MotionOperation.Stop}",(cmd,args)=> { return StopPositionOperation(); });
  409. OP.Subscribe($"{Module}.{Name}.{MotionOperation.Save}", SaveOperation);
  410. OP.Subscribe($"{Module}.{Name}.GotoSavedPosition", (cmd, args) => {
  411. return PositionStation(args[1].ToString()); });
  412. }
  413. /// <summary>
  414. /// 保存操作
  415. /// </summary>
  416. /// <param name="cmd"></param>
  417. /// <param name="args"></param>
  418. /// <returns></returns>
  419. public bool SaveOperation(string cmd, object[] args)
  420. {
  421. if (args.Length >= 2)
  422. {
  423. string key = args[0].ToString();
  424. double paramValue = double.Parse(args[1].ToString());
  425. BeckhoffStationLocationManager.Instance.SaveMotionPosition(key, paramValue);
  426. lock (_locationLocker)
  427. {
  428. List<string> lst = new List<string>();
  429. foreach (Station item in _stationAxis.Stations)
  430. {
  431. if (item.Name == key)
  432. {
  433. item.Position = paramValue.ToString();
  434. _currentStation = item.Name;
  435. if (!lst.Contains(item.Name))
  436. {
  437. lst.Add(item.Name);
  438. }
  439. }
  440. }
  441. _currentStationList.Clear();
  442. if (lst.Count != 0)
  443. {
  444. _currentStationList.AddRange(lst);
  445. }
  446. }
  447. LOG.WriteLog(eEvent.INFO_AXIS, $"{Module}.{Name}", "save success");
  448. }
  449. return true;
  450. }
  451. /// <summary>
  452. /// 计算所处当前工位
  453. /// </summary>
  454. private void CalculateCurrentStation(double motor)
  455. {
  456. lock (_locationLocker)
  457. {
  458. List<string> tmp = _currentStationList.ToList();
  459. List<string> lst = new List<string>();
  460. foreach (Station station in _stationAxis.Stations)
  461. {
  462. if (double.TryParse(station.Position, out double value))
  463. {
  464. if (Math.Round(Math.Abs(motor - value),2) <= _stationAxis.ToleranceDefault)
  465. {
  466. _currentStation = station.Name;
  467. if (!lst.Contains(station.Name))
  468. {
  469. lst.Add(station.Name);
  470. }
  471. }
  472. }
  473. }
  474. _currentStationList.Clear();
  475. if (lst.Count != 0)
  476. {
  477. string str = string.Join(",", tmp);
  478. _currentStationList.AddRange(lst);
  479. string strLst = string.Join(",", _currentStationList);
  480. if (str != strLst)
  481. {
  482. LOG.WriteLog(eEvent.INFO_AXIS, $"{Module}.{Name}", $"position {motor} current {strLst}");
  483. }
  484. }
  485. else
  486. {
  487. _currentStation = "";
  488. }
  489. if (tmp.Count != 0&&_currentStationList.Count==0)
  490. {
  491. LOG.WriteLog(eEvent.INFO_AXIS, $"{Module}.{Name}", $"position {motor} current is empty");
  492. }
  493. }
  494. }
  495. /// <summary>
  496. /// 文本框回车操作
  497. /// </summary>
  498. /// <param name="cmd"></param>
  499. /// <param name="args"></param>
  500. /// <returns></returns>
  501. private bool KeyDownOperation(string cmd, object[] args)
  502. {
  503. if (args.Length < 2)
  504. {
  505. return false;
  506. }
  507. if (double.TryParse(args[1].ToString(), out double value))
  508. {
  509. AxisKeyDown(args[0].ToString(), value);
  510. }
  511. else
  512. {
  513. EV.PostWarningLog($"{Module}.{Name}", eEvent.ERR_AXIS, $"{args[0]} value {args[1]}is not int value");
  514. }
  515. return true;
  516. }
  517. /// <summary>
  518. /// 是否所有IO变量初始化完成
  519. /// </summary>
  520. /// <returns></returns>
  521. private bool AllIoVariableInitialized()
  522. {
  523. foreach (string item in _variableInitializeDic.Keys)
  524. {
  525. if (!_variableInitializeDic[item])
  526. {
  527. LOG.WriteLog(eEvent.ERR_DRYER, Module, $"{item} is not initialized");
  528. return false;
  529. }
  530. }
  531. return true;
  532. }
  533. /// <summary>
  534. /// 更新运动数据
  535. /// </summary>
  536. /// <param name="variable"></param>
  537. /// <param name="value"></param>
  538. private void UpdateMotionData(string variable, object value)
  539. {
  540. if(!MotionData.IsDataInitialized)
  541. {
  542. MotionData.IsDataInitialized = true;
  543. }
  544. PropertyInfo property = MotionData.GetType().GetProperty(variable);
  545. if (property != null)
  546. {
  547. if (JudgeIsScale(variable))
  548. {
  549. if (int.TryParse(value.ToString(), out int intValue))
  550. {
  551. if (JudgeSpeedRatio(variable))
  552. {
  553. property.SetValue(MotionData, CalculateValueAfterScale(CalculateDivideSpeedRatio(intValue)));
  554. }
  555. else if(JudgeAccelerationRation(variable))
  556. {
  557. property.SetValue(MotionData, CalculateValueAfterScale(CalculateMultiplyAccelerationRatio(intValue)));
  558. }
  559. else
  560. {
  561. property.SetValue(MotionData, CalculateValueAfterScale(intValue));
  562. }
  563. }
  564. else
  565. {
  566. property.SetValue(MotionData, value);
  567. }
  568. }
  569. else if(variable==ACTUAL_TORQUE)
  570. {
  571. if (short.TryParse(value.ToString(), out short shortValue))
  572. {
  573. property.SetValue(MotionData, CalculateDivideTorqueRatio(shortValue));
  574. }
  575. else
  576. {
  577. property.SetValue(MotionData, value);
  578. }
  579. }
  580. else
  581. {
  582. property.SetValue(MotionData, value);
  583. }
  584. }
  585. if (variable == IS_SWITCH_ON)
  586. {
  587. _isSwitchOn = MotionData.IsSwitchOn;
  588. }
  589. }
  590. /// <summary>
  591. /// 判定是否需要比例计算
  592. /// </summary>
  593. /// <param name="variable"></param>
  594. /// <returns></returns>
  595. private bool JudgeIsScale(string variable)
  596. {
  597. switch (variable)
  598. {
  599. case PROFILE_VELOCITY:
  600. case PROFILE_ACCEL:
  601. case PROFILE_DECEL:
  602. case MOTOR_POSITION:
  603. case POSITION_ERROR:
  604. case ACTUAL_VELOCITY:
  605. case TARGET_POSITION:
  606. case HOMING_ACCEL:
  607. case HOMING_VELOCITY:
  608. case HOMING_VELOCITY_SLOW:
  609. case HOME_OFFSET:
  610. return true;
  611. default:
  612. return false;
  613. }
  614. }
  615. /// <summary>
  616. /// 判定是否需要速度调整比例
  617. /// </summary>
  618. /// <param name="variable"></param>
  619. /// <returns></returns>
  620. private bool JudgeSpeedRatio(string variable)
  621. {
  622. switch (variable)
  623. {
  624. case PROFILE_VELOCITY:
  625. case ACTUAL_VELOCITY:
  626. case HOMING_VELOCITY:
  627. case HOMING_VELOCITY_SLOW:
  628. case HOME_OFFSET:
  629. return true;
  630. default:
  631. return false;
  632. }
  633. }
  634. /// <summary>
  635. /// 是否是加速度调整比例
  636. /// </summary>
  637. /// <param name="variable"></param>
  638. /// <returns></returns>
  639. protected bool JudgeAccelerationRation(string variable)
  640. {
  641. switch(variable)
  642. {
  643. case PROFILE_ACCEL:
  644. case PROFILE_DECEL:
  645. case HOMING_ACCEL:
  646. return true;
  647. default:
  648. return false;
  649. }
  650. }
  651. /// <summary>
  652. /// motor position发生变化
  653. /// </summary>
  654. /// <param name="location"></param>
  655. private void MotionPositionChanged(int location)
  656. {
  657. if (Math.Abs(location - _currentLocation)/_scaleFactor >= _stationAxis.ToleranceDefault)
  658. {
  659. _currentLocation = location;
  660. _runTime = DateTime.Now;
  661. _isRun = true;
  662. }
  663. }
  664. /// <summary>
  665. /// 更新Digital Inputs
  666. /// </summary>
  667. /// <param name="digitalInputs"></param>
  668. private void UpdateDigitalInputs(uint digitalInputs)
  669. {
  670. if (_isRevSensorLimit)
  671. {
  672. MotionData.RevLimited = !(((digitalInputs>>18) & 0x01) == 0x01);
  673. }
  674. if(_isForwardSensorLimit)
  675. {
  676. MotionData.FwdLimited = !(((digitalInputs >> 17) & 0x01) == 0x01);
  677. }
  678. MotionData.HomedSwitched =((digitalInputs>>22)&0x01) == 0x01;
  679. if(!_isHomeSwitchedTrigger&&MotionData.HomedSwitched)
  680. {
  681. _isHomeSwitchedTrigger = true;
  682. }
  683. }
  684. /// <summary>
  685. /// 更新ManufactureStatus
  686. /// </summary>
  687. /// <param name="manufactureStatus"></param>
  688. private void UpdateManufactureStatus(uint manufactureStatus)
  689. {
  690. MotionData.HomedSwitched = ((manufactureStatus >> 26)&0x01) == 0x01;
  691. if (!_isHomeSwitchedTrigger && MotionData.HomedSwitched)
  692. {
  693. _isHomeSwitchedTrigger = true;
  694. }
  695. }
  696. /// <summary>
  697. /// 更新Torque Limited状态
  698. /// </summary>
  699. private void UpdateTorqueLimited()
  700. {
  701. if(MotionData.NegativeTorqueLimit!=0||MotionData.PositiveTorqueLimit!=0)
  702. {
  703. MotionData.TorqueLimited = (MotionData.ActualTorque >= -MotionData.NegativeTorqueLimit) && (MotionData.ActualTorque <= MotionData.PositiveTorqueLimit) ;
  704. }
  705. else
  706. {
  707. MotionData.TorqueLimited = true;
  708. }
  709. }
  710. /// <summary>
  711. /// 根据位置获取相应的Position数值
  712. /// </summary>
  713. /// <param name="station"></param>
  714. /// <returns></returns>
  715. public (bool success,double position) GetPositionByStation(string station)
  716. {
  717. foreach(Station item in _stationAxis.Stations)
  718. {
  719. if(item.Name.EndsWith(station))
  720. {
  721. if(double.TryParse(item.Position,out double position))
  722. {
  723. return (true, position);
  724. }
  725. else
  726. {
  727. return (false, 0);
  728. }
  729. }
  730. }
  731. return (false, 0);
  732. }
  733. #endregion
  734. #region protected 子类使用共用类,子类不再扩展
  735. /// <summary>
  736. /// 计算比例后的数值
  737. /// </summary>
  738. /// <param name="value"></param>
  739. /// <returns></returns>
  740. protected double CalculateValueAfterScale(int value)
  741. {
  742. if (_scaleFactor != 0)
  743. {
  744. return Math.Round((double)value / _scaleFactor, 2);
  745. }
  746. else
  747. {
  748. return (double)value;
  749. }
  750. }
  751. /// <summary>
  752. /// 确认操作状态
  753. /// </summary>
  754. /// <param name="operation"></param>
  755. protected void ConfirmOperationState(MotionOperation operation)
  756. {
  757. if (_currentOperation == operation)
  758. {
  759. _status = RState.End;
  760. EndOperation();
  761. }
  762. }
  763. /// <summary>
  764. /// 结束操作
  765. /// </summary>
  766. protected void EndOperation()
  767. {
  768. LOG.WriteLog(eEvent.INFO_AXIS,$"{Module}.{Name}", $"{Module}.{Name} execute {_currentOperation} complete");
  769. _currentOperation = MotionOperation.None;
  770. _targetPosition = 0;
  771. }
  772. /// <summary>
  773. /// 订阅变量数值发生变化
  774. /// </summary>
  775. protected void SubscribeValueAction()
  776. {
  777. GalilAxisSubscribeUpdateVariable(IS_SWITCH_ON);
  778. GalilAxisSubscribeUpdateVariable(STOP_CODE);
  779. GalilAxisSubscribeUpdateVariable( MOTOR_POSITION);
  780. GalilAxisSubscribeUpdateVariable( POSITION_ERROR);
  781. GalilAxisSubscribeUpdateVariable( ACTUAL_TORQUE);
  782. GalilAxisSubscribeUpdateVariable( ACTUAL_VELOCITY);
  783. }
  784. /// <summary>
  785. /// 订阅IO变量
  786. /// </summary>
  787. /// <param name="variable"></param>
  788. private void GalilAxisSubscribeUpdateVariable(string variable)
  789. {
  790. _variableInitializeDic[variable] = false;
  791. GalilAxisManager.Instance.SubscribeModuleVariable($"{Module}.{Name}", variable, UpdateVariableValue);
  792. }
  793. /// <summary>
  794. /// 更新变量数值
  795. /// </summary>
  796. /// <param name="variable"></param>
  797. /// <param name="value"></param>
  798. protected void UpdateVariableValue(string variable, object value)
  799. {
  800. if (value == null)
  801. {
  802. return;
  803. }
  804. if (_variableInitializeDic.ContainsKey(variable) && !_variableInitializeDic[variable])
  805. {
  806. _variableInitializeDic[variable] = true;
  807. }
  808. if (variable == MOTOR_POSITION)
  809. {
  810. if (int.TryParse(value.ToString(), out int location))
  811. {
  812. MotionPositionChanged(location);
  813. if (_galilAxisConfig.ForwardSoftwareLimit != 0)
  814. {
  815. MotionData.ForwardSoftwareLimited = location > _galilAxisConfig.ForwardSoftwareLimit-_galilAxisConfig.HomingOffset;
  816. if (!_isForwardSensorLimit && !_isRevSensorLimit)
  817. {
  818. MotionData.FwdLimited = MotionData.ForwardSoftwareLimited;
  819. }
  820. }
  821. if (_galilAxisConfig.ReverseSoftwareLimit != 0)
  822. {
  823. MotionData.ReverseSoftwareLimited = location < _galilAxisConfig.ReverseSoftwareLimit-_galilAxisConfig.HomingOffset;
  824. if (!_isRevSensorLimit && !_isForwardSensorLimit)
  825. {
  826. MotionData.RevLimited = MotionData.ReverseSoftwareLimited;
  827. }
  828. }
  829. }
  830. }
  831. UpdateMotionData(variable, value);
  832. if (variable == MOTOR_POSITION)
  833. {
  834. CalculateCurrentStation(MotionData.MotorPosition);
  835. }
  836. if (variable == ACTUAL_TORQUE)
  837. {
  838. UpdateTorqueLimited();
  839. }
  840. else if (variable == POSITIVE_TORQUE_LIMIT || variable == NEGATIVE_TORQUE_LIMIT)
  841. {
  842. MotionData.TorqueLimit = $"-{MotionData.NegativeTorqueLimit}/+{MotionData.PositiveTorqueLimit}";
  843. }
  844. }
  845. /// <summary>
  846. /// 监控(用于判定是否停止运动)
  847. /// </summary>
  848. protected void JudgeRunMonitor()
  849. {
  850. if (_isRun && DateTime.Now.Subtract(_runTime).TotalMilliseconds >= 500)
  851. {
  852. _isRun = false;
  853. }
  854. }
  855. #endregion
  856. #region public 公开方法
  857. /// <summary>
  858. /// 初始化
  859. /// </summary>
  860. /// <returns></returns>
  861. public bool Initialize()
  862. {
  863. SubscribeValueAction();
  864. return true;
  865. }
  866. /// <summary>
  867. /// 当前位置是否离目标位置不远
  868. /// </summary>
  869. /// <param name="targetPosition"></param>
  870. /// <returns></returns>
  871. public bool JudgeCurrentPositionIsInTargetPosition(int targetPosition)
  872. {
  873. double scaledTargetPosition = targetPosition /_scaleFactor;
  874. double currentMotionPosition = MotionData.MotorPosition;
  875. return Math.Round(Math.Abs(currentMotionPosition-scaledTargetPosition),2) <= _stationAxis.ToleranceDefault;
  876. }
  877. /// <summary>
  878. /// 计算乘以比例后的数值
  879. /// </summary>
  880. /// <param name="value"></param>
  881. /// <returns></returns>
  882. public int CalculateValueMultiplyScale(double value)
  883. {
  884. if (_scaleFactor != 0)
  885. {
  886. return (int)Math.Round(value * _scaleFactor, 0);
  887. }
  888. else
  889. {
  890. return (int)Math.Round(value, 0);
  891. }
  892. }
  893. /// <summary>
  894. /// 计算乘上速度比例后的速度
  895. /// </summary>
  896. /// <param name="speed"></param>
  897. /// <returns></returns>
  898. public int CalculateMultiplySpeedRatio(int speed)
  899. {
  900. return speed * _speedRatio;
  901. }
  902. /// <summary>
  903. /// 计算乘上加速度比例后的加速度
  904. /// </summary>
  905. /// <param name="acceleration"></param>
  906. /// <returns></returns>
  907. public int CalculateMultiplyAccelerationRatio(int acceleration)
  908. {
  909. return acceleration * _accelerationRatio;
  910. }
  911. /// <summary>
  912. /// 计算除以速度比例后的速度
  913. /// </summary>
  914. /// <param name="speed"></param>
  915. /// <returns></returns>
  916. protected int CalculateDivideSpeedRatio(int speed)
  917. {
  918. return speed / _speedRatio;
  919. }
  920. /// <summary>
  921. /// 计算除以加速度比例后的加速度
  922. /// </summary>
  923. /// <param name="acceleration"></param>
  924. /// <returns></returns>
  925. protected int CalculateDivideAccelerationRatio(int acceleration)
  926. {
  927. return acceleration / _accelerationRatio;
  928. }
  929. /// <summary>
  930. /// 计算除以Torque比例后的Torque
  931. /// </summary>
  932. /// <param name="speed"></param>
  933. /// <returns></returns>
  934. protected double CalculateDivideTorqueRatio(int torque)
  935. {
  936. return Math.Round((double)torque / _torqueRatio, 2);
  937. }
  938. /// <summary>
  939. /// Jog Up
  940. /// </summary>
  941. /// <param name="cmd"></param>
  942. /// <param name="args"></param>
  943. /// <returns></returns>
  944. public bool JogUpPosition(string cmd, object[] args)
  945. {
  946. double jog=(double)args[1];
  947. double currentPosition=(double)args[2];
  948. if(_jogLimit!=0)
  949. {
  950. if(jog>_jogLimit)
  951. {
  952. LOG.WriteLog(eEvent.ERR_AXIS, Module, $"Jog Value {jog} is over {_jogLimit}");
  953. return false;
  954. }
  955. }
  956. if (!_isSwitchOn)
  957. {
  958. LOG.WriteLog(eEvent.ERR_AXIS, Module, $"Axis is switch off,cannot jog");
  959. return false;
  960. }
  961. return ProfilePositionOperation(Math.Round(currentPosition + jog,2));
  962. }
  963. /// <summary>
  964. /// Jog Down
  965. /// </summary>
  966. /// <param name="cmd"></param>
  967. /// <param name="args"></param>
  968. /// <returns></returns>
  969. public bool JogDownPosition(string cmd, object[] args)
  970. {
  971. double jog = (double)args[1];
  972. double currentPosition = (double)args[2];
  973. if (_jogLimit != 0)
  974. {
  975. if (jog > _jogLimit)
  976. {
  977. LOG.WriteLog(eEvent.ERR_AXIS, Module, $"Jog Value {jog} is over {_jogLimit}");
  978. return false;
  979. }
  980. }
  981. if(!_isSwitchOn)
  982. {
  983. LOG.WriteLog(eEvent.ERR_AXIS, Module, $"Axis is switch off,cannot jog");
  984. return false;
  985. }
  986. return ProfilePositionOperation(Math.Round(currentPosition - jog,2));
  987. }
  988. /// <summary>
  989. /// Profile position操作
  990. /// </summary>
  991. /// <param name="cmd"></param>
  992. /// <param name="args"></param>
  993. /// <returns></returns>
  994. public bool ProfilePositionOperation(double position)
  995. {
  996. _targetPosition = position;
  997. int targetPosition = CalculateValueMultiplyScale(_targetPosition);
  998. if (_galilAxisConfig.ForwardSoftwareLimit != 0 && targetPosition > _galilAxisConfig.ForwardSoftwareLimit - _galilAxisConfig.HomingOffset)
  999. {
  1000. LOG.WriteLog(eEvent.ERR_AXIS, Module, $"target position {_targetPosition} is over forward limit");
  1001. return false;
  1002. }
  1003. if (_galilAxisConfig.ReverseSoftwareLimit != 0 && targetPosition < _galilAxisConfig.ReverseSoftwareLimit - _galilAxisConfig.HomingOffset)
  1004. {
  1005. LOG.WriteLog(eEvent.ERR_AXIS, Module, $"target position {_targetPosition} is less reverse limit");
  1006. return false;
  1007. }
  1008. return ProfilePosition(targetPosition, _profileVelocity, _profileAcceleration, _profileDeceleration);
  1009. }
  1010. /// <summary>
  1011. /// 移动至指定位置
  1012. /// </summary>
  1013. /// <param name="targetStation"></param>
  1014. /// <returns></returns>
  1015. public bool PositionStation(string targetStation,bool isHome=false,int velocity=0,int acceleration=0,int deceleration=0, bool judgeTorqueLimit = true)
  1016. {
  1017. if (!CheckPositionIsInStation(MotionData.MotorPosition,targetStation))
  1018. {
  1019. if(_interLock!=null&&!isHome&&!_interLock.CheckGotoPosition(targetStation))
  1020. {
  1021. return false;
  1022. }
  1023. var result=GetPositionByStation(targetStation);
  1024. if(result.success)
  1025. {
  1026. _targetPosition = result.position;
  1027. int targetPosition = (int)Math.Round(result.position * _scaleFactor, 0);
  1028. if (velocity != 0)
  1029. {
  1030. return ProfilePosition(targetPosition, velocity, acceleration, deceleration, judgeTorqueLimit);
  1031. }
  1032. else
  1033. {
  1034. return ProfilePosition(targetPosition, _profileVelocity, _profileAcceleration, _profileDeceleration, judgeTorqueLimit);
  1035. }
  1036. }
  1037. LOG.WriteLog(eEvent.ERR_AXIS, Module, $"{targetStation} not in list,cannot goto fixed position");
  1038. return false;
  1039. }
  1040. else
  1041. {
  1042. _status = RState.End;
  1043. }
  1044. return true;
  1045. }
  1046. /// <summary>
  1047. /// 上电
  1048. /// </summary>
  1049. /// <returns></returns>
  1050. public bool WriteSwitchOn()
  1051. {
  1052. return GalilControllerCfgManager.Instance.SetAxisCommand(Module, Name, "SH", null);
  1053. }
  1054. /// <summary>
  1055. /// 下电
  1056. /// </summary>
  1057. /// <returns></returns>
  1058. public bool WriteSwitchOff()
  1059. {
  1060. return GalilControllerCfgManager.Instance.SetAxisCommand(Module, Name, "MO", null);
  1061. }
  1062. /// <summary>
  1063. /// 写入相对位置
  1064. /// </summary>
  1065. /// <param name="referencePosition"></param>
  1066. /// <returns></returns>
  1067. public bool WriteReferencePosition(int referencePosition)
  1068. {
  1069. return GalilControllerCfgManager.Instance.SetAxisCommand(Module, Name, "PR", referencePosition);
  1070. }
  1071. /// <summary>
  1072. /// 写入绝对位置
  1073. /// </summary>
  1074. /// <param name="referencePosition"></param>
  1075. /// <returns></returns>
  1076. public bool WriteAbsolutePosition(int absolutePosition)
  1077. {
  1078. return GalilControllerCfgManager.Instance.SetAxisCommand(Module, Name, "PA", absolutePosition);
  1079. }
  1080. /// <summary>
  1081. /// 写入速度
  1082. /// </summary>
  1083. /// <param name="referencePosition"></param>
  1084. /// <returns></returns>
  1085. public bool WriteSpeed(int speed)
  1086. {
  1087. return GalilControllerCfgManager.Instance.SetAxisCommand(Module, Name, "SP", speed);
  1088. }
  1089. /// <summary>
  1090. /// 写入加速度
  1091. /// </summary>
  1092. /// <param name="referencePosition"></param>
  1093. /// <returns></returns>
  1094. public bool WriteAcceleration(int acceleration)
  1095. {
  1096. return GalilControllerCfgManager.Instance.SetAxisCommand(Module, Name, "AC", acceleration);
  1097. }
  1098. /// <summary>
  1099. /// 写入减速度
  1100. /// </summary>
  1101. /// <param name="referencePosition"></param>
  1102. /// <returns></returns>
  1103. public bool WriteDeceleration(int deceleration)
  1104. {
  1105. return GalilControllerCfgManager.Instance.SetAxisCommand(Module, Name, "DC", deceleration);
  1106. }
  1107. /// <summary>
  1108. /// 停止
  1109. /// </summary>
  1110. /// <returns></returns>
  1111. public bool WriteStop()
  1112. {
  1113. return GalilControllerCfgManager.Instance.SetAxisCommand(Module, Name, "ST", null);
  1114. }
  1115. /// <summary>
  1116. /// 开始运动
  1117. /// </summary>
  1118. /// <returns></returns>
  1119. public bool WriteStartMotion()
  1120. {
  1121. return GalilControllerCfgManager.Instance.SetAxisCommand(Module, Name, "BG", null);
  1122. }
  1123. /// <summary>
  1124. /// Home 电机
  1125. /// </summary>
  1126. /// <returns></returns>
  1127. public bool WriteHomeAxisCommand()
  1128. {
  1129. return GalilControllerCfgManager.Instance.SetAxisCommand(Module, Name, "HM", null);
  1130. }
  1131. /// <summary>
  1132. /// 手动置零
  1133. /// </summary>
  1134. /// <returns></returns>
  1135. public bool WriteDPZero()
  1136. {
  1137. bool result= GalilControllerCfgManager.Instance.SetAxisCommand(Module, Name, "DP", 0);
  1138. if (result)
  1139. {
  1140. return GalilControllerCfgManager.Instance.SetAxisCommand(Module, Name, "DE", 0);
  1141. }
  1142. return false;
  1143. }
  1144. /// <summary>
  1145. /// 写入控制字
  1146. /// </summary>
  1147. /// <param name="controlWord"></param>
  1148. public bool WriteControlWord(ushort controlWord)
  1149. {
  1150. return BeckhoffAxisManager.Instance.WriteVariableValue($"{Module}.{Name}.{CONTROL_WORD}", controlWord);
  1151. }
  1152. /// <summary>
  1153. /// 写入ModeOfOperation
  1154. /// </summary>
  1155. /// <param name="modeOfOperation"></param>
  1156. /// <returns></returns>
  1157. public bool WriteModeOfMode(AxisModeOfOperation modeOfOperation)
  1158. {
  1159. return BeckhoffAxisManager.Instance.WriteVariableValue($"{Module}.{Name}.{MODE_OF_OPERATION}", (byte)modeOfOperation);
  1160. }
  1161. /// <summary>
  1162. /// 写变量数值
  1163. /// </summary>
  1164. /// <param name="variableName"></param>
  1165. /// <param name="value"></param>
  1166. /// <returns></returns>
  1167. public bool WriteVariable(string variableName,object value)
  1168. {
  1169. return BeckhoffAxisManager.Instance.WriteVariableValue($"{Module}.{Name}.{variableName}", value);
  1170. }
  1171. /// <summary>
  1172. /// 检验GotoPosition条件
  1173. /// </summary>
  1174. /// <param name="station"></param>
  1175. public bool CheckGotoPosition(string station)
  1176. {
  1177. return _interLock.CheckGotoPosition(station);
  1178. }
  1179. /// <summary>
  1180. /// 检验当位Position是否在位置上
  1181. /// </summary>
  1182. /// <param name="position"></param>
  1183. /// <param name="stationName"></param>
  1184. /// <returns></returns>
  1185. public bool CheckPositionIsInStation(double position,string stationName)
  1186. {
  1187. foreach (Station station in _stationAxis.Stations)
  1188. {
  1189. if (station.Name.ToLower().EndsWith(stationName.ToLower()))
  1190. {
  1191. if (double.TryParse(station.Position, out double value))
  1192. {
  1193. if (Math.Round(Math.Abs(position - value), 2) <= _stationAxis.ToleranceDefault)
  1194. {
  1195. return true;
  1196. }
  1197. }
  1198. }
  1199. }
  1200. return false;
  1201. }
  1202. /// <summary>
  1203. /// 检验位置是否为空
  1204. /// </summary>
  1205. /// <param name="position"></param>
  1206. /// <returns></returns>
  1207. public bool CheckPositionIsEmpty(double position)
  1208. {
  1209. foreach (Station station in _stationAxis.Stations)
  1210. {
  1211. if (double.TryParse(station.Position, out double value))
  1212. {
  1213. if (Math.Round(Math.Abs(position - value), 2) <= _stationAxis.ToleranceDefault)
  1214. {
  1215. return false;
  1216. }
  1217. }
  1218. }
  1219. return true;
  1220. }
  1221. /// <summary>
  1222. /// 判定与目标位置相对关系
  1223. /// </summary>
  1224. /// <param name="station"></param>
  1225. /// <param name="compareType">Left--位于目标位置左侧,Right--位于目标位置右侧</param>
  1226. /// <returns></returns>
  1227. public bool JudgeCompareTargetStation(string station,string compareType)
  1228. {
  1229. double position = 0;
  1230. var result = GetPositionByStation(station);
  1231. if(result.success)
  1232. {
  1233. position = result.position;
  1234. }
  1235. else
  1236. {
  1237. return false;
  1238. }
  1239. var buffer16Position=GetPositionByStation(station);
  1240. switch(compareType)
  1241. {
  1242. case "Left":
  1243. return IsInStationLeftDirection(position);
  1244. case "Right":
  1245. if (buffer16Position.success)
  1246. {
  1247. position=buffer16Position.position;
  1248. }
  1249. return IsInStationRightPosition(position);
  1250. default:
  1251. return false;
  1252. }
  1253. }
  1254. /// <summary>
  1255. /// 是否位于位置左侧
  1256. /// </summary>
  1257. /// <param name="stationPosition"></param>
  1258. /// <returns></returns>
  1259. private bool IsInStationLeftDirection(double stationPosition)
  1260. {
  1261. double currentPosition = MotionData.MotorPosition;
  1262. double targetPosition = _targetPosition;
  1263. if(_currentOperation==MotionOperation.Position)
  1264. {
  1265. return currentPosition <= stationPosition && targetPosition <= stationPosition;
  1266. }
  1267. else
  1268. {
  1269. return currentPosition <= stationPosition;
  1270. }
  1271. }
  1272. /// <summary>
  1273. /// 是否位于位置右侧
  1274. /// </summary>
  1275. /// <param name="stationPosition"></param>
  1276. /// <returns></returns>
  1277. private bool IsInStationRightPosition(double stationPosition)
  1278. {
  1279. double currentPosition = MotionData.MotorPosition;
  1280. double targetPosition = _targetPosition;
  1281. if (_currentOperation == MotionOperation.Position)
  1282. {
  1283. return currentPosition > stationPosition && targetPosition > stationPosition;
  1284. }
  1285. else
  1286. {
  1287. return currentPosition > stationPosition ;
  1288. }
  1289. }
  1290. #endregion
  1291. #region virtual共用方法,子类可实现更多方法
  1292. /// <summary>
  1293. /// Home共用方法
  1294. /// </summary>
  1295. /// <returns></returns>
  1296. public virtual bool Home()
  1297. {
  1298. if (!_isSwitchOn)
  1299. {
  1300. EV.PostAlarmLog($"{Module}.{Name}", eEvent.ERR_PUF, $"{Module}.{Name} switch off,cannot home");
  1301. return false;
  1302. }
  1303. if (_status == RState.Running)
  1304. {
  1305. EV.PostAlarmLog($"{Module}.{Name}", eEvent.ERR_PUF, $"{Module}.{Name} current execute {_currentOperation},cannot home");
  1306. return false;
  1307. }
  1308. _currentOperation = MotionOperation.Home;
  1309. _status = RState.Running;
  1310. return true;
  1311. }
  1312. /// <summary>
  1313. /// Home(isLogError)共用方法
  1314. /// </summary>
  1315. /// <returns></returns>
  1316. public virtual bool Home(bool isLogError)
  1317. {
  1318. if (!_isSwitchOn)
  1319. {
  1320. EV.PostAlarmLog($"{Module}.{Name}", eEvent.ERR_PUF, $"{Module}.{Name} switch off,cannot home");
  1321. return false;
  1322. }
  1323. if (_status == RState.Running)
  1324. {
  1325. EV.PostAlarmLog($"{Module}.{Name}", eEvent.ERR_PUF, $"{Module}.{Name} current execute {_currentOperation},cannot home");
  1326. return false;
  1327. }
  1328. _currentOperation = MotionOperation.Home;
  1329. _status = RState.Running;
  1330. return true;
  1331. }
  1332. /// <summary>
  1333. /// 更改速度百分比
  1334. /// </summary>
  1335. /// <param name="percent"></param>
  1336. /// <returns></returns>
  1337. public bool ChangePercentSpeedAceleration(int percent)
  1338. {
  1339. double percentSpeed = _initialVelocity * ((double)percent / 100);
  1340. double percentAceleration = _initialAcceleration * ((double)percent / 100);
  1341. double percentDeceleration = _initialDeceleration * ((double)percent / 100);
  1342. int changedSpeed = (int)(Math.Round(percentSpeed, 0));
  1343. int changedAcceleration = (int)(Math.Round(percentAceleration, 0));
  1344. int changedDeceleration = (int)(Math.Round(percentDeceleration, 0));
  1345. bool result= ChangeSpeedAcceleration(changedSpeed,changedAcceleration,changedDeceleration);
  1346. if(result)
  1347. {
  1348. _profileVelocity = changedSpeed;
  1349. _profileAcceleration = changedAcceleration;
  1350. _profileDeceleration = changedDeceleration;
  1351. }
  1352. return result;
  1353. }
  1354. #endregion
  1355. #region public abstract 子类实现方法
  1356. /// <summary>
  1357. /// 停止操作
  1358. /// </summary>
  1359. /// <param name="cmd"></param>
  1360. /// <param name="args"></param>
  1361. /// <returns></returns>
  1362. public abstract bool StopPositionOperation();
  1363. /// <summary>
  1364. /// change speed
  1365. /// </summary>
  1366. /// <param name="speed"></param>
  1367. /// <returns></returns>
  1368. public abstract bool ChangeSpeed(int speed);
  1369. /// <summary>
  1370. /// 改变速度加速度
  1371. /// </summary>
  1372. /// <param name="speed"></param>
  1373. /// <returns></returns>
  1374. public abstract bool ChangeSpeedAcceleration(int speed, int acceleration, int deceleration);
  1375. /// <summary>
  1376. /// Switch On
  1377. /// </summary>
  1378. public abstract bool SwitchOn();
  1379. /// <summary>
  1380. /// Switch Off
  1381. /// </summary>
  1382. public abstract bool SwitchOff();
  1383. /// <summary>
  1384. /// 停止
  1385. /// </summary>
  1386. public abstract void Stop();
  1387. /// <summary>
  1388. /// Enable Operation
  1389. /// </summary>
  1390. /// <returns></returns>
  1391. public abstract bool EnableOperation();
  1392. /// <summary>
  1393. /// 定时器执行
  1394. /// </summary>
  1395. /// <returns></returns>
  1396. public abstract bool OnTimer();
  1397. /// <summary>
  1398. /// Profile operation
  1399. /// </summary>
  1400. /// <param name="targetPoint"></param>
  1401. /// <param name="profileVelocity"></param>
  1402. /// <param name="profileAcceleration"></param>
  1403. /// <param name="profileDeceleration"></param>
  1404. public abstract bool ProfilePosition(int targetPoint, int profileVelocity, int profileAcceleration, int profileDeceleration, bool judgeTorqueLimit = true);
  1405. #endregion
  1406. #region protected abstract 子类实现方法
  1407. /// <summary>
  1408. /// 初始化Routine
  1409. /// </summary>
  1410. protected abstract void InitializeRoutine();
  1411. /// <summary>
  1412. /// 初始化参数
  1413. /// </summary>
  1414. protected abstract void InitializeParameter();
  1415. /// <summary>
  1416. /// 更新状态字
  1417. /// </summary>
  1418. /// <param name="statusWord"></param>
  1419. public abstract void UpdateStatusWord(ushort statusWord);
  1420. /// <summary>
  1421. /// 回车输入
  1422. /// </summary>
  1423. /// <param name="arg"></param>
  1424. /// <param name="value"></param>
  1425. protected abstract void AxisKeyDown(string arg, double value);
  1426. #endregion
  1427. /// <summary>
  1428. /// 监控
  1429. /// </summary>
  1430. public void Monitor()
  1431. {
  1432. }
  1433. public void Reset()
  1434. {
  1435. }
  1436. /// 停止
  1437. /// </summary>
  1438. public void Terminate()
  1439. {
  1440. }
  1441. }
  1442. }