C#读写基恩士PLC 使用TCP/IP 协议 MC协议

本文将使用一个Github开源的组件库技术来读写基恩士PLC数据,使用的是基于以太网的TCP/IP实现,不须要额外的组件,读取操做只要放到后台线程就不会卡死线程,本组件支持超级方便的高性能读写操做css

 github地址:https://github.com/dathlin/HslCommunication 若是喜欢能够star或是fork,还能够打赏支持,打赏请认准源代码项目。html

联系做者及加群方式:http://www.hslcommunication.cn/Cooperation 前端

 

在Visual Studio 中的NuGet管理器中能够下载安装,也能够直接在NuGet控制台输入下面的指令安装:git

 

Install-Package HslCommunication

  

 若是须要教程:Nuget安装教程:http://www.cnblogs.com/dathlin/p/7705014.htmlgithub

 

组件的完整信息和API介绍参照:http://www.cnblogs.com/dathlin/p/7703805.html   组件的使用限制,更新日志,都在该页面里面。服务器

 

若是你须要在读取PLC数据以后,还要群发客户端来实现远程办公室同步监视,能够参考以下的项目(基于该组件扩展起来的,带有帐户验证,版本控制,数据群发,公告管理等等功能)网络

https://github.com/dathlin/ClientServerProject多线程

 

本文将展现如何配置网络参数及怎样使用代码来访问PLC数据,但愿给有须要的人解决一些实际问题。主要对基恩士的数据进行读写操做,具体的参照下面的地址信息tcp

此处使用了网线直接的方式,若是PLC接进了局域网,就能够进行远程读写了^_^oop

此处使用到了2个命名空间:

using HslCommunication.Profinet.Keyence;
using HslCommunication;

  

 

随便聊聊


当咱们一个上位机须要读取100台西门子PLC设备(此处只是举个例子,凡是都是使用Modbus tcp的都是同样的)的时候,你采用服务器主动去请求100台设备的机制对性能来讲是个极大的考验,若是开100个线程去轮询100台设备,那么性能损失将是很是大的,更不用说再增长设备,若是搭建Modbus tcp服务器,就能够完美的解决性能问题,由于链接的压力将会平均分摊给每一台PLC,服务器端只要新增一个时间戳就能够知道客户端有没有链接上。

咱们在100台PLC里都增长发送Modbus tcp方法,将数据发送到服务器的ip和端口上去,服务器根据站号来区分设备。这样就能够搭建一个高性能总站。 本组件支持快速搭建一个高性能的Modbus tcp总站。

http://www.cnblogs.com/dathlin/p/7782315.html

 

关于两种模式


在PLC端,包括三菱,西门子,欧姆龙以及Modbus Tcp客户端的访问器上,都支持两种模式,短链接模式和长链接模式,如今就来解释下什么原理。

短链接:每次读写都是一个单独的请求,请求完毕也就关闭了,若是服务器的端口仅仅支持单链接,那么关闭后这个端口能够被其余链接复用,可是在频繁的网络请求下,容易发生异常,会有其余的请求不成功,尤为是多线程的状况下。

长链接:建立一个公用的链接通道,全部的读写请求都利用这个通道来完成,这样的话,读写性能更快速,即时多线程调用也不会影响,内部有同步机制。若是服务器的端口仅仅支持单链接,那么这个端口就被占用了,好比三菱的端口机制,西门子的Modbus tcp端口机制也是这样的。如下代码默认使用长链接,性能更高,还支持多线程同步。

在短链接的模式下,每次请求都是单独的访问,因此没有重连的困扰,在长链接的模式下,若是本次请求失败了,在下次请求的时候,会自动从新链接服务器,直到请求成功为止。另外,尽可能全部的读写都对结果的成功进行判断。

 

关于日志记录


不论是基恩士的,三菱的数据访问类,仍是西门子的,仍是Modbus tcp访问类,都有一个LogNet属性用来记录日志,该属性是一个接口类,ILogNet,凡事继承该接口的均可以用来记录日志,该日志会在访问失败时,尤为是由于网络的缘由致使访问失败时会进行日志记录(若是你为这个 LogNet 属性配置了真实的日志记录器的话):若是你想使用该记录日志的功能,请参照以下的博客进行实例化:

http://www.cnblogs.com/dathlin/p/7691693.html

 

访问测试项目


下面的一个项目是这个组件的访问测试项目,您能够进行初步的访问的测试,免去了您写测试程序的麻烦,三菱的界面和西门子的界面几乎是一致的。能够同时参考。该项目位于本篇文章开始处的Gitbub源代码里面的

下载地址为:HslCommunicationDemo.zip 

地址的格式在在线文档里:http://118.24.36.220:8080/html/04bd2a21-7ab0-2fb9-f7f1-e0f0ecaf9227.htm

演示项目


下面的三篇演示了具体如何去访问PLC的数据,咱们在访问完成后,一般须要进行处理,如下的示例项目就演示了后台从PLC读取数据后,前台显示并推送给全部在线客户端的功能,客户端并进行图形化显示,具备必定的参考意义,而且推送给网页前端,项目地址为:

