'******************************************************************************* ' 動作説明 : MCプロトコル ' 動作説明 : 通信制御のサンプルコードです。 ' ' 注意 : 本ソフトはフリーソフトです。個人/団体/社内利用を問わず、 ' ご自由にお使い下さい。 ' なお,著作権は作者である"杉本卓也(杉本電気システム)"が ' 保有しています。 ' このソフトウェアを使用したことによって生じたすべての障害・損害・不具 ' 合等に関しては、私と私の関係者および私の所属するいかなる団体・組織とも、 ' 一切の責任を負いません。各自の責任においてご使用ください。 ' ' ' Copyright(c) 2018 T.SUGIMOTO(SUGIMOTO ELECTRIC SYSTEM SOLUTION). All rights reserved. '******************************************************************************* ' 修正履歴 ' 2018/12/31 T.Sugimoto 新規作成 ' '******************************************************************************* Imports System.Collections.Generic Imports System.Collections Imports PlcMelsecManager.PlcSystem.Data Imports System.Text Namespace PlcSystem.Reader ''' ''' PLCレジスタデータ ''' ''' Public Class PLCDataReader Const E71msec As Integer = 250 Dim mObjSck As System.Net.Sockets.TcpClient Dim mObjStm As System.Net.Sockets.NetworkStream Dim mDeviceNameArray() As String = {"D300", "D312", "D320"} ''' ''' ソケットオープン ''' ''' Public Sub Open() mObjSck = New System.Net.Sockets.TcpClient mObjSck.Connect("192.168.1.75", 8192) ' ソケットストリーム取得 mObjStm = mObjSck.GetStream() End Sub ''' ''' 初期化 ''' ''' Public Sub Init() Dim dat() As Byte dat = MakeDiscreteData() SendData(dat) End Sub ''' ''' PLCデータ取得(連続領域) ''' ''' Public Function Read() As PLCData Dim plcData As New PLCData Dim dat() As Byte Dim 応答データ As String = "" 'dat = MakeContinueData() dat = MakeMonitorData() 応答データ = SendData(dat) MessageBox.Show(ConvertReceiveDeviceData(応答データ)) Return plcData End Function ''' ''' ソケットクローズ ''' ''' Public Sub Close() mObjStm.Close() mObjSck.Close() End Sub ''' ''' PLC送信データ生成(連続領域) ''' ''' Function MakeContinueData() As Byte() ' Dレジへのワード単位読み込み ' Dim dat As Byte() = {&H50, &H0, &H0, &HFF, &HFF, &H3, &H0, &HC, &H0, &H10, &H0, &H1, &H4, &H0, &H0, &H2C, &H1, &H0, &HA8, &H3, &H0} 'Dレジへのワード単位書き込み。書き込みのときは書き込みデータにおうじて電文命令長が異なるので、「要求データ長」をちゃんと変更すること。 ' Dim dat As Byte() = {&H50, &H0, &H0, &HFF, &HFF, &H3, &H0, &HE, &H0, &H10, &H0, &H1, &H14, &H0, &H0, &H2C, &H1, &H0, &HA8, &H1, &H0, &HFF, &HFF} Dim 送信データ() As Byte = {&HFA, &HFF} Dim dat(送信データ.Length + 20) As Byte dat(0) = &H50 : dat(1) = &H0 'サブヘッダであり固定 dat(2) = &H0 : dat(3) = &HFF 'ネットワーク番号(PCとE71との通信であればH0, FF . CC-Linkなどを介する場合はマニュアルp74を参考に) dat(4) = &HFF : dat(5) = &H3 : dat(6) = &H0 '二重化CPUでないならFF, 03, 00. その他ならマニュアルp102を参考に 'dat(7) = 12 + 送信データ.Length : dat(8) = &H0 '送信データ長 dat(7) = &HC : dat(8) = &H0 '送信データ長 dat(9) = T250msec2HEX(E71msec, 0) : dat(10) = T250msec2HEX(E71msec, 1) 'CPU監視タイマ ''dat(11) = &H1 : dat(12) = &H14 'コマンド dat(11) = &H1 : dat(12) = &H4 'コマンド dat(13) = &H0 : dat(14) = &H0 'サブコマンド dat(15) = &H2C : dat(16) = &H1 : dat(17) = &H0 '先頭デバイス(16進数6桁 D300 dat(18) = &HA8 dat(19) = &H1 dat(20) = &H0 Array.Copy(送信データ, 0, dat, 21, 送信データ.Length) Return dat End Function ''' ''' PLC送信データ生成(離散領域) ''' ''' Function MakeDiscreteData() As Byte() Dim 送信データ() As Byte = {&HFA, &HFF} Dim deviceCodeArray() As Byte Dim dat(送信データ.Length + 28) As Byte dat(0) = &H50 : dat(1) = &H0 'サブヘッダであり固定 dat(2) = &H0 : dat(3) = &HFF 'ネットワーク番号(PCとE71との通信であればH0, FF . CC-Linkなどを介する場合はマニュアルp74を参考に) dat(4) = &HFF : dat(5) = &H3 : dat(6) = &H0 '二重化CPUでないならFF, 03, 00. その他ならマニュアルp102を参考に 'dat(7) = 20 + 送信データ.Length : dat(8) = &H0 '送信データ長 dat(7) = &H14 : dat(8) = &H0 '送信データ長 dat(9) = T250msec2HEX(E71msec, 0) : dat(10) = T250msec2HEX(E71msec, 1) 'CPU監視タイマ dat(11) = &H1 : dat(12) = &H8 'コマンド dat(13) = &H0 : dat(14) = &H0 'サブコマンド dat(15) = &H3 '16bit データ点数 dat(16) = &H0 '32bit データ点数 'メモリ設定 For i = 0 To mDeviceNameArray.Length - 1 deviceCodeArray = ConvertSendDeviceCode(mDeviceNameArray(i)) Array.Copy(deviceCodeArray, 0, dat, 17 + 4 * i, 4) Next Array.Copy(送信データ, 0, dat, 29, 送信データ.Length) Return dat End Function ''' ''' PLC送信データ生成(モニタ要求) ''' ''' Function MakeMonitorData() As Byte() Dim 送信データ() As Byte = {&HFA, &HFF} Dim dat(送信データ.Length + 14) As Byte dat(0) = &H50 : dat(1) = &H0 'サブヘッダであり固定 dat(2) = &H0 : dat(3) = &HFF 'ネットワーク番号(PCとE71との通信であればH0, FF . CC-Linkなどを介する場合はマニュアルp74を参考に) dat(4) = &HFF : dat(5) = &H3 : dat(6) = &H0 '二重化CPUでないならFF, 03, 00. その他ならマニュアルp102を参考に 'dat(7) = 6 + 送信データ.Length : dat(8) = &H0 '送信データ長 dat(7) = &H6 : dat(8) = &H0 '送信データ長 dat(9) = T250msec2HEX(E71msec, 0) : dat(10) = T250msec2HEX(E71msec, 1) 'CPU監視タイマ dat(11) = &H2 : dat(12) = &H8 'コマンド dat(13) = &H0 : dat(14) = &H0 'サブコマンド Array.Copy(送信データ, 0, dat, 15, 送信データ.Length) Return dat End Function ''' ''' ソケット送信・受信 ''' ''' Function SendData(ByVal sendDat() As Byte) As String Dim 応答データ As String = "" Dim data As Byte() ' ソケット送信 mObjStm.Write(sendDat, 0, sendDat.GetLength(0)) System.Threading.Thread.Sleep(250) ' ソケット受信 If mObjSck.Available > 0 Then data = New Byte(mObjSck.Available - 1) {} mObjStm.Read(data, 0, data.GetLength(0)) For i = 0 To data.Length - 1 応答データ = 応答データ & Convert.ToString(data(i), 16).PadLeft(2, "0") Next End If Return 応答データ End Function ''' ''' 時間 HEX変換 ''' ''' Function T250msec2HEX(ByVal msec As Integer, ByVal i As Integer) As Integer 'msecをHEXに変換する Dim hexi As Integer If msec > 38796720 Then : msec = 38796720 : End If : If msec < 0 Then : msec = 0 : End If If i = 0 Then : hexi = CInt("&H" & CInt(msec / 250).ToString("x4").Substring(0, 2)) : End If If i = 1 Then : hexi = CInt("&H" & CInt(msec / 250).ToString("x4").Substring(2, 2)) : End If If i = 2 Then : hexi = CInt(msec / 250) : End If Return hexi End Function ''' ''' PLC デバイスコード変換 ''' ''' Function ConvertSendDeviceCode(ByVal deviceName As String) As Byte() Dim strDeviceType As String 'デバイス種別 ex "D","M" etc Dim strDeviceNumber As String 'デバイス番号 Dim deviceData(3) As Byte strDeviceType = deviceName.Substring(0, 1) strDeviceNumber = deviceName.Substring(1) Dim iDeviceNumber As Integer = Integer.Parse(strDeviceNumber) '16進文字列に変換 Dim hexText As String = iDeviceNumber.ToString("x6") Dim hexChar As String = "" '16進文字列をbyteに変換 Dim decData(2) As Byte For i = 0 To 2 hexChar = hexText.Substring(i * 2, 2) decData(i) = Convert.ToByte(Convert.ToInt32(hexChar, 16)) Next 'リトルエンディアンに変換 Array.Reverse(decData) Array.Copy(decData, 0, deviceData, 0, 3) Select Case strDeviceType Case "D" deviceData(3) = &HA8 Case "M" deviceData(3) = &H90 Case Else deviceData(3) = &HA8 End Select Return deviceData End Function ''' ''' PLC 受信データ変換 ''' ''' Function ConvertReceiveDeviceData(ByVal receiveDevice As String) As String '16進文字列に変換 Dim hexText As String = receiveDevice.Substring(22) Dim hexChar As String = "" Dim receiveDeviceData As String = "" '16進文字列をbyteに変換 Dim decData(1) As Byte For i = 0 To (hexText.Length / 4 - 1) For j = 0 To 1 hexChar = hexText.Substring(i * 4 + j * 2, 2) decData(j) = Convert.ToByte(Convert.ToInt32(hexChar, 16)) Next receiveDeviceData = receiveDeviceData & BitConverter.ToInt16(decData, 0) & "," Next Return receiveDeviceData End Function End Class End Namespace