Modbus TCP enc28j60 communication problem

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

Modbus TCP enc28j60 communication problem

Postby SIlvesterrr » Tue Aug 30, 2022 9:51 am

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 1872 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: .

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

Re: Modbus TCP enc28j60 communication problem

Postby ESP_alisitsyn » Mon Sep 05, 2022 9:11 am

Hi @Silvesterrr,

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

Who is online

Users browsing this forum: rickygai and 77 guests