LoginSignup
14
10

More than 1 year has passed since last update.

三菱MELSEC MCプロトコルをpythonで送信

Last updated at Posted at 2022-03-26

Pythonで三菱MELSECのMCプロトコル(Ethernet)を送信します

MCプロトコルは三菱のシーケンサのデバイスを値を読み書きすることができます
ここではpythonを使ってEthernet(UDP)でMCプロトコルで通信するクラスを作りました
MCP.py

環境

伝文

3Eフレームでバイナリコードを使用します
3EフレームはMELSEC-QnAシリーズのEthernetインタフェースで使用する伝文構成です

クライアント側環境

python 3.9

使い方

オブジェクトの作成

mcp = MCProtcol3E('192.168.0.41', 4999)

MCProtocol3Eクラスは通信相手のIPアドレスとポート番号を指定してオブジェクトを作ります

ワード単位でデバイスの読出し (最大640点)

data = mcp.read('D0', 10)

readメソッドでアドレスと点数を指定して実行すると戻り値には読み出したデータがバイト配列(bytes)で取得できます

ビット単位で読み出し (最大7168点)

data = mcp.read('SM0', 8, True)

第3引数をTrueにするとビット単位での読出しになります

対象のデバイスは以下のデバイスです

X: 入力
Y: 出力
M: 内部リレー
L: ラッチ
F アナンシエータ
V: エッジリレー
B: リンクリレー
D: データレジスタ
W: リンクレジスタ
TS: タイマ(接点)
TC: タイマ(コイル)
TN: タイマ(現在値)
SS: 積算タイマ(接点)
SC: 積算タイマ(コイル)
SN: 積算タイマ(現在値)
CS: カウンタ(接点)
CC: カウンタ(コイル)
CN: カウンタ(現在値)
SB: リンク特殊リレー
SW: リンク特殊レジスタ
S: ステップリレー
DX:ダイレクト入力
DY: ダイレクト出力
SM: 特殊リレー
SD: 特殊レジスタ

ワード単位で書込み

# 数値の場合の例
data = struct.pack('hhh', 123, 456, 789)
rcv = mcp.write('D20', data)

# 実数の場合の例
data = struct.pack('f', 1.23)
rcv = mcp.write('D10', data)

writeメソッドでアドレスと書込みデータを渡して実行すると戻り値に終了コードが返ってきます
書込みデータはバイト配列で渡します
ちなみに数値をバイト列にするstruct.packでよく使いそうなフォーマットを書いておきます

フォーマット バイト数
h Int16 2
H UInt16 2
i Int32 4
I UInt32 4
q Int64 8
Q UInt64 8
f Float 4
d Double 8

ビット単位で書込み

# ビットの場合の例
data = [0x11, 0x11, 0x10]
rcv = mcp.write('M10', data, 5)

第3引数に書き込むビット数を入れるとビット単位での書込みになります

ランダム読出し

rcv = mcp.RandomRead('D0,TN0,M100,X20', 'D1500,Y160,M1111')

第1引数にワード単位で読み出すデバイスを、第2引数にダブルワード単位で読み出すデバイスをセットして実行すると読み出したデータがバイト配列(bytes)で取得できます

モニタ登録

data = mcp.MonitorSet('D50, D55', 'D60, D64')

第1引数にワード単位で読み出すデバイスを、第2引数にダブルワード単位で読み出すデバイスをセットして実行します

モニタデバイス読出し

data = mcp.MonitorGet()

モニタ登録してあるデバイスの値を読み出します

データ変換

