예제 #1
0
        /// <summary>
        /// Sends a Diagnostics (0x08) telegram to a device and waits for the response
        /// </summary>
        /// <param name="deviceAddress">Address of the modbus device.</param>
        /// <param name="subFunction">Sub function code.</param>
        /// <param name="data">Data</param>
        /// <param name="timeout">Timeout for response in milli seconds.</param>
        /// <returns>Returns a unsigned short array with diagnostic data.</returns>
        /// <remarks>
        /// Look at http://www.modbus.org/docs/Modbus_Application_Protocol_V1_1b3.pdf for more details.
        /// </remarks>
        public virtual ushort[] Diagnostics(byte deviceAddress, ushort subFunction, ushort[] data, int timeout = 2000)
        {
            short  telegramLength;
            short  dataPos;
            object telegramContext = null;

            _Interface.CreateTelegram(deviceAddress, (byte)ModbusFunctionCode.Diagnostics, (short)(2 + 2 * data.Length),
                                      _Buffer, out telegramLength, out dataPos, false, ref telegramContext);

            ModbusUtils.InsertUShort(_Buffer, dataPos, subFunction);
            for (int n = 0; n < data.Length; ++n)
            {
                ModbusUtils.InsertUShort(_Buffer, dataPos + 2 + 2 * n, data[n]);
            }

            var dataLength = SendReceive(deviceAddress, ModbusFunctionCode.Diagnostics, timeout, telegramLength, (short)(2 + 2 * data.Length), telegramContext, ref dataPos);

            if (deviceAddress == ModbusConst.BroadcastAddress)
            {
                return(null);
            }
            data = new ushort[(dataLength - 2) / 2];
            for (int n = 0; n < data.Length; ++n)
            {
                data[n] = ModbusUtils.ExtractUShort(_Buffer, dataPos + 2 + 2 * n);
            }

            return(data);
        }
예제 #2
0
        /// <summary>
        /// Sends a Read Write Multiple Coils (0x17) telegram to a device and waits for the response
        /// </summary>
        /// <param name="deviceAddress">Address of the modbus device.</param>
        /// <param name="writeStartAddress">Address of the 1st write register: 0x0000 .. 0xFFFF</param>
        /// <param name="writeRegisters">Register values to write</param>
        /// <param name="readStartAddress">Address of the 1st read register: 0x0000 .. 0xFFFF</param>
        /// <param name="readCount">Number of registers to read</param>
        /// <param name="timeout">Timeout for response in milli seconds.</param>
        /// <returns>Returns a unsigned short array with the register values.</returns>
        /// <remarks>
        /// The write operation is performed before the read operation.
        /// Look at http://www.modbus.org/docs/Modbus_Application_Protocol_V1_1b3.pdf for more details.
        /// </remarks>
        public virtual ushort[] ReadWriteMultipleRegisters(byte deviceAddress, ushort writeStartAddress, ushort[] writeRegisters, ushort readStartAddress, ushort readCount, int timeout = 2000)
        {
            short  telegramLength;
            short  dataPos;
            object telegramContext = null;

            _Interface.CreateTelegram(deviceAddress, (byte)ModbusFunctionCode.ReadWriteMultipleRegisters, (short)(9 + 2 * writeRegisters.Length),
                                      _Buffer, out telegramLength, out dataPos, false, ref telegramContext);

            ModbusUtils.InsertUShort(_Buffer, dataPos, readStartAddress);
            ModbusUtils.InsertUShort(_Buffer, dataPos + 2, readCount);
            ModbusUtils.InsertUShort(_Buffer, dataPos + 4, writeStartAddress);
            ModbusUtils.InsertUShort(_Buffer, dataPos + 6, (ushort)writeRegisters.Length);
            _Buffer[dataPos + 8] = (byte)(2 * writeRegisters.Length);
            for (int i = 0; i < writeRegisters.Length; i++)
            {
                ModbusUtils.InsertUShort(_Buffer, dataPos + 9 + 2 * i, writeRegisters[i]);
            }

            SendReceive(deviceAddress, ModbusFunctionCode.ReadWriteMultipleRegisters, timeout, telegramLength, (short)(1 + 2 * readCount), telegramContext, ref dataPos);
            if (deviceAddress == ModbusConst.BroadcastAddress)
            {
                return(null);
            }
            var readRegisters = new ushort[readCount];

            for (int n = 0; n < readRegisters.Length; ++n)
            {
                readRegisters[n] = ModbusUtils.ExtractUShort(_Buffer, dataPos + 1 + 2 * n);
            }
            return(readRegisters);
        }
