三菱電機(株)製PLC(シーケンサQシリーズ)のEthernetインターフェースユニットへRubyによりUDP通信を行います。 実行環境は、以下となります。
項目 | 内容 |
---|---|
Rubyのバージョン | ruby 2.6.3p62 (RubyInstaller x86) |
対象としたユニット | Ethernetインターフェースユニット QJ71E71-100または、ユニバーサルモデルCPUの内蔵Ethernet |
通信手順 | MCプロトコル QnA互換3Eフレーム |
GX Works2によりネットワークパラメータ Ethernet/CC IE/MELSECNETで設定します。 UDPポートは、自動オープンUDPポートを使用します。
項目 | 内容 |
---|---|
交信データコード設定 | 「バイナリコード交信」または、「ASCIIコード交信」のどちらでも良い |
イニシャルタイミング設定 | 「常にOPEN待ち(STOPP中交信可能)」を選択 |
IPアドレス設定 | 入力形式「10進数」を選択 IPアドレスをここでは、「192.168.1.78」と設定します。 |
送信フレーム設定 | 「Ethernet(V2.0)」を選択 |
RUN中書込みを許可する | チェックマークを入れます。(許可) |
TCP生存確認設定 | - |
自動オープンUDPポート使用時は、オープン設定が不要でポート番号は、5000となります。 また、交信コードは、動作設定に関係なくバイナリとなります。
GX Works2によりPCパラメータの内蔵Ethernetポート設定で設定します。
項目 | 内容 |
---|---|
IPアドレス設定 | IPアドレスをここでは、「192.168.1.99」と設定します。 |
交信データコード設定 | 「バイナリコード交信」または、「ASCIIコード交信」どちらでも良い |
RUN中書込みを許可する | チェックを入れます。(許可) |
「オープン設定」ボタンでオープン設定ダイアログを表示します。いずれかの番号行に以下を設定します。
項目 | 内容 |
---|---|
プロトコル | UDPを選択します。 |
オープン方式 | MCプロトコルを選択します。 |
自局ポート番号 | ここでは、8200(10進)とします。 |
下記サンプルソフトは、レジスタのD0100より10ワード読み込みを行ってます。エラー処理は行ってません。「q」キーで終了します。
# coding: utf-8
# QJ71E71 UDP MC QnA互換3E
require 'socket'
require "./wincons"
def hexchar(cmj)
srs = ""
cmj.each_byte{ |c|
srs += sprintf("%#04x",c)
}
return srs
end
iflg = 0
irc = 0
hudp = UDPSocket.new()
hudp.connect("192.168.1.78",5000)
#hudp.connect("192.168.1.99",8200)
thr = Thread.start{ #受信スレッド
loop{
irc = hudp.recv(100)
# irc,ipadd = hudp.recvfrom(100)
iflg = 1
}
}
cons1 = Console.new(__ENCODING__)
istep = 1
# コマンドサブ コマンド D100より10ワード読み込み
srsbcmd = 0x0000 #サブコマンド
sdv = 0xA8 #Dデバイス
itopad = 100 #読み込み先頭
ireadsu = 10 #読み込み個数
# コマンドサブ コマンド M100より20ビット読み込み
#srsbcmd = 0x0001 #サブコマンド
#sdv = 0x90 #Mデバイス
#itopad = 100 #読み込み先頭
#ireadsu = 20 #読み込み個数
ched = ["5000"].pack("H4") + # サブベッダ
[0].pack("C") + # ネットワーク番号
[0xff].pack("C") + # PC番号
[0x03FF].pack("S") + # 要求先ユニットIO番号
[0].pack("C") + # 要求先ユニット局番
[0].pack("S") + # 要求先データ長
[0x0010].pack("S") # CPU監視タイマ
cscmd = [0x0401].pack("S") + # コマンド
[srsbcmd].pack("S") + # サブコマンド
[itopad].pack("I")[0,3] + # 先頭デバイス番号
[sdv].pack("C") + # デバイスコード
[ireadsu].pack("S") # 読み出し点数
ilen = cscmd.length + 2 #要求データ長
ched[7,2] = [ilen].pack("S")
sa = ched + cscmd
loop{
case istep
when 1
iflg = 0
hudp.send(sa,0)
# p sa #hexchar(sa)
istep = 2
when 2
if iflg == 1
# p irc #irc.unpack("H*")
sd = ""
if sdv == 0xA8
for ia in 0..(ireadsu - 1)
iz = irc[11 + ia * 2,2].unpack("S")[0]
sd += sprintf("%04X",iz) + ","
end
end
if sdv == 0x90
for ia in 0..(ireadsu / 2 - 1)
iz = irc[11 + ia * 1,1].unpack("C")[0]
sd += ((iz & 0xf0) >> 4).to_s + ","
sd += (iz & 0x0f).to_s + ","
end
end
cons1.cprint sd + "¥r¥n"
# sleep 0.2 #表示遅延用
istep = 1
end
end
ca, = cons1.inkey
if ca == "q" || ca == "Q"
thr.exit #kill
thr.join
hudp.close
break
end
sleep 0.01
}