PLC_DRIVERS.md 6.3 KB

多 PLC 协议支持

概述

YZWater3 基于 HslCommunication 库实现了多 PLC 协议支持,通过统一的 IPlcDriver 接口抽象,可以轻松切换不同品牌的 PLC。

支持的协议

协议 品牌 默认端口 说明
Siemens S7 西门子 102 S200/S200Smart/S300/S400/S1200/S1500
Mitsubishi MC 三菱 6000 Q 系列、iQ-R/iQ-F
Omron Fins 欧姆龙 9600 CJ/CS/CP 系列
Modbus TCP 通用 502 仪表、传感器、其他 PLC
Allen-Bradley AB 44818 ControlLogix/CompactLogix

使用方法

方式一:通过工厂创建

using YZWater.Core.Services.PlcDrivers;

// 创建西门子 S7 驱动
var driver = PlcDriverFactory.Create(
    PlcProtocol.SiemensS7,
    ipAddress: "192.168.1.100",
    port: 102,
    extraConfig: new Dictionary<string, object>
    {
        ["PlcSeries"] = "S200Smart"
    }
);

// 连接
var result = await driver.ConnectAsync();
if (!result.IsSuccess)
{
    Console.WriteLine($"连接失败: {result.Message}");
    return;
}

// 读取数据
var floatResult = await driver.ReadFloatAsync("VD100");
if (floatResult.IsSuccess)
{
    float value = floatResult.Content;
    Console.WriteLine($"VD100 = {value}");
}

// 写入数据
await driver.WriteFloatAsync("VD100", 123.45f);

// 断开
driver.Disconnect();
driver.Dispose();

方式二:直接创建驱动

// 西门子 S7
var siemens = new SiemensS7Driver(SiemensPLCS.S1200);
siemens.SetConnection("192.168.1.100", 102);

// 三菱 MC
var mitsubishi = new MitsubishiMcDriver();
mitsubishi.SetConnection("192.168.1.101", 6000);

// 欧姆龙 Fins
var omron = new OmronFinsDriver();
omron.SetConnection("192.168.1.102", 9600);
omron.SetNodeNumbers(sa1: 0, da1: 0);  // 设置节点号

// Modbus TCP
var modbus = new ModbusTcpDriver();
modbus.SetConnection("192.168.1.103", 502, station: 1);
modbus.SetAddressStart(true);  // 地址从 0 开始

// AB EtherNet/IP
var ab = new AllenBradleyDriver();
ab.SetConnection("192.168.1.104", 44818);

配置示例

yzwater-config.json

{
  "PlcProtocol": "SiemensS7",
  "PlcIp": "192.168.1.100",
  "PlcPort": 102,
  "PlcExtraConfig": {
    "PlcSeries": "S200Smart"
  }
}

不同协议的配置

西门子 S7:

{
  "PlcProtocol": "SiemensS7",
  "PlcIp": "192.168.1.100",
  "PlcPort": 102,
  "PlcExtraConfig": {
    "PlcSeries": "S1200"
  }
}

三菱 MC:

{
  "PlcProtocol": "MitsubishiMC",
  "PlcIp": "192.168.1.101",
  "PlcPort": 6000
}

欧姆龙 Fins:

{
  "PlcProtocol": "OmronFins",
  "PlcIp": "192.168.1.102",
  "PlcPort": 9600,
  "PlcExtraConfig": {
    "SA1": 0,
    "DA1": 0
  }
}

Modbus TCP:

{
  "PlcProtocol": "ModbusTcp",
  "PlcIp": "192.168.1.103",
  "PlcPort": 502,
  "PlcExtraConfig": {
    "Station": 1,
    "AddressStartWithZero": true
  }
}

Allen-Bradley:

{
  "PlcProtocol": "AllenBradley",
  "PlcIp": "192.168.1.104",
  "PlcPort": 44818
}

地址格式

西门子 S7

区域 地址格式 说明
I I0.0 输入位
Q Q0.0 输出位
M M0.0 中间继电器位
DB DB1.0 数据块字节
V/VD VD100 变量区(S200Smart)

三菱 MC

区域 地址格式 说明
D D100 数据寄存器
R R100 文件寄存器
W W100 链接寄存器
X X0 输入
Y Y0 输出
M M0 内部继电器

欧姆龙 Fins

区域 地址格式 说明
D D100 DM 区
C C100 HR 区
W W100 WR 区
H H100 保持位

Modbus TCP

区域 地址格式 说明
0x 0x100 线圈(000001-099999)
1x 1x100 离散输入(100001-199999)
3x 3x100 输入寄存器(300001-399999)
4x 4x100 保持寄存器(400001-499999)

Allen-Bradley

类型 地址格式 说明
Tag TagName 标签名
数组 Tag[0] 数组元素
结构体 Tag.Member 结构体成员

扩展新协议

实现 IPlcDriver 接口:

public class MyCustomDriver : IPlcDriver
{
    public string Name => "My Custom PLC";
    public bool IsConnected { get; private set; }

    public Task<OperateResult> ConnectAsync()
    {
        // 实现连接逻辑
    }

    public void Disconnect()
    {
        // 实现断开逻辑
    }

    public Task<OperateResult<byte[]>> ReadBytesAsync(string address, ushort length)
    {
        // 实现读取逻辑
    }

    // 实现其他接口方法...
}

然后在 PlcDriverFactory 中添加:

public static IPlcDriver Create(PlcProtocol protocol, ...)
{
    IPlcDriver driver = protocol switch
    {
        PlcProtocol.MyCustom => new MyCustomDriver(...),
        // ...
    };
    return driver;
}

注意事项

  1. 线程安全:所有驱动实例都是线程安全的
  2. 连接管理:使用完毕后必须调用 Dispose() 释放资源
  3. 错误处理:检查 OperateResult.IsSuccess 判断操作是否成功
  4. 地址格式:不同 PLC 的地址格式不同,请参考对应的文档
  5. 性能优化:批量读取时使用 ReadBytesAsync 而非多次读取单个值

性能对比

协议 读取延迟 吞吐量 说明
S7 10-50ms 高 优化良好
MC 10-50ms 高 优化良好
Fins 20-80ms 中 相对较慢
Modbus 50-200ms 低 通用协议,开销大
AB 20-100ms 中 取决于标签复杂度

故障排查

连接失败

  1. 检查 IP 和端口是否正确
  2. 检查网络连通性:ping <PLC_IP>
  3. 检查 PLC 是否支持该协议
  4. 查看日志:Logs/log-*.txt

读取失败

  1. 检查地址格式是否正确
  2. 检查地址是否超出 PLC 范围
  3. 检查数据类型是否匹配
  4. 查看 HslCommunication 的返回信息

性能问题

  1. 使用批量读取而非单个读取
  2. 减少轮询频率
  3. 考虑使用 PLC 的主动推送(如 OPC UA)

参考资料