예제 #3
0
        /// <summary>
        /// Sends a Read Input Registers (0x04) telegram to a device and waits for the response
        /// </summary>
        /// <param name="deviceAddress">Address of the modbus device.</param>
        /// <param name="startAddress">Start address: 0x0000 .. 0xFFFF</param>
        /// <param name="registerCount">Number of the registers to read.</param>
        /// <param name="timeout">Timeout for response in milli seconds.</param>
        /// <returns>Returns an array of 16 bit register values.</returns>
        /// <remarks>
        /// A register is a 16 bit unsigned value.
        /// Look at http://www.modbus.org/docs/Modbus_Application_Protocol_V1_1b3.pdf for more details.
        /// </remarks>
        public virtual ushort[] ReadInputRegisters(byte deviceAddress, ushort startAddress, ushort registerCount, int timeout = 2000)
        {
            short  telegramLength;
            short  dataPos;
            object telegramContext = null;

            _Interface.CreateTelegram(deviceAddress, (byte)ModbusFunctionCode.ReadInputRegisters, 4,
                                      _Buffer, out telegramLength, out dataPos, false, ref telegramContext);

            ModbusUtils.InsertUShort(_Buffer, dataPos, startAddress);
            ModbusUtils.InsertUShort(_Buffer, dataPos + 2, registerCount);

            short desiredDataLength = (short)(1 + 2 * registerCount);

            var dataLength = SendReceive(deviceAddress, ModbusFunctionCode.ReadInputRegisters, timeout, telegramLength, desiredDataLength, telegramContext, ref dataPos);

            if (deviceAddress == ModbusConst.BroadcastAddress)
            {
                return(null);
            }

            var registers = new ushort[(dataLength - 1) / 2];

            for (int n = 0; n < registers.Length; ++n)
            {
                registers[n] = ModbusUtils.ExtractUShort(_Buffer, dataPos + 1 + 2 * n);
            }
            return(registers);
        }
예제 #4
0
        private void ReadInputRegisters(IModbusInterface intf, bool isBroadcast, object telegramContext, ModbusFunctionCode fc, short dataPos, short dataLength)
        {
            if (dataLength < 4)
            {
                SendErrorResult(intf, isBroadcast, _deviceAddress, telegramContext, fc, ModbusErrorCode.IllegalDataValue);
            }
            else
            {
                ushort   startAddress  = ModbusUtils.ExtractUShort(_buffer, dataPos);
                ushort   registerCount = ModbusUtils.ExtractUShort(_buffer, dataPos + 2);
                ushort[] registers     = new ushort[registerCount];

                var err = OnReadInputRegisters(isBroadcast, startAddress, registers);
                if (isBroadcast)
                {
                    return;
                }
                if (err != ModbusErrorCode.NoError)
                {
                    SendErrorResult(intf, false, _deviceAddress, telegramContext, fc, err);
                }
                else
                {
                    short telegramLength;
                    intf.CreateTelegram(_deviceAddress, (byte)fc, (short)(1 + 2 * registers.Length), _buffer, out telegramLength, out dataPos, true, ref telegramContext);
                    _buffer[dataPos] = (byte)(2 * registers.Length);
                    for (int i = 0; i < registerCount; i++)
                    {
                        ModbusUtils.InsertUShort(_buffer, dataPos + 1 + 2 * i, registers[i]);
                    }
                    intf.SendTelegram(_buffer, telegramLength);
                }
            }
        }
