简体   繁体   中英

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 .

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.

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. 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.

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.) . 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.

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.

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 . You'd need MyVariable_ValueChanged() to run first or to at least put the code from it that creates myStructPV into 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). 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. 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.

I think Isaac is right to assume that you click on the button that executes CmdSetStruct_Click() before you actually initialize the myStruct Pv. 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.

Could your Lifebit variable on the PLC be global? Would be nice to see the console output of the VS to be able to pinpoint the issue until it crashes.

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.

I'd anyway recommend you to have just one struct for handling the communication in an out of the 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. Once to connect to the ToPlc struct and once to connect to the FromPlc struct. 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 . 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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