简体   繁体   English

创建一个程序以通过PVI和另一个程序建立与PLC的连接

[英]Creating a program to establish connection to PLC through PVI and another program

As the title says I need help writing a program that will connect to PVI and another program ( I am not sure if it is possible to establish communication with a program like this that was written by the original machine manufacturer I will provide as much detail as i can if needed on this. ) this will then exchange information from the PLC to the program running and allow freezing the frame of this program and taking screenshots of it as well as unfreezing it after . 正如标题所述,我需要帮助来编写将连接到PVI的程序和另一个程序我不确定是否可以与原始机器制造商编写的此类程序建立通信,我将提供尽可能多的详细信息如果需要,我可以。 )然后它将信息从PLC交换到正在运行的程序,并允许冻结该程序的框架,截取其屏幕截图以及在之后解冻

I will include the code that i have so far which I wrote using a training manual provided from B&R this is just to establish connection to PVI and the automation studio program running on a PLC. 我将使用贝加莱(B&R)提供的培训手册编写到目前为止所写的代码,这仅仅是为了建立与PVI和PLC上运行的自动化工作室程序的连接。

This is an outdated training manual but is the only source of information I have available for this problem. 这是一本过时的培训手册,但这是我可以解决此问题的唯一信息来源。 The program i wrote does compile and run it does seem to make something of a connection to a PLC that I have connected to my laptop as well as when running the simulation program without a PLC. 我编写的程序确实可以编译并运行,似乎确实可以连接到我连接到笔记本电脑的PLC上,也可以在没有PLC的情况下运行仿真程序。 However it does not read data from the program as the training manual explains it would read the values of some variables i have made in automation studio. 但是,它不会从程序中读取数据,因为培训手册说明它将读取我在Automation Studio中所做的某些变量的值。

Also when attempting to click on any of the buttons i made and i will be honest i am not 100% sure what they are even supposed to do it will give me an error (System.NullReferenceException: 'Object reference not set to an instance of an object.' myStructPV was null.) . 另外,当尝试单击我做出的任何按钮时,我会说实话,我不是100%肯定他们应该做什么,这会给我一个错误(System.NullReferenceException: 'Object reference not set to an instance of an object.' myStructPV was null.) Which i assume is trying to tell me that the variable that is being used when the button is pushed is null however these variables are part of the PVI services namespace and i am not sure what value you would give them in initialization. 我以为是要告诉我,按下按钮时使用的变量为null,但是这些变量是PVI服务名称空间的一部分,我不确定在初始化时会给它们提供什么值。

I do apologize if this does not make much sense as i mentioned i am quite new at developing and have not used Visual studio or C# since college way back. 如果这没有什么意义,我会道歉,因为我提到我在开发中是一个新手,自从大学毕业后就没有使用过Visual Studio或C#。

Any advice or help will be appreciated very much thank you. 非常感谢您的任何建议或帮助。

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();
        }
    }
}

myStructPV is null because you're calling CmdSetStruct_Click() without having created myStructPV . myStructPV为null,因为您在未创建myStructPV情况下调用CmdSetStruct_Click() You'd need MyVariable_ValueChanged() to run first or to at least put the code from it that creates myStructPV into CmdSetStruct_Click() . 您需要MyVariable_ValueChanged()首先运行,或者至少将其中创建myStructPV的代码放入CmdSetStruct_Click()

As long as you are getting to status "Task pvitest Connected" when running the init stuff, then all the PVI connection is working (if you don't have a task on you PLC named pvitest but still make it to CPU Connected then you're doing okay still). 只要在运行初始化程序时进入状态“ Task pvitest Connected”,那么所有PVI连接都可以正常工作(如果您的PLC上没有名为pvitest的任务,但仍将其CPU ConnectedCPU Connected那么您可以还在做还可以)。 You just have to debug your connecting to actual tags. 您只需要调试与实际标签的连接即可。

As far as communicating with an existing Windows program written by the OEM, that's unlikely. 就与OEM编写的现有Windows程序进行通信而言,这不太可能。 You'd have to use some kind of debugger to get at its memory or hope they made some kind of API which is very unlikely. 您将不得不使用某种调试器来获取其内存,或者希望它们创建了某种不太可能的API。

I think Isaac is right to assume that you click on the button that executes CmdSetStruct_Click() before you actually initialize the myStruct Pv. 我认为Isaac正确地假设您在实际初始化myStruct Pv之前单击执行CmdSetStruct_Click()的按钮。 This could be because your connection to the PLC doesn't work up until to the point where you are able to get the valueChanged event from the Lifebit variable. 这可能是因为直到可以从Lifebit变量获取valueChanged事件为止,您与PLC的连接才起作用。

Could your Lifebit variable on the PLC be global? 您在PLC上的Lifebit变量可以是全局变量吗? Would be nice to see the console output of the VS to be able to pinpoint the issue until it crashes. 很高兴看到VS的控制台输出能够查明问题,直到崩溃。

Regarding running in the PVI trial mode you are right, it can create some problems for the initial connection but in that case, if you just stop the PVI manager and start it again, it should all be fine. 对于在PVI试用模式下运行,这是正确的,它可能会给初始连接带来一些问题,但是在那种情况下,如果您只是停止PVI管理器并再次启动它,那应该没问题。

I'd anyway recommend you to have just one struct for handling the communication in an out of the PLC. 无论如何,我还是建议您只有一种结构来处理PLC外部的通讯。 For example: 例如:

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

With that, you would have to go through the PVI variable connection process twice only. 这样,您将只需要执行两次PVI变量连接过程。 Once to connect to the ToPlc struct and once to connect to the FromPlc struct. 一次连接到ToPlc结构,一次连接到FromPlc结构。 Your code will be a lot easier to manage that way. 这样,您的代码将更容易管理。

And finally, you can use the onConnected events of the variables rather than the valueChanged . 最后,您可以使用变量的onConnected事件,而不是使用valueChanged That way before you allow your app to move on, you can wait until you get a valid connection on the variables & catch the errors thrown from the variable connection and handle them gracefully. 这样,在允许您的应用继续运行之前,您可以等待直到在变量上获得有效连接并捕获从变量连接引发的错误并优雅地处理它们。 This would make it possible to prevent your app from crashing. 这样可以防止您的应用崩溃。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM