MaxonAxis.cs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517
  1. using Aitex.Core.RT.Event;
  2. using Aitex.Core.RT.Log;
  3. using Aitex.Core.RT.SCCore;
  4. using MECF.Framework.Common.CommonData.PUF;
  5. using MECF.Framework.Common.TwinCat;
  6. using PunkHPX8_Core;
  7. using System;
  8. using System.Collections.Generic;
  9. using System.Data;
  10. using System.Linq;
  11. using System.Reflection;
  12. using System.Text;
  13. using System.Threading.Tasks;
  14. using PunkHPX8_RT.Devices.AXIS.Maxon;
  15. using MECF.Framework.Common.Device;
  16. using MECF.Framework.Common.Beckhoff.IOAxis;
  17. using static Mono.Security.X509.X520;
  18. namespace PunkHPX8_RT.Devices.AXIS.CANOpen
  19. {
  20. public class MaxonAxis : JetAxisBase
  21. {
  22. #region 内部变量
  23. /// <summary>
  24. /// Home routine
  25. /// </summary>
  26. private MaxonHomeRoutine _homeRoutine;
  27. /// <summary>
  28. /// 运动Routine
  29. /// </summary>
  30. private MaxonProfilePositionRoutine _profilePositionRoutine;
  31. /// <summary>
  32. /// Switch On Routine
  33. /// </summary>
  34. private MaxonSwitchOnRoutine _switchOnRoutine;
  35. /// <summary>
  36. /// Switch off Routine
  37. /// </summary>
  38. private MaxonSwitchOffRoutine _switchOffRoutine;
  39. /// <summary>
  40. /// Stop Position
  41. /// </summary>
  42. private MaxonStopPositionRoutine _stopPositionRoutine;
  43. /// <summary>
  44. /// Beckhoff共用对象
  45. /// </summary>
  46. private BeckhoffCommonAxis _beckhoffCommonAxis;
  47. #endregion
  48. /// <summary>
  49. /// 构造函数
  50. /// </summary>
  51. /// <param name="Module"></param>
  52. public MaxonAxis(string module,string name):base(module,name)
  53. {
  54. }
  55. /// <summary>
  56. /// 初始化参数
  57. /// </summary>
  58. protected override void InitializeParameter()
  59. {
  60. if(SC.ContainsItem("Maxon.SpeedRatio"))
  61. {
  62. _speedRatio = SC.GetValue<int>("Maxon.SpeedRatio");
  63. }
  64. if(SC.ContainsItem("Maxon.TorqueRatio"))
  65. {
  66. _torqueRatio = SC.GetValue<int>("Maxon.TorqueRatio");
  67. }
  68. _beckhoffCommonAxis = new BeckhoffCommonAxis(Module, Name, this);
  69. }
  70. /// <summary>
  71. /// 初始化Routine
  72. /// </summary>
  73. protected override void InitializeRoutine()
  74. {
  75. _homeRoutine = new MaxonHomeRoutine($"{Module}.{Name}", this,_beckhoffCommonAxis);
  76. _profilePositionRoutine = new MaxonProfilePositionRoutine($"{Module}.{Name}", this, _beckhoffCommonAxis);
  77. _switchOnRoutine = new MaxonSwitchOnRoutine($"{Module}.{Name}", this, _beckhoffCommonAxis);
  78. _switchOffRoutine = new MaxonSwitchOffRoutine($"{Module}.{Name}", this,_beckhoffCommonAxis);
  79. _stopPositionRoutine = new MaxonStopPositionRoutine($"{Module}.{Name}", this, _beckhoffCommonAxis);
  80. }
  81. /// <summary>
  82. /// 中止操作
  83. /// </summary>
  84. /// <param name="cmd"></param>
  85. /// <param name="args"></param>
  86. /// <returns></returns>
  87. public override bool StopPositionOperation()
  88. {
  89. if(!IsRun)
  90. {
  91. return true;
  92. }
  93. _currentOperation = MotionOperation.StopPosition;
  94. if (_profilePositionRoutine.Monitor() == RState.Running)
  95. {
  96. _profilePositionRoutine.Abort();
  97. }
  98. _status = _stopPositionRoutine.Start();
  99. return true;
  100. }
  101. /// <summary>
  102. /// 更新StatusWord
  103. /// </summary>
  104. /// <param name="status"></param>
  105. public override void UpdateStatusWord(ushort status)
  106. {
  107. if (status == 0)
  108. {
  109. _commandMotionData.Status = "Status Word is zero";
  110. return;
  111. }
  112. byte bit0 = (byte)(status & 0b0001);
  113. byte bit1 = (byte)((status & 0b0010) >> 1);
  114. byte bit2 = (byte)((status & 0b0100) >> 2);
  115. byte bit3 = (byte)((status & 0b1000) >> 3);
  116. byte bit4 = (byte)((status & 0b10000) >> 4);
  117. byte bit5 = (byte)((status & 0b100000) >> 5);
  118. byte bit6 = (byte)((status & 0b1000000) >> 6);
  119. byte bit7 = (byte)((status & 0b10000000) >> 7);
  120. byte bit8 = (byte)((status & 0b100000000) >> 8);
  121. byte bit9 = (byte)((status & 0b1000000000) >> 9);
  122. byte bit10 = (byte)((status & 0b10000000000) >> 10);
  123. byte bit11 = (byte)((status & 0b100000000000) >> 11);
  124. byte bit12 = (byte)((status & 0b1000000000000) >> 12);
  125. byte bit13 = (byte)((status & 0b10000000000000) >> 13);
  126. byte bit14 = (byte)((status & 0b100000000000000) >> 14);
  127. if (bit0 == 0 && bit1 == 0 && bit2 == 0 && bit3 == 0&&bit4==0&&bit5==0&&bit8==1&&bit14==0)
  128. {
  129. if (bit6 == 0)
  130. {
  131. _commandMotionData.Status = "Not Ready to switch On";
  132. }
  133. else
  134. {
  135. _commandMotionData.Status = "Switch On Disabled";
  136. }
  137. UpdateSwitchOn(false);
  138. }
  139. else if (bit0 == 1 && bit2 == 0 && bit3 == 0 && bit5 == 1 && bit6 == 0&&bit8==1&&bit14==0)
  140. {
  141. _commandMotionData.Status = "Ready to Switch On";
  142. UpdateSwitchOn(false);
  143. }
  144. else if (bit0 == 1 && bit1 == 1 && bit2 == 0 && bit3 == 0 && bit5 == 1 && bit6 == 0 && bit8 == 1 && bit14 == 0)
  145. {
  146. _commandMotionData.Status = "Switched On";
  147. UpdateSwitchOn(true);
  148. }
  149. else if (bit0 == 1 && bit1 == 1 && bit2 == 1 && bit3 == 0 &&bit4==1&& bit5 == 1 && bit6 == 0&&bit8==1&&bit14==0)
  150. {
  151. _commandMotionData.Status = "Operation Enabled";
  152. UpdateSwitchOn(true);
  153. }
  154. else if (bit0 == 1 && bit1 == 1 && bit2 == 1 && bit3 == 0 &&bit4==1&& bit5 == 0 && bit6 == 0&&bit8==1&&bit14==0)
  155. {
  156. _commandMotionData.Status = "Quick Stop Active";
  157. UpdateSwitchOn(true);
  158. }
  159. else if (bit0 == 1 && bit1 == 1 && bit2 == 1 && bit3 == 1 && bit6 == 0)
  160. {
  161. _commandMotionData.Status = "Fault reaction active";
  162. UpdateSwitchOn(false);
  163. }
  164. else if (bit0 == 0 && bit1 == 0 && bit2 == 0 && bit3 == 1 && bit6 == 0)
  165. {
  166. _commandMotionData.Status = "Fault";
  167. UpdateSwitchOn(false);
  168. }
  169. if (bit3 == 1)
  170. {
  171. _isError = true;
  172. }
  173. else
  174. {
  175. _isError = false;
  176. }
  177. if (bit7 == 1)
  178. {
  179. _commandMotionData.Status = "Waring is occured";
  180. }
  181. if (_modeOfOperation == (byte)AxisModeOfOperation.HomingMode)
  182. {
  183. if (bit10 == 1 && bit12 == 1)
  184. {
  185. _isHomed = true;
  186. }
  187. else
  188. {
  189. _isHomed = false;
  190. }
  191. }
  192. else if (_modeOfOperation == (byte)AxisModeOfOperation.ProfilePositionMode)
  193. {
  194. if (bit10 == 1)
  195. {
  196. _inTargetPosition = true;
  197. }
  198. }
  199. }
  200. /// <summary>
  201. /// 更新上电状态
  202. /// </summary>
  203. private void UpdateSwitchOn(bool isSwitchOn)
  204. {
  205. if (!_isSwitchOn && isSwitchOn)
  206. {
  207. _commandMotionData.IsSwitchOn = true;
  208. ConfirmOperationState(MotionOperation.SwitchOn);
  209. }
  210. else if (_isSwitchOn && !isSwitchOn)
  211. {
  212. _commandMotionData.IsSwitchOn = false;
  213. ConfirmOperationState(MotionOperation.SwitchOff);
  214. }
  215. _isSwitchOn = isSwitchOn;
  216. }
  217. /// <summary>
  218. /// Home
  219. /// </summary>
  220. public override bool Home()
  221. {
  222. bool result = base.Home();
  223. if(!result)
  224. {
  225. return false;
  226. }
  227. _homeRoutine.Start(_homeTimeout, _axisConfig.HomingMethod);
  228. MotionData.IsHomed = false;
  229. IsHomeSwitchedTriggered = false;
  230. return true;
  231. }
  232. /// <summary>
  233. /// 停止
  234. /// </summary>
  235. public override void Stop()
  236. {
  237. }
  238. /// <summary>
  239. /// SwitchOff
  240. /// </summary>
  241. public override bool SwitchOff()
  242. {
  243. if (_status == RState.Running)
  244. {
  245. EV.PostAlarmLog($"{Module}.{Name}", eEvent.ERR_AXIS, $"{Module}.{Name} current execute {_currentOperation},cannot switchoff");
  246. return false;
  247. }
  248. _currentOperation = MotionOperation.SwitchOff;
  249. _switchOffRoutine.Start();
  250. _status = RState.Running;
  251. return true;
  252. }
  253. /// <summary>
  254. /// SwitchOn
  255. /// </summary>
  256. public override bool SwitchOn()
  257. {
  258. if (_status == RState.Running)
  259. {
  260. EV.PostAlarmLog($"{Module}.{Name}", eEvent.ERR_AXIS, $"{Module}.{Name} current execute {_currentOperation},cannot SwitchOn");
  261. return false;
  262. }
  263. _currentOperation = MotionOperation.SwitchOn;
  264. _switchOnRoutine.Start();
  265. _status = RState.Running;
  266. return true;
  267. }
  268. /// <summary>
  269. /// 首次启动写入COE线程
  270. /// </summary>
  271. public override void FirstStartUpWriteCOE(string variable)
  272. {
  273. _beckhoffCommonAxis.FirstStartUpWriteCOE(variable);
  274. }
  275. /// <summary>
  276. /// 启动写入COE线程
  277. /// </summary>
  278. public override void StartUpWriteCoeThread()
  279. {
  280. _beckhoffCommonAxis.StartUpWriteCoeThread();
  281. }
  282. /// <summary>
  283. /// OnTimer 定时器执行
  284. /// </summary>
  285. public override bool OnTimer()
  286. {
  287. if(_status == RState.Running)
  288. {
  289. if(_currentOperation == MotionOperation.Position)
  290. {
  291. RState state = _profilePositionRoutine.Monitor();
  292. if (state == RState.End)
  293. {
  294. _inTargetPosition = false;
  295. EndOperation();
  296. _status = RState.End;
  297. LOG.WriteLog(eEvent.INFO_AXIS, $"{Module}.{Name}", $"Position Complete,Current Position {MotionData.MotorPosition}");
  298. }
  299. else if (state == RState.Failed || state == RState.Timeout)
  300. {
  301. if (_currentOperation == MotionOperation.Position)
  302. {
  303. _inTargetPosition = false;
  304. EndOperation();
  305. _status = RState.Failed;
  306. LOG.WriteLog(eEvent.ERR_AXIS, $"{Module}.{Name}", $"Profile Position error {_profilePositionRoutine.ErrorMsg}");
  307. }
  308. }
  309. }
  310. else if(_currentOperation == MotionOperation.Home)
  311. {
  312. RState state = _homeRoutine.Monitor();
  313. if (state==RState.End)
  314. {
  315. MotionData.IsHomed = true;
  316. IsHomed = true;
  317. EndOperation();
  318. _status= RState.End;
  319. }
  320. else if(state==RState.Failed||state==RState.Timeout)
  321. {
  322. EndOperation();
  323. _status= RState.Failed;
  324. LOG.WriteLog(eEvent.ERR_AXIS, $"{Module}.{Name}", "Home error");
  325. }
  326. }
  327. else if (_currentOperation == MotionOperation.SwitchOn)
  328. {
  329. RState state = _switchOnRoutine.Monitor();
  330. if (state == RState.End)
  331. {
  332. EndOperation();
  333. _status= RState.End;
  334. }
  335. else if (state == RState.Failed || state == RState.Timeout)
  336. {
  337. EndOperation();
  338. _status= RState.Failed;
  339. LOG.WriteLog(eEvent.ERR_AXIS, $"{Module}.{Name}", "Switch On error");
  340. }
  341. }
  342. else if (_currentOperation == MotionOperation.SwitchOff)
  343. {
  344. RState state = _switchOffRoutine.Monitor();
  345. if (state == RState.End)
  346. {
  347. EndOperation();
  348. _status= RState.End;
  349. }
  350. else if (state == RState.Failed || state == RState.Timeout)
  351. {
  352. EndOperation();
  353. _status=RState.Failed;
  354. LOG.WriteLog(eEvent.ERR_AXIS, $"{Module}.{Name}", "Switch Off error");
  355. }
  356. }
  357. else if (_currentOperation == MotionOperation.StopPosition)
  358. {
  359. RState state = _stopPositionRoutine.Monitor();
  360. if (state == RState.End)
  361. {
  362. EndOperation();
  363. _status = RState.End;
  364. }
  365. else if (state == RState.Failed || state == RState.Timeout)
  366. {
  367. EndOperation();
  368. _status = RState.Failed;
  369. LOG.WriteLog(eEvent.ERR_AXIS, $"{Module}.{Name}", "StopPosition error");
  370. }
  371. }
  372. }
  373. JudgeRunMonitor();
  374. return true;
  375. }
  376. /// <summary>
  377. /// 位置
  378. /// </summary>
  379. /// <param name="targetPoint"></param>
  380. public override bool ProfilePosition(int targetPoint, int profileVelocity, int profileAcceleration, int profileDeceleration,bool judgeTorqueLimit=true)
  381. {
  382. if (_status == RState.Running)
  383. {
  384. EV.PostAlarmLog($"{Module}.{Name}", eEvent.ERR_AXIS, $"{Module}.{Name} current execute {_currentOperation},cannot profile position");
  385. return false;
  386. }
  387. if(profileAcceleration==0)
  388. {
  389. profileAcceleration = _profileAcceleration;
  390. }
  391. if (profileDeceleration==0)
  392. {
  393. profileDeceleration = _profileDeceleration;
  394. }
  395. _status = _profilePositionRoutine.Start(targetPoint,profileVelocity,profileAcceleration,profileDeceleration,judgeTorqueLimit);
  396. _currentOperation = MotionOperation.Position;
  397. _inTargetPosition = false;
  398. return true;
  399. }
  400. /// <summary>
  401. /// 改变速度
  402. /// </summary>
  403. /// <param name="speed"></param>
  404. /// <returns></returns>
  405. public override bool ChangeSpeed(int speed)
  406. {
  407. bool result = _beckhoffCommonAxis.WriteControlWord(0x2F);
  408. if (!result)
  409. {
  410. return false;
  411. }
  412. result = BeckhoffAxisManager.Instance.WriteVariableValue($"{Module}.{Name}.ProfileVelocity", speed);
  413. if (!result)
  414. {
  415. return false;
  416. }
  417. result = _beckhoffCommonAxis.WriteControlWord(0x3F);
  418. return result;
  419. }
  420. /// <summary>
  421. /// 改变速度加速度
  422. /// </summary>
  423. /// <param name="speed"></param>
  424. /// <returns></returns>
  425. public override bool ChangeSpeedAcceleration(int speed,int acceleration,int deceleration)
  426. {
  427. bool result = _beckhoffCommonAxis.WriteControlWord(0x2F);
  428. if (!result)
  429. {
  430. return false;
  431. }
  432. result = BeckhoffAxisManager.Instance.WriteVariableValue($"{Module}.{Name}.ProfileVelocity", speed);
  433. BeckhoffAxisManager.Instance.WriteVariableValue($"{Module}.{Name}.{PROFILE_ACCEL}", acceleration);
  434. BeckhoffAxisManager.Instance.WriteVariableValue($"{Module}.{Name}.{PROFILE_DECEL}", deceleration);
  435. if (!result)
  436. {
  437. return false;
  438. }
  439. result = _beckhoffCommonAxis.WriteControlWord(0x3F);
  440. return result;
  441. }
  442. /// <summary>
  443. /// KeyDown事件
  444. /// </summary>
  445. /// <param name="arg"></param>
  446. /// <param name="value"></param>
  447. protected override void AxisKeyDown(string arg, double value)
  448. {
  449. switch (arg)
  450. {
  451. case PROFILE_VELOCITY:
  452. _profileVelocity = CalculateMultiplySpeedRatio(CalculateValueMultiplyScale(value));
  453. _commandMotionData.FileProfileVelocity = value;
  454. TwincatCoeManager.Instance.WriteVariableValue($"{Module}.{Name}",arg, _profileVelocity);
  455. break;
  456. case PROFILE_ACCEL:
  457. _profileAcceleration = CalculateDivideAccelerationRatio(CalculateValueMultiplyScale(value));
  458. _commandMotionData.FileAcceleration = value;
  459. TwincatCoeManager.Instance.WriteVariableValue($"{Module}.{Name}",arg, _profileAcceleration);
  460. break;
  461. case PROFILE_DECEL:
  462. _profileDeceleration = CalculateDivideAccelerationRatio(CalculateValueMultiplyScale(value));
  463. _commandMotionData.FileDeceleration = value;
  464. TwincatCoeManager.Instance.WriteVariableValue($"{Module}.{Name}",arg, _profileDeceleration);
  465. break;
  466. case HOMING_VELOCITY:
  467. _profileHomingVelocity = CalculateMultiplySpeedRatio(CalculateValueMultiplyScale(value));
  468. _commandMotionData.FileHomingVelocity = value;
  469. TwincatCoeManager.Instance.WriteVariableValue($"{Module}.{Name}", arg, _profileHomingVelocity);
  470. break;
  471. case HOMING_VELOCITY_SLOW:
  472. _profileHomingVelocitySlow = CalculateMultiplySpeedRatio(CalculateValueMultiplyScale(value));
  473. _commandMotionData.FileHomingVelocitySlow = value;
  474. TwincatCoeManager.Instance.WriteVariableValue($"{Module}.{Name}", arg, _profileHomingVelocitySlow);
  475. break;
  476. case HOMING_ACCEL:
  477. _profileHomingAccel = CalculateDivideAccelerationRatio(CalculateValueMultiplyScale(value));
  478. _commandMotionData.FileHomingAccel = value;
  479. TwincatCoeManager.Instance.WriteVariableValue($"{Module}.{Name}", arg, _profileHomingAccel);
  480. break;
  481. }
  482. }
  483. /// <summary>
  484. /// 初始化Axis配置
  485. /// </summary>
  486. /// <returns></returns>
  487. protected override AxisConfig InitializeAxisConfig()
  488. {
  489. AxisConfig axisConfig = BeckhoffAxisManager.Instance.GetAxis($"{Module}.{Name}");
  490. if (axisConfig != null)
  491. {
  492. BeckhoffAxis beckhoffAxis = axisConfig as BeckhoffAxis;
  493. _beckhoffCommonAxis.InitializeCoeOutputs(beckhoffAxis);
  494. }
  495. return axisConfig;
  496. }
  497. /// <summary>
  498. /// 订阅变量
  499. /// </summary>
  500. protected override void SubscriptionVariable()
  501. {
  502. _beckhoffCommonAxis.SubscriptionVariable();
  503. }
  504. }
  505. }