TwinCAT3のTF6250を使ってModbusTCP/IPのClientを作成します。
Manual
https://download.beckhoff.com/download/document/automation/twincat3/TF6250_TC3_Modbus_TCP_EN.pdf
インストール
以下のLinkをアクセスします。
Software and toolsのTabをクリックします。
EXEをダウンロードし、実行します。
英語を選びます。
はい、Next。
同意します、Next。
適当で、Next。
Completeを選び、Next。
Next。
しばらく待ちます…
Installを。
10分くらいで終わります。
Function Blocks
今回はレジスタを読み書きのFunction Blockを使用します。
読みはFunction3で、書きはFunction16です。
FB_MBREADREGS
このFunctionは1~128のレジスタを読みます(16Bit)。
VAR_INPUT
- sIPAddr
- STRING(15)
- TargetデバイスのIPアドレス
- nTCPPort
- UINT
- TargetデバイスのPort
- nUnitID
- WORD
- Serial sub-networkデバイスの番号です。もしTCP/IPで通信するのあれば、16#FFにしてください。
- nQuantity
- WORD
- 読むレジスタの数です。必ず0より大きくしてください。
- nMBAddr
- WORD
- 読むレジスタのアドレスOFFSET
- cbLength
- UDINT
- レジスタ読み終わった後の保存Bufferの最大SIZE
- pDestAddr
- POINTER OF BYTE
- そのBuzzerのアドレスです。
- bExecute
- BOOL
- Function Blockを実行
- tTimeout
- TIME
- Targetデバイスと接続Timeout時間
VAR_OUTPUT
- bBUSY
- BOOL
- Function Blockはいま実行してる
- bError
- BOOL
- Function Blockがエラーがあります
- nErrId
- UDINT
- Function BlockがエラーあるときのError番号
- cbRead
- UDINT
- 読みだしたのBytes数
FB_MBWriteRegs
このFunctionは1~128のレジスタを書きます(16Bit)。
VAR_INPUT
- sIPAddr
- STRING(15)
- TargetデバイスのIPアドレス
- nTCPPort
- UINT
- TargetデバイスのPort
- nUnitID
- WORD
- Serial sub-networkデバイスの番号です。もしTCP/IPで通信するのあれば、16#FFにしてください。
- nQuantity
- WORD
- 読むレジスタの数です。必ず0より大きくしてください。
- nMBAddr
- WORD
- 書くレジスタのアドレスOFFSET
- cbLength
- UDINT
- レジスタ書き終わった後の保存Bufferの最大SIZE
- pSrcAddr
- POINTER OF BYTE
- そのBuzzerのアドレスです。
- bExecute
- BOOL
- Function Blockを実行
- tTimeout
- TIME
- Targetデバイスと接続Timeout時間
VAR_OUTPUT
- bBUSY
- BOOL
- Function Blockはいま実行してる
- bError
- BOOL
- Function Blockがエラーがあります
- nErrId
- UDINT
- Function BlockがエラーあるときのError番号
実装-TwinCAT3側
まずプロジェクトを作成し、Licenseクリックします。
Manage LicenseのところにTF6250を探し>Add LicenseをCheckbox入れます。
次はModbusTCP/IPライブラリを追加します。
Tc2_ModbusSrvというライブラリを入れてください。
次はDUTsを追加します。このStepはMUSTではないですが、BlockのInterfaceは似ていますので、DUTsを作ったほうが便利ではないかな?と思っています。
まずDUT_MBを追加します。
中にbExecute・bBusy・bError・nErrId4つの変数があります。
TYPE DUT_MB : STRUCT bExecute :BOOL; bBusy :BOOL; bError :BOOL; nErrId :UDINT; END_STRUCT END_TYPE |
次DUT_MBReadsを追加し、DUT_MBからEXTENDSされています。
次はcbReadを追加します。それはFB_MBREADREGSにあるパラメータです。
TYPE DUT_MBReads EXTENDS DUT_MB : STRUCT cbRead:UDINT; END_STRUCT END_TYPE |
Interface
PROGRAM MAIN VAR //Function16 _MBWriteRegs :FB_MBWriteRegs; MBWriteRegs :DUT_MB; ar2 :ARRAY[0..99] OF INT; //Function3 _MBReadRegs :FB_MBReadRegs; MBReadRegs :DUT_MBReads; ar1 :ARRAY[0..99] OF INT; sIPAddr:STRING(15):=’192.168.000.001′; END_VAR |
プログラム
次はプログラムはFB_MBWriteRegsとFB_MBReadRegsを呼び出します。
//Write the Regs to Modbus Server Function16 _MBWriteRegs( sIPAddr:=sIPAddr ,nTCPPort:=MODBUS_TCP_PORT ,nUnitID:=255 ,nQuantity:=2 ,nMBAddr:=0 ,cbLength:=SIZEOF(ar2) ,pSrcAddr:= ADR(ar2) ,bExecute:=MBWriteRegs.bExecute ,tTimeout:=T#1S ,bBusy=>MBWriteRegs.bBusy ,bError=>MBWriteRegs.bError ,nErrId=>MBWriteRegs.nErrId ); //Read the Regs from Modbus Server Function3 _MBReadRegs( sIPAddr:=sIPAddr ,nTCPPort:=MODBUS_TCP_PORT ,nUnitID:=255 ,nQuantity:=10 ,nMBAddr:=0 ,cbLength:=SIZEOF(ar1) ,pDestAddr:=ADR(ar1) ,bExecute:=MBReadRegs.bExecute ,tTimeout:=T#1S ,bBusy=>MBReadRegs.bBusy ,bError=>MBReadRegs.bError ,nErrId=>MBReadRegs.nErrId ,cbRead=>MBReadRegs.cbRead ); |
実装-Siemens側
S7-1500を使用します。
Interface
プログラム
テスト
まずSiemens側のレジスタ0-9を読み出します。
TwinCAT3側でbExecuteをTrueにします。
そうすると、nErrIdが0になり(つまりErrorIDなし)・そしてcbReadが20Bytes(つまり10Words)が読みましたとわかっています。
そしてBufferに設定されたar1にもちゃんと値を読んでたこともわかります。
次はTwinCAT3側を書き込みたいと思います。
2つのレジスタ、0番目は16#63で1番目は16#58にします。
TwinCAT3側でbExecuteをTrueにします。
そうすると、nErrIdが0になり(つまりErrorIDなし)だとわかります。
Siemens側みれば、w0とw1はTwinCAT3側からもらった値に変わりました。
サンプルProject Link:
https://github.com/soup01Threes/TwinCAT3/blob/main/TwinCAT3_ProjectMODBUS_TCP_Client.zip