メソッド名 変換するデータの長さ
toBin バイナリ data = mcp.read('SM0', 8)
print(mcp.toBin(data))
> 0b11000100
toInt16 16bit数値 data = mcp.read('D0', 5)
print(mcp.toInt16(data))
> [-1, 1, 2, 3, 4]
toUInt16 16bit符号なし data = mcp.read('D0', 5)
print(mcp.toUInt16(data))
> [65535, 1, 2, 3, 4]
toInt32 32bit数値 data = mcp.read('D0', 6)
print(mcp.toInt32(data))
> [-1, 196610, 327684]
toUInt32 32bit符号なし data = mcp.read('D0', 6)
print(mcp.toUInt32(data))
> [131071, 196610, 327684]
toInt64 64bit数値 data = mcp.read('D0', 8)
print(mcp.toInt64(data))
> [-1, 1970350607106052]
toUInt64 64bit符号なし data = mcp.read('D0', 8)
print(mcp.toUInt64(data))
> [844433520197631, 1970350607106052]
toFloat 浮動小数点 data = mcp.read('D0', 4)
print(mcp.toFloat(data))
> [-2.2, 0.0]
toDouble 倍精度 data = mcp.read('D0', 8)
print(mcp.toDouble(data))
> [-2.2, 0.0]
toString 文字列 data = mcp.read('D0', 2)
print(mcp.toString(data))
> ABCD

サンプル


# example
# set IPAddress,Port
mcp = MCProtcol3E('192.168.0.41', 4999)

# words
data = mcp.read('D10000', 1)
print(mcp.toInt16(data))        # convert int16
rcv = mcp.write('D10', data)
print(rcv)                      # normal recieve = 0x00 0x00

# bits
data = mcp.read('M8000', 8, True)
print(data)
print(mcp.toBin(data))          # convert bin
rcv = mcp.write('M100', data, 8)
print(rcv)

# numeric
data = struct.pack('hhh', 123, 456, 789)
rcv = mcp.write('D20', data)
print(rcv)
# float
data = struct.pack('f', 1.23)
rcv = mcp.write('D10020', data)
print(rcv)
# bits
data = [0x11, 0x11, 0x10]
rcv = mcp.write('M8100', data, 5)

# RandomRead
rcv = mcp.RandomRead('D0,TN0,M100,X20', 'D1500,Y160,M1111')
print(rcv)
print(mcp.toInt16(rcv[:8]))
print(mcp.toInt32(rcv[8:]))

# Monitor
data = mcp.MonitorSet('D50, D55', 'D60, D64')
rcv = mcp.MonitorGet()
print(mcp.toInt16(rcv[:4]))
print(mcp.toInt32(rcv[4:]))

参考

伝文フォーマット

一括読出し

D100から10ワード読出しコマンド

サブヘッダ ネットワーク番号 PC番号 要求先ユニットI/O番号 要求先ユニット局番号
50 00 00 FF FF 03 00
要求データ長 *1 監視タイマ コマンド サブコマンド *2 先頭番号 デバイスコード 点数
0C 00 10 00 01 04 00 00 64 00 00 A8 0A 00

*1 要求データ長から後ろのバイト数
*2 ビット読出しのときはサブコマンドを01 00にする

正常時の応答伝文
サブヘッダ ネットワーク番号 PC番号 要求先ユニットI/O番号 要求先ユニット局番号
D0 00 00 FF FF 03 00
応答データ長 *1 終了コード 読出しデータ
16 00 00 00 ...

*1 応答データ長から後ろのバイト数

一括書込み

D100から10ワード書込みコマンド

サブヘッダ ネットワーク番号 PC番号 要求先ユニットI/O番号 要求先ユニット局番号
50 00 00 FF FF 03 00
要求データ長 *1 監視タイマ コマンド サブコマンド *2 先頭番号 デバイスコード
20 00 10 00 01 14 00 00 64 00 00 A8
点数 書込みデータ
0A 00 01 00 02 00 03 00 04 00 05 00 06 00 07 00 08 00 09 00 0A 00

*1 要求データ長から後ろのバイト数
*2 ビット読出しのときはサブコマンドを01 00にする

正常時の応答伝文
サブヘッダ ネットワーク番号 PC番号 要求先ユニットI/O番号 要求先ユニット局番号
D0 00 00 FF FF 03 00
応答データ長 *1 終了コード
02 00 00 00

*1 応答データ長から後ろのバイト数

14
10
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
10