https://github.com/dathlin/RemoteMonitor

下面的图片示例中的左边程序就是服务器程序,它应该和PLC直接链接并接入局域网,而后把数据推送给客户端显示。注意:一个复杂高级的程序就应该把处理逻辑程序和界面程序分开,好比这里的服务器程序实现数据采集,推送,存储。让客户端程序去实现数据的整理,分析,显示,这样即便客户端程序由于BUG奔溃,服务器端仍然能够正常的工做。

测试图片

 

 

 

基恩士PLC篇(本组件支持二进制和ASCII通信,二者只是类名不一样,具体的地址,方法都是如出一辙的)


 

初始化访问PLC对象

注意:若是你采用了二进制读写,那么就实例化KeyenceMcNet类,若是采用ASCII来读写数据,请使用KeyenceMcAsciiNet类
若是想使用本组件的数据读取功能,必须先初始化数据访问对象,根据实际状况进行数据的填入。 下面仅仅是测试中的数据:

 

private KeyenceMcNet keyence_net = new KeyenceMcNet( "192.168.8.13", 5000 );

  

打开链接,并能够判断是否链接上

keyence_net.ConnectServer( );

  

若是须要判断,那么按照以下的操做

    OperateResult connect = keyence_net.ConnectServer( );
                if (connect.IsSuccess)
                {
                    MessageBox.Show( "链接成功!" );
                }
                else
                {
                    MessageBox.Show( "链接失败!" );
                }

  

 

 
说明:对象应该放在窗体类下面,此处仅仅针对读取一台设备的plc,也能够在访问的方法中实例化局部对象, 初始化数据,而后读取,该对象几乎不损耗内存,内存垃圾由CLR进行自动回收。此处测试方便,窗体的多个按钮均链接同一台PLC 设备,因此本窗体实例化一个对象便可。

 

展现一些简单实用基础数据读写,这些数据的读写没有进行严格的是否成功判断(判断方法参照后面的代码),通常网络良好的状况下都会成功,但不排除失败,如下代码仅做测试,全部没有严格判断是否成功:

 

            short d100_short = keyence_net.ReadInt16( "D100" ).Content;
            ushort d100_ushort = keyence_net.ReadUInt16( "D100" ).Content;
            int d100_int = keyence_net.ReadInt32( "D100" ).Content;
            uint d100_uint = keyence_net.ReadUInt32( "D100" ).Content;
            long d100_long = keyence_net.ReadInt64( "D100" ).Content;
            ulong d100_ulong = keyence_net.ReadUInt64( "D100" ).Content;
            float d100_float = keyence_net.ReadFloat( "D100" ).Content;
            double d100_double = keyence_net.ReadDouble( "D100" ).Content;
            // need to specify the text length
            string d100_string = keyence_net.ReadString( "D100", 10 ).Content;

            keyence_net.Write( "D100", (short)5 );
            keyence_net.Write( "D100", (ushort)5 );
            keyence_net.Write( "D100", 5 );
            keyence_net.Write( "D100", (uint)5 );
            keyence_net.Write( "D100", (long)5 );
            keyence_net.Write( "D100", (ulong)5 );
            keyence_net.Write( "D100", 5f );
            keyence_net.Write( "D100", 5d );
            // length should Multiples of 2 
            keyence_net.Write( "D100", "12345678" );



以下方法演示读取了M200-M209这10个M的值,注意:读取长度必须为偶数,即时写了奇数,也会补齐至偶数,读取和写入的最大长度为7168,不然报错。如需实际需求确实大于7168的,请分批次读取。
返回值解析:若是读取正常则共返回10个字节的数据,如下示例数据进行批量化的读取

        private void test1()
        {
            OperateResult<bool[]> read = keyence_net.ReadBool( "M100", 10 );
            if(read.IsSuccess)
            {
                bool m100 = read.Content[0];
                // and so on
                bool m109 = read.Content[9];
            }
            else
            {
                // failed
            }
        }

  

写入Bool的操做

bool[] values = new bool[] { true, false, true, true, false, true, false, true, true, false };
            OperateResult read = keyence_net.Write( "M100", values );
            if (read.IsSuccess)
            {
                // success
            }
            else
            {
                // failed
            }

 

高级的批量数据读取(针对连续的地址的时候效率很是的高):

        private void test5( )
        {
            OperateResult<byte[]> read = keyence_net.Read( "D100", 10 );
            if(read.IsSuccess)
            {
                int count = keyence_net.ByteTransform.TransInt32( read.Content, 0 );
                float temp = keyence_net.ByteTransform.TransSingle( read.Content, 4 );
                short name1 = keyence_net.ByteTransform.TransInt16( read.Content, 8 );
                string barcode = Encoding.ASCII.GetString( read.Content, 10, 10 );
            }
        }

  

麻烦之处须要本身写代码解析数据信息

 

更多详细的读写信息请关注本项目学习。

相关文章
相关标签/搜索