C# reads and writes floating-point numbers in Siemens PLC through ModbusTcp protocol

1. Overview of Modbus TCP communication 

MODBUS/TCP is a simple, vendor-neutral derivative of the MODBUS series of communication protocols used to manage and control automation equipment. Obviously, it covers the MODBUS messages in the "Intranet" and "Internet" environments using the TCP/IP protocol. use. The most common use of the protocol is for services such as PLCs, I/O modules, and gateways to other simple domain buses or I/O modules.

The Modbus TCP protocol adds the MBAP header in front of the RTU protocol. Since TCP is a service based on reliable connections, the CRC check code in the RTU protocol is no longer needed, so there is no CRC check code in the Modbus TCP protocol. (Major difference in usage). MBAP message header: identification (2 bytes) length (2 bytes) unit identifier (1 byte)

At present, the Modbus TCP/IP protocol is mainly used in the Internet or Intranet, while Ethernet has a long transmission distance and fast transmission speed, which makes it widely used. The long transmission distance and fast transmission speed make it widely used.

 2. Function codes used by Modbus TCP

There are four types of modbus operation objects: coils, discrete inputs, input registers, and holding registers

Coil: PLC output bit, switch value, readable and writable in MODBUS Discrete
quantity: PLC input bit, switch value, read-only in MODBUS
Input register: register that can only be changed from the analog input terminal in PLC, in Read-only holding registers in MODBUS
: registers used to output analog signals in PLC, readable and writable in MODBUS
According to different objects, the function codes of modbus are:

0x01: read coil
0x02: read discrete input
0x03: read holding register

0x04: read input register

0x05: Write a single coil
0x06: Write a single holding register
0x10: Write multiple holding registers
0x0F: Write multiple coils

 3. nmodbus4 guide

 NModbus4 is a C# based Modbus protocol library that can be used to communicate with Modbus RTU, ASCII, TCP and UDP devices. The Chinese version of NModbus4 is equivalent to a translation of the original version, making it easier for people who do not understand English to use this open source library for programming. NModbus4 is a Modbus communication protocol library written in C#. It supports Modbus protocols including Modbus RTU, ASCII, TCP and UDP. It can be used to program and read registers and coils of Modbus devices. It fully complies with the Modbus protocol specification, and at the same time, through the event calling mechanism used, it can realize the function of disconnection and reconnection.

NModbus4 is a completely open source library that can be downloaded and used for free on GitHub

4. Example of Modbus TCP communication application 

 4.1: Build the environment of Siemens Portal V15

To build a Siemens simulation environment, you need to master these in advance, see my blog

Windows 10 Enterprise Edition installs Siemens Portal V15 --- 01 preparation environment

Windows 10 Enterprise Edition installs Siemens Portal V15 --- 02 installation software

Windows 10 Enterprise Edition installs Siemens Portal V15 --- 03 installs simulation software

Windows 10 Enterprise Edition installs Siemens Portal V15 --- 04 connection test
 

4.2: Familiar with the modbusTCP environment

Need to master these before, see my blog

4.3: Create PLC simulation environment

4.4: Portal V15 to create a project

 This project will be provided at the end of this article, just open it

 4.5: Create data block variables

4.6: Create tcp connection data block

4.7: Create modbustcp communication module

Please note that the reason why it is BYTE 20 here is because the variables mf1 to mf5 have a total of 10 registers, and each register occupies 2 bytes, so it is 20 bytes. After the compilation is completed, download it to the Plc

4.8: Create a monitoring table

 

The above 8 steps complete the modbustcp server, and then make a program to read and write floating-point numbers in the Plc

4.9: Create a winform project

Open VS2019, create a form project, the layout is very simple, 4 button buttons

 

4.10: Add nmodbus4 library

 