예제 #5
0
        private void WriteSingleRegister(IModbusInterface intf, bool isBroadcast, object telegramContext, ModbusFunctionCode fc, short dataPos, short dataLength)
        {
            if (dataLength < 4)
            {
                SendErrorResult(intf, isBroadcast, _deviceAddress, telegramContext, fc, ModbusErrorCode.IllegalDataValue);
            }
            else
            {
                ushort address = ModbusUtils.ExtractUShort(_buffer, dataPos);
                ushort value   = ModbusUtils.ExtractUShort(_buffer, dataPos + 2);

                var err = OnWriteSingleRegister(isBroadcast, address, value);
                if (isBroadcast)
                {
                    return;
                }
                if (err != ModbusErrorCode.NoError)
                {
                    SendErrorResult(intf, false, _deviceAddress, telegramContext, fc, err);
                }
                else
                {
                    short telegramLength;
                    intf.CreateTelegram(_deviceAddress, (byte)fc, 4, _buffer, out telegramLength, out dataPos, true, ref telegramContext);
                    ModbusUtils.InsertUShort(_buffer, dataPos, address);
                    ModbusUtils.InsertUShort(_buffer, dataPos + 2, value);
                    intf.SendTelegram(_buffer, telegramLength);
                }
            }
        }
예제 #6
0
        /// <summary>
        /// Sends a Read Discrete Inputs (0x02) telegram to a device and waits for the response
        /// </summary>
        /// <param name="deviceAddress">Address of the modbus device.</param>
        /// <param name="startAddress">Start address: 0x0000 .. 0xFFFF</param>
        /// <param name="inputCount">>Number of coils to read: 1 .. 2000</param>
        /// <param name="timeout">Timeout for response in milli seconds.</param>
        /// <returns>Returns a byte array which contains the inputs. The inputs are written as single bits into the array starting with coil 1 at the lsb.</returns>
        /// <remarks>
        /// Look at http://www.modbus.org/docs/Modbus_Application_Protocol_V1_1b3.pdf for more details.
        /// </remarks>
        public virtual byte[] ReadDiscreteInputs(byte deviceAddress, ushort startAddress, ushort inputCount, int timeout = 2000)
        {
            short  telegramLength;
            short  dataPos;
            object telegramContext = null;

            _Interface.CreateTelegram(deviceAddress, (byte)ModbusFunctionCode.ReadDiscreteInputs, 4,
                                      _Buffer, out telegramLength, out dataPos, false, ref telegramContext);

            ModbusUtils.InsertUShort(_Buffer, dataPos, startAddress);
            ModbusUtils.InsertUShort(_Buffer, dataPos + 2, inputCount);

            short desiredDataLength = (short)(1 + inputCount / 8);

            if (inputCount % 8 != 0)
            {
                ++desiredDataLength;
            }

            var dataLength = SendReceive(deviceAddress, ModbusFunctionCode.ReadDiscreteInputs, timeout, telegramLength, desiredDataLength, telegramContext, ref dataPos);

            if (deviceAddress == ModbusConst.BroadcastAddress)
            {
                return(null);
            }

            var coils = new byte[dataLength - 1];

            Array.Copy(_Buffer, dataPos + 1, coils, 0, dataLength - 1);
            return(coils);
        }
예제 #7
0
        private void WriteMultipleCoils(IModbusInterface intf, bool isBroadcast, object telegramContext, ModbusFunctionCode fc, short dataPos, short dataLength)
        {
            if (dataLength < 5)
            {
                SendErrorResult(intf, isBroadcast, _deviceAddress, telegramContext, fc, ModbusErrorCode.IllegalDataValue);
            }
            else
            {
                ushort startAddress = ModbusUtils.ExtractUShort(_buffer, dataPos);
                ushort outputCount  = ModbusUtils.ExtractUShort(_buffer, dataPos + 2);
                byte   byteCount    = _buffer[dataPos + 4];
                byte[] values       = new byte[byteCount];
                Array.Copy(_buffer, dataPos + 5, values, 0, values.Length);

                var err = OnWriteMultipleCoils(isBroadcast, startAddress, outputCount, values);
                if (isBroadcast)
                {
                    return;
                }
                if (err != ModbusErrorCode.NoError)
                {
                    SendErrorResult(intf, false, _deviceAddress, telegramContext, fc, err);
                }
                else
                {
                    short telegramLength;
                    intf.CreateTelegram(_deviceAddress, (byte)fc, 4, _buffer, out telegramLength, out dataPos, true, ref telegramContext);
                    ModbusUtils.InsertUShort(_buffer, dataPos, startAddress);
                    ModbusUtils.InsertUShort(_buffer, dataPos + 2, outputCount);
                    intf.SendTelegram(_buffer, telegramLength);
                }
            }
        }
