C#和DL-EPI通信

Posted QtHalcon

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C#和DL-EPI通信相关的知识,希望对你有一定的参考价值。

        DL-EP1是通过Ethernet/IP通信的,较为复杂,不想折腾建议换成DL-EN1,可以直接用TCP发送M0就能获取传感器的值。

         如果实在要通信就用下面的库。

GitHub - rossmann-engineering/EEIP.NET: Ethernet/IP compatible library for .NET implementationshttps://github.com/rossmann-engineering/EEIP.NET        选择这个DEMO

         然后用下面代码替换掉Program.cs的内容

         代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Sres.Net.EEIP;
using System.IO;

//This example demonstrates the usage of Implicit Messaging 
//whith an Keyence NU-EP1 Network Unit. This is an Input Only connection.
//The 128 received bytes returns the state of the Sensors (Page 3-9 of Keyence Manual contains the assignment).
//Keyence Users Manual Page 3-6 No. 2
//此示例演示隐式消息传递的用法
//使用Keyence NU-EP1网络单元。这是一个仅输入的连接。
//接收到的128个字节返回传感器的状态(Keyence手册第3-9页包含分配)。
//Keyence用户手册第3-6页第2页
namespace Keyence_NU_RP1_Implicit

    class Program
    
        static void Main(string[] args)
        
            //
            string Path = Directory.GetCurrentDirectory();
            string[] FileDataList = File.ReadAllLines(Path + "\\\\config.txt",Encoding.Default);
            if (FileDataList.Length <= 0) return;
            for (int i = 0; i < FileDataList.Length; ++i)  
                Console.WriteLine("Data" + i + ":" + FileDataList[i]);
            

            //
            EEIPClient eeipClient = new EEIPClient();
            //Ip-Address of the Ethernet-IP Device (In this case Keyence-NU-EP1)
            eeipClient.IPAddress = FileDataList[0];
            //A Session has to be registered before any communication can be established
            eeipClient.RegisterSession();

            //Parameters from Originator -> Target 来自发起人->目标的参数
            eeipClient.O_T_InstanceID = 0xfe;              //输出程序集的实例ID
            eeipClient.O_T_Length = 0;
            eeipClient.O_T_RealTimeFormat = Sres.Net.EEIP.RealTimeFormat.Header32Bit;   //Header Format
            eeipClient.O_T_OwnerRedundant = false;
            eeipClient.O_T_Priority = Sres.Net.EEIP.Priority.Low;
            eeipClient.O_T_VariableLength = false;
            eeipClient.O_T_ConnectionType = Sres.Net.EEIP.ConnectionType.Point_to_Point;
            eeipClient.RequestedPacketRate_O_T = 500000;    //RPI in  500ms is the Standard value


            //Parameters from Target -> Originator 来自目标->发起人的参数
            eeipClient.T_O_InstanceID = 0x64;
            eeipClient.T_O_Length = 168;
            eeipClient.T_O_RealTimeFormat = Sres.Net.EEIP.RealTimeFormat.Modeless;
            eeipClient.T_O_OwnerRedundant = false;
            eeipClient.T_O_Priority = Sres.Net.EEIP.Priority.Scheduled;
            eeipClient.T_O_VariableLength = false;
            eeipClient.T_O_ConnectionType = Sres.Net.EEIP.ConnectionType.Multicast;
            eeipClient.RequestedPacketRate_T_O = 500000;    //RPI in  500ms is the Standard value

            //Forward open initiates the Implicit Messaging Forward open启动隐式消息传递
            eeipClient.ForwardOpen();

            while (true)
            
                //read pw
                var responze = eeipClient.GetAttributeSingle(0x0E, 0x67,1,0x325);
                int PVInt = BitConverter.ToInt32(responze, 0);
                //read numn point
                var reaponee2 = eeipClient.GetAttributeSingle(0x4D, 0x67,1,0x325);
                int point = BitConverter.ToInt16(reaponee2, 0);
                //用于计算真实数值
                double value = ((double)PVInt) * Math.Pow(0.1, point) ;
                Console.WriteLine("测距值:" + value);


                System.Threading.Thread.Sleep(500);
            

            //Close the Session
            eeipClient.ForwardClose();
            eeipClient.UnRegisterSession();
        
    


        然后在EIPClient.cs添加这个函数


        public byte[] GetAttributeSingle(int service, int classID, int instanceID, int attributeID)
        
            byte[] requestedPath = GetEPath(classID, instanceID, attributeID);
            if (sessionHandle == 0) 
                //If a Session is not Registers, Try to Registers a Session with the predefined IP-Address and Port
                //如果会话未注册,请尝试使用预定义的IP地址和端口注册会话
                this.RegisterSession();
            
            byte[] dataToSend = new byte[42+ requestedPath.Length];
            Encapsulation encapsulation = new Encapsulation();
            encapsulation.SessionHandle = sessionHandle;
            encapsulation.Command = Encapsulation.CommandsEnum.SendRRData;
            encapsulation.Length = (UInt16)(18 + requestedPath.Length);
            //---------------Interface Handle CIP
            encapsulation.CommandSpecificData.Add(0);
            encapsulation.CommandSpecificData.Add(0);
            encapsulation.CommandSpecificData.Add(0);
            encapsulation.CommandSpecificData.Add(0);
            //----------------Interface Handle CIP

            //----------------Timeout
            encapsulation.CommandSpecificData.Add(0);
            encapsulation.CommandSpecificData.Add(0);
            //----------------Timeout

            //Common Packet Format (Table 2-6.1)
            Encapsulation.CommonPacketFormat commonPacketFormat = new Encapsulation.CommonPacketFormat();
            commonPacketFormat.ItemCount = 0x02;

            commonPacketFormat.AddressItem = 0x0000;        //NULL (used for UCMM Messages)
            commonPacketFormat.AddressLength = 0x0000;

            commonPacketFormat.DataItem = 0xB2;
            commonPacketFormat.DataLength = (UInt16)(2 + requestedPath.Length);



            //----------------CIP Command "Get Attribute Single"
            commonPacketFormat.Data.Add((byte)service);
            //commonPacketFormat.Data.Add((byte)Sres.Net.EEIP.CIPCommonServices.Get_Attribute_Single);
            //----------------CIP Command "Get Attribute Single"

            //----------------Requested Path size (number of 16 bit words)
            commonPacketFormat.Data.Add((byte)(requestedPath.Length / 2));
            //----------------Requested Path size (number of 16 bit words)

            //----------------Path segment for Class ID
            //----------------Path segment for Class ID

            //----------------Path segment for Instance ID
            //----------------Path segment for Instace ID

            //----------------Path segment for Attribute ID
            //----------------Path segment for Attribute ID

            for (int i = 0; i < requestedPath.Length; i++)
            
                commonPacketFormat.Data.Add(requestedPath[i]);
            

            byte[] dataToWrite = new byte[encapsulation.toBytes().Length + commonPacketFormat.toBytes().Length];
            System.Buffer.BlockCopy(encapsulation.toBytes(), 0, dataToWrite, 0, encapsulation.toBytes().Length);
            System.Buffer.BlockCopy(commonPacketFormat.toBytes(), 0, dataToWrite, encapsulation.toBytes().Length, commonPacketFormat.toBytes().Length);
            encapsulation.toBytes();

            stream.Write(dataToWrite, 0, dataToWrite.Length);
            byte[] data = new Byte[564];

            Int32 bytes = stream.Read(data, 0, data.Length);

            //--------------------------BEGIN Error?
            if (data[42] != 0)      //Exception codes see "Table B-1.1 CIP General Status Codes"
            
                throw new CIPException(GeneralStatusCodes.GetStatusCode(data[42]));
            
            //--------------------------END Error?

            byte[] returnData = new byte[bytes - 44];
            System.Buffer.BlockCopy(data, 44, returnData, 0, bytes-44);

            return returnData;
        

        最后,具体的参数设置可以根据自己的传感器去设置,我这里是IL-1000

以上是关于C#和DL-EPI通信的主要内容,如果未能解决你的问题,请参考以下文章

Metro 应用程序中 C++ 和 C# 之间的通信

C# 和 Flash 通信

如何使用命名管道通信 C 和 C# 程序

在 C++ 和 C# 之间进行通信?

Lua 和 C# 的进程间通信

C# 串行通信 DLL