4.11: Write "nmodbus4 reads a float" code

 /// <summary>
        /// nmodbus4读取一个float
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button4_Click(object sender, EventArgs e)
        {
            //nmodbus4读取到的数据都是ushort类型
            tcpClient = new TcpClient();
            tcpClient.Connect("192.168.1.199", 6800);//连接到主机
            master = ModbusIpMaster.CreateIp(tcpClient);//Ip 主站  
            byte slaveAddr = byte.Parse("1");//从站地址
            //ushort[] ReadHoldingRegisters(byte slaveAddress, ushort startAddress, ushort numberOfPoints);表示读保持寄存器
            //slaveAddress从站地址(默认为1,通常也是1)
            //startAddress寄存器开始地址(这个地址是modbus的地址,不是Plc变量地址)
            //numberOfPoints寄存器数量(real类型占2个寄存器数量)
            ushort[] uDatas = master.ReadHoldingRegisters(slaveAddr, ushort.Parse("0"), ushort.Parse("2"));
            byte[] t = ByteArrayLib.GetByteArrayFromUShortArray(uDatas);//ushort数组转byte数组
            float[] floats = FloatLib.GetFloatArrayFromByteArray(t);//byte数组转float数组
            string fw1a = string.Join(",", floats);
            float fw1b = FloatLib.GetFloatFromByteArray(t, 0);//byte数组转float
            MessageBox.Show("方式a:" + fw1a.ToString() + ",方式b:" + fw1b.ToString());

            uDatas = master.ReadHoldingRegisters(slaveAddr, ushort.Parse("2"), ushort.Parse("2"));
            t = ByteArrayLib.GetByteArrayFromUShortArray(uDatas);
            floats = FloatLib.GetFloatArrayFromByteArray(t);
            fw1a = string.Join(",", floats);
            fw1b = FloatLib.GetFloatFromByteArray(t, 0);
            MessageBox.Show("方式a:" + fw1a.ToString() + ",方式b:" + fw1b.ToString());

            uDatas = master.ReadHoldingRegisters(slaveAddr, ushort.Parse("4"), ushort.Parse("2"));
            t = ByteArrayLib.GetByteArrayFromUShortArray(uDatas);
            floats = FloatLib.GetFloatArrayFromByteArray(t);
            fw1a = string.Join(",", floats);
            fw1b = FloatLib.GetFloatFromByteArray(t, 0);
            MessageBox.Show("方式a:" + fw1a.ToString() + ",方式b:" + fw1b.ToString());

            uDatas = master.ReadHoldingRegisters(slaveAddr, ushort.Parse("6"), ushort.Parse("2"));
            t = ByteArrayLib.GetByteArrayFromUShortArray(uDatas);
            floats = FloatLib.GetFloatArrayFromByteArray(t);
            fw1a = string.Join(",", floats);
            fw1b = FloatLib.GetFloatFromByteArray(t, 0);
            MessageBox.Show("方式a:" + fw1a.ToString() + ",方式b:" + fw1b.ToString());

            uDatas = master.ReadHoldingRegisters(slaveAddr, ushort.Parse("8"), ushort.Parse("2"));
            t = ByteArrayLib.GetByteArrayFromUShortArray(uDatas);
            floats = FloatLib.GetFloatArrayFromByteArray(t);
            fw1a = string.Join(",", floats);
            fw1b = FloatLib.GetFloatFromByteArray(t, 0);
            MessageBox.Show("方式a:" + fw1a.ToString() + ",方式b:" + fw1b.ToString());
            master.Dispose();
            tcpClient.Dispose();
        }

running result

 All the data in the PLC have been read

 The data read by nmodbus4 are ushort type

 ushort[] ReadHoldingRegisters(byte slaveAddress, ushort startAddress, ushort numberOfPoints); indicates the read holding register slaveAddress slave
            station address (default is 1, usually also 1)
            startAddress register start address (this address is the address of modbus, not the address of Plc variable)
            numberOfPoints Number of registers (real type occupies 2 registers)

 ushort[] uDatas = master.ReadHoldingRegisters(slaveAddr, ushort.Parse("0"), ushort.Parse("2"));

This means to read the 2 register data starting from 0 in the slave station address 1, that is, the data in %DB4.DBD0, and the result is 1.1

Many people don't understand why this is the start address 0, the number is 2, which requires understanding the relationship between the address in the PLC and the MODBUS address, and the data read by nmodbus4 are all ushort types, so type conversion is required. Convert ushort array to byte array, and then convert byte array to float array

4.12: Write "nmodbus4 read all float" code

 /// <summary>
        /// nmodbus4读取全部
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button5_Click(object sender, EventArgs e)
        {
            tcpClient = new TcpClient();
            tcpClient.Connect("192.168.1.188", 6800);//连接到主机
            master = ModbusIpMaster.CreateIp(tcpClient);//Ip 主站  
            byte slaveAddr = byte.Parse("1");
            ushort[] uDatas = master.ReadHoldingRegisters(slaveAddr, ushort.Parse("5"), ushort.Parse("10"));
            byte[] t = ByteArrayLib.GetByteArrayFromUShortArray(uDatas);
            float[] floats = FloatLib.GetFloatArrayFromByteArray(t);
            string fw1a = string.Join(",", floats);
            MessageBox.Show(fw1a.ToString());

            master.Dispose();
            tcpClient.Dispose();
        }

running result

4.13: Write "nmodbus4 write single floating point" code

