Page 1 of 1

Modbus TCP enc28j60 communication problem

Posted: Tue Aug 30, 2022 9:51 am
by SIlvesterrr
Hi, Im trying to setup Modbus TCP Slave on my esp32s3 using enc28j60 module.
Ive combined enc28j60 example with modbus slave tcp example.
Device gets address from dhcp without any problem.
.
.
When I want to read some data from device I do not get any response. Console clearly indicates that it recieved frame and accepted client communication but nothing else happends.
this is log on eth starup:
  1. I (3563) eth_example: Ethernet Got IP Address
  2. I (3573) eth_example: ~~~~~~~~~~~
  3. I (3573) eth_example: ETHIP:192.168.1.34
  4. I (3583) eth_example: ETHMASK:255.255.255.0
  5. I (3583) eth_example: ETHGW:192.168.1.1
  6. I (3593) eth_example: ~~~~~~~~~~~
  7. D (5673) MB_PORT_COMMON: vMBPortSetMode: Port enter critical.
  8. D (5673) MB_PORT_COMMON: vMBPortSetMode: Port exit critical
  9. W (5673) eth_example: Input reg. set to 000000
  10. I (5673) MB_TCP_SLAVE_PORT: Protocol stack initialized.
  11. D (5683) MB_PORT_COMMON: TCP Slave port enable.
  12. I (5683) MB_TCP_SLAVE_PORT: Socket (#54), listener 192.168.1.34 on port: 502, errno=0
.
.
As you can see there seems to be no problem but after trying to communicate with device I do not get any response.
qmodubs_sc.png
qmodubs_sc.png (164.16 KiB) Viewed 1920 times
.
.
My console looks like this while trying to commuincate:
  1. I (165093) MB_TCP_SLAVE_PORT: Socket (#55), accept client connection from address: 192.168.1.12
  2. D (165093) MB_TCP_SLAVE_PORT: | TID = 0001 | PID = 0000 | LEN = 0006 | UID = 01 | FUNC = 04 | DATA = 00000001 |
  3. D (165103) MB_TCP_SLAVE_PORT: Socket (#55)(192.168.1.12), get packet TID=0x1, 12 bytes.
  4. D (165103) MB_PORT_COMMON: EV_FRAME_RECEIVED
  5. D (165113) MB_PORT_COMMON: 04 00 00 00 01
  6. D (165123) MB_PORT_COMMON: eMBPoll:EV_EXECUTE
  7. D (165123) MB_TCP_SLAVE_PORT: Client 0, Socket(#55), processing time = 22852 (us).
.
.
So it clearly recives frame but it doesn't do anything with it.
next data recieve attempt just drops the connection:
  1. E (163033) MB_TCP_SLAVE_PORT: Socket (#55)(192.168.1.12), connection closed by peer.
.
.
Here is my Code:
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include "sdkconfig.h"
  4. #include "freertos/FreeRTOS.h"
  5. #include "freertos/task.h"
  6. #include "esp_netif.h"
  7. #include "esp_eth.h"
  8. #include "esp_event.h"
  9. #include "esp_log.h"
  10. #include "driver/gpio.h"
  11. #include "driver/spi_master.h"
  12. #include "eth_enc28j60/esp_eth_enc28j60.h"
  13.  
  14. #include "mbcontroller.h"
  15. void modbus_tcp(void);
  16. void modbus_slave_task(void *pvParameter);
  17.  
  18. static const char *TAG = "eth_example";
  19.  
  20. /** Event handler for Ethernet events */
  21. static void eth_event_handler(void *arg, esp_event_base_t event_base,
  22.                               int32_t event_id, void *event_data)
  23. {
  24.     uint8_t mac_addr[6] = {0};
  25.     /* we can get the ethernet driver handle from event data */
  26.     esp_eth_handle_t eth_handle = *(esp_eth_handle_t *)event_data;
  27.  
  28.     switch (event_id)
  29.     {
  30.     case ETHERNET_EVENT_CONNECTED:
  31.         esp_eth_ioctl(eth_handle, ETH_CMD_G_MAC_ADDR, mac_addr);
  32.         ESP_LOGI(TAG, "Ethernet Link Up");
  33.         ESP_LOGI(TAG, "Ethernet HW Addr %02x:%02x:%02x:%02x:%02x:%02x",
  34.                  mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
  35.         break;
  36.     case ETHERNET_EVENT_DISCONNECTED:
  37.         ESP_LOGI(TAG, "Ethernet Link Down");
  38.         break;
  39.     case ETHERNET_EVENT_START:
  40.         ESP_LOGI(TAG, "Ethernet Started");
  41.         break;
  42.     case ETHERNET_EVENT_STOP:
  43.         ESP_LOGI(TAG, "Ethernet Stopped");
  44.         break;
  45.     default:
  46.         break;
  47.     }
  48. }
  49. // char *ip;
  50. /** Event handler for IP_EVENT_ETH_GOT_IP */
  51. static void got_ip_event_handler(void *arg, esp_event_base_t event_base,
  52.                                  int32_t event_id, void *event_data)
  53. {
  54.     ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
  55.     const esp_netif_ip_info_t *ip_info = &event->ip_info;
  56.  
  57.     ESP_LOGI(TAG, "Ethernet Got IP Address");
  58.     ESP_LOGI(TAG, "~~~~~~~~~~~");
  59.     ESP_LOGI(TAG, "ETHIP:" IPSTR, IP2STR(&ip_info->ip));
  60.     ESP_LOGI(TAG, "ETHMASK:" IPSTR, IP2STR(&ip_info->netmask));
  61.     ESP_LOGI(TAG, "ETHGW:" IPSTR, IP2STR(&ip_info->gw));
  62.     ESP_LOGI(TAG, "~~~~~~~~~~~");
  63.     // modbus_tcp();
  64. }
  65. esp_netif_t *eth_netif;
  66.  
  67. void init_eth(void)
  68. {
  69.  
  70.     ESP_ERROR_CHECK(gpio_install_isr_service(0));
  71.     // Initialize TCP/IP network interface (should be called only once in application)
  72.     ESP_ERROR_CHECK(esp_netif_init());
  73.     // Create default event loop that running in background
  74.     ESP_ERROR_CHECK(esp_event_loop_create_default());
  75.     esp_netif_config_t netif_cfg = ESP_NETIF_DEFAULT_ETH();
  76.     eth_netif = esp_netif_new(&netif_cfg);
  77.  
  78.     spi_bus_config_t buscfg = {
  79.         .miso_io_num = 39,
  80.         .mosi_io_num = 40,
  81.         .sclk_io_num = 41,
  82.         .quadwp_io_num = -1,
  83.         .quadhd_io_num = -1,
  84.     };
  85.     ESP_ERROR_CHECK(spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_CH_AUTO));
  86.     /* ENC28J60 ethernet driver is based on spi driver */
  87.     spi_device_interface_config_t devcfg = {
  88.         .command_bits = 3,
  89.         .address_bits = 5,
  90.         .mode = 0,
  91.         .clock_speed_hz = 8 * 1000 * 1000,
  92.         .spics_io_num = 42,
  93.         .queue_size = 20,
  94.         .cs_ena_posttrans = enc28j60_cal_spi_cs_hold_time(8),
  95.     };
  96.  
  97.     spi_device_handle_t spi_handle = NULL;
  98.     ESP_ERROR_CHECK(spi_bus_add_device(SPI2_HOST, &devcfg, &spi_handle));
  99.  
  100.     eth_enc28j60_config_t enc28j60_config = ETH_ENC28J60_DEFAULT_CONFIG(spi_handle);
  101.     enc28j60_config.int_gpio_num = 38;
  102.  
  103.     eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
  104.     mac_config.smi_mdc_gpio_num = -1; // ENC28J60 doesn't have SMI interface
  105.     mac_config.smi_mdio_gpio_num = -1;
  106.     esp_eth_mac_t *mac = esp_eth_mac_new_enc28j60(&enc28j60_config, &mac_config);
  107.  
  108.     eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
  109.     phy_config.autonego_timeout_ms = 0; // ENC28J60 doesn't support auto-negotiation
  110.     phy_config.reset_gpio_num = -1;     // ENC28J60 doesn't have a pin to reset internal PHY
  111.     esp_eth_phy_t *phy = esp_eth_phy_new_enc28j60(&phy_config);
  112.  
  113.     esp_eth_config_t eth_config = ETH_DEFAULT_CONFIG(mac, phy);
  114.     esp_eth_handle_t eth_handle = NULL;
  115.     ESP_ERROR_CHECK(esp_eth_driver_install(&eth_config, &eth_handle));
  116.  
  117.     /* ENC28J60 doesn't burn any factory MAC address, we need to set it manually.
  118.        02:00:00 is a Locally Administered OUI range so should not be used except when testing on a LAN under your control.
  119.     */
  120.     mac->set_addr(mac, (uint8_t[]){
  121.                            0x02, 0x00, 0x00, 0x12, 0x34, 0x56});
  122.  
  123.     // ENC28J60 Errata #1 check
  124.     if (emac_enc28j60_get_chip_info(mac) < ENC28J60_REV_B5)
  125.     {
  126.         ESP_LOGE(TAG, "SPI frequency must be at least 8 MHz for chip revision less than 5");
  127.         ESP_ERROR_CHECK(ESP_FAIL);
  128.     }
  129.  
  130.     /* attach Ethernet driver to TCP/IP stack */
  131.     ESP_ERROR_CHECK(esp_netif_attach(eth_netif, esp_eth_new_netif_glue(eth_handle)));
  132.     // Register user defined event handers
  133.     ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, &eth_event_handler, NULL));
  134.     ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, NULL));
  135.     /* start Ethernet driver state machine */
  136.     ESP_ERROR_CHECK(esp_eth_start(eth_handle));
  137. }
  138.  
  139. mb_register_area_descriptor_t reg_area;
  140. mb_param_info_t reg_info;
  141. void setup_input_register(uint16_t offset, void *values, int size)
  142. {
  143.     reg_area.type = MB_PARAM_INPUT;
  144.     reg_area.start_offset = offset;
  145.     reg_area.address = values;
  146.     reg_area.size = size;
  147.     mbc_slave_set_descriptor(reg_area);
  148.     ESP_LOGW(TAG, "Input reg. set to %#06x", offset);
  149. }
  150. void modbus_tcp(void)
  151. {
  152.     mb_communication_info_t comm_info = {0};
  153.  
  154.     comm_info.ip_addr_type = MB_IPV4;
  155.     comm_info.ip_mode = MB_MODE_TCP;
  156.  
  157.     comm_info.ip_port = 502;
  158.  
  159.     void *slave_handler = NULL;
  160.  
  161.     // Initialization of Modbus controller
  162.     esp_err_t err = mbc_slave_init_tcp(&slave_handler);
  163.     MB_RETURN_ON_FALSE((err == ESP_OK && slave_handler != NULL), ESP_ERR_INVALID_STATE,
  164.                        TAG,
  165.                        "mb controller initialization fail.");
  166.  
  167.     comm_info.ip_addr = "192.168.1.34"; // Bind to any address
  168.     comm_info.ip_netif_ptr = eth_netif;
  169.  
  170.     // Setup communication parameters and start stack
  171.     err = mbc_slave_setup(&comm_info);
  172.     MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE,
  173.                        TAG,
  174.                        "mbc_slave_setup fail, returns(0x%x).",
  175.                        (uint32_t)err);
  176.     uint16_t test = 5;
  177.     setup_input_register(0x0, &test, 1);
  178.  
  179.     mbc_slave_start();
  180. }
  181. #define MB_PAR_INFO_GET_TIME_OUT 20
  182. #define MB_READ_MASK (MB_EVENT_INPUT_REG_RD | MB_EVENT_HOLDING_REG_RD | MB_EVENT_DISCRETE_RD | MB_EVENT_COILS_RD)
  183. #define MB_WRITE_MASK (MB_EVENT_HOLDING_REG_WR | MB_EVENT_COILS_WR)
  184. #define MB_READ_WRITE_MASK (MB_READ_MASK | MB_WRITE_MASK)
  185.  
  186. void modbus_slave_task(void *pvParameter)
  187. {
  188.     esp_err_t rc;
  189.     while (1)
  190.     {
  191.  
  192.         rc = ESP_OK;
  193.         vTaskDelay(pdMS_TO_TICKS(100));
  194.         mb_event_group_t event = mbc_slave_check_event(MB_READ_WRITE_MASK);
  195.         ESP_LOGW(TAG, "0x%x", event);
  196.  
  197.         // Check for read/write events of Modbus master for certain events
  198.  
  199.         /* input register read */
  200.         if (event & MB_EVENT_INPUT_REG_RD)
  201.         {
  202.             rc += mbc_slave_get_param_info(&reg_info, MB_PAR_INFO_GET_TIME_OUT);
  203.             ESP_LOGI(TAG, "INPUT READ:, ADDR:%u, SIZE:%u",
  204.                      (uint32_t)reg_info.address,
  205.                      (uint32_t)reg_info.size);
  206.  
  207.             /* discrete register read */
  208.         }
  209.     }
  210.     // Destroy of Modbus controller on alarm
  211.     ESP_LOGE(TAG, "Modbus controller destroyed.");
  212.     vTaskDelay(100);
  213. }
  214. void app_main(void)
  215. {
  216.     init_eth();
  217.     vTaskDelay(pdMS_TO_TICKS(5000));
  218.     modbus_tcp();
  219.     modbus_slave_task(NULL);
  220. }
.
.
I've looked all internet through and could not find anything helpfull. Waiting for response :roll: .

Re: Modbus TCP enc28j60 communication problem

Posted: Mon Sep 05, 2022 9:11 am
by ESP_alisitsyn
Hi @Silvesterrr,

The question is answered here: https://github.com/espressif/esp-idf/issues/9714