Modbus TCP Slave + W5500 static IP information

JonathanJol
Posts: 6
Joined: Sun Nov 22, 2020 8:23 pm

Modbus TCP Slave + W5500 static IP information

Postby JonathanJol » Sat May 07, 2022 1:54 pm

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!

ESP_alisitsyn
Posts: 211
Joined: Fri Feb 01, 2019 4:02 pm
Contact:

Re: Modbus TCP Slave + W5500 static IP information

Postby ESP_alisitsyn » Mon May 09, 2022 2:57 pm

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
(Top) → Modbus TCP Example Configuration
Espressif IoT Development Framework Configuration
Select method to resolve slave IP addresses (Resolve Modbus slave addresses using mDNS service.) --->
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.
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); 
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:

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.
w5500_options.png
example_connection options for w5500
w5500_options.png (54.68 KiB) Viewed 8486 times
If you still have issues with the connection please share your code example and log.

JonathanJol
Posts: 6
Joined: Sun Nov 22, 2020 8:23 pm

Re: Modbus TCP Slave + W5500 static IP information

Postby JonathanJol » Mon May 09, 2022 10:56 pm

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.
  1.     esp_netif_ip_info_t info_ip;
  2.  
  3.     // Initialize TCP/IP network interface (should be called only once in application)
  4.     ESP_ERROR_CHECK(esp_netif_init());
  5.  
  6.     // Create default event loop that running in background
  7.     ESP_ERROR_CHECK(esp_event_loop_create_default());
  8.  
  9.     // Create instance(s) of esp-netif for SPI Ethernet(s)
  10.     esp_netif_inherent_config_t esp_netif_config = ESP_NETIF_INHERENT_DEFAULT_ETH();
  11.     esp_netif_config.if_desc = "eth0";
  12.     esp_netif_config_t cfg_spi = {
  13.         .base = &esp_netif_config,
  14.         .stack = ESP_NETIF_NETSTACK_DEFAULT_ETH
  15.     };
  16.     esp_netif_t *eth_netif_spi = { NULL };
  17.     char if_key_str[10];
  18.     char if_desc_str[10];
  19.     char num_str[3];
  20.     itoa(0, num_str, 10);
  21.     strcat(strcpy(if_key_str, "ETH_SPI_"), num_str);
  22.     strcat(strcpy(if_desc_str, "eth"), num_str);
  23.     esp_netif_config.if_key = if_key_str;
  24.     esp_netif_config.if_desc = if_desc_str;
  25.     esp_netif_config.route_prio = 30;
  26.     eth_netif_spi = esp_netif_new(&cfg_spi);
  27.  
  28.     ESP_ERROR_CHECK(esp_netif_dhcpc_stop(eth_netif_spi));
  29.  
  30.     char* ip= "10.25.10.2";
  31.     char* gateway = "10.25.0.1";
  32.     char* netmask = "255.255.0.0";
  33.     esp_netif_ip_info_t info_t;
  34.     memset(&info_t, 0, sizeof(esp_netif_ip_info_t));
  35.     info_t.ip.addr = esp_ip4addr_aton((const char *)ip);
  36.     info_t.gw.addr = esp_ip4addr_aton((const char *)gateway);
  37.     info_t.netmask.addr = esp_ip4addr_aton((const char *)netmask);
  38.     esp_netif_set_ip_info(eth_netif_spi, &info_t);  
  39.  
  40.     // Init MAC and PHY configs to default
  41.     eth_mac_config_t mac_config_spi = ETH_MAC_DEFAULT_CONFIG();
  42.     eth_phy_config_t phy_config_spi = ETH_PHY_DEFAULT_CONFIG();
  43.  
  44.     // Init SPI bus
  45.     spi_device_handle_t spi_handle = { NULL };
  46.     spi_bus_config_t buscfg = {
  47.         .miso_io_num = GPIO_NUM_36,
  48.         .mosi_io_num = GPIO_NUM_19,
  49.         .sclk_io_num = GPIO_NUM_18,
  50.         .quadwp_io_num = -1,
  51.         .quadhd_io_num = -1,
  52.     };
  53.  
  54.  
  55.     // Install GPIO ISR handler to be able to service SPI Eth modlues interrupts
  56.     gpio_install_isr_service(0);
  57.  
  58.     ESP_ERROR_CHECK(spi_bus_initialize(SPI_HOST, &buscfg, SPI_DMA_CH_AUTO));
  59.  
  60.     // Init specific SPI Ethernet module configuration from Kconfig (CS GPIO, Interrupt GPIO, etc.)
  61.     spi_eth_module_config_t spi_eth_module_config = {
  62.         .spi_cs_gpio = GPIO_NUM_5,
  63.         .phy_reset_gpio = GPIO_NUM_27,
  64.         .int_gpio = GPIO_NUM_4,
  65.         .phy_addr = 10
  66.     };
  67.  
  68.     // Configure SPI interface and Ethernet driver for specific SPI module
  69.     esp_eth_mac_t *mac_spi;
  70.     esp_eth_phy_t *phy_spi;
  71.     esp_eth_handle_t eth_handle_spi = { NULL };
  72.  
  73.     spi_device_interface_config_t devcfg = {
  74.         .command_bits = 16, // Actually it's the address phase in W5500 SPI frame
  75.         .address_bits = 8,  // Actually it's the control phase in W5500 SPI frame
  76.         .mode = 0,
  77.         .clock_speed_hz = 10 * 1000 * 1000,
  78.         .queue_size = 20
  79.     };
  80.  
  81.     // Set SPI module Chip Select GPIO
  82.     devcfg.spics_io_num = spi_eth_module_config.spi_cs_gpio;
  83.  
  84.     ESP_ERROR_CHECK(spi_bus_add_device(SPI_HOST, &devcfg, &spi_handle));
  85.  
  86.     // w5500 ethernet driver is based on spi driver
  87.     eth_w5500_config_t w5500_config = ETH_W5500_DEFAULT_CONFIG(spi_handle);
  88.  
  89.     // Set remaining GPIO numbers and configuration used by the SPI module
  90.     w5500_config.int_gpio_num = spi_eth_module_config.int_gpio;
  91.     phy_config_spi.phy_addr = spi_eth_module_config.phy_addr;
  92.     phy_config_spi.reset_gpio_num = spi_eth_module_config.phy_reset_gpio;
  93.  
  94.     mac_spi = esp_eth_mac_new_w5500(&w5500_config, &mac_config_spi);
  95.     phy_spi = esp_eth_phy_new_w5500(&phy_config_spi);
  96.  
  97.     esp_eth_config_t eth_config_spi = ETH_DEFAULT_CONFIG(mac_spi, phy_spi);
  98.     ESP_ERROR_CHECK(esp_eth_driver_install(&eth_config_spi, &eth_handle_spi));
  99.  
  100.     /* The SPI Ethernet module might not have a burned factory MAC address, we cat to set it manually.
  101.     02:00:00 is a Locally Administered OUI range so should not be used except when testing on a LAN under your control.*/
  102.  
  103.  
  104.     ESP_ERROR_CHECK(esp_eth_ioctl(eth_handle_spi, ETH_CMD_S_MAC_ADDR, (uint8_t[]) {
  105.         0x00, 0x12, 0xCF, 0xC1, 0x55, 0xE2
  106.     }));
  107.  
  108.     // attach Ethernet driver to TCP/IP stack
  109.     ESP_ERROR_CHECK(esp_netif_attach(eth_netif_spi, esp_eth_new_netif_glue(eth_handle_spi)));
  110.  
  111.     // Register user defined event handers
  112.     ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, &eth_event_handler, NULL));
  113.     ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, NULL));
  114.  
  115.  
  116.     /* start Ethernet driver state machine */
  117.     ESP_ERROR_CHECK(esp_eth_start(eth_handle_spi));
  118.  
  119.  
  120.     mb_register_area_descriptor_t reg_area; // Modbus register area descriptor structure
  121.  
  122.     void* slave_handler = NULL;
  123.  
  124.      // Initialization of Modbus controller
  125.     esp_err_t err = mbc_slave_init_tcp(&slave_handler);
  126.     MB_RETURN_ON_FALSE((err == ESP_OK && slave_handler != NULL), ESP_ERR_INVALID_STATE,
  127.                                 SLAVE_TAG,
  128.                                 "mb controller initialization fail.");
  129.  
  130.     mb_communication_info_t comm_info = {
  131.         .ip_port = MB_TCP_SLAVE_PORT,                    // Modbus TCP port number (default = 502)
  132.         .ip_addr_type = MB_IPV4,                   // version of IP protocol
  133.         .ip_mode = MB_MODE_TCP,                    // Port communication mode
  134.         .ip_addr = NULL,                           // This field keeps the client IP address to bind, NULL - bind to any client
  135.         .ip_netif_ptr = (void*)eth_handle_spi     // esp_netif_ptr - pointer to the corresponding network interface
  136.     };
  137.  
  138.     // Setup communication parameters and start stack
  139.     err = mbc_slave_setup((void*)&comm_info);
  140.     MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE,
  141.                                         SLAVE_TAG,
  142.                                         "mbc_slave_setup fail, returns(0x%x).",
  143.                                         (uint32_t)err);
  144.  
  145.     reg_area.type = MB_PARAM_HOLDING;                               // Set type of register area
  146.     reg_area.start_offset = MB_REG_HOLDING_START_AREA0;             // Offset of register area in Modbus protocol
  147.     reg_area.address = (void*)&holding_reg_area[0];                 // Set pointer to storage instance
  148.     reg_area.size = sizeof(holding_reg_area) << 1;                  // Set the size of register storage area in bytes
  149.     ESP_ERROR_CHECK(mbc_slave_set_descriptor(reg_area));
  150.     MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE,
  151.                                     SLAVE_TAG,
  152.                                     "mbc_slave_set_descriptor fail, returns(0x%x).",
  153.                                     (uint32_t)err);
  154.  
  155.     // Starts of modbus controller and stack
  156.     err = mbc_slave_start();
  157.     MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE,
  158.                                         SLAVE_TAG,
  159.                                         "mbc_slave_start fail, returns(0x%x).",
  160.                                         (uint32_t)err);
  161.     vTaskDelay(5);
  162.  
  163.     printf("modbusTCP initialized\n");
  164.     esp_netif_get_ip_info(eth_handle_spi, &ip_info);
  165.     ESP_LOGI(SLAVE_TAG, "ip: " IPSTR ", mask: " IPSTR ", gw: " IPSTR,
  166.             IP2STR(&ip_info.ip),
  167.             IP2STR(&ip_info.netmask),
  168.             IP2STR(&ip_info.gw));
  169.     esp_netif_get_ip_info(eth_netif_spi, &ip_info);
  170.     ESP_LOGI(SLAVE_TAG, "ip: " IPSTR ", mask: " IPSTR ", gw: " IPSTR,
  171.             IP2STR(&ip_info.ip),
  172.             IP2STR(&ip_info.netmask),
  173.             IP2STR(&ip_info.gw));
  174.    
  175.     holding_reg_area[0] = 0x01;
  176.     holding_reg_area[1] = 0x02;
  177.    
  178.     return err;
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.

