版博士V2.0程序
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 

509 行
19 KiB

  1. using Advantech.Motion;
  2. using Newtonsoft.Json;
  3. using Newtonsoft.Json.Linq;
  4. using ProductionControl.Device;
  5. using ProductionControl.Utils;
  6. using System;
  7. using System.Collections.Generic;
  8. using System.ComponentModel;
  9. using System.Data;
  10. using System.Drawing;
  11. using System.Drawing.Imaging;
  12. using System.IO;
  13. using System.Linq;
  14. using System.Text;
  15. using System.Threading;
  16. using System.Threading.Tasks;
  17. using System.Windows.Forms;
  18. using System.Xml.Linq;
  19. using static ProductionControl.Device.AxisDev;
  20. using static ProductionControl.UI.UIAxisDev;
  21. namespace ProductionControl.UI
  22. {
  23. public partial class UIAxisDev : UserControl
  24. {
  25. SynchronizationContext SyncContext = null;
  26. public Action<string> GetParamsEvent;
  27. //
  28. private AxisDevProp prop = new AxisDevProp();
  29. private AxisDev dev;
  30. private JObject dataReturn = new JObject();
  31. //
  32. ScannerDev devScannerGentl;
  33. ScannerDev devScannerCC;
  34. public UIAxisDev()
  35. {
  36. InitializeComponent();
  37. propertyGrid1.PropertyValueChanged += propertyGrid1_PropertyValueChanged;
  38. refreshUIState();
  39. //获取UI线程同步上下文
  40. SyncContext = SynchronizationContext.Current;
  41. //init();
  42. }
  43. private void refreshUIState()
  44. {
  45. foreach (ToolStripItem item in this.toolStrip1.Items)
  46. {
  47. if (item.Text == "打开设备")
  48. item.Visible = (dev == null || !dev.IsInit);
  49. else
  50. this.propertyGrid1.Enabled=item.Enabled = !(dev == null || !dev.IsInit);
  51. }
  52. }
  53. public string getParamsData()
  54. {
  55. if (prop.Enable)
  56. {
  57. string axisIndex = ((int)prop.AxisIndex).ToString();
  58. Utils.Util.addKey(dataReturn, axisIndex, JObject.Parse(prop.serialize()));
  59. }
  60. //return prop.serialize();
  61. return dataReturn.ToString();
  62. }
  63. private void tbtnSave_Click(object sender, EventArgs e)
  64. {
  65. if (dataReturn.Properties().Count() < 1)
  66. {
  67. MessageBox.Show("请设置需要启用的轴!", "失败", MessageBoxButtons.OK, MessageBoxIcon.Error);
  68. return;
  69. }
  70. //GetParamsEvent?.Invoke(prop.serialize());
  71. GetParamsEvent?.Invoke(getParamsData());
  72. }
  73. public bool stopNow()
  74. {
  75. if (dev != null && dev.IsInit)
  76. {
  77. dev.stopNow();
  78. return true;
  79. }
  80. else
  81. return false;
  82. }
  83. public void setParamsData(string json)
  84. {
  85. tsbtnScannerList.Visible = true;
  86. if (json == "") return;
  87. JObject dataReturnTmp = JObject.Parse(json);
  88. //兼容旧版单轴
  89. if (!dataReturnTmp.ContainsKey("0") && !dataReturnTmp.ContainsKey("1") && !dataReturnTmp.ContainsKey("2") && !dataReturnTmp.ContainsKey("3"))
  90. {
  91. if(!dataReturnTmp.ContainsKey("Enable"))
  92. dataReturnTmp.Add("Enable",true);
  93. dataReturn.Add(dataReturnTmp.Value<int>("AxisIndex").ToString(), dataReturnTmp);
  94. }
  95. else
  96. dataReturn = dataReturnTmp;
  97. //
  98. foreach (var property in dataReturn.Properties())
  99. {
  100. prop.deserialize(property.Value.ToString());
  101. break;
  102. }
  103. this.propertyGrid1.Refresh();
  104. }
  105. public void init()
  106. {
  107. this.tbtnSave.Visible = tssSave.Visible = (GetParamsEvent != null);
  108. this.propertyGrid1.SelectedObject = prop;
  109. dev = new AxisDev();
  110. dev.WarningEvent = (level, info) =>
  111. {
  112. txtLog.Text = $"({level}){info}";
  113. };
  114. //STATE
  115. dev.axisStateEvent += new System.Action<int, AxisStateType, uint>((axisIndex, type, stateValue) =>
  116. {
  117. if (axisIndex != (int)prop.AxisIndex)
  118. return;
  119. switch (type)
  120. {
  121. case AxisStateType.AxisState:
  122. if (prop.AxState != (AxisState)stateValue)
  123. {
  124. prop.AxState = (AxisState)stateValue;
  125. this.refreshUI();
  126. }
  127. break;
  128. case AxisStateType.AxisIOState:
  129. if (prop.AxIOStatus != stateValue)
  130. {
  131. prop.AxIOStatus = stateValue;
  132. prop.ALM = (stateValue & (uint)Ax_Motion_IO.AX_MOTION_IO_ALM) > 0;//需IO close
  133. prop.EMG = (stateValue & (uint)Ax_Motion_IO.AX_MOTION_IO_EMG) > 0;//需重置 state
  134. prop.LMTP = (stateValue & (uint)Ax_Motion_IO.AX_MOTION_IO_LMTP) > 0;//右极限 true->false
  135. prop.LMTN = (stateValue & (uint)Ax_Motion_IO.AX_MOTION_IO_LMTN) > 0;//左极限
  136. prop.ORG = (stateValue & (uint)Ax_Motion_IO.AX_MOTION_IO_ORG) > 0;
  137. prop.EZ = (stateValue & (uint)Ax_Motion_IO.AX_MOTION_IO_EZ) > 0;
  138. prop.SVON = (stateValue & (uint)Ax_Motion_IO.AX_MOTION_IO_SVON) > 0;
  139. this.refreshUI();
  140. }
  141. break;
  142. case AxisStateType.AxisMotionState:
  143. if (prop.AxMotionState != stateValue)
  144. {
  145. prop.AxMotionState = stateValue;
  146. this.refreshUI();
  147. }
  148. break;
  149. }
  150. });
  151. //位置POS
  152. dev.axisPosEvent += new System.Action<int, AxisPosType, double>((axisIndex, type, pos) =>
  153. {
  154. if (axisIndex != (int)prop.AxisIndex)
  155. return;
  156. switch (type)
  157. {
  158. case AxisPosType.CmdPos:
  159. if (prop.CmdPos != pos)
  160. {
  161. prop.CmdPos = pos;
  162. this.refreshUI();
  163. }
  164. break;
  165. case AxisPosType.ActualPos:
  166. if (prop.ActualPos != pos)
  167. {
  168. prop.ActualPos = pos;
  169. this.refreshUI();
  170. }
  171. break;
  172. }
  173. });
  174. if (!dev.start(Config.Axis_PulseOutMode,true))
  175. {
  176. this.closeDev();
  177. return;
  178. }
  179. refreshAxisVelParam();
  180. refreshUIState();
  181. }
  182. private void refreshUI(bool must=false)
  183. {
  184. SyncContext.Post(m =>
  185. {
  186. var result = m as string;
  187. if(!stopRefresh || must)
  188. propertyGrid1.Refresh();
  189. tbtnJogOnOff.Text = (prop.AxState == AxisState.STA_AX_EXT_JOG) ? "关闭Jog" : "开启Jog";
  190. tbtnLeft.Enabled = tbtnRight.Enabled = (prop.AxState == AxisState.STA_AX_EXT_JOG);
  191. }, "异步操作完成结果");
  192. }
  193. private void refreshAxisVelParam()
  194. {
  195. int axisIndex = (int)prop.AxisIndex;
  196. //prop.HomeMode = (AxitHomeMode)Config.Axis_HomeMode[axisIndex];
  197. var values = dev.getAxisVelParam(axisIndex);
  198. prop.VelLow = dev.tomm(values[0], Config.Axis_MM2PulseNum[axisIndex]);
  199. prop.VelHigh = dev.tomm(values[1], Config.Axis_MM2PulseNum[axisIndex]);
  200. prop.Acc = dev.tomm(values[2], Config.Axis_MM2PulseNum[axisIndex]);
  201. prop.Dec = dev.tomm(values[3], Config.Axis_MM2PulseNum[axisIndex]);
  202. }
  203. private void closeDev()
  204. {
  205. try
  206. {
  207. if (dev == null)
  208. return;
  209. dev.stop();
  210. closeScannerDev();
  211. }
  212. catch (Exception ex)
  213. {
  214. this.refreshUIState();
  215. MessageBox.Show(ex.Message, "失败", MessageBoxButtons.OK, MessageBoxIcon.Error);
  216. }
  217. }
  218. protected override void OnHandleDestroyed(EventArgs e)
  219. {
  220. base.OnHandleDestroyed(e);
  221. // 在此添加需要手动释放资源的代码
  222. this.closeDev();
  223. }
  224. private void tbtnRun_Click(object sender, EventArgs e)
  225. {
  226. try
  227. {
  228. this.stopRefresh = false;
  229. dev.setAxisVelParam(prop.VelLow, prop.VelHigh, prop.Acc, prop.Dec, (int)prop.AxisIndex);
  230. dev.move_ptp((int)prop.AxisIndex, prop.Value, prop.MoveMode);
  231. //running...
  232. }
  233. catch(Exception ex)
  234. {
  235. MessageBox.Show(ex.Message, "失败", MessageBoxButtons.OK, MessageBoxIcon.Error);
  236. }
  237. }
  238. private void tbtnExport_Click(object sender, EventArgs e)
  239. {
  240. string filePath = FileUtil.saveAsFile($"Axis配置.json", "JSON|*.json");
  241. if (filePath != "")
  242. {
  243. //string jsonText = prop.serialize();
  244. string jsonText = dataReturn.ToString();
  245. File.WriteAllText(filePath, jsonText);
  246. MessageBox.Show("保存成功!", "成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
  247. }
  248. }
  249. private void tbtnImport_Click(object sender, EventArgs e)
  250. {
  251. string filePath = FileUtil.selectFile("JSON|*.json");
  252. if (filePath != "")
  253. {
  254. string jsonText = File.ReadAllText(filePath);
  255. JObject dataReturnTmp = JObject.Parse(jsonText);
  256. //兼容旧版单轴
  257. if (!dataReturnTmp.ContainsKey("0") && !dataReturnTmp.ContainsKey("1") && !dataReturnTmp.ContainsKey("2") && !dataReturnTmp.ContainsKey("3"))
  258. {
  259. dataReturnTmp.Add("Enable", true);
  260. dataReturn.Add(dataReturnTmp.Value<int>("AxisIndex").ToString(), dataReturnTmp);
  261. }
  262. else
  263. dataReturn = dataReturnTmp;
  264. //
  265. foreach (var property in dataReturn.Properties())
  266. {
  267. prop.deserialize(property.Value.ToString());
  268. break;
  269. }
  270. this.propertyGrid1.Refresh();
  271. }
  272. }
  273. private void tbtnHome_Click(object sender, EventArgs e)
  274. {
  275. this.stopRefresh = false;
  276. int axitIndex = (int)prop.AxisIndex;
  277. dev.setAxisVelParam(prop.VelLow, prop.VelHigh, prop.Acc, prop.Dec, (int)prop.AxisIndex);
  278. //dev.setAxisVelParam(prop.VelLow, prop.VelHigh, prop.Acc, prop.Dec, (int)prop.AxisIndex,true);
  279. dev.home(axitIndex, (uint)Config.Axis_HomeMode[axitIndex], (uint)Config.Axis_HomeDir[axitIndex]);
  280. //if (prop.DeviceType == AxisType.默认)
  281. //{
  282. // dev.home((int)prop.AxisIndex);
  283. //}
  284. //else //直线电机
  285. //{
  286. // //dev.move_ptp((int)prop.AxisIndex, - prop.ActualPos, false);
  287. // dev.move_ptp((int)prop.AxisIndex, 0, true);
  288. //}
  289. }
  290. private void tbtnLeft_MouseDown(object sender, MouseEventArgs e)
  291. {
  292. this.stopRefresh = false;
  293. dev.jog((int)prop.AxisIndex, 1);
  294. }
  295. private void tbtnLeft_MouseUp(object sender, MouseEventArgs e)
  296. {
  297. dev.stopDec((int)prop.AxisIndex);
  298. }
  299. private void tbtnRight_MouseDown(object sender, MouseEventArgs e)
  300. {
  301. this.stopRefresh = false;
  302. dev.jog((int)prop.AxisIndex, 0);
  303. }
  304. private void tbtnRight_MouseUp(object sender, MouseEventArgs e)
  305. {
  306. dev.stopDec((int)prop.AxisIndex);
  307. }
  308. private void tbtnJogOnOff_Click(object sender, EventArgs e)
  309. {
  310. this.stopRefresh = false;
  311. if (prop.AxState==AxisState.STA_AX_EXT_JOG)
  312. {
  313. dev.closeJogMode((int)prop.AxisIndex);
  314. //tbtnJogOnOff.Text = "开启Jog";
  315. }
  316. else
  317. {
  318. dev.setAxisVelParam(prop.VelLow, prop.VelHigh, prop.Acc, prop.Dec, (int)prop.AxisIndex);
  319. dev.openJogMode((int)prop.AxisIndex);
  320. //tbtnJogOnOff.Text = "关闭Jog";
  321. }
  322. }
  323. private void tbtnStop_Click(object sender, EventArgs e)
  324. {
  325. this.stopRefresh = false;
  326. dev.stopDec((int)prop.AxisIndex);
  327. }
  328. private void tbtnRestState_Click(object sender, EventArgs e)
  329. {
  330. this.stopRefresh = false;
  331. dev.resetAxisState((int)prop.AxisIndex);
  332. }
  333. private void tbtnResetPos_Click(object sender, EventArgs e)
  334. {
  335. this.stopRefresh = false;
  336. dev.resetCmdPosition((int)prop.AxisIndex);
  337. dev.resetActualPosition((int)prop.AxisIndex);
  338. }
  339. private void propertyGrid1_PropertyValueChanged(object s, PropertyValueChangedEventArgs e)
  340. {
  341. //其中包含了两个重要的属性:OldValue和ChangeItem。
  342. //ChangeItem是“PropertyDescriptorGridEntry”类型。一般可以通过ChangeItem.PropertyDescriptor.ComponentType查找到属性的实际类型。
  343. //而通过ChangeItem的Label,则可以查看到当前在属性编辑输入框中显示的值。
  344. string className = e.ChangedItem.PropertyDescriptor.ComponentType.Name;
  345. string propertyName = e.ChangedItem.PropertyDescriptor.Name;
  346. var oldValue = e.OldValue;
  347. var newValue = e.ChangedItem.Value;
  348. switch (propertyName)
  349. {
  350. case "AxisIndex"://切换前先把old更新,再加载新的prop
  351. //先更新/删除旧的
  352. string oldAxisIndex = ((int)oldValue).ToString();
  353. string newAxisIndex = ((int)newValue).ToString();
  354. if (dataReturn.ContainsKey(oldAxisIndex))
  355. {
  356. if (prop.Enable)
  357. {
  358. JObject o = JObject.Parse(prop.serialize());
  359. o["AxisIndex"] = oldAxisIndex;//改为老的
  360. Utils.Util.addKey(dataReturn, oldAxisIndex, o);
  361. }
  362. else
  363. dataReturn.Remove(oldAxisIndex);
  364. }
  365. //加载新的
  366. if (dataReturn.ContainsKey(newAxisIndex))
  367. prop.deserialize(dataReturn[newAxisIndex].ToString());
  368. else
  369. {
  370. prop.Enable = false;
  371. refreshAxisVelParam();//更新当前速度值
  372. }
  373. refreshUI(true);
  374. break;
  375. case "Enable"://先进行更新数组,保存或删除
  376. string axisIndex = ((int)prop.AxisIndex).ToString();
  377. if ((bool)newValue)
  378. Utils.Util.addKey(dataReturn, axisIndex, JObject.Parse(prop.serialize()));
  379. else if (dataReturn.ContainsKey(axisIndex))
  380. dataReturn.Remove(axisIndex);
  381. break;
  382. }
  383. }
  384. private void tsbtnOpenDev_Click(object sender, EventArgs e)
  385. {
  386. this.init();
  387. }
  388. //打开相机
  389. FrmScannerShow frmScannerShow1;
  390. FrmScannerShow frmScannerShow2;
  391. private void tbtnScanner1_Click(object sender, EventArgs e)
  392. {
  393. if (devScannerGentl==null)
  394. devScannerGentl = new ScannerDev(ScannerDev.ScannerType.GENTL);
  395. devScannerGentl.ScanEvent += new System.Action<int, Bitmap>((num, bmp) =>
  396. {
  397. string path = Config.appBasePath + "\\temp\\" + DateTime.Now.Ticks + ".bmp";
  398. bmp.Save(path, ImageFormat.Bmp);
  399. });
  400. if (!devScannerGentl.open())
  401. {
  402. devScannerGentl.stop();
  403. return;
  404. }
  405. if (!devScannerGentl.start(IntPtr.Zero, null) && !devScannerGentl.IsInit)
  406. {
  407. devScannerGentl.close();
  408. MessageBox.Show("相机打开失败!");
  409. return;
  410. }
  411. if (frmScannerShow1 == null || frmScannerShow1.IsDisposed)
  412. frmScannerShow1 = new FrmScannerShow(devScannerGentl.size, devScannerGentl);
  413. frmScannerShow1.Show();
  414. devScannerGentl.setPreviewWin(frmScannerShow1.picHwnd);
  415. if (!devScannerGentl.isContinuousMode)
  416. devScannerGentl.setMode(true);
  417. }
  418. private void tbtnScanner2_Click(object sender, EventArgs e)
  419. {
  420. if (devScannerCC == null)
  421. devScannerCC = new ScannerDev(ScannerDev.ScannerType.CC);
  422. if (!devScannerCC.open())
  423. {
  424. devScannerCC.stop();
  425. return;
  426. }
  427. if (!devScannerCC.start(IntPtr.Zero, Config.appBasePath + "\\temp") && !devScannerCC.IsInit)
  428. {
  429. devScannerCC.close();
  430. MessageBox.Show("相机打开失败!");
  431. return;
  432. }
  433. if (frmScannerShow2 == null || frmScannerShow2.IsDisposed)
  434. frmScannerShow2 = new FrmScannerShow(devScannerCC.size, devScannerCC);
  435. frmScannerShow2.Show();
  436. devScannerCC.setPreviewWin(frmScannerShow2.picHwnd);
  437. if (!devScannerCC.isContinuousMode)
  438. devScannerCC.setMode(true);
  439. }
  440. private void closeScannerDev()
  441. {
  442. if (devScannerGentl != null && devScannerGentl.IsInit)
  443. {
  444. devScannerGentl.stop();
  445. devScannerGentl.close();
  446. }
  447. if (devScannerCC != null && devScannerCC.IsInit)
  448. {
  449. devScannerCC.stop();
  450. devScannerCC.close();
  451. }
  452. if (frmScannerShow1 != null && !frmScannerShow1.IsDisposed) frmScannerShow1.Close();
  453. if (frmScannerShow2 != null && !frmScannerShow2.IsDisposed) frmScannerShow2.Close();
  454. }
  455. private bool _stopRefresh=false;
  456. private bool stopRefresh{
  457. get { return _stopRefresh; }
  458. set {
  459. _stopRefresh = value;
  460. this.tsbtnStopRefresh.Text = (_stopRefresh?"开启同步":"停止同步");
  461. }
  462. }
  463. private void tsbtnStopRefresh_Click(object sender, EventArgs e)
  464. {
  465. stopRefresh = !stopRefresh;
  466. }
  467. }
  468. }