Modbus TCP SLAVE incorrect mode ERROR

ClosedLoop
Posts: 14
Joined: Mon May 16, 2022 8:13 am
Location: Portugal

Modbus TCP SLAVE incorrect mode ERROR

Postby ClosedLoop » Mon Jun 13, 2022 4:19 pm

Hello, i am trying to use the TCP Slave example together with the wifi Station example. The wifi station works fine, but when i initialize the TCP Slave i obtain the following errors.

Code: Select all

[1B][0;31mE (1883) MB_CONTROLLER_SLAVE: mbc_tcp_slave_setup(66): mb incorrect mode = (0x90).[1B][0m
[1B][0;31mE (1893) MB_CONTROLLER_SLAVE: mbc_slave_setup(145): Slave setup failure error=(0x102).[1B][0m
[1B][0;31mE (1903) SLAVE_TEST: slave_init(361): mbc_slave_setup fail, returns(0x103).[1B][0m
ESP_ERROI (1913) wifi:AP's beacon interval = 102400 us, DTIM period = 1
R_CHECK failed: esp_err_t 0x103 (ESP_ERR_INVALID_STATE) at 0x400883c4
file: "../main/main.c" line 454
func: app_main
expression: slave_init(&comm_info)

abort() was called at PC 0x400883c7 on core 0
This is my code, i don't understand why is there a problem with the modbus mode.

Code: Select all

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include <stdio.h>
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include <string.h>
#include "lwip/err.h"
#include "lwip/sys.h"
#include "esp_netif.h"
#include "driver/gpio.h"

#include "modbus_params.h"  // for modbus parameters structures
#include "mbcontroller.h"

#include "esp_err.h"            // for esp_err_t
#include "esp_modbus_master.h"  // for public interface defines
#include "mdns.h"
#include "protocol_examples_common.h"


#define GREEN_GPIO 4


//************************************** TCP SLAVE COM ACESSO á Internet **********************************************

#define MB_TCP_PORT_NUMBER      (CONFIG_FMB_TCP_PORT_DEFAULT)
#define MB_MDNS_PORT            (502)


// Defines below are used to define register start address for each type of Modbus registers
#define HOLD_OFFSET1(field) ((uint16_t)(offsetof(holding_reg_params_t, field) >> 1))
#define INPUT_OFFSET1(field) ((uint16_t)(offsetof(input_reg_params_t, field) >> 1))
#define MB_REG_DISCRETE_INPUT_START         (0x0000)
#define MB_REG_COILS_START                  (0x0000)
#define MB_REG_INPUT_START_AREA0            (INPUT_OFFSET(data)) // PS% (INPUT_OFFSET(input_data0)) // register offset input area 0
#define MB_REG_INPUT_START_AREA1            (INPUT_OFFSET1(input_data4)) // register offset input area 1
#define MB_REG_HOLDING_START_AREA0          (HOLD_OFFSET1(holding_data0))
#define MB_REG_HOLDING_START_AREA1          (HOLD_OFFSET1(holding_data4))

#define MB_PAR_INFO_GET_TOUT                (10) // Timeout for get parameter info
#define MB_CHAN_DATA_MAX_VAL                (10)
#define MB_CHAN_DATA_OFFSET                 (1.1f)

#define MB_READ_MASK                        (MB_EVENT_INPUT_REG_RD \
                                                | MB_EVENT_HOLDING_REG_RD \
                                                | MB_EVENT_DISCRETE_RD \
                                                | MB_EVENT_COILS_RD)
#define MB_WRITE_MASK                       (MB_EVENT_HOLDING_REG_WR \
                                                | MB_EVENT_COILS_WR)
#define MB_READ_WRITE_MASK                  (MB_READ_MASK | MB_WRITE_MASK)

static const char *TAG1 = "SLAVE_TEST";


static portMUX_TYPE param_lock = portMUX_INITIALIZER_UNLOCKED;

#define WIFI_CONNECTED_BIT BIT0
#define WIFI_FAIL_BIT      BIT1

#define EXAMPLE_ESP_WIFI_SSID      "HELLOHELLO"
#define EXAMPLE_ESP_WIFI_PASS      "12345678"
#define EXAMPLE_ESP_WIFI_CHANNEL   0
#define EXAMPLE_MAX_STA_CONN       4

#define ESP_WIFI_SSID	CONFIG_ESP_WIFI_SSID
#define ESP_WIFI_PASS	CONFIG_ESP_WIFI_PASSWORD

#define EXAMPLE_STATIC_IP_ADDR        "10.0.0.30"
#define EXAMPLE_STATIC_NETMASK_ADDR   "10.0.0.30"
#define EXAMPLE_STATIC_GW_ADDR        "255.255.255.0"

static const char *TAG = "test";
static EventGroupHandle_t s_wifi_event_group;

static void wifi_event_handler(void* arg, esp_event_base_t event_base,
                               int32_t event_id, void* event_data)
{
    if (event_id == WIFI_EVENT_AP_STACONNECTED) {
        wifi_event_ap_staconnected_t* event = (wifi_event_ap_staconnected_t*) event_data;

    } else if (event_id == WIFI_EVENT_AP_STADISCONNECTED) {
        wifi_event_ap_stadisconnected_t* event = (wifi_event_ap_stadisconnected_t*) event_data;
    }
}

void wifi_init_softap(void)
{


    esp_netif_ip_info_t ipInfo;
    esp_netif_t* wifiAP = esp_netif_create_default_wifi_ap();
    IP4_ADDR(&ipInfo.ip, 192,168,2,1);
    IP4_ADDR(&ipInfo.gw, 192,168,2,1);
    IP4_ADDR(&ipInfo.netmask, 255,255,255,0);

    esp_netif_dhcps_stop(wifiAP);
    esp_netif_set_ip_info(wifiAP, &ipInfo);
    esp_netif_dhcps_start(wifiAP);

    ESP_LOGI(TAG, "IP: " IPSTR, IP2STR(&ipInfo.ip));
    ESP_LOGI(TAG, "GW: " IPSTR, IP2STR(&ipInfo.gw));
    ESP_LOGI(TAG, "Mask: " IPSTR, IP2STR(&ipInfo.netmask));

    //esp_netif_create_default_wifi_ap();

    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));

    ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
                                                        ESP_EVENT_ANY_ID,
                                                        &wifi_event_handler,
                                                        NULL,
                                                        NULL));

    wifi_config_t wifi_config = {
        .ap = {
            .ssid = EXAMPLE_ESP_WIFI_SSID,
            .ssid_len = strlen(EXAMPLE_ESP_WIFI_SSID),
            .channel = EXAMPLE_ESP_WIFI_CHANNEL,
            .password = EXAMPLE_ESP_WIFI_PASS,
            .max_connection = EXAMPLE_MAX_STA_CONN,
            .authmode = WIFI_AUTH_WPA_WPA2_PSK
        },
    };
    if (strlen(EXAMPLE_ESP_WIFI_PASS) == 0) {
        wifi_config.ap.authmode = WIFI_AUTH_OPEN;
    }


    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_APSTA));
    ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &wifi_config));
    ESP_ERROR_CHECK(esp_wifi_start());
}

