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.