正如标题所述,我需要帮助编写一个可以连接到PVI和另一个程序的程序(我不确定是否可以与以前这样的程序建立通信由原始机器制造商撰写,我将在需要时提供尽可能多的细节。)然后,这将将信息从PLC交换到正在运行的程序,并允许冻结该程序的框架并采用屏幕截图以及之后将其解冻。
我将包含我到目前为止使用贝加莱提供的培训手册编写的代码,这仅仅是为了建立与PVI和PLC上运行的自动化工作室程序的连接。
这是一本过时的培训手册,但这是我可用于解决此问题的唯一信息来源。 我编写的程序确实可以编译并运行,似乎确实连接了我连接到笔记本电脑的PLC,以及在没有PLC的情况下运行仿真程序。但是,它不会从程序中读取数据,因为培训手册说明它会读取我在Automation Studio中所做的某些变量的值。
此外,当尝试单击我所做的任何按钮时,我会说实话,我不是100%肯定他们应该做什么,这会给我一个错误(System.NullReferenceException: 'Object reference not set to an instance of an object.' myStructPV was null.)
。
我以为是要告诉我,按下按钮时使用的变量为null,但是这些变量是PVI服务名称空间的一部分,我不确定在初始化时会给它们提供什么值。
如果这没有太大意义,我会道歉,因为我提到我在开发方面是一个新手,并且自从大学毕业以来就没有使用过Visual Studio或C#。
非常感谢您的任何建议或帮助。
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 BR.AN.PviServices;
namespace PVITestApp
{
public partial class Form1 : Form
{
public Service myService;
public Cpu myCpu;
public BR.AN.PviServices.Task myTask;
public Variable myVariable;
public Module myModule;
public Variable myVariablePV1;
public Variable myStructPV;
public Form1()
{
InitializeComponent();
// txtStatus.Text = "text box is functioning!";
}
private void MyStructPV_Error(object sender, PviEventArgs e)
{
throw new NotImplementedException();
}
private void MyStructPV_ValueChanged(object sender, VariableEventArgs e)
{
throw new NotImplementedException();
}
private void Form1_Load(object sender, EventArgs e)
{
myService = new Service("service");
myService.Connected += MyService_Connected;
myService.IsStatic = true;
myService.Connect();
}
private void MyService_Connected(object sender, PviEventArgs e)
{
this.txtStatus.Text += "Service Connected\r\n";
if (myCpu == null)
{
myCpu = new Cpu(myService, "cpu");
//myCpu.Connection.DeviceType = BR.AN.PviServices.DeviceType.TcpIp;
myCpu.Connection.DeviceType = DeviceType.TcpIp;
myCpu.Connection.TcpIp.DestinationStation = 2;
myCpu.Connection.TcpIp.DestinationPort = 11160;
myCpu.Connection.TcpIp.DestinationIpAddress = "192.168.0.1";
//myCpu.Connection.TcpIp.DestinationIpAddress = "127.0.0.1";
myCpu.Connected += MyCpu_Connected;
myCpu.Error += MyCpu_Error;
myCpu.Connect(ConnectionType.CreateAndLink);
// maybe need to use this one - myCpu.Connect(ConnectionType.Create);
}
// throw new NotImplementedException();
}
private void MyCpu_Error(object sender, PviEventArgs e)
{
this.txtStatus.Text += e.Name + " Error:" + e.ErrorCode + "\r\n";
// throw new NotImplementedException(txtStatus.Text = "Error connecting.");
}
private void MyCpu_Connected(object sender, PviEventArgs e)
{
this.txtStatus.Text += "CPU Connected\r\n";
myTask = new BR.AN.PviServices.Task(myCpu, "pvitest");
myTask.Connected += MyTask_Connected;
myTask.Error += MyTask_Error;
myTask.Connect();
//throw new NotImplementedException();
}
private void MyTask_Error(object sender, PviEventArgs e)
{
this.txtStatus.Text += e.Name + " Error:" + e.ErrorCode + "\r\n";
//throw new NotImplementedException();
}
private void MyTask_Connected(object sender, PviEventArgs e)
{
this.txtStatus.Text += "Task " + e.Name + " Connected\r\n";
if (myVariable == null)
{
myVariable = new Variable(myTask, "Lifesign");
myVariable.Active = true;
myVariable.RefreshTime = 200;
myVariable.ValueChanged += MyVariable_ValueChanged;
myVariable.Error += MyVariable_Error;
myVariable.Connect();
}
if (myVariablePV1 == null)
{
myVariablePV1 = new Variable(myTask, "VarCreateOnly");
myVariablePV1.Address = "PV1";
myVariablePV1.Connect(ConnectionType.Create);
}
// throw new NotImplementedException();
}
private void MyVariable_Error(object sender, PviEventArgs e)
{
txtStatus.Text += e.Name + " E#" + e.ErrorCode.ToString();
//throw new NotImplementedException();
}
private void MyVariable_ValueChanged(object sender, VariableEventArgs e)
{
if (myStructPV == null) //PG35 stuff may need to move
{
myStructPV = new Variable(myTask, "Pv_Struct");
myStructPV.Active = true;
myStructPV.RefreshTime = 1000;
myStructPV.ValueChanged += MyStructPV_ValueChanged;
myStructPV.Error += MyStructPV_Error;
myStructPV.Connect();
}
// /\ above may need to be moved back.
if (e.Name == "Lifesign")
{
lblValLifesign.Text = ((Variable)sender).Value.ToString();
}
if (e.Name == "linkVarPV1")
{
lblPV1.Text = ((Variable)sender).Value.ToString();
}
Variable tmpVar = (Variable)sender; //PG 36 - 37
if(e.Name == "Pv_Struct")
{
if (tmpVar.Value.DataType == DataType.Structure)
{
foreach (Variable member in tmpVar.Members.Values)
{
txtStatus.Text += member.Value.ToString() + "\r\n";
}
}
}
foreach (String membername in e.ChangedMembers)
{
if (membername != null)
{
txtStatus.Text += tmpVar.Value[membername].ToString() + "\r\n";
}
}
//throw new NotImplementedException();
}
private void CmdConnectPV1_Click(object sender, EventArgs e)
{
Variable myLinkPV1 = new Variable(myVariable, "linkVarPV1");
myLinkPV1.LinkName = myVariablePV1.FullName;
myLinkPV1.Active = true;
myLinkPV1.ValueChanged += MyLinkPV1_ValueChanged;
myLinkPV1.Error += MyLinkPV1_Error;
myLinkPV1.Connect(ConnectionType.Link);
}
private void MyLinkPV1_Error(object sender, PviEventArgs e)
{
//throw new NotImplementedException();
}
private void MyLinkPV1_ValueChanged(object sender, VariableEventArgs e)
{
// throw new NotImplementedException();
}
private void CmdReadVar_Click(object sender, EventArgs e)
{
myVariable.ValueRead += MyVariable_ValueRead;
myVariable.ReadValue();
}
private void MyVariable_ValueRead(object sender, PviEventArgs e)
{
this.lblReadVar.Text = ((Variable)sender).Value.ToString();
//throw new NotImplementedException();
}
private void CmdReadTime_Click(object sender, EventArgs e)
{
myCpu.DateTimeRead += MyCpu_DateTimeRead;
myCpu.ReadDateTime();
}
private void MyCpu_DateTimeRead(object sender, CpuEventArgs e)
{
DateTime dt;
dt = e.DateTime;
this.Text = dt.ToString();
//throw new NotImplementedException();
}
private void CmdWriteVal_Click(object sender, EventArgs e)
{
myVariable.Value = 0;
myVariable.ValueWritten += MyVariable_ValueWritten;
}
private void MyVariable_ValueWritten(object sender, PviEventArgs e)
{
//throw new NotImplementedException();
}
private void CmdSetStruct_Click(object sender, EventArgs e)
{
myStructPV.WriteValueAutomatic = false;
myStructPV.Value["Member1"] = 10;
myStructPV.Value["Member2"] = 20;
myStructPV.Value["Member3"] = myVariable.Value;
myStructPV.WriteValue();
}
}
}
答案 0 :(得分:0)
myStructPV
为空,因为您正在调用CmdSetStruct_Click()
而不创建myStructPV
。您需要MyVariable_ValueChanged()
首先运行,或者至少将其中创建myStructPV
的代码放入CmdSetStruct_Click()
。
只要在运行初始化程序时进入状态“ Task pvitest Connected”,那么所有PVI连接都可以正常工作(如果您的PLC上没有名为pvitest
的任务,但仍然可以到CPU Connected
,然后您就可以了)。您只需要调试与实际标签的连接即可。
就与OEM编写的现有Windows程序进行通信而言,这不太可能。您将不得不使用某种调试器来获取其内存,或者希望他们编写某种不太可能的API。
答案 1 :(得分:0)
我认为Isaac假设您在实际初始化myStruct Pv之前单击执行按钮CmdSetStruct_Click()
是正确的。
这可能是因为直到可以从Lifebit变量获取valueChanged
事件为止,您与PLC的连接才起作用。
您在PLC上的Lifebit变量可以是全局变量吗?很高兴看到VS的控制台输出能够查明问题,直到崩溃。
对于以PVI试用模式运行,这是正确的,它可能会给初始连接带来一些问题,但是在这种情况下,如果您只是停止PVI管理器并重新启动它,那应该没问题。
无论如何,我还是建议您只使用一种结构在PLC外部处理通讯。例如:
gComm.ToPlc.Status.someVariable
gComm.FromPlc.Cmd.startDoingSth
这样,您将只需要执行两次PVI变量连接过程。一次连接到ToPlc结构,一次连接到FromPlc结构。这样,您的代码将更容易管理。
最后,您可以使用变量的onConnected
事件而不是valueChanged
。这样,在允许您的应用继续运行之前,您可以等待直到在变量上获得有效连接并捕获从变量连接引发的错误并优雅地处理它们。这样可以防止您的应用崩溃。