Form1.cs 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852
  1. using snap7Enc;
  2. using System;
  3. using System.Collections.Concurrent;
  4. using System.Collections.Generic;
  5. using System.Drawing;
  6. using System.Linq;
  7. using System.Net;
  8. using System.Net.Sockets;
  9. using System.Runtime.InteropServices;
  10. using System.Text;
  11. using System.Threading;
  12. using System.Threading.Tasks;
  13. using System.Windows.Forms;
  14. using System.Windows.Forms.DataVisualization.Charting;
  15. namespace Test
  16. {
  17. public partial class obstacleDetectionForm : Form
  18. {
  19. private SickTimEnc laserLeft;
  20. private SickTimEnc laserRight;
  21. private int max_axis_Y = 2600;//2250;//画图时Y轴最大量程
  22. private List<DispMsg> dataDispList;
  23. private List<string> colors;//雷达数据颜色
  24. private bool obstacleDetected;
  25. private const string leftTrue = "left: True ";
  26. private const string leftFalse = "left: False ";
  27. private const string rightTrue = "right: True ";
  28. private const string rightFalse = "right: False ";
  29. //************** plc相关参数 *************
  30. /// <summary>
  31. /// PLC 连接状态flag
  32. /// </summary>
  33. public bool isConnected = false;
  34. /// <summary>
  35. /// plc中cpu类型
  36. /// </summary>
  37. private const CpuType cpu = CpuType.S71500;
  38. /// <summary>
  39. /// PLC的IP地址
  40. /// </summary>
  41. private const string ip = "192.168.0.1";
  42. /// <summary>
  43. /// PLC的端口号
  44. /// </summary>
  45. private const Int16 rack = 0;
  46. /// <summary>
  47. /// 工作站号
  48. /// </summary>
  49. private const Int16 slot = 1;
  50. /// <summary>
  51. /// PLC S7连接对象
  52. /// </summary>
  53. protected static Plc plc = null;
  54. /// <summary>
  55. /// 用于将写PLC指令排队的阻塞队列
  56. /// </summary>
  57. private BlockingCollection<MsgNode> writingBlockingCollection = new BlockingCollection<MsgNode>();
  58. /// <summary>
  59. /// 写线程,控制PLC写入频率
  60. /// </summary>
  61. private Thread writeThread;
  62. /// <summary>
  63. /// 系统关闭
  64. /// </summary>
  65. private bool closed;
  66. /// <summary>
  67. /// 读写锁
  68. /// </summary>
  69. private static object readWriteLock = new object();
  70. //写入频率
  71. private const int writeFreq = 25;
  72. private const short DB = 30;
  73. private const short ZPosition = 8;
  74. private const short ZThreshold = 200;
  75. private const short ZStart = 10;
  76. private const short ZStop = 12;
  77. private const short ZPause = 14;
  78. private short ZPositionValue = 0;
  79. private short ZStartValue = 0;
  80. private short ZStopValue = 0;
  81. private short ZPauseValue = 0;
  82. private bool startGoingDown = false;
  83. private bool laserWorking = false;
  84. //流程控制
  85. private void Start()
  86. {
  87. obstacleDetected = false;
  88. colors = new List<string>();
  89. colors.Add(Color.Red.Name);
  90. colors.Add(Color.Yellow.Name);
  91. colors.Add(Color.Cyan.Name);
  92. colors.Add(Color.Blue.Name);
  93. dataDispList = new List<DispMsg>();
  94. //初始化雷达与数据显示
  95. Task.Factory.StartNew(() =>
  96. {
  97. //laserLeft = new SickTimEnc("192.168.0.77", 2111);
  98. laserRight = new SickTimEnc("192.168.0.88", 2111);
  99. while (!IsHandleCreated)
  100. {
  101. Thread.Sleep(500);
  102. Console.WriteLine("等待初始化完成");
  103. }
  104. this.Invoke(new Action(() =>
  105. {
  106. InitChart();
  107. if (laserLeft != null)
  108. {
  109. Pause();
  110. laserLeft.SetLeftRange(65);
  111. laserLeft.SetRightRange(115);
  112. laserLeft.ground_truth_height = 4050;
  113. laserLeft.min_num_point_of_hinder = 20;
  114. laserLeft.min_obstacle_height = 100;
  115. tb_angleLeft.Text = "65";
  116. tb_angleRight.Text = "115";
  117. Pause();
  118. List<List<double>> temp = new List<List<double>>();
  119. temp.Add(laserLeft.yFiltered);
  120. temp.Add(laserLeft.yFilteredKalman);
  121. chartAddData(laserLeft.listx, temp, 1);
  122. }
  123. if (laserRight != null)
  124. {
  125. Pause();
  126. laserRight.SetLeftRange(75);
  127. laserRight.SetRightRange(105);
  128. laserRight.ground_truth_height = 2200;
  129. laserRight.min_num_point_of_hinder = 20;
  130. laserRight.min_obstacle_height = 100;
  131. tb_angleLeft.Text = "75";
  132. tb_angleRight.Text = "125";
  133. Pause();
  134. List<List<double>> temp = new List<List<double>>();
  135. temp.Add(laserRight.yFiltered);
  136. temp.Add(laserRight.yFilteredKalman);
  137. chartAddData(laserRight.listx, temp, 2);
  138. }
  139. }));
  140. while (!closed)
  141. {
  142. System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
  143. sw.Start();
  144. try
  145. {
  146. this.Invoke(new Action(() =>
  147. {
  148. //for (int i = 0; i < dataDispList.Count; i++)
  149. //{
  150. // updateChartData(dataDispList[i].x, dataDispList[i].y, i);
  151. //}
  152. if (dataDispList.Count >= 2)
  153. {
  154. if (laserLeft != null)
  155. {
  156. updateChartData(laserLeft.listx, laserLeft.yFiltered, 0);
  157. updateChartData(laserLeft.listx, laserLeft.yFilteredKalman, 1);
  158. //lb_obstacle.Text = " left:" + laserLeft.obstacleDetected + " ";
  159. lb_obstacle.Text = laserLeft.obstacleDetected ? leftTrue : leftFalse;
  160. //lb_obstacle.Text = " left:" + laserLeft.dataCount + " ";
  161. obstacleDetected = false || laserLeft.obstacleDetected;
  162. }
  163. if (laserRight != null)
  164. {
  165. updateChartData(laserRight.listx, laserRight.yFiltered, dataDispList.Count >=4 ?2:0);
  166. updateChartData(laserRight.listx, laserRight.yFilteredKalman, dataDispList.Count >= 4 ?3:1);
  167. //lb_obstacle.Text = (dataDispList.Count >= 4?lb_obstacle.Text:String.Empty)+"right:" + laserRight.obstacleDetected + " ";
  168. if (dataDispList.Count >= 4)
  169. lb_obstacle.Text += laserRight.obstacleDetected ? rightTrue : rightFalse;
  170. else
  171. lb_obstacle.Text = laserRight.obstacleDetected ? rightTrue : rightFalse;
  172. //lb_obstacle.Text += "right:" + laserRight.dataCount + " ";
  173. obstacleDetected = obstacleDetected || laserRight.obstacleDetected;
  174. }
  175. }
  176. }));
  177. }
  178. catch { Stop(); }
  179. sw.Stop();
  180. Console.WriteLine("laser: " + sw.ElapsedMilliseconds + "ms");
  181. Thread.Sleep(30);
  182. }
  183. });
  184. ////************* PLC 相关逻辑 *************
  185. //bool result = PLCConnect();
  186. //if (!result)
  187. //{
  188. // Console.WriteLine("PLC连接失败");
  189. // Environment.Exit(0);
  190. //}
  191. //else
  192. //{
  193. // MsgNode msg = new MsgNode();
  194. // msg.db = DB;
  195. // msg.length = 2;
  196. // Task.Factory.StartNew(() =>
  197. // {
  198. // while (!closed)
  199. // {
  200. // System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
  201. // sw.Start();
  202. // if (plc == null)
  203. // {
  204. // Thread.Sleep(1000);
  205. // continue;
  206. // }
  207. // msg.start = ZPosition;
  208. // ReadFromPLC(ref msg);
  209. // ZPositionValue = BitConverter.ToInt16(msg.value.ToArray(), 0);
  210. // msg.start = ZStart;
  211. // ReadFromPLC(ref msg);
  212. // ZStartValue = BitConverter.ToInt16(msg.value.ToArray(), 0);
  213. // msg.start = ZStop;
  214. // ReadFromPLC(ref msg);
  215. // ZStopValue = BitConverter.ToInt16(msg.value.ToArray(), 0);
  216. // msg.start = ZPause;
  217. // ReadFromPLC(ref msg);
  218. // ZPauseValue = BitConverter.ToInt16(msg.value.ToArray(), 0);
  219. // //Console.WriteLine("position, start, stop, pause: " + ZPositionValue + ", " + ZStartValue + ", " + ZStopValue + ", " + ZPauseValue);
  220. // if (ZPauseValue == 1)
  221. // {
  222. // Pause();
  223. // //Console.WriteLine("暂停");
  224. // }
  225. // else
  226. // {
  227. // Pause();
  228. // //Console.WriteLine("恢复");
  229. // }
  230. // //收到开始下降信号
  231. // if (ZStartValue == 1 && ZStopValue != 1)
  232. // {
  233. // startGoingDown = true;
  234. // //Console.WriteLine("下降过程");
  235. // }
  236. // else
  237. // {
  238. // startGoingDown = false;
  239. // //Console.WriteLine("非下降过程");
  240. // }
  241. // //进入下降阶段
  242. // if (startGoingDown && ZPositionValue > ZThreshold)
  243. // {
  244. // if (!laserWorking)
  245. // {
  246. // Console.WriteLine("启动雷达");
  247. // //Start();
  248. // laserWorking = true;
  249. // }
  250. // }
  251. // //下降结束复位工作状态
  252. // if (laserWorking && ZStopValue == 1)
  253. // {
  254. // Console.WriteLine("雷达工作结束");
  255. // laserWorking = false;
  256. // }
  257. // if (laserWorking)
  258. // {
  259. // MsgNode writeMsg = new MsgNode();
  260. // writeMsg.db = 41;
  261. // writeMsg.length = 2;
  262. // writeMsg.start = 60;
  263. // byte[] temp = { 0, 0 };
  264. // if (obstacleDetected)
  265. // temp[1] = 1;
  266. // WriteToPLC(writeMsg);
  267. // }
  268. // sw.Stop();
  269. // Console.WriteLine("PLC: " + sw.ElapsedMilliseconds + "ms");
  270. // Thread.Sleep(1000);
  271. // }
  272. // });
  273. //}
  274. }
  275. /// <summary>
  276. /// 暂停雷达数据处理线程
  277. /// </summary>
  278. private void Pause()
  279. {
  280. if (laserLeft != null)
  281. {
  282. laserLeft.Pause();
  283. }
  284. if (laserRight != null)
  285. {
  286. laserRight.Pause();
  287. }
  288. }
  289. /// <summary>
  290. /// 停止获取雷达数据,断开连接
  291. /// </summary>
  292. private void Stop()
  293. {
  294. if (laserLeft != null)
  295. {
  296. laserLeft.Stop();
  297. }
  298. if (laserRight != null)
  299. {
  300. laserRight.Stop();
  301. }
  302. }
  303. public obstacleDetectionForm()
  304. {
  305. InitializeComponent();
  306. Start();
  307. }
  308. //界面按钮
  309. private void button1_Click(object sender, EventArgs e)
  310. {
  311. Start();
  312. }
  313. private void button3_Click(object sender, EventArgs e)
  314. {
  315. Pause();
  316. }
  317. private void button2_Click(object sender, EventArgs e)
  318. {
  319. Stop();
  320. //isok = true;
  321. //for (int i = 0; i < validdatalist.Count; i++)
  322. //{
  323. // string temp = validdatalist[i];
  324. // string[] tempdata = temp.Split(' ');
  325. // for (int j = 0; j < tempdata.Length; j++)
  326. // {
  327. // Log.WriteData("data" + i, tempdata[j]);
  328. // }
  329. //}
  330. //datalist.Clear();
  331. //flag = sendCmd(endCmd);
  332. //Environment.Exit(0);
  333. //this.Close();
  334. }
  335. /// <summary>
  336. /// 初始化图表
  337. /// </summary>
  338. private void InitChart()
  339. {
  340. //定义图表区域
  341. this.laserDataChart.ChartAreas.Clear();
  342. ChartArea chartArea1 = new ChartArea("C1");
  343. this.laserDataChart.ChartAreas.Add(chartArea1);
  344. //定义存储和显示点的容器
  345. this.laserDataChart.Series.Clear();
  346. //Series series1 = new Series("S1");
  347. //series1.ChartArea = "C1";
  348. //Series series2 = new Series("S2");
  349. //series2.ChartArea = "C1";
  350. //this.laserDataChart.Series.Add(series1);
  351. //this.laserDataChart.Series.Add(series2);
  352. //this.chart1.
  353. //设置图表显示样式
  354. this.laserDataChart.ChartAreas[0].AxisY.IsReversed = true;
  355. this.laserDataChart.ChartAreas[0].AxisY.Minimum = 0;
  356. this.laserDataChart.ChartAreas[0].AxisY.Maximum = max_axis_Y;
  357. this.laserDataChart.ChartAreas[0].AxisY.Interval = 50;
  358. this.laserDataChart.ChartAreas[0].AxisX.Minimum = -2500;// -200;
  359. this.laserDataChart.ChartAreas[0].AxisX.Maximum = 2500;// 200;
  360. this.laserDataChart.ChartAreas[0].AxisX.Interval = 100;// 100;
  361. this.laserDataChart.ChartAreas[0].AxisX.MajorGrid.LineColor = System.Drawing.Color.Silver;
  362. this.laserDataChart.ChartAreas[0].AxisY.MajorGrid.LineColor = System.Drawing.Color.Silver;
  363. this.laserDataChart.ChartAreas[0].AxisY.Title = "Y";
  364. this.laserDataChart.ChartAreas[0].AxisX.Title = "X";
  365. //this.chart1.ChartAreas[0].AxisX.ArrowStyle = AxisArrowStyle.Triangle;
  366. //this.chart1.ChartAreas[0].AxisY.ArrowStyle = AxisArrowStyle.Triangle;
  367. //设置标题
  368. this.laserDataChart.Titles.Clear();
  369. this.laserDataChart.Titles.Add("S01");
  370. this.laserDataChart.Titles[0].Text = "雷达显示";
  371. this.laserDataChart.Titles[0].ForeColor = Color.RoyalBlue;
  372. this.laserDataChart.Titles[0].Font = new System.Drawing.Font("Microsoft Sans Serif", 12F);
  373. ////设置图表显示样式
  374. //this.laserDataChart.Series[0].Color = Color.Red;
  375. //this.laserDataChart.Series[0].ChartType = SeriesChartType.Line;
  376. //this.laserDataChart.Series[1].Color = Color.Blue;
  377. //this.laserDataChart.Series[1].ChartType = SeriesChartType.Line;
  378. ////List<double> dis = lineFit3(listy);
  379. //for (int i = left_range; i < right_range; i++)
  380. //{
  381. // //this.chart1.Series[0].Points.AddXY(listx[i], max_axis_Y - listy[i - left_range]);//listy[i - left_range]
  382. // //this.chart1.Series[1].Points.AddXY(listx[i], max_axis_Y - templisty[i - left_range]);
  383. // this.laserDataChart.Series[0].Points.AddXY(listx[i], listy[i - left_range]);//listy[i - left_range]
  384. // this.laserDataChart.Series[1].Points.AddXY(listx[i], templisty[i - left_range]);
  385. //}
  386. }
  387. /// <summary>
  388. /// 向图表中增加数据
  389. /// </summary>
  390. /// <param name="listx">x轴数据</param>
  391. /// <param name="listys">y轴数据包</param>
  392. /// <param name="laserIndex">雷达编号</param>
  393. public void chartAddData(List<double> listx, List<List<double>> listys, int laserIndex)
  394. {
  395. if (laserIndex != 1 && laserIndex != 2)
  396. return;
  397. int index = laserDataChart.Series.Count;
  398. for (int i = 0; i < listys.Count; i++)
  399. {
  400. Series series = new Series("S" + index+i);
  401. series.ChartArea = "C1";
  402. laserDataChart.Series.Add(series);
  403. laserDataChart.Series[index + i].Color = Color.FromName(colors[index + i]);
  404. laserDataChart.Series[index + i].ChartType = SeriesChartType.Line;
  405. int left = 0;
  406. int right = 0;
  407. if (laserIndex == 1)
  408. {
  409. left = laserLeft.GetLeftRange("index");
  410. right = laserLeft.GetRightRange("index");
  411. }
  412. else
  413. {
  414. left = laserRight.GetLeftRange("index");
  415. right = laserRight.GetRightRange("index");
  416. }
  417. if (listx != null && listys[i] != null && listx.Count >= right && listys[i].Count >= right - left)
  418. {
  419. for (int j = left; j < right; j++)
  420. {
  421. laserDataChart.Series[index + i].Points.AddXY(listx[j], listys[i][j - left]);
  422. }
  423. }
  424. dataDispList.Add(new DispMsg(laserDataChart.Series[index + i], left, right, listx, listys[i]));
  425. }
  426. }
  427. /// <summary>
  428. /// 更新图表数据
  429. /// </summary>
  430. /// <param name="listx"></param>
  431. /// <param name="listys"></param>
  432. /// <param name="laserIndex"></param>
  433. public void updateChartData(List<double> listx, List<double> listy, int index)
  434. {
  435. try
  436. {
  437. dataDispList[index].series.Points.Clear();
  438. for (int j = dataDispList[index].left; j < dataDispList[index].right; j++)
  439. {
  440. if (listx != null && listy != null && listx.Count >= dataDispList[index].right && listy.Count >= dataDispList[index].right - dataDispList[index].left)
  441. {
  442. //Console.WriteLine(listx.Count + ", " + listy.Count + ", " + j + ", " + dataDispList[index].left);
  443. double x = listx[j];
  444. double y = listy[j - dataDispList[index].left];
  445. //dataDispList[index].series.Points.AddXY(listx[j], listy[j-dataDispList[index].left]);
  446. dataDispList[index].series.Points.AddXY(x, y);
  447. }
  448. }
  449. }
  450. catch(Exception e) { Console.WriteLine(e.StackTrace); }
  451. }
  452. ///// <summary>
  453. ///// 线性拟合
  454. ///// </summary>
  455. ///// <param name="x"></param>
  456. ///// <param name="y"></param>
  457. ///// <returns></returns>
  458. //private static List<double> lineFit(List<double> x, List<double> y)
  459. //{
  460. // double a, b, c;
  461. // int size = x.Count;
  462. // if (size < 2)
  463. // {
  464. // a = 0;
  465. // b = 0;
  466. // c = 0;
  467. // return null;
  468. // }
  469. // double x_mean = 0;
  470. // double y_mean = 0;
  471. // for (int i = 0; i < size; i++)
  472. // {
  473. // x_mean += x[i];
  474. // y_mean += y[i];
  475. // }
  476. // x_mean /= size;
  477. // y_mean /= size; //至此,计算出了 x y 的均值
  478. // double Dxx = 0, Dxy = 0, Dyy = 0;
  479. // for (int i = 0; i < size; i++)
  480. // {
  481. // Dxx += (x[i] - x_mean) * (x[i] - x_mean);
  482. // Dxy += (x[i] - x_mean) * (y[i] - y_mean);
  483. // Dyy += (y[i] - y_mean) * (y[i] - y_mean);
  484. // }
  485. // double lambda = ((Dxx + Dyy) - Math.Sqrt((Dxx - Dyy) * (Dxx - Dyy) + 4 * Dxy * Dxy)) / 2.0;
  486. // double den = Math.Sqrt(Dxy * Dxy + (lambda - Dxx) * (lambda - Dxx));
  487. // a = Dxy / den;
  488. // b = (lambda - Dxx) / den;
  489. // c = -a * x_mean - b * y_mean;
  490. // Console.WriteLine(a + " " + b + " " + c);
  491. // dis = new List<double>();
  492. // errorIndex.Clear();
  493. // for (int i = 0; i < size; i++)
  494. // {
  495. // if (y[i] < (-a * x[i] - c) / b)
  496. // {
  497. // double d = Math.Abs(a * x[i] + b * y[i] + c) / Math.Sqrt(a * a + b * b);
  498. // if (d > 40)
  499. // {
  500. // dis.Add(d);
  501. // errorIndex.Add(i);
  502. // }
  503. // //Log.WriteLog(LogType.PROCESS, d + "");
  504. // }
  505. // }
  506. // return dis;
  507. //}
  508. //private static List<double> lineFit2(List<double> y)
  509. //{
  510. // double b;
  511. // int size = y.Count;
  512. // if (size < 2)
  513. // {
  514. // b = 0;
  515. // return null;
  516. // }
  517. // double sum = 0;
  518. // for(int i = 0; i < size; i++)
  519. // {
  520. // sum += y[i];
  521. // }
  522. // b = sum / size;
  523. // dis = new List<double>();
  524. // errorIndex.Clear();
  525. // for (int i = 0; i < size; i++)
  526. // {
  527. // if (y[i] < b)
  528. // {
  529. // double d = Math.Abs(y[i] - b);
  530. // if (d > 40)
  531. // {
  532. // dis.Add(d);
  533. // errorIndex.Add(i);
  534. // }
  535. // }
  536. // }
  537. // return dis;
  538. //}
  539. ///// <summary>
  540. ///// 是否有障碍物
  541. ///// </summary>
  542. ///// <param name="testdata"></param>
  543. ///// <param name="deviation"></param>
  544. ///// <returns></returns>
  545. //private static List<double> lineFit3(List<double> y)
  546. //{
  547. // double b;
  548. // int size = y.Count;
  549. // if (size < 2)
  550. // {
  551. // b = 0;
  552. // return null;
  553. // }
  554. // double sum = 0;
  555. // for (int i = left_range; i < right_range; i++)
  556. // {
  557. // sum += y[i];
  558. // }
  559. // b = sum / (right_range - left_range);
  560. // dis = new List<double>();
  561. // errorIndex.Clear();
  562. // for (int i = left_range; i < right_range; i++)
  563. // {
  564. // double d = Math.Abs(y[i] - b);
  565. // if (d > 20)
  566. // {
  567. // double y_update = 0;
  568. // dis.Add(y_update);
  569. // errorIndex.Add(i);
  570. // }
  571. // else
  572. // {
  573. // dis.Add(y[i]);
  574. // }
  575. // }
  576. // return dis;
  577. //}
  578. //private static bool IsHinder(List<double> testdata, double deviation)
  579. //{
  580. // bool isHinder = true;
  581. // //Data errordata = new Data();
  582. // List<int> recorddata = new List<int>();
  583. // for (int i = 0; i < testdata.Count; i++)
  584. // {
  585. // if (testdata[i] > deviation)
  586. // {
  587. // //errordata.key = i;
  588. // //errordata.value = testdata[i];
  589. // //Console.WriteLine(i + " " + testdata[i]);
  590. // recorddata.Add(i);
  591. // }
  592. // }
  593. // if (recorddata.Count <= 5 || IsBorderUpon(recorddata, 10) < 1)
  594. // {
  595. // isHinder = false;
  596. // }
  597. // return isHinder;
  598. //}
  599. ///// <summary>
  600. ///// 连续判断
  601. ///// </summary>
  602. ///// <param name="arr"></param>
  603. ///// <param name="num"></param>
  604. ///// <returns></returns>
  605. //private static int IsBorderUpon(List<int> arr, int num)
  606. //{
  607. // var query = arr.OrderBy(p => p).Aggregate<int, List<List<int>>>(null, (m, n) =>
  608. // {
  609. // if (m == null) return new List<List<int>>() { new List<int>() { n } };
  610. // if (m.Last().Last() != n - 1)
  611. // {
  612. // m.Add(new List<int>() { n });
  613. // }
  614. // else
  615. // {
  616. // m.Last().Add(n);
  617. // }
  618. // return m;
  619. // });
  620. // int flag = 0;
  621. // for (int i = 0; i < query.Count; i++)
  622. // {
  623. // if (query[i].Count > 5)
  624. // {
  625. // flag++;
  626. // }
  627. // }
  628. // return flag;
  629. //}
  630. //********************** PLC ****************************
  631. /// <summary>
  632. /// 连接PLC
  633. /// </summary>
  634. /// <returns></returns>
  635. private bool PLCConnect()
  636. {
  637. closed = false;
  638. writeThread = new Thread(() =>
  639. {
  640. //Stopwatch stopwatch = new Stopwatch();
  641. while (!closed)
  642. {
  643. //stopwatch.Restart();
  644. bool result = WriteAccordingly();
  645. if (!result)
  646. Console.WriteLine("写PLC操作异常");
  647. Thread.Sleep(1000 / writeFreq);
  648. //stopwatch.Stop();
  649. //Console.WriteLine(stopwatch.ElapsedMilliseconds / 1000.0f);
  650. }
  651. });
  652. writeThread.IsBackground = true;
  653. writeThread.Priority = ThreadPriority.AboveNormal;
  654. writeThread.Start();
  655. if (plc == null)
  656. {
  657. plc = new Plc(cpu, ip, rack, slot);
  658. }
  659. if (plc != null)
  660. {
  661. ErrorCode err = plc.Open();
  662. if (err != ErrorCode.NoError) { Console.WriteLine("connection error"); isConnected = false; }
  663. else { Console.WriteLine("connected"); isConnected = true; }
  664. }
  665. else { isConnected = false; }
  666. return isConnected;
  667. }
  668. /// <summary>
  669. /// 关闭PLC连接
  670. /// </summary>
  671. private void PLCDisconnect()
  672. {
  673. //try
  674. //{
  675. // if (writeThread != null)
  676. // writeThread.Abort();
  677. //}
  678. //catch (Exception ex) { Console.WriteLine("强制终止写PLC线程," + ex.Message); }
  679. closed = true;
  680. if (plc != null)
  681. {
  682. plc.Close();
  683. }
  684. }
  685. /// <summary>
  686. /// 从阻塞队列获取需写入PLC数据并写入PLC,时间间隔在线程中控制
  687. /// </summary>
  688. /// <returns></returns>
  689. private bool WriteAccordingly()
  690. {
  691. MsgNode msg = null;
  692. try
  693. {
  694. msg = writingBlockingCollection.Take();
  695. //Console.WriteLine("取出后," + writingBlockingCollection.Count);
  696. }
  697. catch (Exception ex) { Console.WriteLine("获取PLC写对象异常," + ex.Message); }
  698. if (msg == null || !msg.valid)
  699. {
  700. Console.WriteLine("msg is null or invalid");
  701. return false;
  702. }
  703. //更新设备状态
  704. isConnected = plc.IsConnected;
  705. if (isConnected)
  706. {
  707. lock (readWriteLock)
  708. {
  709. plc.WriteBytes(DataType.DataBlock, msg.db, msg.start, msg.value.ToArray());
  710. }
  711. }
  712. else { Console.WriteLine("掉线"); return false; }
  713. return true;
  714. }
  715. /// <summary>
  716. /// 读取PLC数据块
  717. /// </summary>
  718. /// <param name="whichToRead"></param>
  719. /// <param name="index"></param>
  720. /// <returns></returns>
  721. private void ReadFromPLC(ref MsgNode msg)
  722. {
  723. //更新设备状态
  724. isConnected = plc.IsConnected;
  725. List<object> result = new List<object>();
  726. if (!isConnected)
  727. {
  728. PLCConnect();
  729. }
  730. if (isConnected)
  731. {
  732. lock (readWriteLock)
  733. {
  734. msg.value = plc.ReadBytes(DataType.DataBlock, msg.db, msg.start, msg.length).ToList();
  735. if (msg.value.Count != msg.length)
  736. {
  737. msg.valid = false;
  738. }
  739. msg.value.Reverse();
  740. }
  741. }
  742. }
  743. /// <summary>
  744. /// 写入PLC,只支持1,2或4字节
  745. /// </summary>
  746. /// <param name="abstractPLCMsg"></param>
  747. /// <param name="whoami"></param>
  748. /// <returns></returns>
  749. private bool WriteToPLC(MsgNode msg)
  750. {
  751. //更新设备状态
  752. isConnected = plc.IsConnected;
  753. if (msg != null && isConnected)
  754. {
  755. msg.value.Reverse();
  756. writingBlockingCollection.Add(msg);
  757. //Console.WriteLine("加入后," + writingBlockingCollection.Count);
  758. return true;
  759. }
  760. else
  761. return false;
  762. }
  763. public class MsgNode : ICloneable
  764. {
  765. public int db;
  766. public int start;
  767. public int length;
  768. public List<byte> value;
  769. public bool valid;
  770. public MsgNode(int db, int start, int length, List<byte> value)
  771. {
  772. this.db = db;
  773. this.start = start;
  774. this.length = length;
  775. if (value != null && value.Count != length)
  776. {
  777. valid = false;
  778. }
  779. else
  780. {
  781. valid = true;
  782. }
  783. this.value = value;
  784. }
  785. public MsgNode() : this(0, 0, 0, new List<byte>())
  786. {
  787. }
  788. public object Clone()
  789. {
  790. MsgNode obj = new MsgNode();
  791. obj.db = db;
  792. obj.start = start;
  793. obj.length = length;
  794. obj.value = new List<byte>(value);
  795. obj.valid = valid;
  796. return obj;
  797. }
  798. }
  799. public class DispMsg
  800. {
  801. public Series series;
  802. public int left;
  803. public int right;
  804. public List<double> x;
  805. public List<double> y;
  806. public DispMsg(Series series, int left, int right, List<double> x, List<double> y)
  807. {
  808. this.series = series;
  809. this.left = left;
  810. this.right = right;
  811. this.x = x;
  812. this.y = y;
  813. }
  814. }
  815. }
  816. }