C# develops Modbus Rtu client modbus test Demo, Modbus serial communication, virtual MODBUS-RTU test

foreword


 This article will use a component technology disclosed by NuGet to implement a ModBus RTU client, which can easily read and write to a Modbus rtu server. This server can be designed in C# on the computer, or implemented by PLC, or other Any server that supports this communication protocol.

github address: https://github.com/dathlin/HslCommunication  If you like, you can star or fork, and you can also give a reward for support.

 

You can download and install it in the NuGet manager in Visual Studio, or you can directly enter the following command in the NuGet console to install:

Install-Package HslCommunication

NuGet installation tutorial  http://www.cnblogs.com/dathlin/p/7705014.html

Technical support QQ group: 592132877 (The version update details of the component will also be released in the group as soon as possible) Component API address: http://www.cnblogs.com/dathlin/p/7703805.html

 

 

Special thanks to


  • Netizen: Chen Enfu                   's reading test of float and int data fixed the bug that the weights were reversed.
  • Netizen: U4 happy snail       found a wrong method name on the blog, updated on January 8, 2018 13:34:39. And feedback the bug of reading data of some special devices (modbus tcp server). already fixed.

 

just chit chat


The design pattern here is that the client actively requests the server data, and then receives the server's feedback data, supports native command sending and receiving, and supports some other convenient API sending and receiving. The special function code needs to use the native transceiver API. This component supports the following functional operations:

  • 0x01 read coil operation,
  • 0x02 read discrete operations,
  • 0x03 reads the value of the register,
  • 0x05 write a coil operation,
  • 0x06 writes a register value,
  • 0x0F Batch write coil operation,
  • 0x10 batch write register value,

 If your device needs data beyond these functions, you can use the native API method, but the premise of this method is that you are very clear about the MODBUS protocol. If you do not understand this protocol, you can refer to the following blog instructions:

 http://blog.csdn.net/thebestleo/article/details/52269999

 If you need to build your own ModBus server, you can refer to this article: http://www.cnblogs.com/dathlin/p/7782315.html

 

Access the test project

Need to download a serial port virtual software

Virtual Serial Port Driver

Download address: https://virtual-serial-port-driver.en.softonic.com/

Then virtualize the two serial ports, COM4 and COM5 are connected together by default. So we can do local testing

 

 Before you develop your own client program, you can use the MODBUS test tool to test it. An open source project at the following address is a Modbus rtu test tool developed based on this component, which can be directly used for read and write tests.

 ModbusTcpServer.zip    starts the service first, then starts the serial port

  

 


The following item is the access test item of this component, you can conduct preliminary access test, save you the trouble of writing test program, this item is written together with the access of Mitsubishi and Siemens PLC. can be referenced at the same time.

The download address is: HslCommunicationDemo.zip

 

 

Reference


 

All functional classes of ModBus components are in the HslCommunication.ModBus namespace, so add them before using them

using HslCommunication.ModBus;
using HslCommunication;

  

How to Use


 

Instantiate:

It must be instantiated before using the read and write functions:

private ModbusRtu busRtuClient = new ModbusRtu( station );

 

Note: In the devices of the Modbus server, most devices start from address 0, and some special devices start from address 1, so in this component, the default starts from address 0, if you want to start from address 1 , then the following configuration is required:

busRtuClient.AddressStartWithZero = False;

 

 

Then you need to initialize the parameters. For serial ports, the usual parameters include serial port name, baud rate, data bits, stop bits, and parity bits, which provide a way to entrust setting.

            try
            {
                busRtuClient.SerialPortInni( sp =>
                 {
                     sp.PortName = "COM5";
                     sp.BaudRate = 9600;
                     sp.DataBits = 8;
                     sp.StopBits = System.IO.Ports.StopBits.One;
                     sp.Parity = System.IO.Ports.Parity.None;
                 } );
                busRtuClient.Open( ); // open
            }
            catch (Exception ex)
            {
                MessageBox.Show( ex.Message );
            }

 

 If it is closed, call the following method

busRtuClient.Close( );

 

 

 

 