static int s_retry_num = 0;
static int maxRetry = 5;


static void example_set_static_ip(esp_netif_t *netif)
{
    if (esp_netif_dhcpc_stop(netif) != ESP_OK) {
        ESP_LOGE(TAG, "Failed to stop dhcp client");
        return;
    }
    esp_netif_ip_info_t ip;
    memset(&ip, 0 , sizeof(esp_netif_ip_info_t));
    ip.ip.addr = ipaddr_addr(EXAMPLE_STATIC_IP_ADDR);
    ip.netmask.addr = ipaddr_addr(EXAMPLE_STATIC_NETMASK_ADDR);
    ip.gw.addr = ipaddr_addr(EXAMPLE_STATIC_GW_ADDR);
    if (esp_netif_set_ip_info(netif, &ip) != ESP_OK) {
        ESP_LOGE(TAG, "Failed to set ip info");
        return;
    }
    ESP_LOGD(TAG, "Success to set static ip: %s, netmask: %s, gw: %s", EXAMPLE_STATIC_IP_ADDR, EXAMPLE_STATIC_NETMASK_ADDR, EXAMPLE_STATIC_GW_ADDR);
}

static void event_handler(void* arg, esp_event_base_t event_base,
                                int32_t event_id, void* event_data)
{
    if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
        esp_wifi_connect();
    } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_CONNECTED) {
        example_set_static_ip(arg);
    } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
        if (s_retry_num < maxRetry) {
            esp_wifi_connect();
            s_retry_num++;
            ESP_LOGI(TAG, "retry to connect to the AP");
        } else {
            xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT);
        }
        ESP_LOGI(TAG,"connect to the AP fail");
    } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
        ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
        ESP_LOGI(TAG, "static ip:" IPSTR, IP2STR(&event->ip_info.ip));
        s_retry_num = 0;
        xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
    }
}