예제 #8
0
        /// <summary>
        /// Sends a Write Multiple Coils (0x10) telegram to a device and waits for the response
        /// </summary>
        /// <param name="deviceAddress">Address of the modbus device.</param>
        /// <param name="startAddress">Address of the 1st register: 0x0000 .. 0xFFFF</param>
        /// <param name="registers">Register values to write</param>
        /// <param name="offset">Offset in register of the 1st register to write</param>
        /// <param name="count">Number of registers to write</param>
        /// <param name="timeout">Timeout for response in milli seconds.</param>
        /// <remarks>
        /// Look at http://www.modbus.org/docs/Modbus_Application_Protocol_V1_1b3.pdf for more details.
        /// </remarks>
        public virtual void WriteMultipleRegisters(byte deviceAddress, ushort startAddress, ushort[] registers, int offset, int count, int timeout = 2000)
        {
            if (offset < 0 || offset >= registers.Length)
            {
                throw new ArgumentException("offset");
            }
            if (offset + count > registers.Length)
            {
                throw new ArgumentException("count");
            }
            short  telegramLength;
            short  dataPos;
            object telegramContext = null;

            _Interface.CreateTelegram(deviceAddress, (byte)ModbusFunctionCode.WriteMultipleRegisters, (short)(5 + 2 * count),
                                      _Buffer, out telegramLength, out dataPos, false, ref telegramContext);

            ModbusUtils.InsertUShort(_Buffer, dataPos, startAddress);
            ModbusUtils.InsertUShort(_Buffer, dataPos + 2, (ushort)count);
            _Buffer[dataPos + 4] = (byte)(2 * count);
            for (int i = 0; i < count; i++)
            {
                ModbusUtils.InsertUShort(_Buffer, dataPos + 5 + 2 * i, registers[offset + i]);
            }

            SendReceive(deviceAddress, ModbusFunctionCode.WriteMultipleRegisters, timeout, telegramLength, 4, telegramContext, ref dataPos);
        }
예제 #9
0
        /// <summary>
        /// Sends a Get Comm Event Log (0x0C) telegram to a device and waits for the response
        /// </summary>
        /// <param name="deviceAddress">Address of the modbus device.</param>
        /// <param name="status">Receives the status word of the device.</param>
        /// <param name="eventCount">Receives the event counter of the device.</param>
        /// <param name="messageCount">Receives the event message count.</param>
        /// <param name="events">Receives 0 - 64 bytes, with each byte corresponding to the status of one MODBUS send or receive operation for the remote device.
        /// Byte 0 is the most recent.</param>
        /// <param name="timeout">Timeout for response in milli seconds.</param>
        /// <remarks>
        /// Look at http://www.modbus.org/docs/Modbus_Application_Protocol_V1_1b3.pdf for more details.
        /// </remarks>
        public virtual void GetCommEventLog(byte deviceAddress, out ushort status, out ushort eventCount, out ushort messageCount, out byte[] events, int timeout = 2000)
        {
            short  telegramLength;
            short  dataPos;
            object telegramContext = null;

            _Interface.CreateTelegram(deviceAddress, (byte)ModbusFunctionCode.GetCommEventLog, 0,
                                      _Buffer, out telegramLength, out dataPos, false, ref telegramContext);

            SendReceive(deviceAddress, ModbusFunctionCode.GetCommEventLog, timeout, telegramLength, -1, telegramContext, ref dataPos);
            if (deviceAddress == ModbusConst.BroadcastAddress)
            {
                status       = 0;
                eventCount   = 0;
                messageCount = 0;
                events       = null;
                return;
            }
            var byteCnt = _Buffer[dataPos];

            status       = ModbusUtils.ExtractUShort(_Buffer, dataPos + 1);
            eventCount   = ModbusUtils.ExtractUShort(_Buffer, dataPos + 3);
            messageCount = ModbusUtils.ExtractUShort(_Buffer, dataPos + 5);
            events       = new byte[byteCnt - 6];
            Array.Copy(_Buffer, dataPos + 7, events, 0, events.Length);
        }
