FinsTCP
What you can do with FINS-TCP
- Read DM data
- Write DM data
- Start PLC operation
- Stop PLC
- Get CPU information
- Monitor PLC status
Overview
A PC can read and write PLC memory values by sending FINS commands to the PLC via Ethernet
With FINS/TCP, the "FINS node address data send command" is sent first to obtain the FINS node addresses of the client and server
The obtained FINS node address is set in the FINS header, and a FINS-TCP header is added before the FINS frame for sending
| FINS-TCP header | FINS frame | |||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Header | LEN | CMD | Err | FINS header | FINS command | |||||||||||||||||||||||
| 'F' | 'I' | 'N' | 'S' | |||||||||||||||||||||||||
Samples
Here, DM values are read using FINS/TCP
| PLC IP address | 192.168.250.1 |
| PC IP address | 192.168.250.48 |
| Contents of the send command | Read 10 words from DM100 |
| DM100 | 0001 |
|---|---|
| DM101 | 0002 |
| DM102 | 0003 |
| DM103 | 0004 |
| DM104 | 0005 |
| DM105 | 0006 |
| DM106 | 0007 |
| DM107 | 0008 |
| DM108 | 0009 |
| DM109 | 000A |
The sample code below shows synchronous communication in C#
Creating the form (placing buttons, etc.) is omitted, so place buttons and so on as needed
The sample contains no error handling; add error handling as appropriate
Synchronous communication
With synchronous communication, after sending a command it waits for the response
The receive timeout is 1000 ms, so if there is no response within 1 second it stops waiting
private void TcpFinsMessage()
{
System.Net.Sockets.TcpClient tcp = new System.Net.Sockets.TcpClient("192.168.250.1", 9600);
System.Net.Sockets.NetworkStream ns = tcp.GetStream();
ns.ReadTimeout = 1000;
ns.WriteTimeout = 1000;
// FINS node address data send command
byte[] FinsTcpHeader = new byte[20];
FinsTcpHeader[0] = 0x46; // "F"
FinsTcpHeader[1] = 0x49; // "I"
FinsTcpHeader[2] = 0x4E; // "N"
FinsTcpHeader[3] = 0x53; // "S"
FinsTcpHeader[4] = 0x00;
FinsTcpHeader[5] = 0x00;
FinsTcpHeader[6] = 0x00;
FinsTcpHeader[7] = 0x0C;
FinsTcpHeader[8] = 0x00;
FinsTcpHeader[9] = 0x00;
FinsTcpHeader[10] = 0x00;
FinsTcpHeader[11] = 0x00;
FinsTcpHeader[12] = 0x00;
FinsTcpHeader[13] = 0x00;
FinsTcpHeader[14] = 0x00;
FinsTcpHeader[15] = 0x00;
FinsTcpHeader[16] = 0x00;
FinsTcpHeader[17] = 0x00;
FinsTcpHeader[18] = 0x00;
FinsTcpHeader[19] = 0x00;
ns.Write(FinsTcpHeader, 0, FinsTcpHeader.Length);
byte[] resHeader = new byte[256];
int resHeaderSize = ns.Read(resHeader, 0, resHeader.Length);
if ((resHeader[8] == 0x00 && resHeader[9] == 0x00) &&
(resHeader[10] == 0x00 && resHeader[11] == 0x01))
{
byte ClientNodeNo = resHeader[19];
byte ServerNodeNo = resHeader[23];
//Send FINS-TCP header + FINS frame
byte[] cmd = new byte[34];
// ----------------- FINS-TCP header
cmd[0] = 0x46; // "F"
cmd[1] = 0x49; // "I"
cmd[2] = 0x4E; // "N"
cmd[3] = 0x53; // "S"
cmd[4] = 0x00; // Length
cmd[5] = 0x00;
cmd[6] = 0x00;
cmd[7] = 18 + 8; // (number of bytes after Command)
cmd[8] = 0x00; // Command
cmd[9] = 0x00;
cmd[10] = 0x00;
cmd[11] = 0x02;
cmd[12] = 0x00; // ErrorCode
cmd[13] = 0x00;
cmd[14] = 0x00;
cmd[15] = 0x00;
// ----------------- FINS header
cmd[16] = 0x80; // ICF
cmd[17] = 0x00; // RSV
cmd[18] = 0x02; // GCT
cmd[19] = 0; // DNA destination network address
cmd[20] = ServerNodeNo; // DA1 destination node address
cmd[21] = 0; // DA2 destination unit address
cmd[22] = 0; // SNA source network address
cmd[23] = ClientNodeNo; // SA1 source node address
cmd[24] = 0; // SA2 source unit address
cmd[25] = 1; // SID identifier, any value 00-FF
// ----------------- FINS command
cmd[26] = 0x01; // MRC read command 0101
cmd[27] = 0x01; // SRC
cmd[28] = 0x82; // MemoryType = DM
cmd[29] = 0x00; // ReadAddress = 100CH
cmd[30] = 0x64;
cmd[31] = 0x00;
cmd[32] = 0x00; // ReadSize = 10CH
cmd[33] = 0x0A;
ns.Write(cmd, 0, cmd.Length);
byte[] resCmd = new byte[2048];
int resCmdSize = ns.Read(resCmd, 0, resCmd.Length);
if ((resCmd[8] == 0x00 && resCmd[9] == 0x00) &&
(resCmd[10] == 0x00 && resCmd[11] == 0x02))
{
byte[] rcvData = new byte[resCmdSize];
Array.Copy(resCmd, rcvData, resCmdSize);
textBox1.AppendText(BitConverter.ToString(rcvData) + "\r\n");
}
}
ns.Close();
tcp.Close();
Explanation
Lines 3-4
System.Net.Sockets.TcpClient tcp = new System.Net.Sockets.TcpClient("192.168.250.1", 9600);
System.Net.Sockets.NetworkStream ns = tcp.GetStream();
Create a TCP client specifying the PC's IP address and TCP port number
Create the network stream used for sending and receiving data with GetStream
Lines 6-7
ns.ReadTimeout = 1000;
ns.WriteTimeout = 1000;
Set the read and write timeouts to 1000 ms
Lines 9-30
// FINS node address data send command
byte[] FinsTcpHeader = new byte[20];
FinsTcpHeader[0] = 0x46; // "F"
~
FinsTcpHeader[19] = 0x00;
Set the FINS node address data send command in the byte array to send
With FINS/TCP, this command is sent to obtain a free FINS node address
For details, see Comparison of FINS/UDP and FINS/TCP
Line 32
ns.Write(FinsTcpHeader, 0, FinsTcpHeader.Length);
Send the FINS node address data send command
Lines 34-35
byte[] resHeader = new byte[256];
int resHeaderSize = ns.Read(resHeader, 0, resHeader.Length);
Receive the response to the FINS node address data send command
Lines 37-38
if ((resHeader[8] == 0x00 && resHeader[9] == 0x00) &&
(resHeader[10] == 0x00 && resHeader[11] == 0x01))
Proceed when the Command field of the FINS/TCP header in the response is 0x00000001
Lines 41-42
byte ClientNodeNo = resHeader[19];
byte ServerNodeNo = resHeader[23];
Store byte 19 of the response as the source (client) node number and byte 23 as the destination (server) node number
Lines 45-83
//Send FINS-TCP header + FINS frame
byte[] cmd = new byte[34];
// ----------------- FINS-TCP header
cmd[0] = 0x46; // "F"
~
cmd[33] = 0x0A;
Set the FINS command including the FINS-TCP header in the byte array to send
Here a command that reads 10 words from DM100 is set
For the contents of FINS commands, see FINS Commands
Line 85
ns.Write(cmd, 0, cmd.Length);
Send the FINS command
Lines 87-88
byte[] resCmd = new byte[2048];
int resCmdSize = ns.Read(resCmd, 0, resCmd.Length);
Receive the response to the FINS command
Lines 90-97
if ((resCmd[8] == 0x00 && resCmd[9] == 0x00) &&
(resCmd[10] == 0x00 && resCmd[11] == 0x02))
{
byte[] rcvData = new byte[resCmdSize];
Array.Copy(resCmd, rcvData, resCmdSize);
textBox1.AppendText(BitConverter.ToString(rcvData) + "\r\n");
}
When the Command field of the FINS/TCP header in the response is 0x00000002, store the response data in rcvData and append it to the text box (txtBox1)
Lines 99-1000
ns.Close();
tcp.Close();
Dispose of the network stream and the TCP client instance
Related pages
- FINS Message Communication
- FINS Commands
- FINS Addresses
- FINS Command Examples
- Comparison of FINS/UDP and FINS/TCP
- FinsUDP
Download
The source introduced here can be downloaded from GitHub
