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

  

麻煩之處須要本身寫代碼解析數據信息

 

更多詳細的讀寫信息請關注本項目學習。

相關文章
相關標籤/搜索