esp_netif_t *sta_netif;
void wifi_init_sta(void)
{

    s_wifi_event_group = xEventGroupCreate();

    sta_netif = esp_netif_create_default_wifi_sta();
    assert(sta_netif);

    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));

    esp_event_handler_instance_t instance_any_id;
    esp_event_handler_instance_t instance_got_ip;
    ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
                                                        ESP_EVENT_ANY_ID,
                                                        &event_handler,
														sta_netif,
                                                        &instance_any_id));
    ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT,
                                                        IP_EVENT_STA_GOT_IP,
                                                        &event_handler,
														sta_netif,
                                                        &instance_got_ip));

    wifi_config_t wifi_config = {
            .sta = {
                .ssid = ESP_WIFI_SSID,
                .password = ESP_WIFI_PASS,
                // Setting a password implies station will connect to all security modes including WEP/WPA.
                 // However these modes are deprecated and not advisable to be used. Incase your Access point
                 // doesn't support WPA2, these mode can be enabled by commenting below line
                .threshold.authmode = WIFI_AUTH_WPA2_PSK,
                .pmf_cfg = {
                    .capable = true,
                    .required = false
                },
            },
        };
    ESP_LOGI(TAG, "Test -> %s %s.", wifi_config.sta.ssid, wifi_config.sta.password);
    ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config) );
    ESP_ERROR_CHECK(esp_wifi_start());

    ESP_LOGI(TAG, "wifi_init_sta finished.");

    /* Waiting until either the connection is established (WIFI_CONNECTED_BIT) or connection failed for the maximum
     * number of re-tries (WIFI_FAIL_BIT). The bits are set by event_handler() (see above) */
    EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group,
                                           WIFI_CONNECTED_BIT | WIFI_FAIL_BIT,
                                           pdFALSE,
                                           pdFALSE,
                                           portMAX_DELAY);

    /* xEventGroupWaitBits() returns the bits before the call returned, hence we can test which event actually
     * happened. */
    if (bits & WIFI_CONNECTED_BIT) {
        ESP_LOGI(TAG, "connected to ap");
    } else if (bits & WIFI_FAIL_BIT) {
        ESP_LOGI(TAG, "Failed to connect");
    } else {
        ESP_LOGE(TAG, "UNEXPECTED EVENT");
    }

    /* The event will not be processed after unregister */
    ESP_ERROR_CHECK(esp_event_handler_instance_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, instance_got_ip));
    ESP_ERROR_CHECK(esp_event_handler_instance_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, instance_any_id));
    vEventGroupDelete(s_wifi_event_group);
}




//************************************** TCP SLAVE **********************************************


