今回の記事ではPhoenixContactのAXL SE RS485とModbus_RTUライブラリの組わせてModbus RTU Masterを立ち上げ、SchneiderのTM221にあるModbus RTU Slaveと通信します。
さ、はじめよう!
AXL SE RS485
このSmart Elementは、バス・システム上でシリアル・インタフェース(RS485)を持つ標準I/Oデバイスとして使用されます。
- RS-485形式のシリアル入出力チャンネル
- 伝送速度は230,400bpsまで設定可能
- データビット数、ストップビット数、パリティを設定可能
Internal circuit diagram
こちらはAXL SE RS485の内部構成図です。
Layout
こちらはAXL SE RS485モジュールのLayoutです。
LED
こちらはAXL SE RS485モジュールのLEDが持つ意味です。
Wiring Example
RS-485では、2本の信号線で構成される既存のネットワークを利用して、複数の機器によるネットワークを構築することができます。デバイスの接続には、twisted-pairの共通シールドデータケーブルを使用し、そしてRS-485ネットワークの両端のデータケーブルに終端抵抗を取り付けます。
このためには、Smart Elementに内蔵された終端抵抗を、接続R+とR-を介して使用することができます。
注意するのは、AXL SE RS485は半二重伝送にのみ対応していることです。複数の機器から同時にデータが送信されないようにしてください。
Smart Element as the network endpoint
AXL SE RS485がネットワークのEndpointデバイスとして使用する場合の配線例です。
Smart Element in the middle of a network
AXL SE RS485がネットワークの中間デバイスとして使用する場合の配線例です。
Download Library
下記のLinkからPLCNEXT StoreにModbus RTUのライブラリをDownloadしましょう。
https://www.plcnextstore.com/us/app/1432
Downloadボタンをクリックします。
ライセンスに同意しライブラリをDownloadします。
このようなZip FileがDownloadされました。
Function Block/Data Types
ライブラリに含まれているすべてのFunction Blockを説明するのは無理なので、今回記事で使用したFunction Blockのみ説明します。
MB_UDT_RTU_FC_DIAG
MB_UDT_RTU_SND_DIAG : STRUCT iState : INT; wDiagCode : WORD; wAddDiagCode : WORD; bControlByte0 : BYTE; bStatusByte0 : BYTE; END_STRUCT; |
MB_UDT_AXL_SE_RS485_DIAG_MASTER
MB_UDT_AXL_SE_RS485_DIAG_MASTER : STRUCT udtMB_AXL_RS_UNI_REC_Diag : MB_UDT_RTU_REC_DIAG; udtMB_AXL_RS_UNI_SND_Diag : MB_UDT_RTU_SND_DIAG; udtMB_RTU_Master_Diag : MB_UDT_RTU_MASTER_DIAG; END_STRUCT; |
MB_UDT_RTU_REC_DIAG
MB_UDT_RTU_REC_DIAG : STRUCT iState : INT; wDiagCode : WORD; wAddDiagCode : WORD; bControlByte0 : BYTE; bStatusByte0 : BYTE; END_STRUCT; |
MB_UDT_RTU_SND_DIAG
MB_UDT_RTU_SND_DIAG : STRUCT iState : INT; wDiagCode : WORD; wAddDiagCode : WORD; bControlByte0 : BYTE; bStatusByte0 : BYTE; END_STRUCT; |
MB_UDT_RTU_MASTER_DIAG
MB_UDT_RTU_MASTER_DIAG : STRUCT iState : INT; wDiagCode : WORD; wAddDiagCode : WORD; END_STRUCT; |
arrModbus2_W_1_125
arrModbus2_W_1_125 : ARRAY [1..125] OF WORD; |
arrModbus2_W_1_123
arrModbus2_W_1_123 : ARRAY [1..123] OF WORD; |
MB2_AXL_RSUNI2_ARR_B_0_19
MB2_AXL_RSUNI2_ARR_B_0_19 : ARRAY [0..19] OF BYTE |
udtModbus2_Data
udtModbus2_Data : STRUCT (* Modbus handling *) (* Send Modbus request *) xSendRequest : BOOL; (* Indicates FC wants to send a Modbus request *) xNDR : BOOL; (* New modbus response received *) xBusy : BOOL; (* FC only operates if not busy *) xReset : BOOL; (* Reset from input on master FB *) tTimeout : TIME; (* Input tTimeout of the Modbus_Master FB*) (* General Modbus data *) uiSlaveAddress : UINT; (* Address of the Modbus slave *) iFunctionCode : INT; (* Function Code by the Master *) uiStartAddress : UINT; (* Starting address in the Modbus register table *) iSndDataCount : INT; (* Required data length from FC *) iExpDataCount : INT; (* Expected data length depending of the function code number OF bits or words *) uiRcvdDataCount : UINT; (* Received bytes from Serial IF / UINT for the range higher than 127 *) arrData : arrModbus2_W_1_125; (* Modbus telegram *) (* Failure handling (master outputs) *) xMasterActive : BOOL; (* Interface is ready *) xMasterBusy : BOOL; (* Interface is busy *) xMasterError : BOOL; (* Error indication *) wMasterDiagCode : WORD; (* Diagnostics code *) wMasterAddDiagCode : WORD; (* Additional diagnostics code *) xMB_Error : BOOL; (* Exception Code Response *) xFC_Busy : BOOL; (* FC catches bit IF request and not xFC_Busy *) END_STRUCT; |
MB_RTU_FC4
このFunction Blockは Modbus SlaveからInput Registerを読み取ります。
VAR_INPUT
Variable Name | Type | Description |
xActivate | BOOL | True=FBを有効する |
xSendRequest | BOOL | 立ち上がりでマスター・ブロックへの送信リクエストを送ります立ち下がり信号は現在のModbusエラーを削除し、なおかつFB出力をResetします。 |
xEnablePoll | BOOL | 立ち上げ信号でサイクル・ポーリングを始めます。 |
tPollIntervall | TIME | xEnablePollが有効な場合の送信時間間隔 |
uiSlaveAddress | UINT | 通信するSlave IDを指定する(1~255) |
uiStartAddress | UINT | Slaveで読み出しの開始アドレスを指定する |
iDataCount | INT | Skaveで読み出すデバイス数を指定する(1~2000) |
VAR_OUTPUT
Variable Name | Type | Description |
xActive | BOOL | True=FBを有効してる |
xBusy | BOOL | True=FBが実行中 |
xDone | BOOL | True=リクエストが送信され、スレーブからのレスポンスが正常に受信される |
xError | BOOL | True=FBがエラーあり、詳しくはwDiagCodeとwAddDiagCodeに参照 |
wDiagCode | WORD | FB診断情報 |
wAddDiagCode | WORD | FB診断情報2 |
udtDiag | MB_UDT_RTU_FC_DIAG | 診断用の内部変数を持つ構造体変数 |
VAR_INOUT
Variable Name | Type | Description |
arrReadData | arrModbus2_W_1_125 | Modbus データが含まれている構造体になります |
udtMBData | udtModbus2_Data | MB_AXL_SE_RS485_Masterと通信するInterface |
MB_RTU_FC16
このFunction Blockはデータを Modbus のMultiple Holding Registerに書き込みます。
VAR_INPUT
Variable Name | Type | Description |
xActivate | BOOL | True=FBを有効する |
xSendRequest | BOOL | 立ち上がりでマスター・ブロックへの送信リクエストを送ります立ち下がり信号は現在のModbusエラーを削除し、なおかつFB出力をResetします。 |
xEnablePoll | BOOL | 立ち上げ信号でサイクル・ポーリングを始めます。 |
tPollIntervall | TIME | xEnablePollが有効な場合の送信時間間隔 |
uiSlaveAddress | UINT | 通信するSlave IDを指定する(0~255) |
uiStartAddress | UINT | Slaveで読み出しの開始アドレスを指定する |
iDataCount | INT | Skaveで読み出すデバイス数を指定する(1~123) |
VAR_OUTPUT
Variable Name | Type | Description |
xActive | BOOL | True=FBを有効してる |
xBusy | BOOL | True=FBが実行中 |
xDone | BOOL | True=リクエストが送信され、スレーブからのレスポンスが正常に受信される |
xError | BOOL | True=FBがエラーあり、詳しくはwDiagCodeとwAddDiagCodeに参照 |
wDiagCode | WORD | FB診断情報 |
wAddDiagCode | WORD | FB診断情報2 |
udtDiag | MB_UDT_RTU_FC_DIAG | 診断用の内部変数を持つ構造体変数 |
VAR_INOUT
Variable Name | Type | Description |
arrReadData | arrModbus2_W_1_123 | 長さ123 Wordの配列で、Multiple Holding Registerに書き込むための変数 |
udtMBData | udtModbus2_Data | MB_AXL_SE_RS485_Masterと通信するInterface |
MB_AXL_SE_RS485_Master
.このFunction Blockは、指定されたモジュール(今回はAXL SE RS485)の Modbus Masterを実装するために使用されます。
VAR_INPUT
Variable Name | Type | Description |
xActivate | BOOL | True=Function Blockを有効する |
tModbus_Timeout | TIME | Modbus RTUとSlaveの通信Timeout時間Default=TIME#5s |
tPD_Timeout | TIME | PLCとモジュール(今回はAXL SE RS485)のProcess Data通信Timeout時間 |
xReset | BOOL | True=FBをリセットする(注意するのは内部のFC Blocksも含めてリセットされる) |
VAR_OUTPUT
Variable Name | Type | Description |
xActive | BOOL | True=FBを有効してる |
xBusy | BOOL | True=FBが実行中 |
uiRequestsCounter | UINT | 送信リクエスト数 |
uiResponsesCounter | UINT | 受信リクエスト数 |
udtDiag | MB_UDT_AXL_SE_RS485_DIAG_MASTER | 診断情報の構造体 |
VAR_INOUT
Variable Name | Type | Description |
udtMBData | udtModbus2_Data | MB_AXL_SE_RS485_Masterが他のMB_RTU_FCXX Blockと通信するInterface |
arrInputData | MB2_AXL_RSUNI2_ARR_B_0_19 | AXL SE RS485モジュールのProcess Input Data |
arrOutputData | MB2_AXL_RSUNI2_ARR_B_0_19 | AXL SE RS485モジュールのProcess Output Data |
Implementation
Schneider Side
Modbus RTU Slave Configuration
EcoStruxure Machine Expert Basicを立ち上げ、Configuration>SL1を開いてシリアル通信Portを設定します。
Serial line configuration
ProtocolをModbusに設定し、なおかつ通信速度なども設定しましょう。
Modbus Configuration
次はTM221をModbus Slaveとして立ち上げたいので、SL1>Modbusを開きます。
Tranmission ModeをRTUにし、AddressingをSlaveを選択し、Addressを設定しましょう。
Program
次は検証用のプログラムを作成します。Modbus RTU Masterから受信したデータをそのままFeedbackするようなLoop-Backプログラムです。
PLCNEXT Side
Import Library
先程PLCNEXT StoreからDownloadしたライブラリを解凍し、中にDocumentsとFilesのFolderがあり、DocumentsはライブラリのManualで、Filesはライブラリの本体や使用例が格納されています。
ライブラリの本体はPCWLX Fileで、そのFileを下記のPathに複製してください。
C:\Users\Public\Documents\PLCnext Engineer\Libraries
PLCNEXT Engineeringを起動し、COMPONENTS>右クリック>Add User Libraryでライブラリを追加します。
先程複製したPCWLX Fileを開きましょう。
Done!Modbus_RTUライブラリがプロジェクトに追加されました。
ProgrammingにもModbus_RTUのFolderが追加され、中にPLCNEXTのシリアル通信のライブラリが入っています。
今回はSmart ElementsのRS485モジュールからModbus RTU Masterを立ち上げるので、MB_AXL_SE_RS485_Masterを使用することになります。
Add Module
プロジェクトにAXL SE RS485モジュールを追加するため、Axioline Fをダブルクリックします。
Device List画面が表示されます。
今回はSlot3にAXL SE RS485がインストールされたので、#3のType Fieldをクリックし>AXL SE RS485を選択しましょう。
Done!
Data ListにはAXL SE RS485モジュールの関連変数も自動的に宣言されました。
Settings
次はAXL SE RS485のモジュール設定を行います。
AXL SE RS485の通信パラメータをSchneider PLC側のModbus RTU Slaveに合わせて設定していきましょう。
Data Types
DUT_ModbusRTU
DUT_ModbusRTUは今回記事で使用する構造体をまとめるためのData Type定義Sheetです。
DUT_MB_RTU_MASTER
こちらの構造体はMB_AXL_SE_RS485_Master Function Blockに使用するINPUT/OUTPUT/INOUTパラメータをまとめて定義します。
DUT_MB_RTU_MASTER : STRUCT //Inputs xActivate : BOOL; xReset : BOOL; xMode : BOOL; tModbus_Timeout : TIME; tPD_Timeout : TIME; //Output xActive : BOOL; xBusy : BOOL; uiRequestsCounter : UINT; uiResponsesCounter : UINT; xError : BOOL; //InOut udtDiag : MB_UDT_AXL_SE_RS485_DIAG_MASTER; END_STRUCT |
DUT_MB_RTU_FC16
こちらの構造体はMB_RTU_FC16 Function Blockに使用するINPUT/OUTPUT/INOUTパラメータをまとめて定義します。
DUT_MB_RTU_FC16 : STRUCT //Inputs xActivate : BOOL; xSendRequest : BOOL; xEnablePoll : BOOL; tPollInterval : TIME; uiSlaveAddress : UINT; uiStartAddress : UINT; iDataCount : INT; //Outputs xActive : BOOL; xBusy : BOOL; xDone : BOOL; xError : BOOL; wDiagCode : WORD; wAddDiagCode : WORD; udtDiag : MB_UDT_RTU_FC_DIAG; //InOut arrRegisterValues : arrModbus2_W_1_123; END_STRUCT; |
DUT_MB_RTU_FC4
こちらの構造体はMB_RTU_FC4 Function Blockに使用するINPUT/OUTPUT/INOUTパラメータをまとめて定義します。
DUT_MB_RTU_FC4 : STRUCT //Inputs xActivate : BOOL; xSendRequest : BOOL; xEnablePoll : BOOL; tPollInterval : TIME; uiSlaveAddress : UINT; uiStartAddress : UINT; iDataCount : INT; //Outputs xActive : BOOL; xBusy : BOOL; xDone : BOOL; xError : BOOL; wDiagCode : WORD; wAddDiagCode : WORD; udtDiag : MB_UDT_RTU_FC_DIAG; //InOut arrRegisterValues : arrModbus2_W_1_125; END_STRUCT |
DUT_MB_Modbus_RTU
こちらの構造体は先程定義したものをまとめた構造体です。
DUT_MB_Modbus_RTU : STRUCT iState : INT; udtMBData : udtModbus2_Data; udtMB_AXL_SE_RS485_Master : DUT_MB_RTU_MASTER; udtMB_RTU_FC16 : DUT_MB_RTU_FC16; udtMB_RTU_FC4 : DUT_MB_RTU_FC4; END_STRUCT; |
Program
次はプログラムを作成します。
Flow
VAR
今回使用する変数をMainプログラムに定義します。
AXL_SE_RS485_Master | AXL SE RS485にModbus RTU Masterを立ち上げするためのInstance |
RTU_Master | 先程定義した構造体で、Function Blockのパラメータに割り付ける変数が含まれています |
arrInputPD | AXL SE RS485モジュールのProcess Input Data |
arrOutputPD | AXL SE RS485モジュールのProcess Output Data |
RTU_FC16 | Modbus RTU Function Code 16を発行するInstnace |
RTU_FC4 | Modbus RTU Function Code 4を発行するInstnace |
iCounter | PLCNEXT側がSchneider PLCに書き込むのデータ |
xRTUError | Modbus RTU通信エラー発生のFlag |
xRTUReset | Modbus RTUプログラムをリセットするデバイス |
arrRegisterValues | Schneider PLCから読み取ったデータを格納するBuffer |
iLoop | FOR Loop用のCounter |
Code
こちらは実際のプログラムです。
i16_w_Int:=i16_w_Int+1;
r32_w_real:=r32_w_real+0.01;
if r32_w_real>=10000.0 THEN
r32_r_Real:=0.0;
end_if;
case RTU_Master.iState OF
0:
//Parameters Init
RTU_Master.udtMB_AXL_SE_RS485_Master.tModbus_Timeout:=T#5s;
RTU_Master.udtMB_AXL_SE_RS485_Master.tPD_Timeout:=T#2s;
xRTUError:=False;
xRTUReset:=false;
RTU_Master.udtMB_RTU_FC16.xActivate:=false;
RTU_Master.udtMB_RTU_FC16.xSendRequest:=False;
RTU_Master.udtMB_RTU_FC4.xActivate:=false;
RTU_Master.udtMB_RTU_FC4.xSendRequest:=False;
RTU_Master.udtMB_AXL_SE_RS485_Master.xActivate:=False;
if not RTU_Master.udtMB_AXL_SE_RS485_Master.xBusy THEN
RTU_Master.iState:=10;
end_if;
10:
//Startup the RS485-Master
RTU_Master.udtMB_AXL_SE_RS485_Master.xActivate:=True;
if RTU_Master.udtMB_AXL_SE_RS485_Master.xActive THEN
RTU_Master.iState:=20;
END_IF;
if RTU_Master.udtMB_AXL_SE_RS485_Master.xError THEN
RTU_Master.iState:=9990;
end_If;
20:
//Data Init of FC16 Command
RTU_Master.udtMB_RTU_FC16.xEnablePoll:=False;
RTU_Master.udtMB_RTU_FC16.uiSlaveAddress:=1;
RTU_Master.udtMB_RTU_FC16.uiStartAddress:=1;
RTU_Master.udtMB_RTU_FC16.iDataCount:=5;
if iCounter >=100 THEN
iCounter:=1;
END_IF;
iCounter:=iCounter+1;
RTU_Master.udtMB_RTU_FC16.arrRegisterValues[1]:=TO_WORD(iCounter);
RTU_Master.udtMB_RTU_FC16.arrRegisterValues[2]:=TO_WORD(iCounter*10);
RTU_Master.udtMB_RTU_FC16.arrRegisterValues[3]:=TO_WORD(iCounter*20);
RTU_Master.udtMB_RTU_FC16.arrRegisterValues[4]:=TO_WORD(iCounter*30);
RTU_Master.iState:=30;
30:
//Activate the Function block of FC16
RTU_Master.udtMB_RTU_FC16.xActivate:=True;
if RTU_Master.udtMB_RTU_FC16.xActive THEN
RTU_Master.iState:=40;
END_IF;
if RTU_Master.udtMB_RTU_FC16.xError THEN
RTU_Master.iState:=9991;
end_if;
40:
//Send the request to slave with Function Code 16
RTU_Master.udtMB_RTU_FC16.xSendRequest:=True;
if RTU_Master.udtMB_RTU_FC16.xDone THEN
RTU_Master.udtMB_RTU_FC16.xSendRequest:=False;
RTU_Master.iState:=45;
end_if;
if RTU_Master.udtMB_RTU_FC16.xError THEN
RTU_Master.iState:=9992;
end_if;
45:
//Data Init of FC4 Command and Reset FC16 Command
RTU_Master.udtMB_RTU_FC16.xActivate:=False;
RTU_Master.udtMB_RTU_FC4.xEnablePoll:=False;
RTU_Master.udtMB_RTU_FC4.uiSlaveAddress:=1;
RTU_Master.udtMB_RTU_FC4.uiStartAddress:=11;
RTU_Master.udtMB_RTU_FC4.iDataCount:=5;
RTU_Master.iState:=50;
50:
//Check if the FB is reset
if RTU_Master.udtMB_RTU_FC16.xActive=False THEN
RTU_Master.iState:=60;
end_If;
60:
//Activate the Function block of FC4
RTU_Master.udtMB_RTU_FC4.xActivate:=True;
for iLoop :=1 to 125 DO
arrRegisterValues[iLoop]:=0;
end_for;
if RTU_Master.udtMB_RTU_FC4.xActive THEN
RTU_Master.iState:=70;
END_IF;
if RTU_Master.udtMB_RTU_FC4.xError THEN
RTU_Master.iState:=9993;
end_if;
70:
//Send the request to slave with Function Code 4
RTU_Master.udtMB_RTU_FC4.xSendRequest:=True;
if RTU_Master.udtMB_RTU_FC4.xDone THEN
RTU_Master.udtMB_RTU_FC4.xSendRequest:=False;
RTU_Master.udtMB_RTU_FC4.xActivate:=False;
arrRegisterValues:=RTU_Master.udtMB_RTU_FC4.arrRegisterValues;
RTU_Master.iState:=80;
end_if;
if RTU_Master.udtMB_RTU_FC4.xError THEN
RTU_Master.iState:=9994;
end_if;
80:
//Check if the FB is reset
if RTU_Master.udtMB_RTU_FC4.xActive=False THEN
RTU_Master.iState:=20;
end_If;
9991,9992,9993,9994:
//Error
xRTUError:=True;
if xRTUReset THEN
RTU_Master.iState:=0;
end_if;
end_case;
//Function Block for smart elements
AXL_SE_RS485_Master(
xActivate:=RTU_Master.udtMB_AXL_SE_RS485_Master.xActivate
,tModbus_Timeout:=RTU_Master.udtMB_AXL_SE_RS485_Master.tModbus_Timeout
,tPD_Timeout:=RTU_Master.udtMB_AXL_SE_RS485_Master.tPD_Timeout
,xReset:=RTU_Master.udtMB_AXL_SE_RS485_Master.xReset
,xActive=>RTU_Master.udtMB_AXL_SE_RS485_Master.xActive
,xBusy=>RTU_Master.udtMB_AXL_SE_RS485_Master.xBusy
,uiRequestsCounter=>RTU_Master.udtMB_AXL_SE_RS485_Master.uiRequestsCounter
,uiResponsesCounter=>RTU_Master.udtMB_AXL_SE_RS485_Master.uiResponsesCounter
,xError=>RTU_Master.udtMB_AXL_SE_RS485_Master.xError
,udtDiag=>RTU_Master.udtMB_AXL_SE_RS485_Master.udtDiag
,udtMbData:=RTU_Master.udtMBData
,arrInputData:=arrInputPD
,arrOutputData:=arrOutputPD
)
;
//Function Block of FC16
RTU_FC16(
xActivate:=RTU_Master.udtMB_RTU_FC16.xActivate
,xSendRequest:=RTU_Master.udtMB_RTU_FC16.xSendRequest
,xEnablePoll:=RTU_Master.udtMB_RTU_FC16.xEnablePoll
,uiSlaveAddress:=RTU_Master.udtMB_RTU_FC16.uiSlaveAddress
,uiStartAddress:=RTU_Master.udtMB_RTU_FC16.uiStartAddress
,iDataCount:=RTU_Master.udtMB_RTU_FC16.iDataCount
,xActive=>RTU_Master.udtMB_RTU_FC16.xActive
,xBusy=>RTU_Master.udtMB_RTU_FC16.xBusy
,xDone=>RTU_Master.udtMB_RTU_FC16.xDone
,xError=>RTU_Master.udtMB_RTU_FC16.xError
,wDiagCode=>RTU_Master.udtMB_RTU_FC16.wDiagCode
,wAddDiagCode=>RTU_Master.udtMB_RTU_FC16.wAddDiagCode
,arrRegisterValues:=RTU_Master.udtMB_RTU_FC16.arrRegisterValues
,udtMbData:=RTU_Master.udtMBData
)
;
//Function Block of FC4
RTU_FC4(
xActivate:=RTU_Master.udtMB_RTU_FC4.xActivate
,xSendRequest:=RTU_Master.udtMB_RTU_FC4.xSendRequest
,xEnablePoll:=RTU_Master.udtMB_RTU_FC4.xEnablePoll
,uiSlaveAddress:=RTU_Master.udtMB_RTU_FC4.uiSlaveAddress
,uiStartAddress:=RTU_Master.udtMB_RTU_FC4.uiStartAddress
,iDataCount:=RTU_Master.udtMB_RTU_FC4.iDataCount
,xActive=>RTU_Master.udtMB_RTU_FC4.xActive
,xBusy=>RTU_Master.udtMB_RTU_FC4.xBusy
,xDone=>RTU_Master.udtMB_RTU_FC4.xDone
,xError=>RTU_Master.udtMB_RTU_FC4.xError
,wDiagCode=>RTU_Master.udtMB_RTU_FC4.wDiagCode
,wAddDiagCode=>RTU_Master.udtMB_RTU_FC4.wAddDiagCode
,arrReaddata:=RTU_Master.udtMB_RTU_FC4.arrRegisterValues
,udtMbData:=RTU_Master.udtMBData
)
;
Mapping
先程arrInputPDとarrOutputPDのIN Port・Out Port変数を定義しましたが、この変数をAXL SE RS485モジュールのProcess Dataと紐つける必要があります。
Mainプログラムを開きます。
MainプログラムのGDS Port List画面が表示されました。
IN Port
IN PortはAXL SE RS485のProcess Output Dataと紐つけるため、IN Port欄を選択し>Axioline F>Serial-1/~DO160を設定します。
Done!
OUT Port
IN PortはAXL SE RS485のProcess Input Dataと紐つけるため、OUT Port欄を選択し>Axioline F>Serial-1/~DI160を設定します。
Done!
Structure
こちらは実際のプログラムの構造です。
Result
Done!プログラムがエラーなしで稼働しています。
RTU_Masterの構造体変数をMonitorします。
リクエストのCounterとリスボンのCounterも加算され、Slaveと通信してることがわかります。
Schneider TM221がLoopbackしたデータが受信できました。
同じく、Schneider TM221からもPLCNEXTのデータを受信できました。
こちらの動画から実際にAXL SE RS485が正常ときのLED Statusを確認できます。
Download
こちらのLinkからプロジェクトをDownloadできます。
https://github.com/soup01Threes/PLCNEXT/blob/main/Project-RS485pcwex.pcwex