上位機程序控制PLC模擬量通道輸出周期性正弦波信號,並采集所造成改變的模擬量輸入信號,並繪制數據變化曲線。
界面如圖:
最后測試效果如圖:
代碼:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using ZedGraph; namespace ProfessionalTest { public partial class FrMain : Form { #region 構造函數 int tickStart = 0; int tickStart2 = 0; int zQ1 = 0; int zQ2 = 0; int fZ1 = 0; int fZ2 = 0; int pY1 = 0; int pY2 = 0; public FrMain() { InitializeComponent(); this.ControlBox = false; } #endregion /// <summary> /// 窗體加載對兩個表進行初始化 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void FrMain_Load(object sender, EventArgs e) { //無需油源流量壓力設置,油源手動控制 //OPC.OpcServer server = OPC.OpcServer.GetServer(); ///一個PC ACCESS 即為一個OPC server //server["油源"]["專業台當前流量"] = (float)50; //server["油源"]["專業台當前壓力"] = (float)10; #region 負載模擬1 //獲取引用 GraphPane myPane = zedGraphControl1.GraphPane; //設置標題 myPane.Title.Text = "負載模擬1"; //設置X軸說明文字 myPane.XAxis.Title.Text = "時間"; //設置Y軸說明文字 myPane.YAxis.Title.Text = "給定壓力/實測壓力"; //設置1200個點,假設每50毫秒更新一次,剛好檢測1分鍾,一旦構造后將不能更改這個值 RollingPointPairList list = new RollingPointPairList(1200); RollingPointPairList list2 = new RollingPointPairList(1200); //開始,增加的線是沒有數據點的(也就是list為空) //增加一條名稱:Voltage,顏色Color.Bule,無符號,無數據的空線條 LineItem curve = myPane.AddCurve("給定壓力", list, Color.Blue, SymbolType.None); LineItem curve2 = myPane.AddCurve("實際壓力", list2, Color.Red, SymbolType.None); timerDraw.Interval = 1000; //設置timer控件的間隔為500毫秒 timerDraw.Enabled = true; //timer可用 timerDraw.Stop(); //開始 myPane.XAxis.Scale.Min = 0; //X軸最小值0 myPane.XAxis.Scale.Max = 30; //X軸最大30 myPane.XAxis.Scale.MinorStep = 1;//X軸小步長1,也就是小間隔 myPane.XAxis.Scale.MajorStep = 5;//X軸大步長為5,也就是顯示文字的大間隔 //改變軸的刻度 zedGraphControl1.AxisChange(); //保存開始時間 //tickStart = Environment.TickCount; #endregion #region 負載模擬2 //獲取引用 GraphPane myPane1 = zedGraphControl2.GraphPane; //設置標題 myPane1.Title.Text = "負載模擬2"; //設置X軸說明文字 myPane1.XAxis.Title.Text = "時間"; //設置Y軸說明文字 myPane1.YAxis.Title.Text = "給定壓力/實測壓力"; //設置1200個點,假設每50毫秒更新一次,剛好檢測1分鍾,一旦構造后將不能更改這個值 RollingPointPairList list3 = new RollingPointPairList(1200); RollingPointPairList list4 = new RollingPointPairList(1200); //開始,增加的線是沒有數據點的(也就是list為空) //增加一條名稱:Voltage,顏色Color.Bule,無符號,無數據的空線條 LineItem curve3 = myPane1.AddCurve("給定壓力", list3, Color.Blue, SymbolType.None); LineItem curve4 = myPane1.AddCurve("實際壓力", list4, Color.Red, SymbolType.None); timer1Draw.Interval = 1000; //設置timer控件的間隔為500毫秒 timer1Draw.Enabled = true; //timer可用 timer1Draw.Stop(); //暫不啟動 myPane1.XAxis.Scale.Min = 0; //X軸最小值0 myPane1.XAxis.Scale.Max = 30; //X軸最大30 myPane1.XAxis.Scale.MinorStep = 1;//X軸小步長1,也就是小間隔 myPane1.XAxis.Scale.MajorStep = 5;//X軸大步長為5,也就是顯示文字的大間隔 //改變軸的刻度 zedGraphControl2.AxisChange(); //保存開始時間 //tickStart2 = Environment.TickCount; #endregion } /// <summary> /// 負載1模擬開始 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void button1_Click(object sender, EventArgs e) { try { zQ1 = int.Parse(textBox1.Text); fZ1 = int.Parse(textBox2.Text); pY1 = int.Parse(textBox5.Text); if (zQ1<=10) { MessageBox.Show("周期過小,請將周期設為10秒以上") ; return; } if (fZ1<=5) { MessageBox.Show("幅值過小,請將幅值設為5MPa以上"); return; } else if (fZ1>=15) { MessageBox.Show("幅值過大,請將幅值設為15MPa以下"); return; } if (pY1-fZ1 <0) { MessageBox.Show("壓力過小,請將壓力設為0MPa以上"); return; } else if (fZ1 +pY1> 31.5) { MessageBox.Show("壓力過大,請將壓力設為15MPa以下"); return; } button1.Enabled = false; timerDraw.Start(); //保存開始時間 tickStart = Environment.TickCount; #region 清空原有圖表 //確保CurveList不為空 if (zedGraphControl1.GraphPane.CurveList.Count <= 0) { return; } //取Graph第一個曲線,也就是第一步:在GraphPane.CurveList集合中查找CurveItem LineItem curve = zedGraphControl1.GraphPane.CurveList[0] as LineItem; LineItem curve2 = zedGraphControl1.GraphPane.CurveList[1] as LineItem; if (curve == null | curve2 == null) { return; } //第二步:在CurveItem中訪問PointPairList(或者其它的IPointList),根據自己的需要增加新數據或修改已存在的數據 IPointListEdit list = curve.Points as IPointListEdit; IPointListEdit list2 = curve2.Points as IPointListEdit; list.Clear(); list2.Clear(); //第三步:調用Form.Invalidate()方法更新圖表 zedGraphControl1.Invalidate(); #endregion } catch (Exception) { MessageBox.Show("請輸入正確數值"); } } /// <summary> /// 負載2模擬開始 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void button2_Click(object sender, EventArgs e) { try { zQ2 = int.Parse(textBox3.Text); fZ2 = int.Parse(textBox4.Text); pY2 = int.Parse(textBox6.Text); if (zQ2 <= 10) { MessageBox.Show("周期過小,請將周期設為10秒以上"); return; } if (fZ2 <= 5) { MessageBox.Show("幅值過小,請將幅值設為5MPa以上"); return; } else if (fZ2 >= 15) { MessageBox.Show("幅值過大,請將幅值設為15MPa以下"); return; } if (pY2 - fZ2 < 0) { MessageBox.Show("壓力過小,請將壓力設為0MPa以上"); return; } else if (fZ2 + pY2 > 31.5) { MessageBox.Show("壓力過大,請將壓力設為15MPa以下"); return; } button2.Enabled = false; timer1Draw.Start(); //保存開始時間 tickStart2 = Environment.TickCount; #region 清空原有圖表 //確保CurveList不為空 if (zedGraphControl2.GraphPane.CurveList.Count <= 0) { return; } //取Graph第一個曲線,也就是第一步:在GraphPane.CurveList集合中查找CurveItem LineItem curve3 = zedGraphControl2.GraphPane.CurveList[0] as LineItem; LineItem curve4 = zedGraphControl2.GraphPane.CurveList[1] as LineItem; if (curve3 == null | curve4 == null) { return; } //第二步:在CurveItem中訪問PointPairList(或者其它的IPointList),根據自己的需要增加新數據或修改已存在的數據 IPointListEdit list3 = curve3.Points as IPointListEdit; IPointListEdit list4 = curve4.Points as IPointListEdit; if (list3 == null | list4 == null) { return; } list3.Clear(); list4.Clear(); //第三步:調用Form.Invalidate()方法更新圖表 zedGraphControl2.Invalidate(); #endregion } catch (Exception) { MessageBox.Show("請輸入正確數值"); } } /// <summary> /// 負載1模擬停止 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void button3_Click(object sender, EventArgs e) { timerDraw.Enabled = false; timerDraw.Stop(); button1.Enabled = true; OPC.OpcServer server = OPC.OpcServer.GetServer(); server["專業試驗台"]["比例溢流閥4_1模擬緩存"] = (float)0;//寫入壓力0 } /// <summary> /// 負載2模擬停止 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void button4_Click(object sender, EventArgs e) { timer1Draw.Enabled = false; timer1Draw.Stop(); button2.Enabled = true; OPC.OpcServer server = OPC.OpcServer.GetServer(); server["專業試驗台"]["比例溢流閥4_2模擬緩存"] = (float)0;//寫入壓力0 } /// <summary> /// 負載模擬1表格定時更新 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void timerDraw_Tick(object sender, EventArgs e) { //確保CurveList不為空 if (zedGraphControl1.GraphPane.CurveList.Count <= 0) { return; } //取Graph第一個曲線,也就是第一步:在GraphPane.CurveList集合中查找CurveItem LineItem curve = zedGraphControl1.GraphPane.CurveList[0] as LineItem; LineItem curve2 = zedGraphControl1.GraphPane.CurveList[1] as LineItem; if (curve == null | curve2 == null) { return; } //第二步:在CurveItem中訪問PointPairList(或者其它的IPointList),根據自己的需要增加新數據或修改已存在的數據 IPointListEdit list = curve.Points as IPointListEdit; IPointListEdit list2 = curve2.Points as IPointListEdit; if (list == null | list2 == null) { return; } // 時間用秒表示 double time = (Environment.TickCount - tickStart) / 1000.0; // 周期為zQ1,幅值為fZ1 OPC.OpcServer server = OPC.OpcServer.GetServer(); float gDYL = (float)(fZ1 * Math.Sin(2.0 * Math.PI * time / zQ1))+pY1;//給定壓力值 float sJYL = server["專業試驗台"]["負載模擬壓力緩存1_1"];//實際讀取壓力值 server["專業試驗台"]["比例溢流閥4_1模擬緩存"] = gDYL;//將周期值寫入PLC list.Add(time, (double)gDYL); list2.Add(time, (double)sJYL); Console.WriteLine(time.ToString()); Scale xScale = zedGraphControl1.GraphPane.XAxis.Scale; if (time > xScale.Max - xScale.MajorStep) { xScale.Max = time + xScale.MajorStep; xScale.Min = xScale.Max - 30.0; } //第三步:調用ZedGraphControl.AxisChange()方法更新X和Y軸的范圍 zedGraphControl1.AxisChange(); //第四步:調用Form.Invalidate()方法更新圖表 zedGraphControl1.Invalidate(); } /// <summary> /// 負載模擬2表格定時更新 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void timer1Draw_Tick(object sender, EventArgs e) { //確保CurveList不為空 if (zedGraphControl2.GraphPane.CurveList.Count <= 0) { return; } //取Graph第一個曲線,也就是第一步:在GraphPane.CurveList集合中查找CurveItem LineItem curve3 = zedGraphControl2.GraphPane.CurveList[0] as LineItem; LineItem curve4 = zedGraphControl2.GraphPane.CurveList[1] as LineItem; if (curve3 == null | curve4 == null) { return; } //第二步:在CurveItem中訪問PointPairList(或者其它的IPointList),根據自己的需要增加新數據或修改已存在的數據 IPointListEdit list3 = curve3.Points as IPointListEdit; IPointListEdit list4 = curve4.Points as IPointListEdit; if (list3 == null | list4 == null) { return; } // 時間用秒表示 double time = (Environment.TickCount - tickStart2) / 1000.0; // 周期為zQ2,幅值為fZ2 OPC.OpcServer server = OPC.OpcServer.GetServer(); float gDYL = (float)(fZ2 * Math.Sin(2.0 * Math.PI * time / zQ2))+pY2;//給定壓力值 float sJYL = server["專業試驗台"]["負載模擬壓力緩存1_2"];//實際讀取壓力值 server["專業試驗台"]["比例溢流閥4_2模擬緩存"] = gDYL;//將周期值寫入PLC list3.Add(time, gDYL); list4.Add(time, sJYL); Console.WriteLine(time.ToString()); Scale xScale = zedGraphControl2.GraphPane.XAxis.Scale; if (time > xScale.Max - xScale.MajorStep) { xScale.Max = time + xScale.MajorStep; xScale.Min = xScale.Max - 30.0; } //第三步:調用ZedGraphControl.AxisChange()方法更新X和Y軸的范圍 zedGraphControl2.AxisChange(); //第四步:調用Form.Invalidate()方法更新圖表 zedGraphControl2.Invalidate(); } /// <summary> /// 關閉窗體 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void button5_Click(object sender, EventArgs e) { OPC.OpcServer server = OPC.OpcServer.GetServer(); server["專業試驗台"]["比例溢流閥4_1模擬緩存"] = (float)0;//寫入壓力0 server["專業試驗台"]["比例溢流閥4_2模擬緩存"] = (float)0;//寫入壓力0 this.Close(); } } }