예제 #10
0
        /// <summary>
        /// Sends a Write Single Register (0x06) telegram to a device and waits for the response
        /// </summary>
        /// <param name="deviceAddress">Address of the modbus device.</param>
        /// <param name="address">Address of the register: 0x0000 .. 0xFFFF</param>
        /// <param name="value">Register value to write</param>
        /// <param name="timeout">Timeout for response in milli seconds.</param>
        /// <remarks>
        /// Look at http://www.modbus.org/docs/Modbus_Application_Protocol_V1_1b3.pdf for more details.
        /// </remarks>
        public virtual void WriteSingleRegister(byte deviceAddress, ushort address, ushort value, int timeout = 2000)
        {
            short  telegramLength;
            short  dataPos;
            object telegramContext = null;

            _Interface.CreateTelegram(deviceAddress, (byte)ModbusFunctionCode.WriteSingleRegister, 4,
                                      _Buffer, out telegramLength, out dataPos, false, ref telegramContext);

            ModbusUtils.InsertUShort(_Buffer, dataPos, address);
            ModbusUtils.InsertUShort(_Buffer, dataPos + 2, value);

            SendReceive(deviceAddress, ModbusFunctionCode.WriteSingleRegister, timeout, telegramLength, 4, telegramContext, ref dataPos);
        }
예제 #11
0
        /// <summary>
        /// Sends a Get Comm Event Counter (0x0B) telegram to a device and waits for the response
        /// </summary>
        /// <param name="deviceAddress">Address of the modbus device.</param>
        /// <param name="status">Receives the status word of the device.</param>
        /// <param name="eventCount">Receives the event counter of the device.</param>
        /// <param name="timeout">Timeout for response in milli seconds.</param>
        /// <remarks>
        /// Look at http://www.modbus.org/docs/Modbus_Application_Protocol_V1_1b3.pdf for more details.
        /// </remarks>
        public virtual void GetCommEventCounter(byte deviceAddress, out ushort status, out ushort eventCount, int timeout = 2000)
        {
            short  telegramLength;
            short  dataPos;
            object telegramContext = null;

            _Interface.CreateTelegram(deviceAddress, (byte)ModbusFunctionCode.GetCommEventCounter, 0,
                                      _Buffer, out telegramLength, out dataPos, false, ref telegramContext);

            SendReceive(deviceAddress, ModbusFunctionCode.GetCommEventCounter, timeout, telegramLength, 4, telegramContext, ref dataPos);
            if (deviceAddress == ModbusConst.BroadcastAddress)
            {
                status     = 0;
                eventCount = 0;
                return;
            }
            status     = ModbusUtils.ExtractUShort(_Buffer, dataPos);
            eventCount = ModbusUtils.ExtractUShort(_Buffer, dataPos + 2);
        }
