Modbus TCP SLAVE incorrect mode ERROR
Posted: 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.
This is my code, i don't understand why is there a problem with the modbus mode.
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
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(®_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(¶m_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(¶m_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);
}
}