// Set register values into known state
static void setup_reg_data(void)
{
    // Define initial state of parameters


    holding_reg_params.holding_data0 = 1.34;
    holding_reg_params.holding_data1 = 2.56;
    holding_reg_params.holding_data2 = 3.78;
    holding_reg_params.holding_data3 = 4.90;

    holding_reg_params.holding_data4 = 5.67;
    holding_reg_params.holding_data5 = 6.78;
    holding_reg_params.holding_data6 = 7.79;
    holding_reg_params.holding_data7 = 8.80;
    coil_reg_params.coils_port0 = 0x55;
    coil_reg_params.coils_port1 = 0xAA;





    input_reg_params.data[0]=10;
    input_reg_params.data[1]=11;
    input_reg_params.data[2]=12;
    input_reg_params.data[3]=13;
    input_reg_params.data[4]=14;
    input_reg_params.data[5]=15;


    holding_reg_params.data_reg[0]=20;
    holding_reg_params.data_reg[1]=21;
    holding_reg_params.data_reg[2]=22;
    holding_reg_params.data_reg[3]=23;
    holding_reg_params.data_reg[4]=24;
    holding_reg_params.data_reg[5]=25;
    holding_reg_params.data_reg[6]=26;
    holding_reg_params.data_reg[7]=27;
    holding_reg_params.data_reg[8]=28;

}

static void slave_operation_func(void *arg)
{
    mb_param_info_t reg_info; // keeps the Modbus registers access information

    ESP_LOGI(TAG1, "Modbus slave stack initialized.");
    ESP_LOGI(TAG1, "Start modbus test...");
    // The cycle below will be terminated when parameter holding_data0
    // incremented each access cycle reaches the CHAN_DATA_MAX_VAL value.
  //  for(;holding_reg_params.holding_data0 < MB_CHAN_DATA_MAX_VAL;) {
        // Check for read/write events of Modbus master for certain events
        mb_event_group_t event = mbc_slave_check_event(MB_READ_WRITE_MASK);
      if(event == MB_EVENT_NO_EVENTS) return;

        const char* rw_str = (event & MB_READ_MASK) ? "\n\n\nREAD\n\n\n" : "\n\n\nWRITE\n\n\n";
        // Filter events and process them accordingly
        if(event & (MB_EVENT_HOLDING_REG_WR | MB_EVENT_HOLDING_REG_RD)) {
            // Get parameter information from parameter queue
            ESP_ERROR_CHECK(mbc_slave_get_param_info(&reg_info, MB_PAR_INFO_GET_TOUT));
            ESP_LOGI(TAG1, "\n\n>>>>>>>>>>>>>>>>>>>>>>> HOLDING %s (%u us), ADDR:%u, TYPE:%u, INST_ADDR:0x%.4x, SIZE:%u",
                    rw_str,
                    (uint32_t)reg_info.time_stamp,
                    (uint32_t)reg_info.mb_offset,
                    (uint32_t)reg_info.type,
                    (uint32_t)reg_info.address,
                    (uint32_t)reg_info.size);
            if (reg_info.address == (uint8_t*)&holding_reg_params.holding_data0)
            {
                portENTER_CRITICAL(&param_lock);
                holding_reg_params.holding_data0 += MB_CHAN_DATA_OFFSET;
                if (holding_reg_params.holding_data0 >= (MB_CHAN_DATA_MAX_VAL - MB_CHAN_DATA_OFFSET)) {
                    coil_reg_params.coils_port1 = 0xFF;
                }
                portEXIT_CRITICAL(&param_lock);
            }
        }
  //    }
}



// Modbus slave initialization
static esp_err_t slave_init(mb_communication_info_t* comm_info)
{

    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,
                                TAG1,
                                "mb controller initialization fail.");

    // Setup communication parameters and start stack
    err = mbc_slave_setup((void*)&comm_info);
    MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE,
                                        TAG1,
                                        "mbc_slave_setup fail, returns(0x%x).",
                                        (uint32_t)err);

    // The code below initializes Modbus register area descriptors
    // for Modbus Holding Registers, Input Registers, Coils and Discrete Inputs
    // Initialization should be done for each supported Modbus register area according to register map.
    // When external master trying to access the register in the area that is not initialized
    // by mbc_slave_set_descriptor() API call then Modbus stack
    // will send exception response for this register area.

