上位機程序控制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();
}
}
}
