6

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

PLC 有一个非常简单的梯形逻辑如下:如果DM100值为#0001,则触发输出101.00。(这里,“Trigger”只是内存区域的符号名D100,“Output”是输出的符号101.00在此处输入图像描述

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

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

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

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

我怀疑数组中有错误fins_cmnd,但从我的代码中可以看出,我对每个值都做了尽可能详细的注释;我不可能发现自己缺少任何东西。我怀疑我可能没有正确解析十六进制,但同样,我没有例外来指导我。

我不知道在哪里以及如何进行故障排除。希望这里有FINS编程或PLC经验的人能给我一些帮助。

[ANSWER]
感谢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();
4

1 回答 1

6

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

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

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

我刚刚将此页面视为协议的参考,最好将消息直接创建为字节,而不是指定 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 个字节。这些与您所拥有的不匹配,因此我扩展了该部分。

于 2012-03-14T04:08:02.213 回答