The Foxtrot 1 series PLCs had a driver on the Ethernet interface to support two connections via the Modbus TCP protocol, which made the entire scratchpad area addressable by the Modbus protocol accessible. Foxtrot 2 series PLCs do not include this support and the Modbus TCP protocol is provided via the ModbusRTU library, namely the fbModbusTCPslave function block. In most cases, this block is used in such a way that it reserves user-defined fields for Modbus TCP access and the rest of the scratchpad is protected against access by this protocol.
In case the backward compatibility with the Foxtrot 1 series PLC is to be maintained, the fbModbusTCPslave block can be called to access the entire addressable area of the scratchpad identically to the original driver. The following example describes how to achieve the same behavior.
The first step is to add the ModbusRTU library to the project.
Then we add a file with the definition of the beginnings of scratchpad zones accessible by the Modbus TCP protocol. These definitions must be made in mnemonic code so that they do not conflict with user variables. Add the file to the project from the menu "File"> "New"> "New file ..." Confirm that the file is to be included in the project and select the type "Mosaic source files (* .mos)". After adding the file, it moves up in the "Project files" window so that it is the first one after the configuration file "CONFIG.HWC" in the translation and we add the following definitions to it:
;definition of the beginning of the registry
#def _X_0 %X0.0
#def _S_ %S0
#def _Y_0 %Y0.0
#def _R_ %R0
Then, by default, it is enough to add a program with a call to the fbModbusTCPslave block and add the VAR_EXTERNAL section in front of it, which will make the definitions of zone origins available to a higher language. The finished program will look like this:
//assign the beginning of the registry for a higher language
VAR_EXTERNAL
_X_0 : BOOL;
_Y_0 : BOOL;
_S_ : UINT;
_R_ : UINT;
END_VAR
PROGRAM prgModbusSlave
//program serving ModbusTCP connections
VAR CONSTANT
lastTcp : UINT := 1; //index of last connection (count-1)
END_VAR
VAR_OUTPUT
END_VAR
VAR
iTcp : UINT;
TcpSockets : ARRAY[0..lastTcp] OF UINT; //socket numbers
MdbTcp : ARRAY[0..lastTcp] OF fbModbusTCPslave; //service blocks
END_VAR
VAR_TEMP
END_VAR
FOR iTcp := 0 TO lastTcp DO
IF TcpSockets[iTcp] = 0 THEN
TcpSockets[iTcp] := OpenUniSocket(protocol := UNI_TCP_SERVER);
END_IF;
MdbTcp[iTcp](UnitID := 0, chanCode := TcpSockets[iTcp],
port := 502,
inputsCnt := 65535,
coilsCnt := 65535,
inputRegCnt := 32768,
holdingRegCnt := 65535,
inputs := _X_0,
coils := _Y_0,
inputRegs := _S_,
holdingRegs := _R_);
END_FOR;
END_PROGRAM
As written, the program provides compatible behavior with the original implementation. In addition, it is possible to define the number of connections to be serviced simultaneously by changing the lastTcp constant.
An archive group of projects containing the entire example can be downloaded in the attached documents.
Associated documents
- Archive of project group with an example