This is a three-part tutorial about SunSpec, an open specification that aims at increasing the interoperability within the solar and distributed energy industry. The goal of this series is to give an overview of the specification and to demonstrate how it can be used for basic use cases. This part focuses on fundamentals about the Modbus protocol which is, at time of writing, the most important communication technology for working with the SunSpec specification. The second part gives a brief introduction to SunSpec in general. It elaborates on the Sunspec information model and its relationship to Modbus. The third part is a hands-on tutorial. It shows how to use an ESP32/ESP8266 to retrieve data from a Kostal Plenticore hybrid inverter (Kostal Plenticore plus).
This introduction should not be seen as a comprehensive guide for starting with Modbus. Instead, only aspects are considered that are important for reading the other two parts and, in addition, might be necessary to get a good understanding of SunSpec in general.
Modbus
According to the Modbus Application Specification, Modbus is the industry’s serial de facto standard since 1979 and enable millions of automation devices to communicate. Even though technologies originating from the industrial domain are known to have long lifespans, it is kind of remarkable that Modbus has recently been chosen to be SunSpec’s main communication protocol. I came across Modbus several times during my studies, professional or private life. My personal opinion about Modbus is that, on the one hand, appears to be somewhat antiquated, but on the other hand, is also very easy to use. Especially when it comes to simply retrieving data without having too many other requirements, the ease of use of Modbus can be a major advantage.
When talking about Modbus, one has to specify what exactly is meant: Modbus defines the so-called “Modbus Application Layer” that is implemented for various bus/network types (e.g. EIA/TIA-232 or TCP/IP). In particular, the Modbus Application Layer describes a messaging protocol for client/server communication. In further specifications it is describe how to apply the messaging protocol for a specific bus/network type. For example, the application of the Modbus messaging protocol on TCP/IP (Ethernet) is described in “MODBUS Messaging on TCP/IP Implementation Guide V1.0a”.
In this tutorial series, the focus is set to the Modbus messaging protocol over TCP/IP (also called ModbusTCP).
Modbus Protocol (Basics)
Similar to many other protocols, Modbus is a client/server protocol meaning a single or multiple clients communicate with a server. A client is typically a “user application” (e.g. monitoring application), whereas the server is typically a “device” being monitored (e.g. heat pump with sensor values).
The protocol data unit (PDU) of Modbus has two fields: “Function Code” and “Data”. The function code field specifies which action to be performed when a message is sent from the client to the server. The data field contains additional data that belong to the function code. For some function codes / actions, the data field is not required and, therefore, contains 0 bytes.
Besides the PDU, Modbus defines a so-called application data unit (ADU). The ADU contains and additional address, the PDU and an error check. Basically, the ADU is a mapping of a message to a specific bus or network type.
<- Application Data Unit (ADU) ->
------------------------------------------------------------------
| Additional address | Function code | Data | Error Check |
------------------------------------------------------------------
<- Protocol Data Unit (PDU ) ->
Modbus Data Model
Besides the Modbus protocol, there exists a specific data model in Modbus. The data model distinguishes between discrete inputs, coils, input registers and holding registers. Normally, the client send messages (ADUs) to the server in order to retrieve data that is organized based on the Modbus data model. When implementing a Modbus server on a device, the developer can decide how to organize the sensor values into the Modbus data model. The Modbus specification does only restrict the size of the data model elements (1bit or 16bit) and whether a data element is readable or readable/writeable:
Primary tables | Object type (size) | Type of (r/w) | Comments |
Discrete Input | Single bit | Read-only | This type of data can be provided by an I/O system (device). |
Coils | Single bit | Read/Write | This type of data can be alterable by a user application. |
Input Registers | 16-bit word | Read-only | This type of data can be provided by an I/O system (device). |
Holding Registers | 16-bit word | Read/Write | This type of data can be alterable by a user application. |
Accessing data
Let’s assume a device organizes it sensor values according to the Modbus data model. For example, some sensor values are stored as discrete inputs as they are only “true” or “false” (e.g. light barrier sensors) and some other sensor values are input registers as they have to be represented as numeric values (e.g. temperature sensors). Moreover, Let’s assume the device has some configuration values that can also be written by a user application. The device would store them into the coils and holding registers data space.
If a user application (client) wants to access this data, it has to send a message with a function code. For example, if a coil has to be read, function code 0x01 has to be sent to the device (server). In addition to the function code, the client sends also the starting address and the number of coils to be read (stored in the data frame of the message). If successful, the server sends a response with the same function code, the byte count (length of the coil status) and the coil status (actual values).
The following table shows some of the most important functions codes:
Function code | Name | Access |
0x01 | Read Coils | Bit access |
0x02 | Read Discrete Inputs | Bit access |
0x03 | Read Holding Registers | 16 bits access |
0x04 | Read Input Registers | 16 bits access |
0x05 | Write Single Coil | Bit access |
0x06 | Write Single Registers | 16 bits access |
Modbus on TCP
When using Modbus on TCP/IP, clients and servers communicate over an Ethernet network. The default port for Modbus servers is 502. It is also possible that servers listen on an additional port, however, according to the specification, port 502 must always be available (“It is important to note that even if another TCP server port is configured for MODBUS service in certain applications, TCP server port 502 must still be available in addition to any application specific ports“).
The Modbus Implementation Guide (MODBUS Messaging on TCP/IP Implementation Guide V1.0a) contains many more details on how to communicate Modbus over TCP/IP. For the two other two parts of this tutorials series, it is not required to know these further details.
In the second part, you will learn more about SunSpec and how it is related to Modbus (coming soon!).
Can’t wait for second part. There are few good sources about SunSpec and Modbus.
Can’t wait for second part.
Can not wait for the next part on esp32 intergrtion. I am trying to connect to a Sungrow Sh5K with no luck. I can connect to the inverter via nodered however the ESP modbus library do not show data.