/// <summary>
        /// nmodbus4写入单个浮点
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button7_Click(object sender, EventArgs e)
        {
            tcpClient = new TcpClient();
            tcpClient.Connect("192.168.1.199", 6800);//连接到主机
            master = ModbusIpMaster.CreateIp(tcpClient);//Ip 主站   
            //从站地址
            byte slaveAddr = byte.Parse("1");
            开始地址
            ushort startAddr = ushort.Parse("0");
            数据的值
            string vals = ("12.625");
            float[] uVals02 = vals.Split(',').Select(s => float.Parse(s)).ToArray();
            byte[] y = ByteArrayLib.GetByteArrayFromFloatArray(uVals02);
            ushort[] ushorts = UShortLib.GetUShortArrayFromByteArray(y);
            //void WriteMultipleRegisters(byte slaveAddress, ushort startAddress, ushort[] data);//写入多保持寄存器,意思是指向多个寄存器地址写入数据,也就是指同时向多个寄存器写入数据
            //slaveAddress表示从站地址,通常为1,默认也为1
            //startAddress表示寄存器开始地址,必须是ushort类型
            //data表示写入的具体数值,必须是ushort数组
            master.WriteMultipleRegisters(slaveAddr, startAddr, ushorts);//向第一个寄存器(地址是0)写入数据12.625
            MessageBox.Show("【 通过多保持寄存器】写入正数成功!");

            float floatValue = 12.625f;
            startAddr = ushort.Parse("2");
            byte[] byteArray = ByteArrayLib.GetByteArrayFromFloat(floatValue);
            //将字节数组中第0个开始的2个字节转换成ushort类型,即0,1
            ushort ua = UShortLib.GetUShortFromByteArray(byteArray, 0, DataFormat.ABCD);
            master.WriteSingleRegister(slaveAddr, startAddr, ua);//向从站地址1中的第3个寄存器(地址为2)写入数据ua
            //将字节数组中第2个开始的2个字节转换成ushort类型,即2,3 
            ushort ub = UShortLib.GetUShortFromByteArray(byteArray, 2, DataFormat.ABCD);
            startAddr = ushort.Parse("3");
            master.WriteSingleRegister(slaveAddr, startAddr, ub);//向从站地址1中的第4个寄存器(地址为3)写入数据ub
            MessageBox.Show("【 通过单保持寄存器】写入正数成功!"); 

            vals = ("-18.326");
            startAddr = ushort.Parse("8");
            uVals02 = vals.Split(',').Select(s => float.Parse(s)).ToArray();
            y = ByteArrayLib.GetByteArrayFromFloatArray(uVals02);
            ushorts = UShortLib.GetUShortArrayFromByteArray(y);
            master.WriteMultipleRegisters(slaveAddr, startAddr, ushorts);
            MessageBox.Show("【 通过多保持寄存器】写入负数成功!");

            master.Dispose();
            tcpClient.Dispose();
        }

 running result

 4.14: Write "nmodbus4 writes multiple floats" code

 /// <summary>
        /// nmodbus4写入多个浮点
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button6_Click(object sender, EventArgs e)
        {
            tcpClient = new TcpClient();
            tcpClient.Connect("192.168.1.199", 6800);//连接到主机
            master = ModbusIpMaster.CreateIp(tcpClient);//Ip 主站  

            //从站地址
            byte slaveAddr = byte.Parse("1");
            //开始地址
            ushort startAddr = ushort.Parse("0");
            //数据的值
            string vals = ("4.9635,6.9635,-1.28,67,-902");
            float[] uVals02 = vals.Split(',').Select(s => float.Parse(s)).ToArray();
            byte[] y = ByteArrayLib.GetByteArrayFromFloatArray(uVals02);
            ushort[] ushorts = UShortLib.GetUShortArrayFromByteArray(y);
            master.WriteMultipleRegisters(slaveAddr, startAddr, ushorts);
            MessageBox.Show("【 多保持寄存器】写入成功!");
            master.Dispose();
            tcpClient.Dispose();
        }

 running result

Floating-point numbers include integers, decimals, and positive or negative numbers, so positive integers, negative integers, positive decimals, and negative decimals can all be written

Five: Summary of modbustcp protocol

MODBUS TCP combines the Ethernet physical network with the network standard TCP/IP and the data representation method with MODBUS as the application protocol standard. The MODBUS TCP communication message is encapsulated in the Ethernet TCP/IP data packet, and the maximum length of a frame of data specified by the MODBUS protocol is 256 bytes.

There are two types of devices in the MODBUS TCP/IP communication system: MODBUS TCP/IP client and server devices.

1. MODBUS client

The client (TCP Client) actively initiates a connection request to the server (TCP Server), and the connection is successfully established, only the client is allowed to actively initiate a communication request.

When the Ethernet model is used as a MODBUS TCP client, establish a TCP connection through the S_OPEN command, and initiate a MODBUS request through the M_TCP command.

2. MODBUS server

The server actively listens to port 502, waits for the connection request from the client, and the connection is established successfully, and responds to the data communication request conforming to the Modbus TCP protocol specification.

3. Advantages 

Advantages: Free, simple, and easy to use, the Modbus protocol is the most widely used protocol in the domestic industrial field, not only PLC equipment, but also various terminal equipment, such as water control machines, water meters, electric meters, industrial scales, and various acquisition equipment.

4. Features

  1. Communication using master-slave question and answer

  2. Modbus TCP is an application layer protocol, implemented based on the transport layer TCP protocol

  3. Modbus TCP port number is 502 by default, but in this case it is changed to 6800, of course you can change it to other

Six: Code download

 Link: https://pan.baidu.com/s/1mARLDATOBphLKbecj4sW8g 
Extraction code: lggv  

 

Guess you like

Origin blog.csdn.net/hqwest/article/details/132655132