Modbusの利用 (1) 電源S8VK-X
Modbusには、物理層にRS-485を使うModbus/ASCIIとRTUが、TCP/IPを使うModbus/TCPがあります。Modbusは、下記の資料が詳しいです。Modbus/RTUとModbus/TCPでは、エラー・チェックを除きデータのフォーマットは同じです。
オムロンのS8VK-Xシリーズは、カタログにModbus対応と書かれています。ここでは、5V出力のS8VK-X03005-EIPを利用します。ミスミで購入しました。このシリーズは、5~24Vの電圧、各種電流が用意されています。DINレールに取り付けられ、イーサネットのコネクタがついています。
読み出すためのユーティリティPower Supply Monitoring Toolが無料で利用できます。
●IPアドレスをふる
デフォルトで192.168.250.20が振られています。筆者のLANは192.168.111.xxxです。通常使っているPCはDHCPサーバからIPアドレスが振られます。
「スイッチングパワーサプライ 通信マニュアル」に設定方法が書かれています。有料のNetwork Configuratorと無料のPower Supply Monitoring Toolが使えます。Network Configuratorは、同社のPLC用のアプリケーションのようです。
PCを192.168.240.2(2は任意、サブネットは255.255.255.0 ゲートウェイは0.0.0.0)に変更しました。Windows10は変更後にipconfigでIPアドレスが変わっていることを確認します。PCとS8VK-Xはハブにつないでいます。pingをS8VK-Xに打って、正しく応答が返ってくることを確認します。ipconfig、pingはコマンドプロンプトで実行します。
Power Supply Monitoring ToolのIPアドレスを振る項目で、固定IPアドレス、192.168.111.20に変更しました。一度電源を入れなおし、イーサネットのLED MSとNSの両方が緑色で点滅することを確認します。正しくIPアドレスがふれなかったらNSは赤色になります。
その時は、一度電源を切り、RSTボタンを押したまま電源を入れ、10秒待ちます。これで、工場出荷時の初期状態に戻ります。
●エラーが返る
Modbus/TCPの通信手順は、「s8vk-x通信設定」に書かれています。こちらの記事「はじめてのModbus (2) Lチカ」で有用だったツールのCAS Modbus Scannerを使っても、データではないものが返ってくるというエラーが表示されます。
●ソケット・プログラムでアクセス
動作を確認するためにWindows10のPython3で、s8vk-x通信設定に書かれているコマンド列でアクセスします。
IPv4のプロトコルで、ポートはModbusの502です。送っているコマンドは、
0x00,0x00,0x00,0x00,0x00,0x06,0xff,0x03,0x00,volt,0x00,0x02
です。Modbusのメッセージ構成とは異なりますが、Read Holding Register(03)の用法とは似ています。
トランザクションID | プロトコルID | 転送バイト | ユニットID | ファンクション・コード | 開始アドレス | 読み出しワード数 | |||
---|---|---|---|---|---|---|---|---|---|
0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x06 | 0xff | 0x03 | 下記の表 | 0x0002 |
開始アドレス | データ名 | 読み出したデータの範囲 |
---|---|---|
0x0000 | ステータス | 省略 |
0x0001 | 出力電圧 | 0x0000(0.00V)~0x2706(99.90V) |
0x0002 | 出力電流 | 0x0000(0.00A)~0x2706(99.90A) |
0x0003 | ピーク・ホールド電流 | 0x0000(0.00A)~0x2706(99.90A) |
0x0004 | 交換時期までの年数 | 0x0000(0)~0x5dc0(150.0年) |
0x0005 | 交換時期までの割合 | 0x0000(0)~0x3e8(100.0%) |
0x0006 | 積算稼働時間 | 0x0000(0)~0x40290(262,800時間) |
0x0008 | 連続稼働時間 | 0x0000(0)~0xf099c0(15,768,000分) |
import socket
volt = 0x01
current = 0x02
peakcurrent = 0x03
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("192.168.111.20", 502))
print("send 0x03")
s.send(bytearray([0x00,0x00,0x00,0x00,0x00,0x06,0xff,0x03,0x00,volt,0x00,0x02]))
data = s.recv(100)
s.close()
print( int(str((hex(data[9]<<8 | data[10]))),16) /100 )
読み出した2バイトのデータ出力電圧は100倍の値なので、100で割ります。結果は5.0でした。アナログ-ディジタル変換の確度は8~10ビットと思われます。稼働しているときの電力値を得るという目的なので、十分だと言えます。