1
1

More than 3 years have passed since last update.

Siemens#Modbus TCP serverとして使う

Last updated at Posted at 2019-12-25

今回はSiemensのPLCでModbus TCP serverを使うときの手順を説明します。
ここにも文章が乗っています↓。
http://soup01.com/ja/2019/12/24/post-1948/

TIAバージョン

image.png

実機バージョン

image.png

Function Block

image.png

ではまず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”を入れれば、自動的変数が作られいます。
image.png

  • InterfaceId
    • image.png
    • あなたが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の出力だけですね。

image.png

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

Input Interface

image.png

Output Interface

image.png

InOut Interface

image.png

Static Interface

image.png

Network3-10

パラメータをCONNECT変数に転送するだけです。
image.png
image.png
image.png

Network11

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

Network13 

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

Netowork14

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

Network15

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

Network17-20

MB_SERVERの実行状態を出力するだけです。
image.png
image.png

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

PythonでModbus TCP/IPクライアント

使用するOSとバージョン

image.png

実装

#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()

ではーお疲れ様です!

1
1
0

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
1
1