テクセル
RubyでPLC UDP通信(三菱Qシリーズ)

三菱電機(株)製PLC(シーケンサQシリーズ)のEthernetインターフェースユニットへRubyによりUDP通信を行います。 実行環境は、以下となります。

項目 内容
Rubyのバージョン  ruby 2.6.3p62 (RubyInstaller x86)
対象としたユニット Ethernetインターフェースユニット QJ71E71-100または、ユニバーサルモデルCPUの内蔵Ethernet
通信手順  MCプロトコル QnA互換3Eフレーム

■ EthernetインターフェースユニットQJ71E71-100での設定

GX Works2によりネットワークパラメータ Ethernet/CC IE/MELSECNETで設定します。 UDPポートは、自動オープンUDPポートを使用します。

1)動作設定

項目 内容
交信データコード設定 「バイナリコード交信」または、「ASCIIコード交信」のどちらでも良い
イニシャルタイミング設定 「常にOPEN待ち(STOPP中交信可能)」を選択
IPアドレス設定 入力形式「10進数」を選択
IPアドレスをここでは、「192.168.1.78」と設定します。
送信フレーム設定 「Ethernet(V2.0)」を選択
RUN中書込みを許可する チェックマークを入れます。(許可)
TCP生存確認設定 -

2)オープン設定

自動オープンUDPポート使用時は、オープン設定が不要でポート番号は、5000となります。 また、交信コードは、動作設定に関係なくバイナリとなります。

■ Ethernetポート内蔵CPUユニバーサルモデルでの設定

GX Works2によりPCパラメータの内蔵Ethernetポート設定で設定します。

項目 内容
IPアドレス設定 IPアドレスをここでは、「192.168.1.99」と設定します。
交信データコード設定 「バイナリコード交信」または、「ASCIIコード交信」どちらでも良い
RUN中書込みを許可する チェックを入れます。(許可)

「オープン設定」ボタンでオープン設定ダイアログを表示します。いずれかの番号行に以下を設定します。

項目 内容
プロトコル UDPを選択します。
オープン方式 MCプロトコルを選択します。
自局ポート番号 ここでは、8200(10進)とします。

■ サンプルソフト

下記サンプルソフトは、レジスタのD0100より10ワード読み込みを行ってます。エラー処理は行ってません。「q」キーで終了します。

「wincons.rb」の説明及びダウンロード


# 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
}
   
参考資料
・Q対応Ethernetインターフェースユニット ユーザーズマニュアル(基本編)(三菱電機(株))
・Q対応MELSECコミュニケーションプロトコル リファレンスマニュアル(三菱電機(株))
・QnUCPU ユーザーズマニュアル(内蔵Ethernet ポート通信編)(三菱電機(株))
Rubyユーティリティ
©2005-2019 TEXCELL CORPORATION
テクセル株式会社