版博士V2.0程序
No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.
 
 
 
 

816 líneas
35 KiB

  1. using Advantech.Motion;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.ComponentModel;
  5. using System.IO;
  6. using System.Linq;
  7. using System.Reflection;
  8. using System.Security.Cryptography;
  9. using System.Text;
  10. using System.Threading;
  11. using System.Threading.Tasks;
  12. using System.Timers;
  13. namespace ProductionControl.Device
  14. {
  15. public class Axis : IDisposable
  16. {
  17. public enum AxisStateType
  18. {
  19. [Description("轴状态")]
  20. AxisState = 0,
  21. [Description("轴运动状态")]
  22. AxisMotionState = 1,
  23. [Description("轴IO状态")]
  24. AxisIOState = 2,
  25. }
  26. public Action<int, AxisStateType, uint> axisStateEvent;
  27. public enum AxisPosType
  28. {
  29. [Description("命令位置")]
  30. CmdPos = 0,
  31. [Description("反馈位置")]
  32. ActualPos = 1,
  33. }
  34. public Action<int, AxisPosType, double> axisPosEvent;
  35. /// <summary> 使用
  36. /// 轴状态(AxisState 0-14) 单一值,无需按位取
  37. /// STA_AxDisable -- 轴被禁用,用户可打开并激活
  38. /// STA_AxReady ---- 轴已准备就绪,等待新的命令 *
  39. /// STA_Stopping ---- 轴停止
  40. /// STA_AxErrorStop --- 出现错误,轴停止
  41. /// STA_AxHoming ---- 轴正在执行返回原点运动
  42. /// STA_AxPtpMotion ---- 轴正在执行PTP 运动
  43. /// STA_AxContiMotion ---- 轴正在执行连续运动
  44. /// STA_AxSyncMotion --- 轴在一个群组中,群组正在执行插补运动;或轴是一个从轴,正在执行Ecam/E-gear/Gantry 运动。
  45. /// STA_AX_EXT_JOG -- 轴由外部信号控制。当外部信号激活时,轴将执行JOG 模式运动。
  46. /// STA_AX_EXT_MPG --- 轴由外部信号控制。当外部信号激活时,轴将执行MPG 模式运动
  47. /// </summary>
  48. //public Action<int, int> axisStateEvent;
  49. /// <summary>
  50. /// 轴运动状态 使用
  51. /// 位 说明
  52. /// Stop ---- 停止
  53. /// WaitERC---- 等待ERC 完成
  54. /// InFA ---- 处于特定速度中 = FA
  55. /// InFL ---- 处于低速中 = FL
  56. /// InACC ---- 加速中
  57. /// InFH ---- 处于最大速度中 = FH
  58. /// InDEC ---- 减速中
  59. /// WaitINP---- 到位等待
  60. /// </summary>
  61. //public Action<int, int> axisMotionStateEvent;
  62. /// <summary>
  63. /// 轴IO状态 (Ax_Motion_IO) 使用
  64. /// RDY---- RDY 针脚输入
  65. /// ALM ---- 报警信号输入 *
  66. /// LMT+ ---- 限位开关+ *
  67. /// LMT- ---- 限位开关- *
  68. /// ORG---- 原始开关 *
  69. /// DIR ---- DIR 输出
  70. /// EMG ---- 紧急信号输入
  71. /// INP ---- 到位信号输入
  72. /// SVON ---- 伺服开启(OUT6) *
  73. /// ALRM ---- 报警复位输出状态
  74. /// SLMT+ ---- 软件限位+
  75. /// SLMT- ---- 软件限位-
  76. /// CMP----- 比较信号(OUT5)
  77. /// </summary>
  78. //public Action<int, bool, bool, bool, bool> axisIOStateEvent;
  79. /// <summary>
  80. /// 告警(级别1 2 3)
  81. /// </summary>
  82. public Action<int, string> warningEvent;
  83. /// <summary>
  84. /// Log输出,(0-info,1-warning 2-error)
  85. /// </summary>
  86. public Action<int, string> log;
  87. /// <summary>
  88. /// 设备列表(多张PCI板卡)
  89. /// </summary>
  90. public List<DEV_LIST> DevList { get; private set; }
  91. /// <summary>
  92. /// 设备数量
  93. /// </summary>
  94. //private uint deviceCount = 0;
  95. /// <summary>
  96. /// 设备号,用于打开设备(非索引)
  97. /// </summary>
  98. //public uint DeviceNum { get; private set; } = 0;
  99. /// <summary>
  100. /// 设备句柄
  101. /// </summary>
  102. private IntPtr m_DeviceHandle = IntPtr.Zero;
  103. /// <summary>
  104. /// 轴数量
  105. /// </summary>
  106. private uint m_ulAxisCount = 0;
  107. private IntPtr[] m_Axishand = new IntPtr[0];
  108. public double[] CmdPos { get; private set; } = new double[32];//轴命令位置
  109. public double[] ActualPos { get; private set; } = new double[32];//轴实际(反馈)位置
  110. public UInt16[] AxState { get; private set; } = new UInt16[32];//轴状态
  111. public UInt32[] IOStatus { get; private set; } = new UInt32[32];//轴IO状态
  112. public uint[] AxMotionState { get; private set; } = new uint[32];//轴运动状态
  113. private uint[] AxEnableEvtArray = new uint[32];
  114. private uint[] GpEnableEvt = new uint[32];
  115. /// <summary>
  116. /// 组
  117. /// </summary>
  118. private IntPtr m_GpHand = IntPtr.Zero;
  119. /// <summary>
  120. /// 是否打开设备成功
  121. /// </summary>
  122. public bool IsInit { get; private set; } = false;
  123. Thread checkEventThread;
  124. private System.Timers.Timer timer = new System.Timers.Timer();
  125. /// <summary>
  126. /// 获取设备列表
  127. /// </summary>
  128. /// <returns></returns>
  129. /// <exception cref="Exception"></exception>
  130. //public static List<DEV_LIST> getDevList()
  131. //{
  132. // DEV_LIST[] curAvailableDevs = new DEV_LIST[Motion.MAX_DEVICES];
  133. // uint deviceCount = 0;
  134. // int Result = Motion.mAcm_GetAvailableDevs(curAvailableDevs, Motion.MAX_DEVICES, ref deviceCount);
  135. // if (Result != (int)ErrorCode.SUCCESS || curAvailableDevs.Length < 1)
  136. // throw new Exception("Get Device Numbers Failed With Error Code: [0x" + Convert.ToString(Result, 16) + "] DevCount=" + curAvailableDevs.Length);
  137. // return curAvailableDevs.ToList().Take((int)deviceCount).ToList();
  138. //}
  139. public Axis()
  140. {
  141. DEV_LIST[] curAvailableDevs = new DEV_LIST[Motion.MAX_DEVICES];
  142. uint deviceCount = 0;
  143. int Result = Motion.mAcm_GetAvailableDevs(curAvailableDevs, Motion.MAX_DEVICES, ref deviceCount);
  144. if (Result != (int)ErrorCode.SUCCESS || curAvailableDevs.Length < 1)
  145. throw new Exception("Get Device Numbers Failed With Error Code: [0x" + Convert.ToString(Result, 16) + "] DevCount=" + curAvailableDevs.Length);
  146. DevList = curAvailableDevs.ToList().Take((int)deviceCount).ToList();
  147. }
  148. public void Dispose()
  149. {
  150. stop();
  151. }
  152. /// <summary>
  153. /// 打开设备
  154. /// </summary>
  155. /// <exception cref="Exception"></exception>
  156. public void start()
  157. {
  158. if (DevList == null || DevList.Count < 1)
  159. throw new Exception("设备为空!");
  160. start(DevList[0].DeviceNum);
  161. }
  162. public void start(uint DeviceNum)
  163. {
  164. if (IsInit) return;
  165. //打开设备
  166. uint uResult = Motion.mAcm_DevOpen(DeviceNum, ref m_DeviceHandle);
  167. if (uResult != (int)ErrorCode.SUCCESS)
  168. throw new Exception("Open Device Failed With Error Code: [0x" + Convert.ToString(uResult, 16) + "]");
  169. //读取轴数量
  170. uResult = Motion.mAcm_GetU32Property(m_DeviceHandle, (uint)PropertyID.FT_DevAxesCount, ref m_ulAxisCount);
  171. if (uResult != (uint)ErrorCode.SUCCESS)
  172. throw new Exception("Get Axis Number Failed With Error Code: [0x" + Convert.ToString(uResult, 16) + "]");
  173. m_Axishand = new IntPtr[m_ulAxisCount];
  174. //打开轴
  175. for (int i = 0; i < m_ulAxisCount; i++)
  176. {
  177. //打开每个轴并获得每个轴句柄
  178. uResult = Motion.mAcm_AxOpen(m_DeviceHandle, (UInt16)i, ref m_Axishand[i]);
  179. if (uResult != (uint)ErrorCode.SUCCESS)
  180. throw new Exception("Open Axis Failed With Error Code: [0x" + Convert.ToString(uResult, 16) + "]");
  181. //打开电源使能,1: On
  182. uResult = Motion.mAcm_AxSetSvOn(m_Axishand[i], 1);
  183. if (uResult != (uint)ErrorCode.SUCCESS)
  184. throw new Exception("Servo On Failed With Error Code: [0x" + Convert.ToString(uResult, 16) + "]");
  185. //每个轴的初始属性(reset 命令位置和实际(反馈)位置)
  186. //double cmdPosition = new double();
  187. //cmdPosition = 0;
  188. //为指定的轴设置命令位置
  189. //Motion.mAcm_AxSetCmdPosition(m_Axishand[i], cmdPosition);
  190. //为指定的轴设置实际(反馈)位置
  191. //Motion.mAcm_AxSetActualPosition(m_Axishand[i], cmdPosition);
  192. //Event
  193. AxEnableEvtArray[i] |= (uint)EventType.EVT_AX_MOTION_DONE; //运动完成(减速直至停止)
  194. AxEnableEvtArray[i] |= (uint)EventType.EVT_AX_VH_START; //轴加速到运行速度时
  195. AxEnableEvtArray[i] |= (uint)EventType.EVT_AX_VH_END;//轴运行速度结束时,开始减速
  196. //初次获取轴的运动I/O状态。
  197. this.refreshAxisState(i);
  198. }
  199. //根据加载的文件设置设备的所有配置
  200. string cfgPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\DevCfg\\Axis_" + DeviceNum + ".cfg";
  201. if (File.Exists(cfgPath))
  202. {
  203. uResult = Motion.mAcm_DevLoadConfig(m_DeviceHandle, cfgPath);
  204. if (uResult != (uint)ErrorCode.SUCCESS)
  205. throw new Exception("Load Config Failed With Error Code: [0x" + Convert.ToString(uResult, 16) + "]");
  206. }
  207. uResult = Motion.mAcm_EnableMotionEvent(m_DeviceHandle, AxEnableEvtArray, GpEnableEvt, m_ulAxisCount, 3);
  208. if (uResult != (uint)ErrorCode.SUCCESS)
  209. throw new Exception("EnableMotionEvent Filed With Error Code[0x" + Convert.ToString(uResult, 16) + "]");
  210. IsInit = true;
  211. timer.Elapsed += Timer_Elapsed;
  212. timer.Interval = 100;
  213. timer.Enabled = true;
  214. //用户应该创建一个新的线程来检查事件状态,例如:CheckEvtThread()函数
  215. checkEventThread = new Thread(new ThreadStart(checkEvtThread));
  216. checkEventThread.Start();
  217. }
  218. /// <summary>
  219. /// 关闭设备
  220. /// </summary>
  221. /// <exception cref="Exception"></exception>
  222. public void stop()
  223. {
  224. if (!IsInit) return;
  225. uint i;
  226. for (i = 0; i < m_ulAxisCount; i++)
  227. {
  228. if (AxState[i] == (uint)AxisState.STA_AX_ERROR_STOP)
  229. {
  230. log?.Invoke(1, i + "轴处于ErrorStop状态,已重置!");
  231. //重置轴的状态。如果轴处于ErrorStop状态,则调用此函数后状态将更改为Ready
  232. Motion.mAcm_AxResetError(m_Axishand[i]);
  233. }
  234. // 命令轴减速停止(缓停)
  235. Motion.mAcm_AxStopDec(m_Axishand[i]);
  236. //sleep? 关闭电源使能,1: On
  237. uint uResult = Motion.mAcm_AxSetSvOn(m_Axishand[i], 0);
  238. if (uResult != (uint)ErrorCode.SUCCESS)
  239. throw new Exception("Servo On Failed With Error Code: [0x" + Convert.ToString(uResult, 16) + "]");
  240. }
  241. //删除组中的所有轴并关闭组句柄
  242. //Motion.mAcm_GpClose(ref m_GpHand);
  243. //m_GpHand = IntPtr.Zero;
  244. for (i = 0; i < m_ulAxisCount; i++)
  245. {
  246. //Close Axes
  247. Motion.mAcm_AxClose(ref m_Axishand[i]);
  248. }
  249. timer.Elapsed -= Timer_Elapsed;
  250. m_ulAxisCount = 0;
  251. //Close Device
  252. Motion.mAcm_DevClose(ref m_DeviceHandle);
  253. m_DeviceHandle = IntPtr.Zero;
  254. IsInit = false;
  255. timer.Enabled = false;
  256. }
  257. /// <summary>
  258. /// 缓停,jog时用
  259. /// </summary>
  260. public void stopDec(int axisIndex = -1)
  261. {
  262. for (int i = 0; i < m_ulAxisCount; i++)
  263. {
  264. if (i == axisIndex || axisIndex == -1)
  265. {
  266. Motion.mAcm_AxStopDec(m_Axishand[i]);
  267. }
  268. }
  269. }
  270. /// <summary>
  271. /// 急停
  272. /// </summary>
  273. public void stop(int axisIndex = -1)
  274. {
  275. if (!IsInit) return;
  276. for (int i = 0; i < m_ulAxisCount; i++)
  277. {
  278. if (i == axisIndex || axisIndex == -1)
  279. {
  280. Motion.mAcm_AxStopEmg(m_Axishand[i]);
  281. }
  282. }
  283. }
  284. public void resetAxisState(int axisIndex)
  285. {
  286. if (!IsInit) return;
  287. if (AxState[axisIndex] == (uint)AxisState.STA_AX_ERROR_STOP)
  288. {
  289. //重置轴的状态。如果轴处于ErrorStop状态,则调用此函数后状态将更改为Ready
  290. Motion.mAcm_AxResetError(m_Axishand[axisIndex]);
  291. }
  292. // 命令轴减速停止(缓停)
  293. Motion.mAcm_AxStopDec(m_Axishand[axisIndex]);
  294. }
  295. /// <summary>
  296. /// 指定的轴设置命令位置
  297. /// </summary>
  298. public void resetCmdPosition(int axisIndex = -1, double position = 0)
  299. {
  300. if (!IsInit) return;
  301. for (int i = 0; i < m_ulAxisCount; i++)
  302. {
  303. if (i == axisIndex || axisIndex == -1)
  304. {
  305. Motion.mAcm_AxSetCmdPosition(m_Axishand[i], position);
  306. }
  307. }
  308. }
  309. /// <summary>
  310. /// 指定的轴设置实际(反馈)位置
  311. /// </summary>
  312. public void resetActualPosition(int axisIndex=-1, double position = 0)
  313. {
  314. if (!IsInit) return;
  315. for (int i = 0; i < m_ulAxisCount; i++)
  316. {
  317. if (i == axisIndex || axisIndex == -1)
  318. {
  319. Motion.mAcm_AxSetActualPosition(m_Axishand[i], position);
  320. }
  321. }
  322. }
  323. /// <summary>
  324. /// 获取速度 [vellow,velhigh,acc,dec,Jerk]
  325. /// </summary>
  326. /// <param name="axisIndex"></param>
  327. /// <returns></returns>
  328. public double[] getAxisVelParam(int axisIndex)
  329. {
  330. double[] value=new double[5];
  331. Motion.mAcm_GetF64Property(m_Axishand[axisIndex], (uint)PropertyID.PAR_AxVelLow, ref value[0]);
  332. Motion.mAcm_GetF64Property(m_Axishand[axisIndex], (uint)PropertyID.PAR_AxVelHigh, ref value[1]);
  333. Motion.mAcm_GetF64Property(m_Axishand[axisIndex], (uint)PropertyID.PAR_AxAcc, ref value[2]);
  334. Motion.mAcm_GetF64Property(m_Axishand[axisIndex], (uint)PropertyID.PAR_AxDec, ref value[3]);
  335. Motion.mAcm_GetF64Property(m_Axishand[axisIndex], (uint)PropertyID.PAR_AxJerk, ref value[4]);//0-T/S 型曲线
  336. return value;
  337. }
  338. /// <summary>
  339. /// 速度设置 注:运动的过程中可变速度,加速度和减速度需使用AxChangeVelEx方法
  340. /// </summary>
  341. /// <param name="velLow">起始速度</param>
  342. /// <param name="high">运行速度</param>
  343. /// <param name="acc">加速度</param>
  344. /// <param name="dec">减速度</param>
  345. /// <param name="axisIndex"></param>
  346. public void setAxisVelParam(double velLow, double high = 0, double acc = 0, double dec = 0, int axisIndex = -1)
  347. {
  348. uint result;
  349. for (int i = 0; i < m_ulAxisCount; i++)
  350. {
  351. if (i == axisIndex || axisIndex == -1)
  352. {
  353. if ((AxisState)AxState[i] != AxisState.STA_AX_READY)
  354. continue;
  355. if (velLow > 0) result = Motion.mAcm_SetF64Property(m_Axishand[i], (uint)PropertyID.PAR_AxVelLow, velLow);
  356. if (high > 0) result = Motion.mAcm_SetF64Property(m_Axishand[i], (uint)PropertyID.PAR_AxVelHigh, high);
  357. if (acc > 0) result = Motion.mAcm_SetF64Property(m_Axishand[i], (uint)PropertyID.PAR_AxAcc, acc);
  358. if (dec > 0) result = Motion.mAcm_SetF64Property(m_Axishand[i], (uint)PropertyID.PAR_AxDec, dec);
  359. result = Motion.mAcm_SetF64Property(m_Axishand[i], (uint)PropertyID.PAR_AxJerk, 0);//0-T/S 型曲线
  360. //Ret = Acm_SetF64Property(m_Axishand[0], PAR_AxVelLow, 2000); // 起始速度
  361. //Ret = Acm_SetF64Property(m_Axishand[0], PAR_AxVelHigh, 8000); // 运行速度
  362. //Ret = Acm_SetF64Property(m_Axishand[0], PAR_AxAcc, 10000); // 加速度
  363. //Ret = Acm_SetF64Property(m_Axishand[0], PAR_AxDec, 10000); // 减速度
  364. //Ret = Acm_SetF64Property(m_Axishand[0], PAR_AxJerk, 0); //0-T/S 型曲线
  365. }
  366. }
  367. }
  368. /// <summary>
  369. /// 回HOME
  370. /// </summary>
  371. /// <param name="axisIndex"></param>
  372. /// <param name="homeMode">16种回HOME模式(0-15)</param>
  373. /// <param name="dir">0-正向 1-负向</param>
  374. /// <exception cref="Exception"></exception>
  375. public void home(int axisIndex = -1, uint homeMode = 11, uint dir = 1)
  376. {
  377. //研华运动控制卡共提供两个函数执行回Home: Acm_AxHome 和Acm_AxMoveHome
  378. //调用Acm_AxHome 执行回Home 时,通过PAR_AxVelLow、PAR_AxVelHigh、PAR_AxAcc、 PAR_AxDec、PAR_AxJerk 设置初速度,运行速度、加速度、减速度、速度曲线类型。
  379. //调用Acm_AxMoveHome 执行回Home 时,通过PAR_AxHomeVelLow、PAR_AxHomeVelHigh、 PAR_AxHomeAcc、PAR_AxHomeDec、PAR_AxHomeJerk 设置初速度,运行速度、加速度、 减速度、速度曲线类型。
  380. uint result;
  381. for (int i = 0; i < m_ulAxisCount; i++)
  382. {
  383. if (i == axisIndex || axisIndex == -1)
  384. {
  385. if ((AxisState)AxState[i] != AxisState.STA_AX_READY)
  386. continue;
  387. result = Motion.mAcm_AxHome(m_Axishand[i], homeMode, dir);
  388. if (result != (uint)ErrorCode.SUCCESS)
  389. throw new Exception("AxHome Failed With Error Code: [0x" + Convert.ToString(result, 16) + "]");
  390. }
  391. }
  392. }
  393. /// <summary>
  394. /// 点到点运动
  395. /// </summary>
  396. /// <param name="axisIndex"></param>
  397. /// <param name="pos">PPU位置,方向为正负值</param>
  398. /// <param name="isAbs">true:绝对 false:相对</param>
  399. public bool move_ptp(int axisIndex, double pos, bool isAbs)
  400. {
  401. uint result;
  402. if ((AxisState)AxState[axisIndex] != AxisState.STA_AX_READY)
  403. return false;
  404. if (isAbs) //Start single axis's absolute position motion.
  405. result = Motion.mAcm_AxMoveAbs(m_Axishand[axisIndex], pos);
  406. else //Start single axis's relative position motion
  407. result = Motion.mAcm_AxMoveRel(m_Axishand[axisIndex], pos);
  408. if (result != (uint)ErrorCode.SUCCESS)
  409. {
  410. log?.Invoke(2, "PTP Move Failed With Error Code[0x" + Convert.ToString(result, 16) + "]");
  411. return false;
  412. }
  413. return true;
  414. }
  415. #region JOG
  416. public void openJogMode(int axisIndex)
  417. {
  418. if (!IsInit) return;
  419. if ((AxisState)AxState[axisIndex] != AxisState.STA_AX_READY)
  420. return;
  421. uint result;
  422. //启用/禁用外置硬盘模式.0: Disabled (stop command) 1: JOG Mode 2: MPG Mode
  423. result = Motion.mAcm_AxSetExtDrive(m_Axishand[axisIndex], 0);
  424. result = Motion.mAcm_AxSetExtDrive(m_Axishand[axisIndex], 1);
  425. if (result != (uint)ErrorCode.SUCCESS)
  426. throw new Exception("Start external driver Failed With Error Code[0x" + Convert.ToString(result, 16) + "]");
  427. //设置外部驱动器的输入引脚
  428. //0 轴 0(默认值) 仅支持 0
  429. //1 轴 1(不支持)
  430. //2 轴 2(不支持)
  431. //3 轴 3(不支持)
  432. result = Motion.mAcm_SetU32Property(m_Axishand[axisIndex], (uint)PropertyID.CFG_AxExtMasterSrc, 0);
  433. if (result != (uint)ErrorCode.SUCCESS)
  434. throw new Exception("Set Property-AxExtMasterSrc Failed With Error Code[0x" + Convert.ToString(result, 16) + "]");
  435. //当启用外部驱动时。此属性允许通过数字输入通道选择驱动轴
  436. result = Motion.mAcm_SetU32Property(m_Axishand[axisIndex], (uint)PropertyID.CFG_AxExtSelEnable, 1);
  437. if (result != (uint)ErrorCode.SUCCESS && result != (uint)ErrorCode.PropertyIDNotSupport)//Added for Supporting PCI1245 and PCI1265
  438. throw new Exception("Set Property-AxExtSelEnable Failed With Error Code[0x" + Convert.ToString(result, 16) + "]");
  439. //理论脉冲数
  440. result = Motion.mAcm_SetU32Property(m_Axishand[axisIndex], (uint)PropertyID.CFG_AxExtPulseNum, 1000);
  441. if (result != (uint)ErrorCode.SUCCESS && result != (uint)ErrorCode.PropertyIDNotSupport)//Added for Supporting PCI1245 and PCI1265
  442. throw new Exception("Set Property-CFG_AxExtPulseNum Failed With Error Code[0x" + Convert.ToString(result, 16) + "]");
  443. }
  444. public void closeJogMode(int axisIndex = -1)
  445. {
  446. if (!IsInit) return;
  447. uint result;
  448. for (int i = 0; i < m_ulAxisCount; i++)
  449. {
  450. if (i == axisIndex || axisIndex == -1)
  451. {
  452. axisIndex = i;
  453. if ((AxisState)AxState[axisIndex] == AxisState.STA_AX_EXT_JOG)
  454. {
  455. //启用/禁用外置硬盘模式.0: Disabled (stop command) 1: JOG Mode 2: MPG Mode
  456. result = Motion.mAcm_AxSetExtDrive(m_Axishand[axisIndex], 0);
  457. //命令轴减速停止
  458. result = Motion.mAcm_AxStopDec(m_Axishand[axisIndex]);
  459. }
  460. }
  461. }
  462. }
  463. /// <summary>
  464. /// jog运行
  465. /// </summary>
  466. /// <param name="axisIndex"></param>
  467. /// <param name="dic">0:正向,1:负向</param>
  468. public void jog(int axisIndex, ushort dic)
  469. {
  470. //Jog 运动的方向,0:正向,1:负向
  471. Motion.mAcm_AxJog(m_Axishand[axisIndex], dic);
  472. }
  473. #endregion
  474. #region Private
  475. private void Timer_Elapsed(object sender, ElapsedEventArgs e)
  476. {
  477. if (!IsInit) return;
  478. for (int i = 0; i < m_ulAxisCount; i++)
  479. refreshAxisState(i);
  480. }
  481. private void refreshAxisState(int AxisIndex)
  482. {
  483. uint result;
  484. //获取指定轴的当前命令位置
  485. if ((uint)ErrorCode.SUCCESS == Motion.mAcm_AxGetCmdPosition(m_Axishand[AxisIndex], ref CmdPos[AxisIndex]))
  486. axisPosEvent?.Invoke(AxisIndex, AxisPosType.CmdPos, CmdPos[AxisIndex]);
  487. //获取指定轴的当前实际(反馈)位置
  488. if ((uint)ErrorCode.SUCCESS == Motion.mAcm_AxGetActualPosition(m_Axishand[AxisIndex], ref ActualPos[AxisIndex]))
  489. axisPosEvent?.Invoke(AxisIndex, AxisPosType.ActualPos, ActualPos[AxisIndex]);
  490. //获取轴的运动I/O状态。
  491. if ((uint)ErrorCode.SUCCESS == Motion.mAcm_AxGetMotionIO(m_Axishand[AxisIndex], ref IOStatus[AxisIndex]))
  492. axisStateEvent?.Invoke(AxisIndex, AxisStateType.AxisIOState, IOStatus[AxisIndex]);
  493. //log?.Invoke(0, $"({AxisIndex}轴)AxisMotionIO = {((Ax_Motion_IO)IOStatus[AxisIndex]).ToString()}");
  494. //checkMotionIOStatus(AxisIndex, IOStatus[AxisIndex]);
  495. //获取Axis的当前状态
  496. if ((uint)ErrorCode.SUCCESS == Motion.mAcm_AxGetState(m_Axishand[AxisIndex], ref AxState[AxisIndex]))
  497. axisStateEvent?.Invoke(AxisIndex, AxisStateType.AxisState, AxState[AxisIndex]);
  498. //log?.Invoke(0, $"({AxisIndex}轴)AxisState = {((AxisState)AxState[AxisIndex]).ToString()}");
  499. //获取Axis的当前运动状态
  500. if ((uint)ErrorCode.SUCCESS == Motion.mAcm_AxGetMotionStatus(m_Axishand[AxisIndex], ref AxMotionState[AxisIndex]))
  501. axisStateEvent?.Invoke(AxisIndex, AxisStateType.AxisMotionState, AxMotionState[AxisIndex]);
  502. //log?.Invoke(0, $"({AxisIndex}轴)AxisMotionStatus = {AxMotionState[AxisIndex].ToString()}");
  503. }
  504. private bool _ORG, _EL_R, _EL_L, _ALM, _SVON;
  505. private void checkMotionIOStatus(int axisIndex, uint IOStatus)
  506. {
  507. if ((IOStatus & (uint)Ax_Motion_IO.AX_MOTION_IO_ALM) > 0)//报警信号输出
  508. warningEvent?.Invoke(2, $"轴{axisIndex} 发出告警!!");
  509. bool ALM = (IOStatus & (uint)Ax_Motion_IO.AX_MOTION_IO_ALM) > 0;
  510. bool ORG = (IOStatus & (uint)Ax_Motion_IO.AX_MOTION_IO_ORG) > 0;//ORG
  511. bool EL_R = (IOStatus & (uint)Ax_Motion_IO.AX_MOTION_IO_LMTP) > 0;//右极限
  512. bool EL_L = (IOStatus & (uint)Ax_Motion_IO.AX_MOTION_IO_LMTN) > 0;//-EL 左
  513. bool SVON = (IOStatus & (uint)Ax_Motion_IO.AX_MOTION_IO_SVON) > 0;
  514. }
  515. /// <summary>
  516. /// 轴事件
  517. /// </summary>
  518. private void checkEvtThread()
  519. {
  520. uint Result;
  521. UInt32[] AxEvtStatusArray = new UInt32[32];
  522. UInt32[] GpEvtStatusArray = new UInt32[32];
  523. UInt32 i;
  524. while (IsInit)
  525. {
  526. //如果你想获得轴或组的事件状态,你应该通过调用 Motion.mAcm_EnableMotionEvent 来启用这些事件
  527. //AxEvtStatusArray[n],返回每个轴的中断事件状态,n 表示运动设备的轴个数
  528. //GpEnableEvtArrayy[n]:返回每个群组的中断事件状态
  529. //AxArrayElements U32 IN AxEvtStatusArray 中元素个数
  530. //GpArrayElements U32 IN GpEvtStatusArray 中元素个数
  531. //Millisecond U32 IN 设定每次Check 事件时的等待时间
  532. Result = Motion.mAcm_CheckMotionEvent(m_DeviceHandle, AxEvtStatusArray, GpEvtStatusArray, m_ulAxisCount, 4, 4);//3,10
  533. if (Result == (uint)ErrorCode.SUCCESS)
  534. {
  535. for (i = 0; i < m_ulAxisCount; i++)
  536. {
  537. if ((AxEvtStatusArray[i] & (uint)EventType.EVT_AX_MOTION_DONE) > 0)
  538. {
  539. //m_AxDoneEvtCnt[i]++;
  540. }
  541. if ((AxEvtStatusArray[i] & (uint)EventType.EVT_AX_VH_START) > 0)
  542. {
  543. //m_AxVHStartCnt[i]++;
  544. }
  545. if ((AxEvtStatusArray[i] & (uint)EventType.EVT_AX_VH_END) > 0)
  546. {
  547. //m_AxVHEndCnt[i]++;
  548. }
  549. }
  550. //if (m_GpHand != IntPtr.Zero)
  551. //{
  552. // if (textBoxGpID.Text != "")
  553. // {
  554. // if ((GpEvtStatusArray[0] & ((uint)EventType.EVT_GP1_MOTION_DONE << Convert.ToByte(textBoxGpID.Text))) > 0)
  555. // {
  556. // m_GpDoneEvtCnt++;
  557. // }
  558. // if ((GpEvtStatusArray[1] & ((uint)EventType.EVT_GP1_VH_START << Convert.ToByte(textBoxGpID.Text))) > 0)
  559. // {
  560. // m_GpVHStartCnt++;
  561. // }
  562. // if ((GpEvtStatusArray[2] & ((uint)EventType.EVT_GP1_VH_END << Convert.ToByte(textBoxGpID.Text))) > 0)
  563. // {
  564. // m_GpVHEndCnt++;
  565. // }
  566. // }
  567. //}
  568. }
  569. }
  570. }
  571. private string getErrInfo(uint errorCode)
  572. {
  573. StringBuilder ErrorMsg = new StringBuilder("", 100);
  574. //Get the error message according to error code returned from API
  575. Boolean res = Motion.mAcm_GetErrorMessage(errorCode, ErrorMsg, 100);
  576. if (res) return ErrorMsg.ToString();
  577. return "获取错误信息失败!";
  578. }
  579. #endregion
  580. /*
  581. [Category("HLMT")]
  582. [Description("启用/禁用硬件限制信号.")]
  583. public HLmtEnable ElEnable
  584. {
  585. get
  586. {
  587. if ((FtHELMap & 1) == 0)
  588. {
  589. return HLmtEnable.NOT_SUPPORT;
  590. }
  591. if (Handle != IntPtr.Zero)
  592. {
  593. uint BufferLength = 4u;
  594. Motion.mAcm_GetProperty(Handle, 574u, ref m_ElEnable, ref BufferLength);
  595. return (HLmtEnable)m_ElEnable;
  596. }
  597. return (HLmtEnable)m_ElEnable;
  598. }
  599. set
  600. {
  601. m_ElEnable = (uint)value;
  602. if (Handle != IntPtr.Zero)
  603. {
  604. if (m_ElEnable != 2)
  605. {
  606. uint bufferLength = 4u;
  607. result = Motion.mAcm_SetProperty(Handle, 574u, ref m_ElEnable, bufferLength);
  608. if (result == 0)
  609. {
  610. designValue.ElEnable = value;
  611. }
  612. else if (result != 2147483658u && result != 2147504130u)
  613. {
  614. MessageBox.Show("Set ElEnable=" + ElEnable.ToString() + " failed with Error Code[0x" + Convert.ToString(result, 16) + "]:" + (ErrorCode)result, "Advantech Motion Component", MessageBoxButtons.OK, MessageBoxIcon.Hand, MessageBoxDefaultButton.Button1);
  615. }
  616. }
  617. }
  618. else
  619. {
  620. designValue.ElEnable = value;
  621. }
  622. }
  623. }
  624. [Category("HLMT")]
  625. [Description("启用/禁用此轴的负硬件限制.")]
  626. public HLmtEnable MelEnable
  627. {
  628. get
  629. {
  630. if ((FtHELMap & 1) == 0)
  631. {
  632. return HLmtEnable.NOT_SUPPORT;
  633. }
  634. if (Handle != IntPtr.Zero)
  635. {
  636. uint BufferLength = 4u;
  637. Motion.mAcm_GetProperty(Handle, 758u, ref m_MelEnable, ref BufferLength);
  638. return (HLmtEnable)m_MelEnable;
  639. }
  640. return (HLmtEnable)m_MelEnable;
  641. }
  642. set
  643. {
  644. m_MelEnable = (uint)value;
  645. if (Handle != IntPtr.Zero)
  646. {
  647. if (m_MelEnable != 2)
  648. {
  649. uint bufferLength = 4u;
  650. result = Motion.mAcm_SetProperty(Handle, 758u, ref m_MelEnable, bufferLength);
  651. if (result == 0)
  652. {
  653. designValue.MelEnable = value;
  654. }
  655. else if (result != 2147483658u && result != 2147504130u)
  656. {
  657. MessageBox.Show("Set MelEnable=" + m_MelEnable.ToString() + " failed with Error Code[0x" + Convert.ToString(result, 16) + "]:" + (ErrorCode)result, "Advantech Motion Component", MessageBoxButtons.OK, MessageBoxIcon.Hand, MessageBoxDefaultButton.Button1);
  658. }
  659. }
  660. }
  661. else
  662. {
  663. designValue.MelEnable = value;
  664. }
  665. }
  666. }
  667. [Category("HLMT")]
  668. [Description("启用/禁用此轴的正向硬件限制.")]
  669. public HLmtEnable PelEnable
  670. {
  671. get
  672. {
  673. if ((FtHELMap & 1) == 0)
  674. {
  675. return HLmtEnable.NOT_SUPPORT;
  676. }
  677. if (Handle != IntPtr.Zero)
  678. {
  679. uint BufferLength = 4u;
  680. Motion.mAcm_GetProperty(Handle, 757u, ref m_PelEnable, ref BufferLength);
  681. return (HLmtEnable)m_PelEnable;
  682. }
  683. return (HLmtEnable)m_PelEnable;
  684. }
  685. set
  686. {
  687. m_PelEnable = (uint)value;
  688. if (Handle != IntPtr.Zero)
  689. {
  690. if (m_PelEnable != 2)
  691. {
  692. uint bufferLength = 4u;
  693. result = Motion.mAcm_SetProperty(Handle, 757u, ref m_PelEnable, bufferLength);
  694. if (result == 0)
  695. {
  696. designValue.PelEnable = value;
  697. }
  698. else if (result != 2147483658u && result != 2147504130u)
  699. {
  700. MessageBox.Show("Set PelEnable=" + m_PelEnable.ToString() + " failed with Error Code[0x" + Convert.ToString(result, 16) + "]:" + (ErrorCode)result, "Advantech Motion Component", MessageBoxButtons.OK, MessageBoxIcon.Hand, MessageBoxDefaultButton.Button1);
  701. }
  702. }
  703. }
  704. else
  705. {
  706. designValue.PelEnable = value;
  707. }
  708. }
  709. }
  710. [Category("HLMT")]
  711. [Description("为硬件限位信号设置活动逻辑.")]
  712. public HLmtLogic ElLogic
  713. {
  714. get
  715. {
  716. if ((FtHELMap & 2) == 0)
  717. {
  718. return HLmtLogic.NOT_SUPPORT;
  719. }
  720. if (Handle != IntPtr.Zero)
  721. {
  722. uint BufferLength = 4u;
  723. Motion.mAcm_GetProperty(Handle, 575u, ref m_ElLogic, ref BufferLength);
  724. return (HLmtLogic)m_ElLogic;
  725. }
  726. return (HLmtLogic)m_ElLogic;
  727. }
  728. set
  729. {
  730. m_ElLogic = (uint)value;
  731. if (Handle != IntPtr.Zero)
  732. {
  733. if (m_ElLogic != 2)
  734. {
  735. uint BufferLength = 4u;
  736. result = Motion.mAcm_SetProperty(Handle, 575u, ref m_ElLogic, BufferLength);
  737. if (result == 0)
  738. {
  739. designValue.ElLogic = value;
  740. Motion.mAcm_GetProperty(Handle, 704u, ref m_PelLogic, ref BufferLength);
  741. Motion.mAcm_GetProperty(Handle, 705u, ref m_MelLogic, ref BufferLength);
  742. }
  743. else if (result != 2147483658u && result != 2147504130u)
  744. {
  745. MessageBox.Show("Set ElLogic=" + m_ElLogic.ToString() + " failed with Error Code[0x" + Convert.ToString(result, 16) + "]:" + (ErrorCode)result, "Advantech Motion Component", MessageBoxButtons.OK, MessageBoxIcon.Hand, MessageBoxDefaultButton.Button1);
  746. }
  747. }
  748. }
  749. else
  750. {
  751. designValue.ElLogic = value;
  752. }
  753. }
  754. }
  755. */
  756. }
  757. }