OMRONの通信プロトコルのFINSコマンドをpythonで送る
FINSコマンドはメッセージサービス用の通信コマンドでPC-PLC間やPLC-デバイス間で使用されています
pythonを使ってEtherenetでPLCとメッセージ通信するクラスを作りました
環境
Windows10
python3.9
PLC OMRON CJ/NJ/NX series
ファンクション一覧
メソッド名 | 内容 |
---|---|
read | メモリエリアの読み出し |
write | メモリエリアへ書き込み |
fill | メモリエリアの一括書き込み |
run | 動作モード切り替え |
stop | プログラムモードに切り替え |
ReadUnitData | CPUユニット情報の読出し |
ReadUnitStatus | CPUユニットステータスの読出し |
ReadCycletime | サイクルタイム読出し |
Clock | 時間情報の読出し |
SetClock | 時間情報の書込み |
ErrorClear | 異常解除 |
ErrorLogRead | 異常履歴の読出し |
ErrorLogClear | 異常履歴のクリア |
SendCommand | その他のFINSコマンドを送信 |
使い方
インスタンスの作成 fins(IPAddress, 相手FinsAddress, 自分FinsAddress)
finsudp = fins('192.168.250.1', '0.1.0', '0.10.0')
finsクラスは通信相手のIPアドレス, 相手のFINSアドレス, 自分のFINSアドレスを指定してオブジェクトを作ります
FINSアドレスを省略すると相手のIPアドレスの下1桁の数値をノードとして相手先FINSアドレスとします
finsクラスは通信相手のIPアドレスと相手と自分のFINSアドレスを指定してインスタンスを作ります
FINSアドレスとは 「FINSネットワークアドレス . ノードアドレス . 号機アドレス」の3つの数字を . (ドット)でつなぎます
ネットワークアドレスは直接接続することを想定して 0 (自ネットワーク)にしています
ノードアドレスはIPアドレスの一番下の数値と合わせて受信側(PLC)は 1 を、送信元(PC)はIPアドレスは192.168.250.10としているので 10 としています
号機アドレスは 0 (CPU宛て)とします
read(address, num)
# E0_30000から10CH読出し
data = finsudp.read('E0_30000', 10)
上で作ったオブジェクトのreadメソッドでアドレスとCH数を指定して値を読み出します
アドレスはCIOは000、DMはD0、EMはE0_0、WRはW0のように指定します
読み出したデータはバイト列(bytes)で受け取ります
write(address, data)
# E0_0からdataを書込み
rcv = finsudp.write('E0_0', data)
writeメソッドでアドレスと書き込みデータを渡して書き込みます
書き込みデータdataはバイト列(bytes)で渡します
fill(address, num, data)
# D110から10CH分(D110-119)に55を書込み
rcv = finsudp.fill('D110', 10, 55)
連続したメモリエリアに同一のデータを書き込みます
run(mode)
# 動作モード切り替え (0x02=Monitor 0x04=Run)
rcv = finsudp.run(0x02)
stop()
# プログラムモードに切り替え
rcv = finsudp.stop()
ReadUnitData()
# CPUユニット情報の読出し
rcv = finsudp.ReadUnitData()
レスポンス内容
byte数 | 4 | 20 | 20 | 40 | 12 |
---|---|---|---|---|---|
内容 | 05 01 00 00 | CPUユニットの形式 | システムバージョン | システム情報 | エリア情報 |
ReadUnitStatus()
# CPUユニットステータスの読出し
rcv = finsudp.ReadUnitStatus()
レスポンス内容
byte数 | 4 | 1 | 1 | 2 | 2 | 2 | 2 | 16 |
---|---|---|---|---|---|---|---|---|
内容 | 06 01 00 00 | 運転状態 | 動作モード | 運転停止異常情報 | 運転継続異常情報 | メッセージ有無 | 故障コード | 異常メッセージ |
ReadCycletime()
# サイクルタイム読出し
rcv = finsudp.ReadCycletime()
レスポンス内容
byte数 | 4 | 4 | 4 | 4 |
---|---|---|---|---|
内容 | 06 20 00 00 | 平均 | 最大 | 最小 |
Clock()
# 時間情報の読出し
rcv = finsudp.Clock()
レスポンス内容
byte数 | 4 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
---|---|---|---|---|---|---|---|---|
内容 | 07 01 00 00 | 年 | 月 | 日 | 時 | 分 | 秒 | 曜日 |
SetClock(datetime)
# 時間情報の書込み(PCの時間を書込み)
rcv = finsudp.SetClock(datetime.now())
ErrorClear()
# 異常解除
rcv = finsudp.ErrorClear()
発生中の異常を解除
ErrorLogRead()
# 異常履歴の読出し 最新10件
rcv = finsudp.ErrorLogRead()
レスポンス内容
byte数 | 4 | 2 | 2 | 2 | 10 | ... | 10 |
---|---|---|---|---|---|---|---|
内容 | 21 02 00 00 | レコード最大数 | 格納数 | 読出しレコード数 | 異常履歴データ | ... | 異常履歴データ |
ErrorLogClear()
# 異常履歴のクリア
rcv = finsudp.ErrorLogClear()
SendCommand()
cmd = bytearray([0x05,0x01])
rcv = finsudp.SendCommand(cmd)
FINSコマンドを直接送信するメソッドです
データ変換
print (finsudp.toInt16(data))
受け取ったデータのバイト列(bytes)を変換するためのメソッド
バイト列のデータがどのようなデータかによってメソッドが変わります
メソッド名 | 変換するデータの長さ |
---|---|
toInt16 | 16bit数値 |
toUInt16 | 16bit符号なし |
toInt32 | 32bit数値 |
toUInt32 | 32bit符号なし |
toInt64 | 64bit数値 |
toUInt64 | 64bit符号なし |
toFloat | 浮動小数点 |
toDouble | 倍精度 |
toString | 文字列 |
サンプル
# D100から10CH分のデータを読出し
data = finsudp.read('D100', 10)
print (finsudp.toInt16(data))
出力
> [1, 2, 500, 1000, 30000, 32767, -1, 0, 0, 0]