【问题标题】:Creating a program to establish connection to PLC through PVI and another program创建一个程序以通过 PVI 和另一个程序建立与 PLC 的连接
【发布时间】:2019-09-10 03:56:22
【问题描述】:

正如标题所说,我需要帮助编写将连接到 PVI 和另一个程序的程序我不确定是否可以与这样的程序建立通信原机器制造商编写它的屏幕截图以及之后解冻它。

我将包含到目前为止我使用 B&R 提供的培训手册编写的代码,这只是为了建立与 PVI 和在 PLC 上运行的自动化工作室程序的连接。

这是一个过时的培训手册,但它是我可用于解决此问题的唯一信息来源。 我编写的程序确实编译并运行它似乎确实与我连接到我的笔记本电脑的 PLC 建立了某种连接,以及在没有 PLC 的情况下运行模拟程序时。但是它不会从程序中读取数据,因为培训手册解释它会读取我在自动化工作室中制作的一些变量的值。

此外,当我尝试点击我制作的任何按钮时,老实说,我不能 100% 确定他们应该做什么,这会给我一个错误(System.NullReferenceException: 'Object reference not set to an instance of an object.' myStructPV was 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();
        }
    }
}

【问题讨论】:

  • 嗨@SandyOne,欢迎来到SO。你说的这个“PVI”的东西……是什么?这是某个产品的专有 SDK 吗?看来您的问题是针对这些库的,恐怕真的很难回答。从代码来看,如果 MyVariable_ValueChanged() 没有被首先调用,CmdSetStruct_Click() 似乎总是会失败,myStructPVnull
  • 嗨@istepaniuk PVI 代表过程可视化界面。基本上,用于为贝加莱 PLC 编写软件的程序自动化工作室使用 PVI 将编写的软件传输到 PLC 以及处理许多其他数据,例如变量。非常感谢您的回复。
  • 培训手册已过时,因为使用 PVI 已过时。您可能应该为此使用 OPC UA 或 Modbus(nModbus4 是一个很棒的库)。但是,PVI 确实具有向您显示 PLC 上的所有变量并允许您访问它们而无需对 PLC 代码执行任何操作的好处。听起来你的 PVI 通讯正常工作,只是你的 PLC 上实际上没有 C# 代码中使用的名称的变量。您的状态文本一直到 Task pvitest Connected?
  • 感谢艾萨克,我非常感谢您的反馈。我不知道如何使用 OPC UA 或 Modbus 来看看它。关于确实发生的任务 pvitest 连接,但我无法创建一致的连接(我有时会连接,有时无论我尝试什么都无法连接。)我认为这可能与我的 pvi 的事实有关许可证在试用模式下运行?

标签: c# automation


【解决方案1】:

myStructPV 为空,因为您在没有创建 myStructPV 的情况下调用 CmdSetStruct_Click()。您需要先运行MyVariable_ValueChanged(),或者至少将其中创建myStructPV 的代码放入CmdSetStruct_Click()

只要您在运行 init 内容时进入“Task pvitest Connected”状态,那么所有 PVI 连接都在工作(如果您的 PLC 上没有名为 pvitest 的任务,但仍然可以CPU Connected 那么你还可以)。您只需调试与实际标签的连接即可。

就与 OEM 编写的现有 Windows 程序进行通信而言,这不太可能。您必须使用某种调试器来获取它的内存,或者希望他们制作某种不太可能的 API。

【讨论】:

  • 非常感谢您,我一定会尝试的。为了检查它是否有效,我会尝试,但正如你提到的,与 OEM 创建的 Windows 程序进行通信是不可能的。我确实有他们之前创建的程序来执行此操作,但由于他们在运行此软件的 PC 上使用的操作系统发生了变化,它将不再在该 PC 上运行。我无法反编译他们制作的两个程序中的任何一个,所以我无法真正看到他们是如何做到这一点的。不过再次感谢您的回答。
【解决方案2】:

我认为 Isaac 假设您在实际初始化 myStruct Pv 之前单击了执行CmdSetStruct_Click() 的按钮是正确的。 这可能是因为您与 PLC 的连接无法正常工作,直到您能够从 Lifebit 变量中获取 valueChanged 事件。

PLC 上的 Lifebit 变量可以是全局变量吗?很高兴看到 VS 的控制台输出能够查明问题,直到它崩溃。

关于在 PVI 试用模式下运行你是对的,它可能会在初始连接时产生一些问题,但在这种情况下,如果你只是停止 PVI 管理器并重新启动它,应该一切都很好。

无论如何,我建议您只使用一个结构来处理 PLC 外部的通信。例如:

gComm.ToPlc.Status.someVariable
gComm.FromPlc.Cmd.startDoingSth

这样,您只需执行两次 PVI 变量连接过程。一次连接到 ToPlc 结构,一次连接到 FromPlc 结构。以这种方式管理您的代码会容易得多。

最后,您可以使用变量的onConnected 事件而不是valueChanged。这样,在您允许您的应用程序继续运行之前,您可以等到您在变量上获得有效连接并捕获从变量连接抛出的错误并优雅地处理它们。这样可以防止您的应用程序崩溃。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-12
    相关资源
    最近更新 更多