今回はSiemensのPLCでModbus TCP serverを使うときの手順を説明します。
TIAバージョン

実機バージョン

Function Block

ではまずF1でHelpをみましょう。
このMB_SERVER命令はModbus TCP serverとして動作しProfinet接続に通じてModbus TCP Clientと接続、送信、通信とModbusリクエストを処理することができます。
S7-1200
―FirmwareV4.0ではこの命令のバージョンV3.1まで使えます。
―FirmwareV4.1ではこの命令バージョン全て使えます。
S7-1500
―この命令バージョン全て使えます。
!注意
セキュリティ上ではModbus ClientはModbus holding register上のメモリエリア全て読み書きすることができます。なので、ServerにアクセスできるClientのIPアドレスは制限するのはおすすめです。
INPUT
DISCONNECT:Bool
– 0:Passive Connectionが確立する。
-1:Connectionは“TCON_IP_v4”に元にいて設定初期化する。初期化成功したらSTATUSは3にアウトプットされます。
InOut
MB_HOLD_REG:Variant
Siemensを使っている人にもVariantに対してわけわからない人も多いと思いますが、私いつも“なんでもあり”ということを説明します。つまり、この変数は結局単なるBoolでもいいし、構造体でもいいし、配列でもいいし、なんでも変数として扱えるってことです。
このFunctionのVariantほしいのはMemory Areaです。Modbus サーパーとして働いてるから当然Clientから読み書きしたいMemory Areaがあります。例えばParameterなど…
注意:
- Memory Area最低2Byteにしましょう。
- アクセスできるのはModbus Function 3(よみ)、6(書き)、16(マルチ書き)と23(一つJobでマルチ書き)だけになります。
CONNECT:Variant
このCONNECTパラメータ使えいるのSDT(System Data Type)は二種類があります。
TCON_IP_V4:通信成立するため必要なネットワークパラメータが含められてる。Defaultアドレスは0.0.0.0です。もちろんプログラム上で変更することが可能です。このSDTを使うと、通信成立するには“MB_SERVER”が呼びされてるときです。
TCON_Configured:アドレスパラメータのみが入っています。もしこのSDTを使うと、通信成立するにはCPUがハードウェア構成をダウンロードされたあとになります。
Output
NDR
“New Data Ready”
0:新しいデータが来てません。
1:新しいデータが来ています(つまりClientから書き込みあります)。
DR
“Data Read”
0:データが読み込まれいません。
1:データがClientに読み込まれいます。
ERROR
MB_SERVERが実行してるときにエーラがあれば1になります。STATUSにはそのエラーコードが帰っています。
STATUS
MB_SERVERの実行状態が見えます。
TCON_IP_V4とは?
まずData Typeのところに“TCON_IP_v4”を入れれば、自動的変数が作られいます。

InterfaceId
あなたがModbus TCP/IPに使う予定のPortのIDです。
今回はS7-1200のPortを使うので、64ですね。

ID
1個目のMB_SERVERはIDを1にしましょう。もし一台のCPUの中に複数のMB_SERVERがあればこのIDをかぶれないようにしましょう。
ConnectionType
11はTCP/IP、19はUDP
ActiveEstablished
いわゆるActiveかPassiveですね。今回はPassiveにします。
RemoteAddress
長さ4のByte配列です。ここで接続しようとするClientのIPを設定できます。0.0.0.0ならどこのClientでも接続できます。
RemotePort
相手のPortです。もしClientに特にPortのアクセス制限がなければ0にいいでしょう 。
LocalPort
自分のPortで接続されたClientと通信を監視するPortになります。
これで、パラメータある程度把握できましたね。
実装
これは私のやりかたですが、こういう構造体(Variant)が必要されるとき、もしパラメータそんなに多くなければいつも細かくばらします。つまりこうですね。これは私が作ったClass_ModbusServerのFunction Blockです。
Inputのところが多いと思われますが、よくみたら単なるTCON_IP_V4とMB_SERVERの変数だけです。そしてOutputはMB_SERVERの出力だけですね。

注意するのはioMB_HOLD_REGですね。ここに入れるのはP#DB3.DBX0.0です。このDB中には51のIntが入っています。

Input Interface

Output Interface

InOut Interface

Static Interface

Network3-10
パラメータをCONNECT変数に転送するだけです。








Network11
MB_SERVERを呼び出します。先Network3-10まで転送した変数CONNECTをこおで使えいます。

Network13
DISCONNECT=1はつまりパラメータ初期化すること。ここで読み書きのCounterをリセットします。

Netowork14
まぁ、Clientにデータを読まれたら+1するだけです。

Network15
まぁ、Clientがデータを書き込んでたときを+1するだけです。

Network17-20
MB_SERVERの実行状態を出力するだけです。




お疲れ様です!と言いたいですが、せっかくですからここでPythonを使ってModbus TCP Clientを作ってアクセスしてみよう。
使用するOSとバージョン

実装
#Library Import from pyModbusTCP.client import ModbusClient import time import random #Host,Port Settings SERVER_HOST='192.168.0.17' SERVER_PORT=502 #Client client=ModbusClient() #Debug client.debug(False) #Config client.host(SERVER_HOST) client.port(SERVER_PORT) #Connect client.open() #Read and Write while True: if not client.is_open(): if not client.open(): print('Can not connect to {},{}'.format(SERVER_HOST,SERVER_PORT)) if client.is_open(): regs=client.read_holding_registers(0,10) if regs: print('data:'+str(regs)) else: print('can not read.') reg_list=[random.randint(1,32000) for i in range(10)] regs=client.write_multiple_registers(0,reg_list) if regs: print('data is sent.') else: print('data can not sent') time.sleep(0.02) #Disconnect client.close()
ではーお疲れ様です!