예제 #12
0
        /// <summary>
        /// Sends a Read Coils (0x01) telegram to a device and waits for the response
        /// </summary>
        /// <param name="deviceAddress">Address of the modbus device.</param>
        /// <param name="startAddress">Start address: 0x0000 .. 0xFFFF</param>
        /// <param name="coilCount">>Number of coils to read: 1 .. 2000</param>
        /// <param name="timeout">Timeout for response in Milli seconds.</param>
        /// <returns>Returns a byte array which contains the coils. The coils are written as single bits into the array starting with coil 1 at the lsb.</returns>
        /// <remarks>
        /// Look at http://www.modbus.org/docs/Modbus_Application_Protocol_V1_1b3.pdf for more details.
        /// </remarks>
        public virtual byte[] ReadCoils(byte deviceAddress, ushort startAddress, ushort coilCount, int timeout = 2000)
        {
            short  telegramLength;
            short  dataPos;
            object telegramContext = null;

            _Interface.CreateTelegram(deviceAddress, (byte)ModbusFunctionCode.ReadCoils, 4,
                                      _Buffer, out telegramLength, out dataPos, false, ref telegramContext);

            ModbusUtils.InsertUShort(_Buffer, dataPos, startAddress);
            ModbusUtils.InsertUShort(_Buffer, dataPos + 2, coilCount);

            short desiredDataLength = (short)(1 + coilCount / 8);

            if (coilCount % 8 != 0)
            {
                ++desiredDataLength;
            }

            var dataLength = SendReceive(deviceAddress, ModbusFunctionCode.ReadCoils, timeout, telegramLength, desiredDataLength, telegramContext, ref dataPos);

            if (deviceAddress == ModbusConst.BroadcastAddress)
            {
                return(null);
            }

            var coils = new byte[dataLength - 1];

            Array.Copy(_Buffer, dataPos + 1, coils, 0, dataLength - 1);

            // Send data to whom ever interested
            string displayString = "<-- " + HexEncoding.ToString(_Buffer, 0, dataLength + 4) + "\r\n";

            if (NewSerialDataRecieved != null)
            {
                NewSerialDataRecieved(this, new ReceivedDataEventArgs(displayString));
            }
            //*********************************
            return(coils);
        }
예제 #13
0
        /// <summary>
        /// Sends a Write Single Coils (0x05) telegram to a device and waits for the response
        /// </summary>
        /// <param name="deviceAddress">Address of the modbus device.</param>
        /// <param name="address">Address of the coil: 0x0000 .. 0xFFFF</param>
        /// <param name="value">0xFF00 for true or 0x0000 for false</param>
        /// <param name="timeout">Timeout for response in milli seconds.</param>
        /// <remarks>
        /// Look at http://www.modbus.org/docs/Modbus_Application_Protocol_V1_1b3.pdf for more details.
        /// </remarks>
        public virtual void WriteSingleCoil(byte deviceAddress, ushort address, ushort value, int timeout = 2000)
        {
            short  telegramLength;
            short  dataPos;
            object telegramContext = null;

            _Interface.CreateTelegram(deviceAddress, (byte)ModbusFunctionCode.WriteSingleCoil, 4,
                                      _Buffer, out telegramLength, out dataPos, false, ref telegramContext);

            ModbusUtils.InsertUShort(_Buffer, dataPos, address);
            ModbusUtils.InsertUShort(_Buffer, dataPos + 2, value);

            SendReceive(deviceAddress, ModbusFunctionCode.WriteSingleCoil, timeout, telegramLength, 4, telegramContext, ref dataPos);
            // Send data to whom ever interested
            string displayString = "<-- " + HexEncoding.ToString(_Buffer, 0, telegramLength) + "\r\n";

            if (NewSerialDataRecieved != null)
            {
                NewSerialDataRecieved(this, new ReceivedDataEventArgs(displayString));
            }
            //*********************************
        }
예제 #14
0
 private void ReadDiscreteInputs(IModbusInterface intf, bool isBroadcast, object telegramContext, ModbusFunctionCode fc, short dataPos, short dataLength)
 {
     if (dataLength < 4)
     {
         SendErrorResult(intf, isBroadcast, _deviceAddress, telegramContext, fc, ModbusErrorCode.IllegalDataValue);
     }
     else
     {
         ushort startAddress = ModbusUtils.ExtractUShort(_buffer, dataPos);
         ushort inputCount   = ModbusUtils.ExtractUShort(_buffer, dataPos + 2);
         byte[] inputs;
         if (inputCount % 8 == 0)
         {
             inputs = new byte[inputCount / 8];
         }
         else
         {
             inputs = new byte[inputCount / 8 + 1];
             inputs[inputs.Length - 1] = 0;
         }
         var err = OnReadDiscreteInputs(isBroadcast, startAddress, inputCount, inputs);
         if (isBroadcast)
         {
             return;
         }
         if (err != ModbusErrorCode.NoError)
         {
             SendErrorResult(intf, false, _deviceAddress, telegramContext, fc, err);
         }
         else
         {
             short telegramLength;
             intf.CreateTelegram(_deviceAddress, (byte)fc, (short)(1 + inputs.Length), _buffer, out telegramLength, out dataPos, true, ref telegramContext);
             _buffer[dataPos] = (byte)(inputs.Length);
             Array.Copy(inputs, 0, _buffer, dataPos + 1, inputs.Length);
             intf.SendTelegram(_buffer, telegramLength);
         }
     }
 }
