Nmodbus和多个奴隶

时间:2015-11-11 09:14:38

标签: c# modbus

我正在尝试制作能源工厂模拟器,我想在我的应用程序中模拟一些设备。

这个想法是主要的东西和应用程序请求所需的奴隶并做出一些东西。

我刚开始使用Nmodbus,并且所有设备都能正常工作。 我尝试使用SlaveId来询问每个设备,但是当我读或写时,我都在相同的数据存储区中编写了所有内容。 应用和设备在localhost中运行。

这就是我在同一网络中声明每个设备的方式:

        int port = 502;
        IPAddress address = new IPAddress(new byte[] { 127, 0, 0, 1 });

        // create and start the TCP slave
        slaveTcpListener = new TcpListener(address, port);
        slaveTcpListener.Start();

        slave1 = ModbusTcpSlave.CreateTcp(1, slaveTcpListener);
        slave1.DataStore = DataStoreFactory.CreateDefaultDataStore();
        slave1.Listen();

        slave2 = ModbusTcpSlave.CreateTcp(2, slaveTcpListener);
        slave2.DataStore = DataStoreFactory.CreateDefaultDataStore();
        slave2.Listen();

这就是我如何请求每台设备的数据:

        using (TcpClient client = new TcpClient("127.0.0.1", 502))
        {
            ModbusIpMaster master = ModbusIpMaster.CreateIp(client);

            // read five input values
            ushort startAddress = 0;
            ushort numInputs = 10;
            ushort[] inputs = master.ReadHoldingRegisters(1,startAddress, numInputs);
            ushort[] inputs2 = master.ReadHoldingRegisters(2, startAddress, numInputs);


        }

但结果始终是slave1的数据存储区。

2 个答案:

答案 0 :(得分:1)

不幸的是,没有办法运行多个从设备,因为slave.Listen()方法包含无限循环:

 public override void Listen()
    {
        while (true)
        {
            try
            {
                try
                {
                    // read request and build message
                    byte[] frame = SerialTransport.ReadRequest();
                    IModbusMessage request = ModbusMessageFactory.CreateModbusRequest(frame);

                    if (SerialTransport.CheckFrame && !SerialTransport.ChecksumsMatch(request, frame))
                    {
                        string msg = $"Checksums failed to match {string.Join(", ", request.MessageFrame)} != {string.Join(", ", frame)}.";
                        Debug.WriteLine(msg);
                        throw new IOException(msg);
                    }

                    // only service requests addressed to this particular slave
                    if (request.SlaveAddress != UnitId)
                    {
                        Debug.WriteLine($"NModbus Slave {UnitId} ignoring request intended for NModbus Slave {request.SlaveAddress}");
                        continue;
                    }

                    // perform action
                    IModbusMessage response = ApplyRequest(request);

                    // write response
                    SerialTransport.Write(response);
                }
                catch (IOException ioe)
                {
                    Debug.WriteLine($"IO Exception encountered while listening for requests - {ioe.Message}");
                    SerialTransport.DiscardInBuffer();
                }
                catch (TimeoutException te)
                {
                    Debug.WriteLine($"Timeout Exception encountered while listening for requests - {te.Message}");
                    SerialTransport.DiscardInBuffer();
                }

                // TODO better exception handling here, missing FormatException, NotImplemented...
            }
            catch (InvalidOperationException)
            {
                // when the underlying transport is disposed
                break;
            }
        }

答案 1 :(得分:0)

同样的限制给我带来了问题,所以我接手了NModbus4项目(现在只是NModbus):

https://github.com/NModbus/NModbus

public static async Task StartModbusSerialRtuSlaveNetwork()
{
   using (SerialPort slavePort = new SerialPort("COM5"))
   {
       // configure serial port
       slavePort.BaudRate = 19200;
       slavePort.DataBits = 8;
       slavePort.Parity = Parity.Even;
       slavePort.StopBits = StopBits.One;
       slavePort.Open();

       //Create an instance of the ModbusFactory
       IModbusFactory factory = new ModbusFactory();

       //Create an adapter for the serial port
       var adapter = new SerialPortAdapter(slavePort);

       //Create the slave network
       IModbusSlaveNetwork modbusSlaveNetwork = factory.CreateRtuSlaveNetwork(adapter);

       //Create the slaves
       IModbusSlave slave1 = factory.CreateSlave(1);
       IModbusSlave slave2 = factory.CreateSlave(2);

       //Add the slaves to the network
       modbusSlaveNetwork.AddSlave(slave1);
       modbusSlaveNetwork.AddSlave(slave2);

       await modbusSlaveNetwork.ListenAsync();

       await Task.Delay(1);
    }
}