Send FINS command from C# to PLC
None of those strings will be parsed as hexadecimal. NumberStyles.AllowHexSpecifier
allows the hexadecimal prefix "0x" but doesn't parse the number as hex unless it is present.
So you'd want (char)Int16.Parse("0x64", NumberStyles.AllowHexSpecifier)
.
However, numeric literals in C# can be hexadecimal, so instead of doing all that you can just write 0x64
instead.
I've just looked at this page as a reference for the protocol, and it would also be better to create the message directly as bytes rather than specifying Unicode code points and decoding those to bytes as ASCII. You can also use the array specification syntax to remove a lot of clutter:
var message = new byte[]
{
// header
0x80, //(ICF) Display frame information: 1000 0001
0x00, //(RSV) Reserved by system: (hex)00
0x02, //(GCT) Permissible number of gateways: (hex)02
0x00, //(DNA) Destination network address: (hex)00, local network
0x00, //(DA1) Destination node address: (hex)00, local PLC unit
0x00, //(DA2) Destination unit address: (hex)00, PLC
0x00, //(SNA) Source network address: (hex)00, local network
0x05, //(SA1) Source node address: (hex)05, PC's IP is 192.168.250.5
0x00, //(SA2) Source unit address: (hex)00, PC only has one ethernet
0x19, //(SID) Service ID: just give a random number 19
// command
0x01, //(MRC) Main request code: 01, memory area write
0x02, //(SRC) Sub-request code: 02, memory area write
// data
0x82, //Memory area code, 2 bytes: 82(DM)
0x00, //Write start address DM100
0x64,
0x00,
0x00, //Word write: only one address
0x01,
0x00, //Write value of 1 to address DM100 (0000 0000 0000 0001)
0x01, // - this value is 0xaabbccdd -> cc dd aa bb
0x00,
0x00,
};
It also looks like there are some problems with your data section - according to the linked document the memory address should be 4 bytes, the write length 2 bytes, and the values 4 bytes each. These don't match with what you have, so I've expanded that section.
KMC
Tutorials: WPF C# Databinding C# Programming Guide .NET Framework Data Provider for SQL Server Entity Framework LINQ-to-Entity The Layout System Resources: LifeCharts: free .NET charts FileHelper: text file helper cmdow
Updated on June 14, 2022Comments
-
KMC almost 2 years
I try to send FINS commands through UDP from PC (C#.NET) to PLC Ethernet module (Omron), but is not getting any responds from the PLC and have no clue where I can start troubleshooting.
PLC has a very simple ladder logic as follow: If
DM100
has value of#0001
, then trigger on output101.00
. (Here, "Trigger" is just a symbol name for memory areaD100
, and "Output" is a symbol for output101.00
)Then I wrote a piece of C# that performs FINS command of "Memory Area Write" which has command code of
01 02
, followed by beginning address, number of items to be written, and the data. The C# code should write a value of #0001
to PLC'sD100
area to trigger ON on101.00
.[deleted code that doesn't work]..
The output
101.00
did not get triggered, nor I receive any exception. I have made sure the following:- Port, node and address configured correctly as confirmed by "Work Online" in CX-Programmer. I have also ping each IP to make sure nodes are connected.
- The
UdpClient
code is valid since I wrote a very simple server / client code that successfully send and receive packets. - Ladder logic has no problem. I transfered the ladder to PLC and test out by Work Online in Monitor mode and setting
D100
a value manually.
I suspect there is mistake in the
fins_cmnd
array, but as seen in my code, I have commented as detail as possible on each value; I can't possibly find myself missing anything. I suspect I may not be parsing the hexadecimal correctly, but again, I have no exception to guide me.I have no idea where and how I can troubleshoot. Hope someone here with
FINS
programming or PLC experience can offer me some help.[ANSWER]
Thanks Porge for the link - that got me found out the problem. After a couple trails finally get it to work. See below for the working code.string SERV_IP_ADDR = "192.168.250.1"; const int FINS_UDP_PORT = 9600; byte[] sendPacket = new byte[] { // Full UDP packet: 80 00 02 00 00 00 00 05 00 19 01 02 82 00 64 00 00 01 00 01 // Header 0x80, //0.(ICF) Display frame information: 1000 0001 0x00, //1.(RSV) Reserved by system: (hex)00 0x02, //2.(GCT) Permissible number of gateways: (hex)02 0x00, //3.(DNA) Destination network address: (hex)00, local network 0x00, //4.(DA1) Destination node address: (hex)00, local PLC unit 0x00, //5.(DA2) Destination unit address: (hex)00, PLC 0x00, //6.(SNA) Source network address: (hex)00, local network 0x05, //7.(SA1) Source node address: (hex)05, PC's IP is 192.168.250.5 0x00, //8.(SA2) Source unit address: (hex)00, PC only has one ethernet 0x19, //9.(SID) Service ID: just give a random number 19 // Command 0x01, //10.(MRC) Main request code: 01, memory area write 0x02, //11.(SRC) Sub-request code: 02, memory area write // PLC Memory Area 0x82, //12.Memory area code (1 byte): 82(DM) // Address information 0x00, //13.Write start address (2 bytes): D100 0x64, 0x00, //15.Bit address (1 byte): Default 0 0x00, //16.No. of items (2 bytes): only one address which is D100 0x01, // Write Data 0x00, //18.Data to write (2 bytes): value is 1 0x01, }; UdpClient client = new UdpClient(); //create a UdpClient instance try { client.Send(sendPacket, sendPacket.Length, SERV_IP_ADDR, FINS_UDP_PORT); } catch (SocketException se) { Console.WriteLine(se.ErrorCode + ": " + se.Message); } client.Close();
-
KMC about 12 yearsThe memory is, yes, 4 bytes, hence I have two array item one 0x00 and 0x64 together 4 bytes. because each "section" only takes 16 bits.
-
porges about 12 years@KMC: I've expanded the 'data' part based on what I think it is meant to look like from the given page. Does it help?