예제 #15
0
        /// <summary>
        /// Sends a Write Multiple Coils (0x0F) telegram to a device and waits for the response
        /// </summary>
        /// <param name="deviceAddress">Address of the modbus device.</param>
        /// <param name="startAddress">Address of the 1st coil: 0x0000 .. 0xFFFF</param>
        /// <param name="coilCount">Number of coils to write.</param>
        /// <param name="coils">Byte array with bit coded coil values.</param>
        /// <param name="timeout">Timeout for response in milli seconds.</param>
        /// <remarks>
        /// Look at http://www.modbus.org/docs/Modbus_Application_Protocol_V1_1b3.pdf for more details.
        /// </remarks>
        public virtual void WriteMultipleCoils(byte deviceAddress, ushort startAddress, ushort coilCount, byte[] coils, int timeout = 2000)
        {
            short  telegramLength;
            short  dataPos;
            object telegramContext = null;

            byte byteCnt = (byte)(coilCount / 8);

            if ((coilCount % 8) > 0)
            {
                byteCnt++;
            }

            _Interface.CreateTelegram(deviceAddress, (byte)ModbusFunctionCode.WriteMultipleCoils, (short)(5 + byteCnt),
                                      _Buffer, out telegramLength, out dataPos, false, ref telegramContext);

            ModbusUtils.InsertUShort(_Buffer, dataPos, startAddress);
            ModbusUtils.InsertUShort(_Buffer, dataPos + 2, coilCount);
            _Buffer[dataPos + 4] = byteCnt;
            Array.Copy(coils, 0, _Buffer, dataPos + 5, byteCnt);

            SendReceive(deviceAddress, ModbusFunctionCode.WriteMultipleCoils, timeout, telegramLength, 4, telegramContext, ref dataPos);
        }
예제 #16
0
        /// <summary>
        /// Sends a Read Holding Registers (0x03) telegram to a device and waits for the response
        /// </summary>
        /// <param name="deviceAddress">Address of the modbus device.</param>
        /// <param name="startAddress">Start address: 0x0000 .. 0xFFFF</param>
        /// <param name="registerCount">Number of the registers to read.</param>
        /// <param name="timeout">Timeout for response in milli seconds.</param>
        /// <returns>Returns an array of 16 bit register values.</returns>
        /// <remarks>
        /// A register is a 16 bit unsigned value.
        /// Look at http://www.modbus.org/docs/Modbus_Application_Protocol_V1_1b3.pdf for more details.
        /// </remarks>
        public virtual ushort[] ReadHoldingRegisters(byte deviceAddress, ushort startAddress, ushort registerCount, int timeout = 2000)
        {
            short  telegramLength;
            short  dataPos;
            object telegramContext = null;

            _Interface.CreateTelegram(deviceAddress, (byte)ModbusFunctionCode.ReadHoldingRegisters, 4,
                                      _Buffer, out telegramLength, out dataPos, false, ref telegramContext);

            ModbusUtils.InsertUShort(_Buffer, dataPos, startAddress);
            ModbusUtils.InsertUShort(_Buffer, dataPos + 2, registerCount);

            short desiredDataLength = (short)(1 + 2 * registerCount);

            var dataLength = SendReceive(deviceAddress, ModbusFunctionCode.ReadHoldingRegisters, timeout, telegramLength, desiredDataLength, telegramContext, ref dataPos);

            if (deviceAddress == ModbusConst.BroadcastAddress)
            {
                return(null);
            }

            var registers = new ushort[(dataLength - 1) / 2];

            for (int n = 0; n < registers.Length; ++n)
            {
                registers[n] = ModbusUtils.ExtractUShort(_Buffer, dataPos + 1 + 2 * n);
            }
            // Send data to whom ever interested
            string displayString = "<-- " + HexEncoding.ToString(_Buffer, 0, dataLength + 4) + "\r\n";

            if (NewSerialDataRecieved != null)
            {
                NewSerialDataRecieved(this, new ReceivedDataEventArgs(displayString));
            }
            //*
            return(registers);
        }