The following code demonstrates common read and write operations. For the sake of convenience, IsSuccess is no longer judged, and it is generally successful:

        private void userButton30_Click(object sender, EventArgs e)
        {
            // read operation
            bool coil100 = busRtuClient.ReadCoil("100").Content; // Read the on-off of coil 100
            short short100 = busRtuClient.ReadInt16("100").Content; // Read the short value of register 100
            ushort ushort100 = busRtuClient.ReadUInt16("100").Content; // Read the ushort value of register 100
            int int100 = busRtuClient.ReadInt32("100").Content; // read the int value of registers 100-101
            uint uint100 = busRtuClient.ReadUInt32("100").Content; // Read the uint value of registers 100-101
            float float100 = busRtuClient.ReadFloat("100").Content; // read the float value of registers 100-101
            long long100 = busRtuClient.ReadInt64("100").Content; // read the long value of registers 100-103
            ulong ulong100 = busRtuClient.ReadUInt64("100").Content; // Read the ulong value of registers 100-103
            double double100 = busRtuClient.ReadDouble("100").Content; // read the double value of registers 100-103
            string str100 = busRtuClient.ReadString("100", 5).Content;// Read a string of 10 characters from 100 to 104

            // write operation
            busRtuClient.WriteCoil("100", true);// Write coil 100 to pass
            busRtuClient.Write("100", (short)12345);//Write register 100 to 12345
            busRtuClient.Write("100", (ushort)45678);//Write register 100 to 45678
            busRtuClient.Write("100", 123456789);//Write register 100-101 to 123456789
            busRtuClient.Write("100", (uint)123456778);//Write register 100-101 to 123456778
            busRtuClient.Write("100", 123.456);//Write register 100-101 to 123.456
            busRtuClient.Write("100", 12312312312414L);//Write registers 100-103 as a big data
            busRtuClient.Write("100", 12634534534543656UL);// Write registers 100-103 as a large data
            busRtuClient.Write("100", 123.456d);//Write register 100-103 as a double-precision data
            busRtuClient.Write("100", "K123456789");
            
        }

 

Strict operations and batched complex read and write operations will be explained below. Suppose you want to read 1,000 M, and it may take 3 seconds to read 1,000 times in a loop. If the following batch read is used, only It takes 50ms, but you need to be familiar with the principle of bytes to handle it easily

 

 

Read coil API:

 Here is an example to read the number of coils with an address of 0 and a length of 10. The read data has been automatically converted into a bool array, which is convenient for secondary processing:

        private void userButton8_Click(object sender,EventArgs e)
        {
            HslCommunication.OperateResult<bool[]> read = busRtuClient.ReadCoil("0", 10);
            if(read.IsSuccess)
            {
                bool coil_0 = read.Content[0];
                bool coil_1 = read.Content[1];
                bool coil_2 = read.Content[2];
                bool coil_3 = read.Content[3];
                bool coil_4 = read.Content[4];
                bool coil_5 = read.Content[5];
                bool coil_6 = read.Content[6];
                bool coil_7 = read.Content[7];
                bool coil_8 = read.Content[8];
                bool coil_9 = read.Content[9];
            }
            else
            {
                MessageBox.Show(read.ToMessageShowString());
            }
        }

  Of course, you can also use the data conversion API provided by the component to achieve data extraction:

Read discrete data:

The codes for reading discrete data and reading coils are almost the same, and the processing methods are also the same, except that the method name is changed to:

        private void userButton8_Click(object sender,EventArgs e)
        {
            HslCommunication.OperateResult<bool[]> read = busRtuClient.ReadDiscrete("0", 10);
            if(read.IsSuccess)
            {
                bool coil_0 = read.Content[0];
                bool coil_1 = read.Content[1];
                bool coil_2 = read.Content[2];
                bool coil_3 = read.Content[3];
                bool coil_4 = read.Content[4];
                bool coil_5 = read.Content[5];
                bool coil_6 = read.Content[6];
                bool coil_7 = read.Content[7];
                bool coil_8 = read.Content[8];
                bool coil_9 = read.Content[9];
            }
            else
            {
                MessageBox.Show(read.ToMessageShowString());
            }
        }

Read register data:

 Suppose we need to read data with address 0 and length 10, that is, 10 data, 2 bytes each, for a total of 20 bytes of data. Before parsing the data below, assumptions are made first. You can refer to the following parsing before parsing your own data.

        private void userButton10_Click(object sender, EventArgs e)
        {
            HslCommunication.OperateResult<byte[]> read = busRtuClient.Read("0", 10);
            if (read.IsSuccess)
            {
                // A total of 20 bytes are returned, 2 bytes for each data, high order first, low order last
                // Before data parsing, you need to know what type of data is stored in it, so you need to make some assumptions:
                // The first two bytes are of the short data type
                short value1 = busTcpClient.ByteTransform.TransInt16(read.Content, 0);
                // The next 2 bytes are of type ushort
                ushort value2 = busTcpClient.ByteTransform.TransUInt16(read.Content, 2);
                // The next 4 bytes are of type int
                int value3 = busTcpClient.ByteTransform.TransInt32(read.Content, 4);
                // The next 4 bytes are of type float
                float value4 = busTcpClient.ByteTransform.TransFloat(read.Content, 8);
                // All the next bytes, a total of 8 bytes are specification information
                string speci = Encoding.ASCII.GetString(read.Content, 12, 8);

                // All data has been fetched
            }
            else
            {
                MessageBox.Show(read.ToMessageShowString());
            }
        }

Write a coil:

Write a coil, this is relatively simple, assuming we need to write coil 0, for the pass

        private void userButton11_Click(object sender, EventArgs e)
        {
            HslCommunication.OperateResult write = busRtuClient.WriteCoil("0", true);
            if (write.IsSuccess)
            {
                // write successfully
                textBox1.Text = "Write successful";
            }
            else
            {
                MessageBox.Show(write.ToMessageShowString());
            }
        }

Write a register:

The operation of writing a register is also very convenient. Three overloaded methods are provided here, allowing three ways to write: write, short, ushort, byte respectively:

        private void userButton12_Click(object sender, EventArgs e)
        {
            short value = -1234;
            HslCommunication.OperateResult write = busRtuClient.WriteOneRegister("0", value);
            if (write.IsSuccess)
            {
                // write successfully
                textBox1.Text = "Write successful";
            }
            else
            {
                MessageBox.Show(write.ToMessageShowString());
            }
        }

  

        private void userButton12_Click(object sender, EventArgs e)
        {
            ushort value = 56713;
            HslCommunication.OperateResult write = busRtuClient.WriteOneRegister("0", value);
            if (write.IsSuccess)
            {
                // write successfully
                textBox1.Text = "Write successful";
            }
            else
            {
                MessageBox.Show(write.ToMessageShowString());
            }
        }

  

        private void userButton12_Click(object sender, EventArgs e)
        {
            // 0x00 is high, 0x10 is low
            HslCommunication.OperateResult write = busRtuClient.WriteOneRegister("0", 0x00, 0x10);
            if (write.IsSuccess)
            {
                // write successfully
                textBox1.Text = "Write successful";
            }
            else
            {
                MessageBox.Show(write.ToMessageShowString());
            }
        }

 

Bulk write to coils:

private void userButton13_Click(object sender, EventArgs e)
        {
            // Coil 0 is True, Coil 1 is false, Coil 2 is true... and so on, and so on, as many coils are written as the array length is
            bool[] value = new bool[] { true, false, true, true, false, false };
            HslCommunication.OperateResult write = busRtuClient.WriteCoil("0", value);
            if (write.IsSuccess)
            {
                // write successfully
                textBox1.Text = "Write successful";
            }
            else
            {
                MessageBox.Show(write.ToMessageShowString());
            }
        }

  

Bulk write registers:

The first case writes a string of short arrays. This case is relatively simple:

        private void userButton14_Click(object sender, EventArgs e)
        {
            short[] value = new short[] { -1234, 467, 12345 };
            HslCommunication.OperateResult write = busRtuClient.Write("0", value);
            if (write.IsSuccess)
            {
                // write successfully
                textBox1.Text = "Write successful";
            }
            else
            {
                MessageBox.Show(write.ToMessageShowString());
            }
        }

The second case is to write a string of ushort arrays, which is also relatively simple:

        private void userButton14_Click(object sender, EventArgs e)
        {
            ushort[] value = new ushort[] { 46789, 467, 12345 };
            HslCommunication.OperateResult write = busRtuClient.Write("0", value);
            if (write.IsSuccess)
            {
                // write successfully
                textBox1.Text = "Write successful";
            }
            else
            {
                MessageBox.Show(write.ToMessageShowString());
            }
        }

The more complicated thing is to write custom data, read registers according to the above, for example, I need to write an int data composed of register 0 and register 1, then we write as follows:

        private void userButton15_Click(object sender, EventArgs e)
        {
            int value = 12345678;//A data waiting to be written

            HslCommunication.OperateResult write = busRtuClient.Write("0", value);
            if (write.IsSuccess)
            {
                // write successfully
                textBox1.Text = "Write successful";
            }
            else
            {
                MessageBox.Show(write.ToMessageShowString());
            }
        }

You can refer to this for other data. If you don’t understand anything, you can contact the QQ group above.

 

Ultimate data manipulation, using native packets to manipulate data:

Pass in a byte array, the data content is consistent with the original data, for example, if I want to read the data whose register address is 0 and the length is 3 through the native API, then the HEX identification form of the byte is 01 03 00 00 00 03 excluding CRC check code

        private void button26_Click( object sender, EventArgs e )
        {
            try
            {
                OperateResult<byte[]> read = busRtuClient.ReadBase( HslCommunication.Serial.SoftCRC16.CRC16(HslCommunication.BasicFramework.SoftBasic.HexStringToBytes( "01 03 00 00 00 03" )) );
                if (read.IsSuccess)
                {
                    textBox11.Text = "结果:" + HslCommunication.BasicFramework.SoftBasic.ByteToHexString( read.Content,' ' );
                }
                else
                {
                    MessageBox.Show( "Failed to read: " + read.ToMessageShowString( ) );
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show( "Failed to read: " + ex.Message );
            }
        }

 

 

  The above code uses a conversion mechanism during operation. The input is hexadecimal text and converted into byte[] data. The separator in the middle can be a space, can be '-', or can be ',', '_ 'Wait and so on, the data conversion function of the component base is called.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325166092&siteId=291194637