Modbus TCP Slave + W5500 static IP information
-
- Posts: 6
- Joined: Sun Nov 22, 2020 8:23 pm
Modbus TCP Slave + W5500 static IP information
Hello,
I have been trying to get Modbus TCP to work through SPI Ethernet interface. I am able to start processes successfully but I have some questions about the different IP addresses. It is obvious that both the w5500 module and the ESP32 have different IP addresses, the problem is that I'm only able to change
and set as static the ESP32 IP address, the Ethernet handle shows two different IP information, once after configuring the W5500 and another after setting up the Modbus TCP.
My objective is to be able to set the IP address and subnet mask that the Modbus TCP master needs to see. I'm not an expert on this matter. Thanks!
I have been trying to get Modbus TCP to work through SPI Ethernet interface. I am able to start processes successfully but I have some questions about the different IP addresses. It is obvious that both the w5500 module and the ESP32 have different IP addresses, the problem is that I'm only able to change
and set as static the ESP32 IP address, the Ethernet handle shows two different IP information, once after configuring the W5500 and another after setting up the Modbus TCP.
My objective is to be able to set the IP address and subnet mask that the Modbus TCP master needs to see. I'm not an expert on this matter. Thanks!
-
- Posts: 211
- Joined: Fri Feb 01, 2019 4:02 pm
- Contact:
Re: Modbus TCP Slave + W5500 static IP information
Hello @JonathanJol,
What do you mean under "ESP32 IP address"? Is it the address of the WiFi interface?
The Modbus TCP example uses the example_connect common code to initialize the netif. It supports an ethernet connection over the W5500 driver. The master IP address should be obtained automatically from DHCP in this case. Below are the options set in the Example Connection Configuration menuconfig to use the W5500. If you configured the interface accordingly and selected the
See the https://docs.espressif.com/projects/esp ... on-options for more information on how to configure the Modbus slave IP addresses manually.
If you need, it is possible to change the netif IP and gateway manually using the function below.
in this case, you have to make sure you configured your network correctly and set connection options in your modbus slaves accordingly.
The place where you can change it on master: https://github.com/espressif/esp-idf/bl ... ter.c#L747
You can check the actual network parameters configured for you netif interface using the code below:
If you configured the described options properly, your master should be able to connect to your slave.
The TCP slave network configuration is very similar to what is shown above.
If you still have issues with the connection please share your code example and log.
What do you mean under "ESP32 IP address"? Is it the address of the WiFi interface?
The Modbus TCP example uses the example_connect common code to initialize the netif. It supports an ethernet connection over the W5500 driver. The master IP address should be obtained automatically from DHCP in this case. Below are the options set in the Example Connection Configuration menuconfig to use the W5500. If you configured the interface accordingly and selected the
that corresponds to `CONFIG_MB_MDNS_IP_RESOLVER` kconfig option the master should be able to find all configured slaves in the network and should be able to read data from them.(Top) → Modbus TCP Example Configuration
Espressif IoT Development Framework Configuration
Select method to resolve slave IP addresses (Resolve Modbus slave addresses using mDNS service.) --->
See the https://docs.espressif.com/projects/esp ... on-options for more information on how to configure the Modbus slave IP addresses manually.
If you need, it is possible to change the netif IP and gateway manually using the function below.
Code: Select all
esp_err_t esp_netif_set_ip_info(esp_netif_t *esp_netif, const esp_netif_ip_info_t *ip_info);
Code: Select all
esp_netif_t* pnetif = (esp_netif_t*)comm_info.ip_netif_ptr;
esp_netif_ip_info_t ip_info;
IP4_ADDR(&ip_info.ip, 192, 168, 33, 103);
IP4_ADDR(&ip_info.gw, 192, 168, 33, 3);
IP4_ADDR(&ip_info.netmask, 255, 255, 254, 0);
esp_netif_set_ip_info(pnetif, &ip_info);
The place where you can change it on master: https://github.com/espressif/esp-idf/bl ... ter.c#L747
You can check the actual network parameters configured for you netif interface using the code below:
Code: Select all
esp_netif_t* pnetif = (esp_netif_t*)comm_info.ip_netif_ptr;
esp_netif_ip_info_t ip_info;
esp_netif_get_ip_info(pnetif, &ip_info);
printf("IP: " IPSTR "\n", IP2STR(&ip_info.ip));
printf("GW: " IPSTR "\n", IP2STR(&ip_info.gw));
printf("NETMASK: " IPSTR "\n", IP2STR(&ip_info.netmask));
If you configured the described options properly, your master should be able to connect to your slave.
The TCP slave network configuration is very similar to what is shown above.
If you still have issues with the connection please share your code example and log.
-
- Posts: 6
- Joined: Sun Nov 22, 2020 8:23 pm
Re: Modbus TCP Slave + W5500 static IP information
Hello, @ESP_alisitsyn,
Thank you for your answer. I will explain a bit more about my setup. This is an ESP32 that is going to be working as a TCP Slave device so someone else can connect to it and get the data from the registers with an HMI. While configuring and checking IP Addresses, I noticed that I have two different addresses, one for the original netif handler, and a second one for the ethernet handler. I'm able to change the netif IP without any issue using the functions you have shown me here, but I'm not able to set the IP address and subnet mask of the ethernet interface, which, as far as I know, are the ones that the Master TCP will need to communicate with my slave.
What I need is to be able to change the IP and subnet mask of the ethernet interface since they appear to be random. I will send a snippet of my code.
I can't show you the log right now, but I have no error and it is showing what it is supposed to show. In the beginning, I thought the netif would attach its IP information to the ethernet interface but it didn't work like that, so what I really want to do is manually set the Ip address and subnet mask of my TCP Slave, either by some Modbus config or by the ethernet configuration. Something worth mentioning is that the ethernet interface creates a random IP and subnet mask, but then that same one has randomly changed again after starting the TCP stack. Also, I can't configure the TCP master being used for certain reasons.
Thank you for your answer. I will explain a bit more about my setup. This is an ESP32 that is going to be working as a TCP Slave device so someone else can connect to it and get the data from the registers with an HMI. While configuring and checking IP Addresses, I noticed that I have two different addresses, one for the original netif handler, and a second one for the ethernet handler. I'm able to change the netif IP without any issue using the functions you have shown me here, but I'm not able to set the IP address and subnet mask of the ethernet interface, which, as far as I know, are the ones that the Master TCP will need to communicate with my slave.
What I need is to be able to change the IP and subnet mask of the ethernet interface since they appear to be random. I will send a snippet of my code.
- esp_netif_ip_info_t info_ip;
- // Initialize TCP/IP network interface (should be called only once in application)
- ESP_ERROR_CHECK(esp_netif_init());
- // Create default event loop that running in background
- ESP_ERROR_CHECK(esp_event_loop_create_default());
- // Create instance(s) of esp-netif for SPI Ethernet(s)
- esp_netif_inherent_config_t esp_netif_config = ESP_NETIF_INHERENT_DEFAULT_ETH();
- esp_netif_config.if_desc = "eth0";
- esp_netif_config_t cfg_spi = {
- .base = &esp_netif_config,
- .stack = ESP_NETIF_NETSTACK_DEFAULT_ETH
- };
- esp_netif_t *eth_netif_spi = { NULL };
- char if_key_str[10];
- char if_desc_str[10];
- char num_str[3];
- itoa(0, num_str, 10);
- strcat(strcpy(if_key_str, "ETH_SPI_"), num_str);
- strcat(strcpy(if_desc_str, "eth"), num_str);
- esp_netif_config.if_key = if_key_str;
- esp_netif_config.if_desc = if_desc_str;
- esp_netif_config.route_prio = 30;
- eth_netif_spi = esp_netif_new(&cfg_spi);
- ESP_ERROR_CHECK(esp_netif_dhcpc_stop(eth_netif_spi));
- char* ip= "10.25.10.2";
- char* gateway = "10.25.0.1";
- char* netmask = "255.255.0.0";
- esp_netif_ip_info_t info_t;
- memset(&info_t, 0, sizeof(esp_netif_ip_info_t));
- info_t.ip.addr = esp_ip4addr_aton((const char *)ip);
- info_t.gw.addr = esp_ip4addr_aton((const char *)gateway);
- info_t.netmask.addr = esp_ip4addr_aton((const char *)netmask);
- esp_netif_set_ip_info(eth_netif_spi, &info_t);
- // Init MAC and PHY configs to default
- eth_mac_config_t mac_config_spi = ETH_MAC_DEFAULT_CONFIG();
- eth_phy_config_t phy_config_spi = ETH_PHY_DEFAULT_CONFIG();
- // Init SPI bus
- spi_device_handle_t spi_handle = { NULL };
- spi_bus_config_t buscfg = {
- .miso_io_num = GPIO_NUM_36,
- .mosi_io_num = GPIO_NUM_19,
- .sclk_io_num = GPIO_NUM_18,
- .quadwp_io_num = -1,
- .quadhd_io_num = -1,
- };
- // Install GPIO ISR handler to be able to service SPI Eth modlues interrupts
- gpio_install_isr_service(0);
- ESP_ERROR_CHECK(spi_bus_initialize(SPI_HOST, &buscfg, SPI_DMA_CH_AUTO));
- // Init specific SPI Ethernet module configuration from Kconfig (CS GPIO, Interrupt GPIO, etc.)
- spi_eth_module_config_t spi_eth_module_config = {
- .spi_cs_gpio = GPIO_NUM_5,
- .phy_reset_gpio = GPIO_NUM_27,
- .int_gpio = GPIO_NUM_4,
- .phy_addr = 10
- };
- // Configure SPI interface and Ethernet driver for specific SPI module
- esp_eth_mac_t *mac_spi;
- esp_eth_phy_t *phy_spi;
- esp_eth_handle_t eth_handle_spi = { NULL };
- spi_device_interface_config_t devcfg = {
- .command_bits = 16, // Actually it's the address phase in W5500 SPI frame
- .address_bits = 8, // Actually it's the control phase in W5500 SPI frame
- .mode = 0,
- .clock_speed_hz = 10 * 1000 * 1000,
- .queue_size = 20
- };
- // Set SPI module Chip Select GPIO
- devcfg.spics_io_num = spi_eth_module_config.spi_cs_gpio;
- ESP_ERROR_CHECK(spi_bus_add_device(SPI_HOST, &devcfg, &spi_handle));
- // w5500 ethernet driver is based on spi driver
- eth_w5500_config_t w5500_config = ETH_W5500_DEFAULT_CONFIG(spi_handle);
- // Set remaining GPIO numbers and configuration used by the SPI module
- w5500_config.int_gpio_num = spi_eth_module_config.int_gpio;
- phy_config_spi.phy_addr = spi_eth_module_config.phy_addr;
- phy_config_spi.reset_gpio_num = spi_eth_module_config.phy_reset_gpio;
- mac_spi = esp_eth_mac_new_w5500(&w5500_config, &mac_config_spi);
- phy_spi = esp_eth_phy_new_w5500(&phy_config_spi);
- esp_eth_config_t eth_config_spi = ETH_DEFAULT_CONFIG(mac_spi, phy_spi);
- ESP_ERROR_CHECK(esp_eth_driver_install(ð_config_spi, ð_handle_spi));
- /* The SPI Ethernet module might not have a burned factory MAC address, we cat to set it manually.
- 02:00:00 is a Locally Administered OUI range so should not be used except when testing on a LAN under your control.*/
- ESP_ERROR_CHECK(esp_eth_ioctl(eth_handle_spi, ETH_CMD_S_MAC_ADDR, (uint8_t[]) {
- 0x00, 0x12, 0xCF, 0xC1, 0x55, 0xE2
- }));
- // attach Ethernet driver to TCP/IP stack
- ESP_ERROR_CHECK(esp_netif_attach(eth_netif_spi, esp_eth_new_netif_glue(eth_handle_spi)));
- // Register user defined event handers
- ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, NULL));
- ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, NULL));
- /* start Ethernet driver state machine */
- ESP_ERROR_CHECK(esp_eth_start(eth_handle_spi));
- mb_register_area_descriptor_t reg_area; // Modbus register area descriptor structure
- void* slave_handler = NULL;
- // Initialization of Modbus controller
- esp_err_t err = mbc_slave_init_tcp(&slave_handler);
- MB_RETURN_ON_FALSE((err == ESP_OK && slave_handler != NULL), ESP_ERR_INVALID_STATE,
- SLAVE_TAG,
- "mb controller initialization fail.");
- mb_communication_info_t comm_info = {
- .ip_port = MB_TCP_SLAVE_PORT, // Modbus TCP port number (default = 502)
- .ip_addr_type = MB_IPV4, // version of IP protocol
- .ip_mode = MB_MODE_TCP, // Port communication mode
- .ip_addr = NULL, // This field keeps the client IP address to bind, NULL - bind to any client
- .ip_netif_ptr = (void*)eth_handle_spi // esp_netif_ptr - pointer to the corresponding network interface
- };
- // Setup communication parameters and start stack
- err = mbc_slave_setup((void*)&comm_info);
- MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE,
- SLAVE_TAG,
- "mbc_slave_setup fail, returns(0x%x).",
- (uint32_t)err);
- reg_area.type = MB_PARAM_HOLDING; // Set type of register area
- reg_area.start_offset = MB_REG_HOLDING_START_AREA0; // Offset of register area in Modbus protocol
- reg_area.address = (void*)&holding_reg_area[0]; // Set pointer to storage instance
- reg_area.size = sizeof(holding_reg_area) << 1; // Set the size of register storage area in bytes
- ESP_ERROR_CHECK(mbc_slave_set_descriptor(reg_area));
- MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE,
- SLAVE_TAG,
- "mbc_slave_set_descriptor fail, returns(0x%x).",
- (uint32_t)err);
- // Starts of modbus controller and stack
- err = mbc_slave_start();
- MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE,
- SLAVE_TAG,
- "mbc_slave_start fail, returns(0x%x).",
- (uint32_t)err);
- vTaskDelay(5);
- printf("modbusTCP initialized\n");
- esp_netif_get_ip_info(eth_handle_spi, &ip_info);
- ESP_LOGI(SLAVE_TAG, "ip: " IPSTR ", mask: " IPSTR ", gw: " IPSTR,
- IP2STR(&ip_info.ip),
- IP2STR(&ip_info.netmask),
- IP2STR(&ip_info.gw));
- esp_netif_get_ip_info(eth_netif_spi, &ip_info);
- ESP_LOGI(SLAVE_TAG, "ip: " IPSTR ", mask: " IPSTR ", gw: " IPSTR,
- IP2STR(&ip_info.ip),
- IP2STR(&ip_info.netmask),
- IP2STR(&ip_info.gw));
- holding_reg_area[0] = 0x01;
- holding_reg_area[1] = 0x02;
- return err;
-
- Posts: 211
- Joined: Fri May 07, 2021 10:35 am
Re: Modbus TCP Slave + W5500 static IP information
Hi JonathanJol,
I see where the issue is. You misunderstood the ESP NETIF concept. The ESP NETIF is associated with Ethernet handle, it is kind of intermediate layer between IP stack and Ethernet driver, please see https://docs.espressif.com/projects/esp ... netif.html for more info.
Hence you need to fix the code as follows:
And remove this:
The above one was the reason why you got random IP address since you passed to the function incorrect memory area which was not associated with NETIF.
Ondrej
I see where the issue is. You misunderstood the ESP NETIF concept. The ESP NETIF is associated with Ethernet handle, it is kind of intermediate layer between IP stack and Ethernet driver, please see https://docs.espressif.com/projects/esp ... netif.html for more info.
Hence you need to fix the code as follows:
Code: Select all
mb_communication_info_t comm_info = {
.ip_port = MB_TCP_SLAVE_PORT, // Modbus TCP port number (default = 502)
.ip_addr_type = MB_IPV4, // version of IP protocol
.ip_mode = MB_MODE_TCP, // Port communication mode
.ip_addr = NULL, // This field keeps the client IP address to bind, NULL - bind to any client
.ip_netif_ptr = eth_netif_spi // esp_netif_ptr - pointer to the corresponding network interface
};
Code: Select all
esp_netif_get_ip_info(eth_handle_spi, &ip_info);
ESP_LOGI(SLAVE_TAG, "ip: " IPSTR ", mask: " IPSTR ", gw: " IPSTR,
IP2STR(&ip_info.ip),
IP2STR(&ip_info.netmask),
IP2STR(&ip_info.gw));
Ondrej
-
- Posts: 211
- Joined: Fri Feb 01, 2019 4:02 pm
- Contact:
Re: Modbus TCP Slave + W5500 static IP information
@JonathanJol ,
Thank you for your code snippet and clarification. The code you provided is fully functional and Modbus communication with the static IP can be established once you set the netif interface correctly in the Modbus slave configuration as @ESP_ondrej described above.
https://docs.espressif.com/projects/esp ... on-options
Try to set it as described and let me know your result.
Thank you for your code snippet and clarification. The code you provided is fully functional and Modbus communication with the static IP can be established once you set the netif interface correctly in the Modbus slave configuration as @ESP_ondrej described above.
https://docs.espressif.com/projects/esp ... on-options
Try to set it as described and let me know your result.
-
- Posts: 6
- Joined: Sun Nov 22, 2020 8:23 pm
Re: Modbus TCP Slave + W5500 static IP information
Hello, @ESP_alisitsyn and @ESP_ondrej
Thank you very much for your answers, I have successfully reached communication with my ESP32 as a slave. It was not immediate though, after applying the fix I still struggled to get things going, so I went straight to day 0 and compiled an ethernet basic example which worked as intended. This made me compare both my code and the example to make sure I didn't forget a tiny detail, here are my findings:
1-. I never told you what was the ESP-IDF version I was working on, which is 4.3.1. I think this was very important for the following reason.
2. The esp_eth_set_default_handlers function was missing from my code, since the example of the v4.4 doesn't have it in it.
Just to give you context into why I was using a v4.4 example in this, I'm working in a remote Raspberry Pi environment that is using v4.3.1 since v4.4 can't compile for another known error. On my local PC, I was working using the examples in the working environment I have and then sending files through WinSCP. When I did the basic Ethernet example I used the example inside the RPi environment, so that is why it worked immediately.
I take that this is my error since I haven't seen anyone talking about the missing function in v4.4, but just in case, can you guys confirm to me that v4.4 is not necessary to call for esp_eth_set_default_handlers?
Thank you!
Thank you very much for your answers, I have successfully reached communication with my ESP32 as a slave. It was not immediate though, after applying the fix I still struggled to get things going, so I went straight to day 0 and compiled an ethernet basic example which worked as intended. This made me compare both my code and the example to make sure I didn't forget a tiny detail, here are my findings:
1-. I never told you what was the ESP-IDF version I was working on, which is 4.3.1. I think this was very important for the following reason.
2. The esp_eth_set_default_handlers function was missing from my code, since the example of the v4.4 doesn't have it in it.
Just to give you context into why I was using a v4.4 example in this, I'm working in a remote Raspberry Pi environment that is using v4.3.1 since v4.4 can't compile for another known error. On my local PC, I was working using the examples in the working environment I have and then sending files through WinSCP. When I did the basic Ethernet example I used the example inside the RPi environment, so that is why it worked immediately.
I take that this is my error since I haven't seen anyone talking about the missing function in v4.4, but just in case, can you guys confirm to me that v4.4 is not necessary to call for esp_eth_set_default_handlers?
Thank you!
-
- Posts: 211
- Joined: Fri May 07, 2021 10:35 am
Re: Modbus TCP Slave + W5500 static IP information
Yes, it is not necessary to call `esp_eth_set_default_handlers` in ESP-IDF 4.4 and higher.
-
- Posts: 4
- Joined: Sun Jan 23, 2022 4:01 pm
Re: Modbus TCP Slave + W5500 static IP information
Hi, Im still strugling with ethernet modbus TCP (ENC28J60). If you could provide a code that would be awesome.
-
- Posts: 211
- Joined: Fri Feb 01, 2019 4:02 pm
- Contact:
Re: Modbus TCP Slave + W5500 static IP information
Hi Silvesterrr,
Have you been able to solve your issue here https://github.com/espressif/esp-idf/issues/9714 ?
Have you been able to solve your issue here https://github.com/espressif/esp-idf/issues/9714 ?
-
- Posts: 4
- Joined: Sun Jan 23, 2022 4:01 pm
Who is online
Users browsing this forum: jcolebaker and 174 guests