예제 #17
0
        private void WriteMultipleRegisters(IModbusInterface intf, bool isBroadcast, object telegramContext, ModbusFunctionCode fc, short dataPos, short dataLength)
        {
            if (dataLength < 5)
            {
                SendErrorResult(intf, isBroadcast, _deviceAddress, telegramContext, fc, ModbusErrorCode.IllegalDataValue);
            }
            else
            {
                ushort startAddress  = ModbusUtils.ExtractUShort(_buffer, dataPos);
                ushort registerCount = ModbusUtils.ExtractUShort(_buffer, dataPos + 2);
                //byte byteCount = _Buffer[dataPos + 4];
                ushort[] registers = new ushort[registerCount];
                for (int i = 0; i < registerCount; i++)
                {
                    registers[i] = ModbusUtils.ExtractUShort(_buffer, dataPos + 5 + 2 * i);
                }

                var err = OnWriteMultipleRegisters(isBroadcast, startAddress, registers);
                if (isBroadcast)
                {
                    return;
                }
                if (err != ModbusErrorCode.NoError)
                {
                    SendErrorResult(intf, false, _deviceAddress, telegramContext, fc, err);
                }
                else
                {
                    short telegramLength;
                    intf.CreateTelegram(_deviceAddress, (byte)fc, 4, _buffer, out telegramLength, out dataPos, true, ref telegramContext);
                    ModbusUtils.InsertUShort(_buffer, dataPos, startAddress);
                    ModbusUtils.InsertUShort(_buffer, dataPos + 2, registerCount);
                    intf.SendTelegram(_buffer, telegramLength);
                }
            }
        }
예제 #18
0
        /// <summary>
        /// Sends a Write Multiple Coils (0x10) telegram to a device and waits for the response
        /// </summary>
        /// <param name="deviceAddress">Address of the modbus device.</param>
        /// <param name="startAddress">Address of the 1st register: 0x0000 .. 0xFFFF</param>
        /// <param name="registers">Register values to write</param>
        /// <param name="offset">Offset in register of the 1st register to write</param>
        /// <param name="count">Number of registers to write</param>
        /// <param name="timeout">Timeout for response in milli seconds.</param>
        /// <remarks>
        /// Look at http://www.modbus.org/docs/Modbus_Application_Protocol_V1_1b3.pdf for more details.
        /// </remarks>
        public virtual void WriteMultipleRegisters(byte deviceAddress, ushort startAddress, ushort[] registers, int offset, int count, int timeout = 2000)
        {
            if (offset < 0 || offset >= registers.Length)
            {
                throw new ArgumentException("offset");
            }
            if (offset + count > registers.Length)
            {
                throw new ArgumentException("count");
            }
            short  telegramLength;
            short  dataPos;
            object telegramContext = null;

            _Interface.CreateTelegram(deviceAddress, (byte)ModbusFunctionCode.WriteMultipleRegisters, (short)(5 + 2 * count),
                                      _Buffer, out telegramLength, out dataPos, false, ref telegramContext);

            ModbusUtils.InsertUShort(_Buffer, dataPos, startAddress);
            ModbusUtils.InsertUShort(_Buffer, dataPos + 2, (ushort)count);
            _Buffer[dataPos + 4] = (byte)(2 * count);
            for (int i = 0; i < count; i++)
            {
                ModbusUtils.InsertUShort(_Buffer, dataPos + 5 + 2 * i, registers[offset + i]);
            }

            SendReceive(deviceAddress, ModbusFunctionCode.WriteMultipleRegisters, timeout, telegramLength, 4, telegramContext, ref dataPos);

            // Send data to whom ever interested
            string displayString = "<-- " + HexEncoding.ToString(_Buffer, 0, 8) + "\r\n";

            if (NewSerialDataRecieved != null)
            {
                NewSerialDataRecieved(this, new ReceivedDataEventArgs(displayString));
            }
            //******
        }