// Começa endeço 8
    reg_area.type = MB_PARAM_HOLDING; // Set type of register area
    reg_area.start_offset = 8; // Offset of register area in Modbus protocol
    reg_area.address = (void*)&holding_reg_params.data_reg; // Set pointer to storage instance
    reg_area.size = 148;
    err = mbc_slave_set_descriptor(reg_area);
    MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE,
                                    TAG1,
                                    "mbc_slave_set_descriptor 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_AREA1; // Offset of register area in Modbus protocol
    reg_area.address = (void*)&holding_reg_params.holding_data4; // Set pointer to storage instance
    reg_area.size = sizeof(float) << 2; // Set the size of register storage instance
    err = mbc_slave_set_descriptor(reg_area);
    MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE,
                                    TAG1,
                                    "mbc_slave_set_descriptor fail, returns(0x%x).",
                                    (uint32_t)err);


    // Set values into known state
    setup_reg_data();

    // Starts of modbus controller and stack
    err = mbc_slave_start();
    MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE,
                                        TAG1,
                                        "mbc_slave_start fail, returns(0x%x).",
                                        (uint32_t)err);
    vTaskDelay(5);
    return err;
}



void app_main(void)
{


    //Initialize NVS
    esp_err_t ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
        ESP_ERROR_CHECK(nvs_flash_erase());
        ret = nvs_flash_init();
    }
    ESP_ERROR_CHECK(ret);

    ESP_ERROR_CHECK(esp_netif_init());
    ESP_ERROR_CHECK(esp_event_loop_create_default());

    // led green
    gpio_reset_pin(GREEN_GPIO);
    gpio_set_direction(GREEN_GPIO, GPIO_MODE_OUTPUT);


  // wifi_init_softap();

   gpio_set_level(GREEN_GPIO, 1);
   vTaskDelay(100);


   wifi_init_sta();

   gpio_set_level(GREEN_GPIO, 0);
   ESP_LOGI(TAG, "\n\n\n\n\n wifi_init_sta OK \n\n\n\n");


   //TCP SLAVE
  // ESP_ERROR_CHECK(init_services());
//	    // Set UART log level
	    esp_log_level_set(TAG1, ESP_LOG_INFO);

	    mb_communication_info_t comm_info = {
		    	   .ip_port = MB_TCP_PORT_NUMBER,                           // 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,            // assign table of IP addresses
				   .ip_netif_ptr = sta_netif     // esp_netif_ptr pointer to the corresponding network interface

		    };

	    ESP_ERROR_CHECK(slave_init(&comm_info));


	    ESP_LOGI(TAG, "\n\n\n\n\n ALL INIT OK \n\n\n\n");

   while(1){


   	vTaskDelay(100);
   	slave_operation_func(NULL);


   }

}


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

Re: Modbus TCP SLAVE incorrect mode ERROR

Postby ESP_alisitsyn » Tue Jun 14, 2022 3:14 pm

Hello ClosedLoop,

Please change the code as below:

Code: Select all

// Modbus slave initialization
static esp_err_t slave_init(mb_communication_info_t* pcomm_info)
{

    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,
                                TAG1,
                                "mb controller initialization fail.");

    // Setup communication parameters and start stack
    err = mbc_slave_setup((void*)pcomm_info);   // <<<< the function needs the pointer to `mb_communication_info_t`
    MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE,
                                        TAG1,
                                        "mbc_slave_setup fail, returns(0x%x).",
                                        (uint32_t)err);
 ...................                                       

ClosedLoop
Posts: 14
Joined: Mon May 16, 2022 8:13 am
Location: Portugal

Re: Modbus TCP SLAVE incorrect mode ERROR

Postby ClosedLoop » Wed Jun 15, 2022 7:48 am

Hello, thank you fo your response. I made the change but i still get the same error. I managed to implement what i wanted with sockets and it works fine.

ClosedLoop
Posts: 14
Joined: Mon May 16, 2022 8:13 am
Location: Portugal

Re: Modbus TCP SLAVE incorrect mode ERROR

Postby ClosedLoop » Wed Jun 15, 2022 8:41 am

Actually it works fine now, i tried on a different ESP and the error stop appearing. Thank you.

Who is online

Users browsing this forum: stvlaa and 115 guests