c# - 从 C# 向 PLC 发送 FINS 命令

标签 c# udp plc fins

我尝试通过 UDP 从 PC (C#.NET) 向 PLC 以太网模块 (Omron) 发送 FINS 命令,但没有从 PLC 获得任何响应,也不知道从哪里开始故障排除。

PLC 有一个非常简单的梯形图逻辑如下: 如果 DM100 的值为 #0001,则触发输出 101.00。 (这里,“Trigger”只是存储区D100的符号名,“Output”是输出101.00的符号名) enter image description here

然后我写了一段C#,执行“内存区域写入”的FINS命令,命令代码为01 02,后面是起始地址、要写入的项目数和数据. C# 代码应将值 #0001 写入 PLC 的 D100 区域以在 101.00 触发 ON。

[删除了不起作用的代码]..

输出 101.00 没有被触发,我也没有收到任何异常。 我已确定以下内容:

  1. CX-Programmer 中的“在线工作”确认端口、节点和地址配置正确。我还对每个 IP 执行了 ping 操作,以确保节点已连接。
  2. UdpClient 代码是有效的,因为我编写了一个非常简单的服务器/客户端代码,可以成功发送和接收数据包。
  3. 梯形图逻辑没问题。我将梯形图传输到 PLC 并通过 Work Online 在监控模式下进行测试并手动设置 D100 一个值。

我怀疑 fins_cmnd 数组有误,但正如在我的代码中看到的那样,我已经对每个值进行了尽可能详细的注释;我不可能发现自己错过任何东西。我怀疑我可能没有正确解析十六进制,但同样,我也不异常(exception)地指导我。

我不知道在哪里以及如何解决问题。希望这里有 FINS 编程或 PLC 经验的人能给我一些帮助。

[答案]
感谢 Porge 提供的链接 - 这让我找到了问题所在。经过几次尝试后,终于让它开始工作了。请参阅下面的工作代码。

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();

最佳答案

这些字符串都不会被解析为十六进制。 NumberStyles.AllowHexSpecifier 允许十六进制前缀“0x”但不将数字解析为十六进制,除非它存在。

所以你需要 (char)Int16.Parse("0x64", NumberStyles.AllowHexSpecifier)

但是,C# 中的数字文字可以是十六进制的,因此您可以编写 0x64 而不是执行所有操作。

我刚看过 this page as a reference对于协议(protocol),最好直接将消息创建为字节而不是指定 Unicode 代码点并将它们解码为字节作为 ASCII。您还可以使用数组规范语法来消除大量困惑:

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, 
};

您的数据部分似乎也存在一些问题 - 根据链接文档,内存地址应为 4 字节,写入长度应为 2 字节,每个值应为 4 字节。这些与您拥有的不匹配,因此我扩展了该部分。

关于c# - 从 C# 向 PLC 发送 FINS 命令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9695639/

相关文章:

ios - 如何在iOS中开发IP Messenger?

sqlite - 无需 C(或任何其他主流语言)实现 SQLite

c# - Android 通过 LAN 从 C# 桌面应用程序接收 UDP 广播?

c# - 无法加载文件或程序集 WebMarkupMin.Core

c# - 从文本文件中读取并将其写入 XML

c# - PHP 类到 C# 类?

udp - ESP32 接收广播 UDP 数据包时出现问题 (ESP IDF)

ruby - 有谁知道是否有用于工业环境的带有 ruby​​ 的程序 PLC 项目?

plc - 未知的 PLC 功能 block 符号

c# - Xamarin Forms 中数据模板 View 单元格内的绑定(bind)上下文