ESP_ondrej
Posts: 211
Joined: Fri May 07, 2021 10:35 am

Re: Modbus TCP Slave + W5500 static IP information

Postby ESP_ondrej » Tue May 10, 2022 6:23 am

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:

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
    };
And remove this:

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));
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

ESP_alisitsyn
Posts: 211
Joined: Fri Feb 01, 2019 4:02 pm
Contact:

Re: Modbus TCP Slave + W5500 static IP information

Postby ESP_alisitsyn » Tue May 10, 2022 10:10 am

@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.

JonathanJol
Posts: 6
Joined: Sun Nov 22, 2020 8:23 pm

Re: Modbus TCP Slave + W5500 static IP information

Postby JonathanJol » Wed May 11, 2022 4:20 am

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!

ESP_ondrej
Posts: 211
Joined: Fri May 07, 2021 10:35 am

Re: Modbus TCP Slave + W5500 static IP information

Postby ESP_ondrej » Wed May 11, 2022 9:10 am

Yes, it is not necessary to call `esp_eth_set_default_handlers` in ESP-IDF 4.4 and higher.

SIlvesterrr
Posts: 4
Joined: Sun Jan 23, 2022 4:01 pm

Re: Modbus TCP Slave + W5500 static IP information

Postby SIlvesterrr » Mon Aug 22, 2022 1:42 pm

Hi, Im still strugling with ethernet modbus TCP (ENC28J60). If you could provide a code that would be awesome.

ESP_alisitsyn
Posts: 211
Joined: Fri Feb 01, 2019 4:02 pm
Contact:

Re: Modbus TCP Slave + W5500 static IP information

Postby ESP_alisitsyn » Wed Sep 14, 2022 8:19 am

Hi Silvesterrr,

Have you been able to solve your issue here https://github.com/espressif/esp-idf/issues/9714 ?

SIlvesterrr
Posts: 4
Joined: Sun Jan 23, 2022 4:01 pm

Re: Modbus TCP Slave + W5500 static IP information

Postby SIlvesterrr » Thu Sep 22, 2022 4:03 pm

Yes

Who is online

Users browsing this forum: No registered users and 126 guests