README.md
1# Modbus TCP Master Example
2
3This example demonstrates using of FreeModbus stack port implementation for ESP32 as a TCP master device.
4This implementation is able to read/write values of slave devices connected into Modbus segment. All parameters to be accessed are defined in data dictionary of the modbus master example source file.
5The values represented as characteristics with its name and characteristic CID which are linked into registers of slave devices connected into Modbus segment.
6The example implements simple control algorithm and checks parameters from slave device and gets alarm (relay in the slave device) when value of parameter exceeded limit.
7The instances for the modbus parameters are common for master and slave examples and located in `examples/protocols/modbus/mb_example_common` folder.
8
9Example parameters definition:
10--------------------------------------------------------------------------------------------------
11| Slave Address | Characteristic ID | Characteristic name | Description |
12|---------------------|----------------------|----------------------|----------------------------|
13| MB_DEVICE_ADDR1 | CID_INP_DATA_0, | Data_channel_0 | Data channel 1 |
14| MB_DEVICE_ADDR1 | CID_HOLD_DATA_0, | Humidity_1 | Humidity 1 |
15| MB_DEVICE_ADDR1 | CID_INP_DATA_1 | Temperature_1 | Sensor temperature |
16| MB_DEVICE_ADDR1 | CID_HOLD_DATA_1, | Humidity_2 | Humidity 2 |
17| MB_DEVICE_ADDR1 | CID_INP_DATA_2 | Temperature_2 | Ambient temperature |
18| MB_DEVICE_ADDR1 | CID_HOLD_DATA_2 | Humidity_3 | Humidity 3 |
19| MB_DEVICE_ADDR1 | CID_RELAY_P1 | RelayP1 | Alarm Relay outputs on/off |
20| MB_DEVICE_ADDR1 | CID_RELAY_P2 | RelayP2 | Alarm Relay outputs on/off |
21--------------------------------------------------------------------------------------------------
22Note: The Slave Address is the same for all parameters for example test but it can be changed in the `Example Data (Object) Dictionary` table of master example to address parameters from other slaves.
23The Kconfig ```Modbus slave address``` - CONFIG_MB_SLAVE_ADDR parameter in slave example can be configured to create Modbus multi slave segment.
24
25Simplified Modbus connection schematic for example test:
26 ```
27 MB_DEVICE_ADDR1
28 ------------- -------------
29 | | Network | |
30 | Slave 1 |---<>--+---<>---| Master |
31 | | | |
32 ------------- -------------
33```
34Modbus multi slave segment connection schematic:
35```
36 MB_DEVICE_ADDR1
37 -------------
38 | |
39 | Slave 1 |---<>--+
40 | | |
41 ------------- |
42 MB_DEVICE_ADDR2 |
43 ------------- | -------------
44 | | | | |
45 | Slave 2 |---<>--+---<>---| Master |
46 | | | | |
47 ------------- | -------------
48 MB_DEVICE_ADDR3 |
49 ------------- Network (Ethernet or WiFi connection)
50 | | |
51 | Slave 3 |---<>--+
52 | |
53 -------------
54```
55
56## Hardware required :
57Option 1:
58PC (Modbus TCP Slave application) + ESP32(-S2) development board with modbus_tcp_slave example.
59
60Option 2:
61Several ESP32(-S2) boards flashed with modbus_tcp_slave example software to represent slave devices. The IP slave addresses for each board have to be configured in `Modbus Example Configuration` menu according to the communication table of example.
62One ESP32(-S2) development board should be flashed with modbus_master example and connected to the same network. All the boards require configuration of network settings as described in `examples/common_components/protocol_examples_common`.
63
64## How to setup and use an example:
65
66### Configure the application
67Start the command below to setup configuration:
68```
69idf.py menuconfig
70```
71
72The communication parameters of Modbus stack allow to configure it appropriately but usually it is enough to use default settings.
73See the help string of parameters for more information.
74There are three ways to configure how the master example will obtain slave IP addresses in the network:
75* Enable CONFIG_MB_MDNS_IP_RESOLVER option allows to query for modbus services provided by Modbus slaves in the network and automatically configure IP table. This requires to activate the same option for each slave with unique modbus slave address configured in `Modbus Example Configuration` menu.
76* Enable CONFIG_MB_SLAVE_IP_FROM_STDIN option to define IP addresses of slaves manually. In order to enter the IP addresses wait for the prompt and type the string with IP address following format. Prompt: "Waiting IPN from stdin:", then enter the IP address of the slave to connect: "IPN=192.168.1.21", where N = (configured slave address - 1).
77* Configure slave addresses manually as below:
78```
79char* slave_ip_address_table[MB_DEVICE_COUNT] = {
80 "192.168.1.21", // Address corresponds to MB_DEVICE_ADDR1 and set to predefined value by user
81 "192.168.1.22", // Address corresponds to MB_DEVICE_ADDR2 of slave device in the Modbus data dictionary
82 NULL // Marker of end of list
83 };
84```
85
86### Setup external Modbus slave devices or emulator
87Option 1:
88Configure the external Modbus master software according to port configuration parameters used in the example. The Modbus Slave application can be used with this example to emulate slave devices with its parameters. Use official documentation for software to setup emulation of slave devices.
89
90Option 2:
91Other option is to have the modbus_slave example application flashed into ESP32 WROVER KIT board and connect boards together as showed on the Modbus connection schematic above. See the Modbus slave API documentation to configure communication parameters and slave addresses as defined in "Example parameters definition" table above.
92
93### Build and flash software of master device
94Build the project and flash it to the board, then run monitor tool to view serial output:
95```
96idf.py -p PORT flash monitor
97```
98
99(To exit the serial monitor, type ``Ctrl-]``.)
100
101See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.
102
103## Example Output
104Example output of the application:
105```
106I (4644) esp_netif_handlers: example_connect: sta ip: 192.168.1.39, mask: 255.255.255.0, gw: 192.168.1.1
107I (4644) example_connect: Got IPv4 event: Interface "example_connect: sta" address: 192.168.1.39
108I (5644) example_connect: Got IPv6 event: Interface "example_connect: sta" address: fe80:0000:0000:0000:bedd:c2ff:fed1:b210, type: ESP_IP6_ADDR_IS_LINK_LOCAL
109I (5644) example_connect: Connected to example_connect: sta
110I (5654) example_connect: - IPv4 address: 192.168.1.39
111I (5664) example_connect: - IPv6 address: fe80:0000:0000:0000:bedd:c2ff:fed1:b210, type: ESP_IP6_ADDR_IS_LINK_LOCAL
112I (5674) uart: ESP_INTR_FLAG_IRAM flag not set while CONFIG_UART_ISR_IN_IRAM is enabled, flag updated
113I (5684) MASTER_TEST: Leave IP(0) = [192.168.1.21] set by user.
114I (5694) MASTER_TEST: IP(1) is not set in the table.
115I (5694) MASTER_TEST: Configured 1 IP addresse(s).
116I (5704) MASTER_TEST: Modbus master stack initialized...
117I (5704) MB_TCP_MASTER_PORT: TCP master stack initialized.
118I (5724) MB_TCP_MASTER_PORT: Host[IP]: "192.168.1.21"[192.168.1.21]
119I (5724) MB_TCP_MASTER_PORT: Add slave IP: 192.168.1.21
120I (5734) MB_TCP_MASTER_PORT: Connecting to slaves...
121-.-.-.I (5844) MB_TCP_MASTER_PORT: Connected 1 slaves, start polling...
122I (6004) MASTER_TEST: Start modbus test...
123I (6044) MASTER_TEST: Characteristic #0 Data_channel_0 (Volts) value = 1.120000 (0x3f8f5c29) read successful.
124I (6054) MASTER_TEST: Characteristic #1 Humidity_1 (%rH) value = 1.340000 (0x3fab851f) read successful.
125I (6074) MASTER_TEST: Characteristic #2 Temperature_1 (C) value = 2.340000 (0x4015c28f) read successful.
126I (6084) MASTER_TEST: Characteristic #3 Humidity_2 (%rH) value = 2.560000 (0x4023d70a) read successful.
127I (6094) MASTER_TEST: Characteristic #4 Temperature_2 (C) value = 3.560000 (0x4063d70a) read successful.
128I (6104) MASTER_TEST: Characteristic #5 Humidity_3 (%rH) value = 3.780000 (0x4071eb85) read successful.
129I (6124) MASTER_TEST: Characteristic #6 RelayP1 (on/off) value = OFF (0x55) read successful.
130I (6134) MASTER_TEST: Characteristic #7 RelayP2 (on/off) value = OFF (0xaa) read successful.
131I (6854) MASTER_TEST: Characteristic #0 Data_channel_0 (Volts) value = 1.120000 (0x3f8f5c29) read successful.
132I (7064) MASTER_TEST: Characteristic #1 Humidity_1 (%rH) value = 1.740000 (0x3fdeb852) read successful.
133I (7264) MASTER_TEST: Characteristic #2 Temperature_1 (C) value = 2.340000 (0x4015c28f) read successful.
134...
135I (45974) MASTER_TEST: Characteristic #4 Temperature_2 (C) value = 3.560000 (0x4063d70a) read successful.
136I (46174) MASTER_TEST: Characteristic #5 Humidity_3 (%rH) value = 3.780000 (0x4071eb85) read successful.
137I (46384) MASTER_TEST: Characteristic #6 RelayP1 (on/off) value = OFF (0x55) read successful.
138I (46584) MASTER_TEST: Characteristic #7 RelayP2 (on/off) value = ON (0xff) read successful.
139I (47094) MASTER_TEST: Alarm triggered by cid #7.
140I (47094) MASTER_TEST: Destroy master...
141```
142The example reads the characteristics from slave device(s), while alarm is not triggered in the slave device (See the "Example parameters definition"). The output line describes Timestamp, Cid of characteristic, Characteristic name (Units), Characteristic value (Hex data).
143
144