MODBUS Serial example not working (IDFGH-5822)

Hi newbie here, working with esp-idf 4.2.2
I am working on MODBUS Serial example of esp-idf,I simply just connected the hardware as shown in the example.
ESP32-1(Master) and ESP32-2(Slave) by using two TTL to RS485 converters.
But I am not able to get the expected output. I am gettinfg the 0x108 Err that is invalid slave response.
Master output:
 E (65579) MB_CONTROLLER_MASTER: mbc_master_get_parameter(111): SERIAL master get parameter failure error=(0x108) (ESP_ERR_INVALID_RESPONSE). E (65579) MASTER_TEST: Characteristic #0 (Data_channel_0) read fail, err = 0x108 (ESP_ERR_INVALID_RESPONSE). E (65599) MB_CONTROLLER_MASTER: mbc_master_get_parameter(111): SERIAL master get parameter failure error=(0x108) (ESP_ERR_INVALID_RESPONSE).  E (65609) MASTER_TEST: Characteristic #1 (Humidity_1) read fail, err = 0x108 (ESP_ERR_INVALID_RESPONSE). E (65619) MB_CONTROLLER_MASTER: mbc_master_get_parameter(111): SERIAL master get parameter failure error=(0x108) (ESP_ERR_INVALID_RESPONSE). E (65629) MASTER_TEST: Characteristic #2 (Temperature_1) read fail, err = 0x108 (ESP_ERR_INVALID_RESPONSE). E (65649) MB_CONTROLLER_MASTER: mbc_master_get_parameter(111): SERIAL master get parameter failure error=(0x108) (ESP_ERR_INVALID_RESPONSE).  E (65649) MASTER_TEST: Characteristic #3 (Humidity_2) read fail, err = 0x108 (ESP_ERR_INVALID_RESPONSE). E (65669) MB_CONTROLLER_MASTER: mbc_master_get_parameter(111): SERIAL master get parameter failure error=(0x108) (ESP_ERR_INVALID_RESPONSE). E (65679) MASTER_TEST: Characteristic #4 (Temperature_2) read fail, err = 0x108 (ESP_ERR_INVALID_RESPONSE). E (65699) MB_CONTROLLER_MASTER: mbc_master_get_parameter(111): SERIAL master get parameter failure error=(0x108) (ESP_ERR_INVALID_RESPONSE). E (65699) MASTER_TEST: Characteristic #5 (Humidity_3) read fail, err = 0x108 (ESP_ERR_INVALID_RESPONSE). E (65719) MB_CONTROLLER_MASTER: mbc_master_get_parameter(111): SERIAL master get parameter failure error=(0x108) (ESP_ERR_INVALID_RESPONSE). E (65729) MASTER_TEST: Characteristic #6 (Test_regs) read fail, err = 0x108 (ESP_ERR_INVALID_RESPONSE). I (65739) MASTER_TEST: Characteristic #7 RelayP1 (on/off) value = OFF (0x55) read successful. I (65749) MASTER_TEST: Characteristic #8 RelayP2 (on/off) value = OFF (0xaa) read successful. E (67749) MASTER_TEST: Alarm is not triggered after 30 retries. I (67749) MASTER_TEST: Destroy master...

Thank you in advance.

Hi @rjrajbir ,
Your connection looks correct but we need to check if your RS485 tranceivers can work reliable. There may different types of chips with different voltage (3.3V or 5V). Which one do you have on the boards?

I would recommend you to check your connection using
rs485 echo example

Do you have any change in the
master Data Dictionary or  area descriptors of slave ?
According to log your slave device do not recognize requests from master to read holding registers and input registers.

Please also increase the response time in the master configuration to = 400 ms instead of 150 ms as on the picture below and recompile.
cd $IDF_PATH idf.py menuconfig idf.py fullclean idf.py build idf.py -p PORT -b 921600 flash monitor

Let me know if you have any issues according to instruction above.

Thank you for the reply, i have tried this but haven't got the results.
I think its the  esp-idf version issue, I have installed new version i.e. 4.3 in my another PC and its working fine with the same setup
and not working with the 4.2.2 version.

I can check if the v4.2.2 has issues but recommend you to work with the latest master.

Please also take a look to extended documentation for API usage which recently merged in commit 2146b5b291e1b067908998f83cf563aa220eadb7.

I have made some codes with 4.2.2 so i have integrate it with them.
Could you please tell me the codes made in previous versions can work in the new verions or not.

Yes. They should work just fine without changes.

Yes, I recommend to check the issue, because maxium work has been done on 4.2,2

@rjrajbir ,
As I described above I have checked the v4.2.2 tag and it works just fine. I guess you have some preliminary commit of release v4.2 and this is why the bug is there. Please use the latest official releases. You do not need to update your Modbus application.

Ok Thank you for the help.
I want to make the cpp lib of MODBUS SERIAL example. But the code you made is so complicated. Can you please give me simple version of modbus serial.

@rjrajbir ,
Please consider the simple Modbus master code.
This example is just to read/write couple of registers in slave.
Let me know if you need more help.

Thank you for the help, i'll check and get back to you

master.zip
Here is my code but its showing many errors, Please help

Your Arduino library duplicates the basic functionality of low layer ESP_Modbus stack. The ESP_Modbus API is extended library compare to Arduino and they are very different.
What is your goal? Do you want to update the code to do the same readings/writings with the ESP_Modbus library instead?
Please provide more information or questions to explain what is your project. For now I can give you the code which will be able to read/write any registers of any slave using the ESP_Modbus. Actually it is provided in the simple Modbus example above and can be used together with your other CPP code. If absolutely required the CPP interface wrapper class can be created for ESP_Modbus.

Actually i want to create a c++ wrapper for esp-idf modbus-serial example. I am new with c++.
That its simple for user to just call the function for reading and writing different registers in modbus.

I propose you to start this and learn how to use ESP_Modbus and CPP. The functionality of the basic Modbus read/write can be implemented using the mbc_serial_master_send_request() function call of the library.
My preliminary instructions on how to start from scratch to create wrapper are below:

Use your ModbusMaster class template to modify. Include the required header files of ESP_Modbus. The ESP_Modbus headers include the required CPP guards.
Its begin method will get two parameters: 1: address of slave being accessed 2: mb_communication_info_t type as second parameter. The method saves the communication info and address of slave into corresponding class properties for future use in read/write methods.
This method calls the initialization functions similar to what is done in master_init() function of the example and uses saved communication parameters.
The corresponded methods ModbusMaster::readCoils, ModbusMaster::readHoldingRegisters, ModbusMaster::readInputRegisters of the class shall be translated to calls of
mbc_serial_master_send_request function with prefilled mb_param_request_t structure. It uses the saved slave address property.
The input parameters: register offset to read/write, number of registers, pointer to data buffer to read/write to/from the slave.

See the example on how to fill the request structure
Each method handles the Modbus transaction reads/writes data to/from buffer provided as data pointer and returns the error code to application.
See the simple Modbus master code

The destroy method of the class to free all resources and destroy all active objects. See the example to implement.

The API usage information

Hi, Sorry for the late reply, but have made just simple code to test but I am getting some errors.
too many initializers for 'mb_parameter_opt_t' this error in below section
const mb_parameter_descriptor_t device_parameters[500] = {     // { CID, Param Name, Units, Modbus Slave Addr, Modbus Reg Type, Reg Start, Reg Size, Instance Offset, Data Type, Data Size, Parameter Options, Access Mode}     { CID_INP_DATA_0, STR("Data_channel_0"), STR("Volts"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 0, 2,                     INPUT_OFFSET(input_data0), PARAM_TYPE_FLOAT, 4, OPTS( -10, 10, 1 ), PAR_PERMS_READ_WRITE_TRIGGER },     { CID_HOLD_DATA_0, STR("Humidity_1"), STR("%rH"), MB_DEVICE_ADDR1, MB_PARAM_HOLDING, 0, 2,             HOLD_OFFSET(holding_data0), PARAM_TYPE_FLOAT, 4, OPTS( 0, 100, 1 ), PAR_PERMS_READ_WRITE_TRIGGER },     { CID_INP_DATA_1, STR("Temperature_1"), STR("C"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 2, 2,             INPUT_OFFSET(input_data1), PARAM_TYPE_FLOAT, 4, OPTS( -40, 100, 1 ), PAR_PERMS_READ_WRITE_TRIGGER },     { CID_HOLD_DATA_1, STR("Humidity_2"), STR("%rH"), MB_DEVICE_ADDR1, MB_PARAM_HOLDING, 2, 2,             HOLD_OFFSET(holding_data1), PARAM_TYPE_FLOAT, 4, OPTS( 0, 100, 1 ), PAR_PERMS_READ_WRITE_TRIGGER },     { CID_INP_DATA_2, STR("Temperature_2"), STR("C"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 4, 2,             INPUT_OFFSET(input_data2), PARAM_TYPE_FLOAT, 4, OPTS( -40, 100, 1 ), PAR_PERMS_READ_WRITE_TRIGGER },     { CID_HOLD_DATA_2, STR("Humidity_3"), STR("%rH"), MB_DEVICE_ADDR1, MB_PARAM_HOLDING, 4, 2,             HOLD_OFFSET(holding_data2), PARAM_TYPE_FLOAT, 4, OPTS( 0, 100, 1 ), PAR_PERMS_READ_WRITE_TRIGGER },     { CID_HOLD_TEST_REG, STR("Test_regs"), STR("__"), MB_DEVICE_ADDR1, MB_PARAM_HOLDING, 10, 58,             HOLD_OFFSET(test_regs), PARAM_TYPE_ASCII, 116, OPTS( 0, 100, 1 ), PAR_PERMS_READ_WRITE_TRIGGER },     { CID_RELAY_P1, STR("RelayP1"), STR("on/off"), MB_DEVICE_ADDR1, MB_PARAM_COIL, 0, 8,             COIL_OFFSET(coils_port0), PARAM_TYPE_U16, 2, OPTS( BIT1, 0, 0 ), PAR_PERMS_READ_WRITE_TRIGGER },     { CID_RELAY_P2, STR("RelayP2"), STR("on/off"), MB_DEVICE_ADDR1, MB_PARAM_COIL, 8, 8,             COIL_OFFSET(coils_port1), PARAM_TYPE_U16, 2, OPTS( BIT0, 0, 0 ), PAR_PERMS_READ_WRITE_TRIGGER } };
Please help me solve this, and I would be great if you could make a simple c++ template for modbus, so that i can use it complete the wrapper.

I am confused with your code, its just too complicated

Hi,

Please help me solve this.

Please use the modified master code to check  it under CPP:
master.zip

I would be great if you could make a simple c++ template for modbus, so that i can use it complete the wrapper.

The wrapper the data dictionary is not required because the function mbc_master_send_request() does not use this.
I will send you the wrapper according to my plans.

Hi, Sorry for the late reply, I was busy with something else, By the way thank you so much for the wrapper, I just checked it, Further I am also planning for slave CPP wrapper, If you can help with that, please do reply, I will be so thankful to you for this.

Awaiting for the response.

Hi,
Sorry for delay. The code you provided has very different interface and the wrapper for slave shall have different interface.
Some preliminary comments are below:

slave.setBaud() -> setup slave
regBank.add() method can be changed to call of mbc_slave_set_descriptor() function which will define whole addressable register area in one call.
regBank.get(reg_addr) to find the instance address which corresponds to register address  and return corresponded value of register from register area defined on previous step.
The regBank.set(reg_addr, value) will find the instance address which corresponds to register address  and then set the data of register to the value. The critical section is required to set the data in the register area.
the code here can be used to block task until slave registers are not accessed.

Try to implement the slave wrapper by yourself. I will help once possible.

Any update?

Sorry for the late reply. Do not have update for now.

Alright, Thank you still waiting

Hi,
The ModbusSlave wrapper update here.

Which energy meter are you using and could you please share the errors and code

SELEC MFM384-R-C energy meter
and I am using a simple Modbus master code for reading INPUT REGISTERS
CODE:-
#include "mbcontroller.h"   // for common Modbus defines
#include "string.h"
#include "esp_log.h"
#define MASTER_MAX_CIDS 2
#define MASTER_MAX_RETRY 100
#define MASTER_PORT_NUM 2
#define MASTER_SPEED 115200
#define MASTER_TAG "MODBUS_MASTER"
#define MB_UART_RXD_PIN 16
#define MB_UART_TXD_PIN 17
#define MB_UART_RTS_PIN 18
#define MASTER_CHECK(a, ret_val, str, ...)
if (!(a)) {
ESP_LOGE(MASTER_TAG, "%s(%u): " str, FUNCTION, LINE, ##VA_ARGS);
return (ret_val);
}
#define STR(fieldname) ((const char*)( fieldname ))
#define OPTS(min_val, max_val, step_val) { .opt1 = min_val, .opt2 = max_val, .opt3 = step_val }
// Enumeration of modbus slave addresses accessed by master device
enum {
MB_DEVICE_ADDR1 = 1
};
// Enumeration of all supported CIDs for device (used in parameter definition table)
enum {
CID_DEV_REG0 = 0,
CID_DEV_REG1
};
extern "C" {
// Example Data (Object) Dictionary for Modbus parameters
const mb_parameter_descriptor_t device_parameters[2] = {
// CID, Name, Units, Modbus addr, register type, Modbus Reg Start Addr, Modbus Reg read length,
// Instance offset (NA), Instance type, Instance length (bytes), Options (NA), Permissions
{ CID_DEV_REG0, STR("MB_input_reg-0"), STR("Data"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 0, 1,
0, PARAM_TYPE_U16, 2, OPTS( 0,0,0 ), PAR_PERMS_READ_WRITE_TRIGGER },
{ CID_DEV_REG1, STR("MB_input_reg-1"), STR("Data"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 2, 1,
0, PARAM_TYPE_U16, 2, OPTS( 0,0,0 ), PAR_PERMS_READ_WRITE_TRIGGER }
};
// Calculate number of parameters in the table
const uint16_t num_device_parameters = (sizeof(device_parameters)/sizeof(device_parameters[0]));
static esp_err_t read_modbus_parameter(uint16_t cid, uint16_t par_data)
{
const mb_parameter_descriptor_t param_descriptor = NULL;
esp_err_t err = mbc_master_get_cid_info(cid, &param_descriptor);
if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) {
    uint8_t type = 0;
    err = mbc_master_get_parameter(cid, (char*)param_descriptor->param_key,
                                                    (uint8_t*)par_data, &type);
    if (err == ESP_OK) {
        ESP_LOGI(MASTER_TAG, "Characteristic #%d %s (%s) value = (0x%x) parameter read successful.",
                                 param_descriptor->cid,
                                 (char*)param_descriptor->param_key,
                                 (char*)param_descriptor->param_units,
                                 *(uint16_t*)par_data);
    }
    else
    {
        ESP_LOGE(MASTER_TAG, "Characteristic #%d %s (%s), parameter read fail.",
                                param_descriptor->cid,
                                (char*)param_descriptor->param_key,
                                (char*)param_descriptor->param_units);
    }
}
return err;

}
static esp_err_t write_modbus_parameter(uint16_t cid, uint16_t par_data)
{
const mb_parameter_descriptor_t param_descriptor = NULL;
esp_err_t err = mbc_master_get_cid_info(cid, &param_descriptor);
if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) {
    uint8_t type = 0; // type of parameter from dictionary
    err = mbc_master_set_parameter(cid, (char*)param_descriptor->param_key,
                                                    (uint8_t*)par_data, &type);
    if (err == ESP_OK) {
        ESP_LOGI(MASTER_TAG, "Characteristic #%d %s (%s) value = (0x%04x), write successful.",
                                    param_descriptor->cid,
                                    (char*)param_descriptor->param_key,
                                    (char*)param_descriptor->param_units,
                                    *(uint16_t*)par_data);
    } else {
        ESP_LOGE(MASTER_TAG, "Characteristic #%d (%s) write fail, err = 0x%x (%s).",
                                param_descriptor->cid,
                                (char*)param_descriptor->param_key,
                                (int)err,
                                (char*)esp_err_to_name(err));
    }
}
return err;

}
// This is user function to read and write modbus holding registers
static void master_read_write_func(void *arg)
{
esp_err_t err = ESP_OK;
uint16_t register_data = 0;
ESP_LOGI(MASTER_TAG, "Start modbus test...");

for(uint16_t retry = 0; retry <= MASTER_MAX_RETRY; retry++) {
    // Simply read your register here CID_DEV_REG0 - one register from address 0 (see device_parameters)
    err = read_modbus_parameter(CID_DEV_REG0, &register_data);
    if (err == ESP_OK) {
        // if read successful then increase value of the parameter
        // Insert your modbus read_write register functionality here
        register_data += 1;
        err = write_modbus_parameter(CID_DEV_REG0, &register_data);
    }
    err = read_modbus_parameter(CID_DEV_REG1, &register_data);
    if (err == ESP_OK) {
        register_data += 1;
        err = write_modbus_parameter(CID_DEV_REG1, &register_data);
    }
}
ESP_LOGI(MASTER_TAG, "Modbus test is completed.");

}
// Modbus master initialization
static esp_err_t master_init(void)
{
// Initialize and start Modbus controller
mb_communication_info_t comm;
comm.port = MASTER_PORT_NUM;
comm.port = MASTER_PORT_NUM;
comm.mode = MB_MODE_RTU;
comm.baudrate = MASTER_SPEED;
comm.parity = MB_PARITY_NONE;
void* master_handler = NULL;

esp_err_t err = mbc_master_init(MB_PORT_SERIAL_MASTER, &master_handler);
MASTER_CHECK((master_handler != NULL), ESP_ERR_INVALID_STATE,
                            "mb controller initialization fail.");
MASTER_CHECK((err == ESP_OK), ESP_ERR_INVALID_STATE,
                        "mb controller initialization fail, returns(0x%x).",
                        (uint32_t)err);
err = mbc_master_setup((void*)&comm);
MASTER_CHECK((err == ESP_OK), ESP_ERR_INVALID_STATE,
                        "mb controller setup fail, returns(0x%x).",
                        (uint32_t)err);

// Set UART pin numbers
err = uart_set_pin(MASTER_PORT_NUM, MB_UART_TXD_PIN, MB_UART_RXD_PIN,
                        MB_UART_RTS_PIN, UART_PIN_NO_CHANGE);

err = mbc_master_start();
MASTER_CHECK((err == ESP_OK), ESP_ERR_INVALID_STATE,
                        "mb controller start fail, returns(0x%x).",
                        (uint32_t)err);

MASTER_CHECK((err == ESP_OK), ESP_ERR_INVALID_STATE,
        "mb serial set pin failure, uart_set_pin() returned (0x%x).", (uint32_t)err);
// Set driver mode to Half Duplex
err = uart_set_mode(MASTER_PORT_NUM, UART_MODE_RS485_HALF_DUPLEX);
MASTER_CHECK((err == ESP_OK), ESP_ERR_INVALID_STATE,
        "mb serial set mode failure, uart_set_mode() returned (0x%x).", (uint32_t)err);

vTaskDelay(5);
err = mbc_master_set_descriptor(&device_parameters[0], num_device_parameters);
MASTER_CHECK((err == ESP_OK), ESP_ERR_INVALID_STATE,
                            "mb controller set descriptor fail, returns(0x%x).",
                            (uint32_t)err);
ESP_LOGI(MASTER_TAG, "Modbus master stack initialized...");
return err;

}
void app_main()
{
// Initialization of device peripheral and objects
ESP_ERROR_CHECK(master_init());
vTaskDelay(10);
// Write registers to predefined state

write_modbus_parameter(CID_DEV_REG0, &register_data);

write_modbus_parameter(CID_DEV_REG1, &register_data);

master_read_write_func(NULL);

}
}
ERRORS:-
SERIAL master get parameter failure error=(0x108) (ESP_ERR_INVALID_RESPONSE)
Bunch of this type of errors coming
can you pls suggest any code I am new to this...Thanks in advance

You shold use this https://github.com/alisitsyn/modbus_support/tree/mb_support/simple_modbus_master to test and at first check if the data is coming on https://www.win-tech.com/demos/modscan64.zip Software.

ANYONE can help ??

Anyone can help???

@HEMILSHAH007 ,
The simple modbus example demonstrates the read/write of modbus holding registers. In your case you are going to access INPUT registers in read only area. You can use  read_modbus_parameter(CID_DEV_REGX, &register_data); function to read data in the static void master_read_write_func(void *arg); function and remove all calls like write_modbus_parameter(CID_DEV_REGX, &register_data); from your code. This should help to avoid errors reading the registers if you configured the data dictionary for your device correctly. You need the Modbus registers mapping table for your device to configure the data dictionary accordingly. Please refer to ESP_Modbus official documentation for more information on how to do this. If you still have issues with configuration and data access please provide the data mapping for your device and I can help you to configure it.
Thanks.

@alisitsyn Thanks for the reply
Are you asking about this mapping table ??

pls help me regarding this I am totally new to this and very keen to work on this more now...

@HEMILSHAH007,
Please use the data dictionary configured as below in simple modbus master:

enum {
    CID_V_1ST_PHASE = 0,
    CID_V_2ND_PHASE,
    CID_V_3RD_PHASE,
    CID_V_AVERAGE_LN,
    CID_V12,
    CID_V23,
    CID_V31,
    CID_V_AVERAGE_LL,
    CID_CURRENT_I1,
    CID_CURRENT_I2,
    CID_CURRENT_I3,
    CID_CURRENT_AVERAGE,
    CID_KW1,
    CID_KW2,
    CID_KW3,
    CID_HOLD_TEST_REG,
    CID_COUNT
};

const mb_parameter_descriptor_t device_parameters[] = {
    // { CID, Param Name, Units, Modbus Slave Addr, Modbus Reg Type, Reg Start, Reg Size, Instance Offset, Data Type, Data Size, Parameter Options, Access Mode}
    { CID_V_1ST_PHASE, STR("Voltage first phase"), STR("Volts"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 0, 2,
            0, PARAM_TYPE_U32, 4, OPTS(0, 65535, 1 ), PAR_PERMS_READ_WRITE_TRIGGER },
    { CID_V_2ND_PHASE, STR("Voltage second phase"), STR("Volts"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 2, 2,
            0, PARAM_TYPE_U32, 4, OPTS(0, 65535, 1 ), PAR_PERMS_READ_WRITE_TRIGGER },
    { CID_V_3RD_PHASE, STR("Voltage third phase"), STR("Volts"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 4, 2,
            0, PARAM_TYPE_U32, 4, OPTS(0, 65535, 1 ), PAR_PERMS_READ_WRITE_TRIGGER },
    { CID_V_AVERAGE_LN, STR("Average voltage LN"), STR("Volts"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 6, 2,
            0, PARAM_TYPE_U32, 4, OPTS(0, 65535, 1 ), PAR_PERMS_READ_WRITE_TRIGGER },
    { CID_V12, STR("Voltage_V12"), STR("Volts"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 8, 2,
            0, PARAM_TYPE_U32, 4, OPTS(0, 65535, 1 ), PAR_PERMS_READ_WRITE_TRIGGER },
    { CID_V23, STR("Voltage_V23"), STR("Volts"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 10, 2,
            0, PARAM_TYPE_U32, 4, OPTS(0, 65535, 1 ), PAR_PERMS_READ_WRITE_TRIGGER },
    { CID_V31, STR("Voltage_V31"), STR("Volts"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 12, 2,
            0, PARAM_TYPE_U32, 4, OPTS(0, 65535, 1 ), PAR_PERMS_READ_WRITE_TRIGGER },
    { CID_V_AVERAGE_LL, STR("Voltage_AVERAGE_LL"), STR("Volts"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 14, 2,
            0, PARAM_TYPE_U32, 4, OPTS(0, 65535, 1 ), PAR_PERMS_READ_WRITE_TRIGGER },
    { CID_CURRENT_I1, STR("Current_I1"), STR("A"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 16, 2,
            0, PARAM_TYPE_U32, 4, OPTS(0, 65535, 1 ), PAR_PERMS_READ_WRITE_TRIGGER },
    { CID_CURRENT_I2, STR("Current_I2"), STR("A"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 18, 2,
            0, PARAM_TYPE_U32, 4, OPTS(0, 65535, 1 ), PAR_PERMS_READ_WRITE_TRIGGER },
    { CID_CURRENT_AVERAGE, STR("Current_Average"), STR("A"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 22, 2,
            0, PARAM_TYPE_U32, 4, OPTS(0, 65535, 1 ), PAR_PERMS_READ_WRITE_TRIGGER }
};

Then you can read each parameter using the function:
static esp_err_t read_modbus_parameter(uint16_t cid, uint32_t par_data)
{
const mb_parameter_descriptor_t param_descriptor = NULL;

esp_err_t err = mbc_master_get_cid_info(cid, &param_descriptor);
if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) {
    uint8_t type = 0;
    err = mbc_master_get_parameter(cid, (char*)param_descriptor->param_key,
                                                    (uint8_t*)par_data, &type);
    if (err == ESP_OK) {
        ESP_LOGI(MASTER_TAG, "Characteristic #%d %s (%s) value = (0x%x) parameter read successful.",
                                 param_descriptor->cid,
                                 (char*)param_descriptor->param_key,
                                 (char*)param_descriptor->param_units,
                                 *(uint32_t*)par_data);
    }
    else
    {
        ESP_LOGE(MASTER_TAG, "Characteristic #%d %s (%s), parameter read fail.",
                                param_descriptor->cid,
                                (char*)param_descriptor->param_key,
                                (char*)param_descriptor->param_units);
    }
}
return err;

}

// The code below can be used to read every parameter from device with slave address == 1
    uint32_t parameter_data;
    err = read_modbus_parameter(CID_V23, &parameter_data);
    if (err == ESP_OK) {
        // if read successful then the parameter_data contains the data read from device

    }

I modified this table accordingly still
It shows these errors:-
E (407) MB_CONTROLLER_MASTER: mbc_serial_master_set_descriptor(162): mb descriptor cid field is incorrect.
E (407) MB_CONTROLLER_MASTER: mbc_master_set_descriptor(124): Master set descriptor failure, error=(0x102) (ESP_ERR_INVALID_ARG).
E (417) MODBUS_MASTER: master_init(234): mb controller set descriptor fail, returns(0x102).
ESP_ERROR_CHECK failed: esp_err_t 0x103 (ESP_ERR_INVALID_STATE) at 0x40086af4
I don't know why it is showing CID incorrect.

Yes CID error solved now.Thanks.But I am getting master get parameter failure and parameter failure. Can you help regarding this?

Yes, Please provide the log of the communication.

#include "mbcontroller.h"   // for common Modbus defines
#include "string.h"
#include "esp_log.h"
#define MASTER_MAX_CIDS 2
#define MASTER_MAX_RETRY 100
#define MASTER_PORT_NUM 2
#define MASTER_SPEED 115200
#define MASTER_TAG "MODBUS_MASTER"
#define MB_UART_RXD_PIN 22
#define MB_UART_TXD_PIN 23
#define MB_UART_RTS_PIN 18
#define MASTER_CHECK(a, ret_val, str, ...)
if (!(a)) {
ESP_LOGE(MASTER_TAG, "%s(%u): " str, FUNCTION, LINE, ##VA_ARGS);
return (ret_val);
}
#define STR(fieldname) ((const char*)( fieldname ))
#define OPTS(min_val, max_val, step_val) { .opt1 = min_val, .opt2 = max_val, .opt3 = step_val }
// Enumeration of modbus slave addresses accessed by master device
enum {
MB_DEVICE_ADDR1 = 1
};
// Enumeration of all supported CIDs for device (used in parameter definition table)
enum {
CID_V_1ST_PHASE = 0,
CID_V_2ND_PHASE,
CID_V_3RD_PHASE,
CID_V_AVERAGE_LN,
CID_V12,
CID_V23,
CID_V31,
CID_V_AVERAGE_LL,
CID_CURRENT_I1,
CID_CURRENT_I2,
CID_CURRENT_I3,
CID_CURRENT_AVERAGE,
CID_KW1,
CID_KW2,
CID_KW3,
CID_HOLD_TEST_REG,
CID_COUNT
};
const mb_parameter_descriptor_t device_parameters[] = {
// { CID, Param Name, Units, Modbus Slave Addr, Modbus Reg Type, Reg Start, Reg Size, Instance Offset, Data Type, Data Size, Parameter Options, Access Mode}
{ CID_V_1ST_PHASE, STR("Voltage first phase"), STR("Volts"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 0, 2,
0, PARAM_TYPE_U32, 4, OPTS(0, 65535, 1 ), PAR_PERMS_READ_WRITE_TRIGGER },
{ CID_V_2ND_PHASE, STR("Voltage second phase"), STR("Volts"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 2, 2,
0, PARAM_TYPE_U32, 4, OPTS(0, 65535, 1 ), PAR_PERMS_READ_WRITE_TRIGGER },
{ CID_V_3RD_PHASE, STR("Voltage third phase"), STR("Volts"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 4, 2,
0, PARAM_TYPE_U32, 4, OPTS(0, 65535, 1 ), PAR_PERMS_READ_WRITE_TRIGGER },
{ CID_V_AVERAGE_LN, STR("Average voltage LN"), STR("Volts"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 6, 2,
0, PARAM_TYPE_U32, 4, OPTS(0, 65535, 1 ), PAR_PERMS_READ_WRITE_TRIGGER },
{ CID_V12, STR("Voltage_V12"), STR("Volts"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 8, 2,
0, PARAM_TYPE_U32, 4, OPTS(0, 65535, 1 ), PAR_PERMS_READ_WRITE_TRIGGER },
{ CID_V23, STR("Voltage_V23"), STR("Volts"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 10, 2,
0, PARAM_TYPE_U32, 4, OPTS(0, 65535, 1 ), PAR_PERMS_READ_WRITE_TRIGGER },
{ CID_V31, STR("Voltage_V31"), STR("Volts"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 12, 2,
0, PARAM_TYPE_U32, 4, OPTS(0, 65535, 1 ), PAR_PERMS_READ_WRITE_TRIGGER },
{ CID_V_AVERAGE_LL, STR("Voltage_AVERAGE_LL"), STR("Volts"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 14, 2,
0, PARAM_TYPE_U32, 4, OPTS(0, 65535, 1 ), PAR_PERMS_READ_WRITE_TRIGGER },
{ CID_CURRENT_I1, STR("Current_I1"), STR("A"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 16, 2,
0, PARAM_TYPE_U32, 4, OPTS(0, 65535, 1 ), PAR_PERMS_READ_WRITE_TRIGGER },
{ CID_CURRENT_I2, STR("Current_I2"), STR("A"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 18, 2,
0, PARAM_TYPE_U32, 4, OPTS(0, 65535, 1 ), PAR_PERMS_READ_WRITE_TRIGGER }
};
// Calculate number of parameters in the table
const uint16_t num_device_parameters = (sizeof(device_parameters)/sizeof(device_parameters[0]));
/*static esp_err_t read_modbus_parameter(uint16_t cid, uint16_t par_data)
{
const mb_parameter_descriptor_t param_descriptor = NULL;
esp_err_t err = mbc_master_get_cid_info(cid, &param_descriptor);
if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) {
    uint8_t type = 0;
    err = mbc_master_get_parameter(cid, (char*)param_descriptor->param_key,
                                                    (uint8_t*)par_data, &type);
    if (err == ESP_OK) {
        ESP_LOGI(MASTER_TAG, "Characteristic #%d %s (%s) value = (0x%04x) parameter read successful.",
                                 param_descriptor->cid,
                                 (char*)param_descriptor->param_key,
                                 (char*)param_descriptor->param_units,
                                 *(uint16_t*)par_data);
    }
    else
    {
        ESP_LOGE(MASTER_TAG, "Characteristic #%d %s (%s), parameter read fail.",
                                param_descriptor->cid,
                                (char*)param_descriptor->param_key,
                                (char*)param_descriptor->param_units);
    }
}
return err;

}*/
static esp_err_t read_modbus_parameter(uint16_t cid, uint32_t par_data)
{
const mb_parameter_descriptor_t param_descriptor = NULL;
esp_err_t err = mbc_master_get_cid_info(cid, &param_descriptor);
if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) {
uint8_t type = 0;
err = mbc_master_get_parameter(cid, (char*)param_descriptor->param_key,
(uint8_t*)par_data, &type);
if (err == ESP_OK) {
ESP_LOGI(MASTER_TAG, "Characteristic #%d %s (%s) value = (0x%x) parameter read successful.",
param_descriptor->cid,
(char*)param_descriptor->param_key,
(char*)param_descriptor->param_units,
(uint32_t)par_data);
}
else
{
ESP_LOGE(MASTER_TAG, "Characteristic #%d %s (%s), parameter read fail.",
param_descriptor->cid,
(char*)param_descriptor->param_key,
(char*)param_descriptor->param_units);
}
}
return err;
}
/*static esp_err_t write_modbus_parameter(uint16_t cid, uint16_t par_data)
{
const mb_parameter_descriptor_t param_descriptor = NULL;
esp_err_t err = mbc_master_get_cid_info(cid, &param_descriptor);
if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) {
    uint8_t type = 0; // type of parameter from dictionary
    err = mbc_master_set_parameter(cid, (char*)param_descriptor->param_key,
                                                    (uint8_t*)par_data, &type);
    if (err == ESP_OK) {
        ESP_LOGI(MASTER_TAG, "Characteristic #%d %s (%s) value = (0x%04x), write successful.",
                                    param_descriptor->cid,
                                    (char*)param_descriptor->param_key,
                                    (char*)param_descriptor->param_units,
                                    *(uint16_t*)par_data);
    } else {
        ESP_LOGE(MASTER_TAG, "Characteristic #%d (%s) write fail, err = 0x%x (%s).",
                                param_descriptor->cid,
                                (char*)param_descriptor->param_key,
                                (int)err,
                                (char*)esp_err_to_name(err));
    }
}
return err;

}*/
// This is user function to read and write modbus holding registers
static void master_read_func(void *arg)
{
esp_err_t err = ESP_OK;
uint32_t parameter_data;
ESP_LOGI(MASTER_TAG, "Start modbus test...");

for(uint16_t retry = 0; retry <= MASTER_MAX_RETRY; retry++) {
    // Simply read your register here CID_DEV_REG0 - one register from address 0 (see device_parameters)
    err = read_modbus_parameter(CID_V_1ST_PHASE, &parameter_data);
    if (err == ESP_OK) {
        // if read successful then increase value of the parameter
        // Insert your modbus read_write register functionality here

        parameter_data += 1;

    }

   /* err = read_modbus_parameter(CID_DEV_REG1, &register_data);
    if (err == ESP_OK) {
        register_data += 1;
        err = write_modbus_parameter(CID_DEV_REG1, &register_data);
    }*/
}
ESP_LOGI(MASTER_TAG, "Modbus test is completed.");

}
// Modbus master initialization
static esp_err_t master_init(void)
{
// Initialize and start Modbus controller
mb_communication_info_t comm = {
.port = MASTER_PORT_NUM,
.mode = MB_MODE_RTU,
.baudrate = MASTER_SPEED,
.parity = MB_PARITY_NONE
};
void* master_handler = NULL;
esp_err_t err = mbc_master_init(MB_PORT_SERIAL_MASTER, &master_handler);
MASTER_CHECK((master_handler != NULL), ESP_ERR_INVALID_STATE,
                            "mb controller initialization fail.");
MASTER_CHECK((err == ESP_OK), ESP_ERR_INVALID_STATE,
                        "mb controller initialization fail, returns(0x%x).",
                        (uint32_t)err);
err = mbc_master_setup((void*)&comm);
MASTER_CHECK((err == ESP_OK), ESP_ERR_INVALID_STATE,
                        "mb controller setup fail, returns(0x%x).",
                        (uint32_t)err);

// Set UART pin numbers
err = uart_set_pin(MASTER_PORT_NUM, MB_UART_TXD_PIN, MB_UART_RXD_PIN,
                        MB_UART_RTS_PIN, UART_PIN_NO_CHANGE);

err = mbc_master_start();
MASTER_CHECK((err == ESP_OK), ESP_ERR_INVALID_STATE,
                        "mb controller start fail, returns(0x%x).",
                        (uint32_t)err);

MASTER_CHECK((err == ESP_OK), ESP_ERR_INVALID_STATE,
        "mb serial set pin failure, uart_set_pin() returned (0x%x).", (uint32_t)err);
// Set driver mode to Half Duplex
err = uart_set_mode(MASTER_PORT_NUM, UART_MODE_RS485_HALF_DUPLEX);
MASTER_CHECK((err == ESP_OK), ESP_ERR_INVALID_STATE,
        "mb serial set mode failure, uart_set_mode() returned (0x%x).", (uint32_t)err);

vTaskDelay(5);
err = mbc_master_set_descriptor(&device_parameters[0], num_device_parameters);
MASTER_CHECK((err == ESP_OK), ESP_ERR_INVALID_STATE,
                            "mb controller set descriptor fail, returns(0x%x).",
                            (uint32_t)err);
ESP_LOGI(MASTER_TAG, "Modbus master stack initialized...");
return err;

}
void app_main(void)
{
// Initialization of device peripheral and objects
ESP_ERROR_CHECK(master_init());
vTaskDelay(10);
// Write registers to predefined state
/*uint16_t register_data = 0x1234;
write_modbus_parameter(CID_DEV_REG0, &register_data);
register_data = 0x5678;
write_modbus_parameter(CID_DEV_REG1, &register_data);*/

master_read_func(NULL);

}

#include "mbcontroller.h"   // for common Modbus defines
#include "string.h"
#include "esp_log.h"
#define MASTER_MAX_CIDS 2
#define MASTER_MAX_RETRY 100
#define MASTER_PORT_NUM 2
#define MASTER_SPEED 115200
#define MASTER_TAG "MODBUS_MASTER"
#define MB_UART_RXD_PIN 22
#define MB_UART_TXD_PIN 23
#define MB_UART_RTS_PIN 18
#define MASTER_CHECK(a, ret_val, str, ...)
if (!(a)) {
ESP_LOGE(MASTER_TAG, "%s(%u): " str, FUNCTION, LINE, ##VA_ARGS);
return (ret_val);
}
#define STR(fieldname) ((const char*)( fieldname ))
#define OPTS(min_val, max_val, step_val) { .opt1 = min_val, .opt2 = max_val, .opt3 = step_val }
// Enumeration of modbus slave addresses accessed by master device
enum {
MB_DEVICE_ADDR1 = 1
};
// Enumeration of all supported CIDs for device (used in parameter definition table)
enum {
CID_V_1ST_PHASE = 0,
CID_V_2ND_PHASE,
CID_V_3RD_PHASE,
CID_V_AVERAGE_LN,
CID_V12,
CID_V23,
CID_V31,
CID_V_AVERAGE_LL,
CID_CURRENT_I1,
CID_CURRENT_I2,
CID_CURRENT_I3,
CID_CURRENT_AVERAGE,
CID_KW1,
CID_KW2,
CID_KW3,
CID_HOLD_TEST_REG,
CID_COUNT
};
const mb_parameter_descriptor_t device_parameters[] = {
// { CID, Param Name, Units, Modbus Slave Addr, Modbus Reg Type, Reg Start, Reg Size, Instance Offset, Data Type, Data Size, Parameter Options, Access Mode}
{ CID_V_1ST_PHASE, STR("Voltage first phase"), STR("Volts"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 0, 2,
0, PARAM_TYPE_U32, 4, OPTS(0, 65535, 1 ), PAR_PERMS_READ_WRITE_TRIGGER },
{ CID_V_2ND_PHASE, STR("Voltage second phase"), STR("Volts"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 2, 2,
0, PARAM_TYPE_U32, 4, OPTS(0, 65535, 1 ), PAR_PERMS_READ_WRITE_TRIGGER },
{ CID_V_3RD_PHASE, STR("Voltage third phase"), STR("Volts"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 4, 2,
0, PARAM_TYPE_U32, 4, OPTS(0, 65535, 1 ), PAR_PERMS_READ_WRITE_TRIGGER },
{ CID_V_AVERAGE_LN, STR("Average voltage LN"), STR("Volts"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 6, 2,
0, PARAM_TYPE_U32, 4, OPTS(0, 65535, 1 ), PAR_PERMS_READ_WRITE_TRIGGER },
{ CID_V12, STR("Voltage_V12"), STR("Volts"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 8, 2,
0, PARAM_TYPE_U32, 4, OPTS(0, 65535, 1 ), PAR_PERMS_READ_WRITE_TRIGGER },
{ CID_V23, STR("Voltage_V23"), STR("Volts"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 10, 2,
0, PARAM_TYPE_U32, 4, OPTS(0, 65535, 1 ), PAR_PERMS_READ_WRITE_TRIGGER },
{ CID_V31, STR("Voltage_V31"), STR("Volts"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 12, 2,
0, PARAM_TYPE_U32, 4, OPTS(0, 65535, 1 ), PAR_PERMS_READ_WRITE_TRIGGER },
{ CID_V_AVERAGE_LL, STR("Voltage_AVERAGE_LL"), STR("Volts"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 14, 2,
0, PARAM_TYPE_U32, 4, OPTS(0, 65535, 1 ), PAR_PERMS_READ_WRITE_TRIGGER },
{ CID_CURRENT_I1, STR("Current_I1"), STR("A"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 16, 2,
0, PARAM_TYPE_U32, 4, OPTS(0, 65535, 1 ), PAR_PERMS_READ_WRITE_TRIGGER },
{ CID_CURRENT_I2, STR("Current_I2"), STR("A"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 18, 2,
0, PARAM_TYPE_U32, 4, OPTS(0, 65535, 1 ), PAR_PERMS_READ_WRITE_TRIGGER }
};
// Calculate number of parameters in the table
const uint16_t num_device_parameters = (sizeof(device_parameters)/sizeof(device_parameters[0]));
static esp_err_t read_modbus_parameter(uint16_t cid, uint32_t par_data)
{
const mb_parameter_descriptor_t param_descriptor = NULL;
esp_err_t err = mbc_master_get_cid_info(cid, &param_descriptor);
if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) {
uint8_t type = 0;
err = mbc_master_get_parameter(cid, (char*)param_descriptor->param_key,
(uint8_t*)par_data, &type);
if (err == ESP_OK) {
ESP_LOGI(MASTER_TAG, "Characteristic #%d %s (%s) value = (0x%x) parameter read successful.",
param_descriptor->cid,
(char*)param_descriptor->param_key,
(char*)param_descriptor->param_units,
(uint32_t)par_data);
}
else
{
ESP_LOGE(MASTER_TAG, "Characteristic #%d %s (%s), parameter read fail.",
param_descriptor->cid,
(char*)param_descriptor->param_key,
(char*)param_descriptor->param_units);
}
}
return err;
}
// This is user function to read and write modbus holding registers
static void master_read_func(void *arg)
{
esp_err_t err = ESP_OK;
uint32_t parameter_data;
ESP_LOGI(MASTER_TAG, "Start modbus test...");

for(uint16_t retry = 0; retry <= MASTER_MAX_RETRY; retry++) {
    // Simply read your register here CID_DEV_REG0 - one register from address 0 (see device_parameters)
    err = read_modbus_parameter(CID_V_1ST_PHASE, &parameter_data);
    if (err == ESP_OK) {
        // if read successful then increase value of the parameter
        // Insert your modbus read_write register functionality here

        parameter_data += 1;

    }

}
ESP_LOGI(MASTER_TAG, "Modbus test is completed.");

}
// Modbus master initialization
static esp_err_t master_init(void)
{
// Initialize and start Modbus controller
mb_communication_info_t comm = {
.port = MASTER_PORT_NUM,
.mode = MB_MODE_RTU,
.baudrate = MASTER_SPEED,
.parity = MB_PARITY_NONE
};
void* master_handler = NULL;
esp_err_t err = mbc_master_init(MB_PORT_SERIAL_MASTER, &master_handler);
MASTER_CHECK((master_handler != NULL), ESP_ERR_INVALID_STATE,
                            "mb controller initialization fail.");
MASTER_CHECK((err == ESP_OK), ESP_ERR_INVALID_STATE,
                        "mb controller initialization fail, returns(0x%x).",
                        (uint32_t)err);
err = mbc_master_setup((void*)&comm);
MASTER_CHECK((err == ESP_OK), ESP_ERR_INVALID_STATE,
                        "mb controller setup fail, returns(0x%x).",
                        (uint32_t)err);

// Set UART pin numbers
err = uart_set_pin(MASTER_PORT_NUM, MB_UART_TXD_PIN, MB_UART_RXD_PIN,
                        MB_UART_RTS_PIN, UART_PIN_NO_CHANGE);

err = mbc_master_start();
MASTER_CHECK((err == ESP_OK), ESP_ERR_INVALID_STATE,
                        "mb controller start fail, returns(0x%x).",
                        (uint32_t)err);

MASTER_CHECK((err == ESP_OK), ESP_ERR_INVALID_STATE,
        "mb serial set pin failure, uart_set_pin() returned (0x%x).", (uint32_t)err);
// Set driver mode to Half Duplex
err = uart_set_mode(MASTER_PORT_NUM, UART_MODE_RS485_HALF_DUPLEX);
MASTER_CHECK((err == ESP_OK), ESP_ERR_INVALID_STATE,
        "mb serial set mode failure, uart_set_mode() returned (0x%x).", (uint32_t)err);

vTaskDelay(5);
err = mbc_master_set_descriptor(&device_parameters[0], num_device_parameters);
MASTER_CHECK((err == ESP_OK), ESP_ERR_INVALID_STATE,
                            "mb controller set descriptor fail, returns(0x%x).",
                            (uint32_t)err);
ESP_LOGI(MASTER_TAG, "Modbus master stack initialized...");
return err;

}
void app_main(void)
{
// Initialization of device peripheral and objects
ESP_ERROR_CHECK(master_init());
vTaskDelay(10);
master_read_func(NULL);

}

This above is my modified code ...

Please attach the code as archive here because the github removes some details. And please include your error log.

SMM.txt

I had attached code in these SMM file and this errors I am getting in my serial monitor.

This means that your slave device does not respond.

Please make sure the device is connected to the communication interface correctly and is able to respond to the master simulator.
Make sure the address of the slave in the network segment is configured == MB_DEVICE_ADDR1 and the baud rate is set to the same value as in the master example.

Yes, my connection is correct as I am successfully running the UART ECHO code.
My slave address is 1 and the baud rate is the same too, still I am checking this all once again...

All slave devices of different manufacturers sometimes have different Modbus address notations.  Please also try to change register addresses in the data dictionary like below:
{ CID_V_1ST_PHASE, STR("Voltage first phase"), STR("Volts"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 30000, 2,
0, PARAM_TYPE_U32, 4, OPTS(0, 65535, 1 ), PAR_PERMS_READ_WRITE_TRIGGER },

.... other changes here...

Yes I am checking by changing values..

I changed the values of registers constantly but I don't know why these errors are still coming....something is still not configured.

This error just means that your slave does not recognize the request and does not respond to the master.
In order to find the reason for the error I propose you configure the  Modbus Slave Simulator tool. Add there the registers of your slave device and try to communicate from the master with the Slave simulator first. This will allow us to record the communication traffic and find the reason for the issue.
Please:

install the simulator.
create the input register configuration window with the registers as per your slave register map table.
Start your master and then slave simulator and record the traffic.

Thanks.

I had tried and got a
Uploading Communication log.txt…
communication log I am attaching it...

I had tried this and got a communication log in MODPOLL
Communication log.txt

@HEMILSHAH007,
The log looks good and your master should work the same way. Please try to increase slave response time in kconfig menu (see above in the topic). Could you connect your simple modbus master to Modbus Slave simulator and also record the traffic?

Please connect your devices like below:
                                                      Modbus Slave SW
                                                      Record MB Master Traffic from ESP
    -------------                 -------------        -------------
    |   ESP     |-TX--@---- +--RX-|           |        |           |
    |  MODBUS   |---<>---+  |     |TTL to USB |--------|PC_MB_SLAVE|
    |  MASTER   |-RX-+   |  @  TX-|  adapter  |        |           |
    -------------    |  RTS |     -------------        -------------
                     |   |  |
                     |   |  |
                  ---+---+--+--
                  |RO RE/DE DI|
                  | RS485     |
                  |           |
                  -------------
                    |    |
                    A    B
    -------------   |    |
    |           |---+    |
    |METER RS485|        |
    |           |--------+
    -------------

In your given schematic diagram RE/DE means to short them or take any one of them because I am shorting both of them always to RTS.

In your given schematic diagram RE/DE means to short them or take any one of them because I am shorting both of them always to RTS.

@alisitsyn I tried this way it didn't work. I dont know why traffic is not showing in slave simulator.

I can not check this on your side but in fact, it should work just fine if you follow the connection diagram. Please try just connection to serial simulator using your USB-TTL adapter. A better way is to connect the simple Modbus master to your meter and record the traffic using the logic analyzer or oscilloscope.
    -------------                 -------------        -------------
    |   ESP     |-TX--@-----+--RX-|           |        |           |
    |  MODBUS   |---              |TTL to USB |--------|PC_MB_SLAVE|
    |  MASTER   |-RX-+---------TX-|  adapter  |        |           |
    -------------                 -------------        -------------

Connection:-
RS485 USB TTL(COM 6) - TO ->MAX485 ->ESP32 (COM 4)
Now from the same PC, I am trying to send data(HELLO) from TX OF USB TTL COM 6 to RX OF UART OF ESP32.  I had already done reverse connection such as sending data from ESP TO USB TTL and it succeeds but when I am doing USB TTL TO ESP32 data send it is not showing data on serial monitor of esp32 ... I am sending code hereby for both Proceses.
CODE:-
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_log.h"
#include "driver/uart.h"
#include "string.h"
#include "driver/gpio.h"
static const int RX_BUF_SIZE = 1024;
#define TXD_PIN (GPIO_NUM_17)
#define RXD_PIN (GPIO_NUM_16)
#define RTS_PIN (GPIO_NUM_18)
void init(void) {
const uart_config_t uart_config = {
.baud_rate = 115200,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
.source_clk = UART_SCLK_APB,
};
// We won't use a buffer for sending data.
uart_driver_install(UART_NUM_1, RX_BUF_SIZE * 2, 0, 0, NULL, 0);
uart_param_config(UART_NUM_1, &uart_config);
uart_set_pin(UART_NUM_1, TXD_PIN, RXD_PIN, RTS_PIN , UART_PIN_NO_CHANGE);
}
int sendData(const char* logName, char* data)
{
const int len = strlen(data);
const int txBytes = uart_write_bytes(UART_NUM_1, data, len);
ESP_LOGI(logName, "Wrote %d bytes", txBytes);
return txBytes;
}
/*static void tx_task(void *arg)
{
static const char TX_TASK_TAG = "TX_TASK";
esp_log_level_set(TX_TASK_TAG, ESP_LOG_INFO);
while (1) {
sendData(TX_TASK_TAG, "HELLO HEMIL\n");
vTaskDelay(2000 / portTICK_PERIOD_MS);
}
}/
static void rx_task(void arg)
{
{
static const char RX_TASK_TAG = "RX_TASK";
esp_log_level_set(RX_TASK_TAG, ESP_LOG_INFO);
uint8_t data = (uint8_t) malloc(RX_BUF_SIZE+1);
while (1) {
const int rxBytes = uart_read_bytes(UART_NUM_1, data, RX_BUF_SIZE, 1000 / portTICK_PERIOD_MS);
if (rxBytes > 0) {
ESP_LOGI(RX_TASK_TAG, "Read %d bytes: '%s'", rxBytes, data);
printf("%s", data);
  }
}

}
}
void app_main(void)
{
init();
xTaskCreate(rx_task, "uart_rx_task", 10242, NULL, configMAX_PRIORITIES, NULL);
//  xTaskCreate(tx_task, "uart_tx_task", 10242, NULL, configMAX_PRIORITIES-1, NULL);
}

I want to check whether UART RX is receiving something or not so I did this,  UART Tx successfully prints data on RX OF USB TTL so it's done.

I want to check whether UART RX is receiving something or not so I did this, UART Tx successfully prints data on RX OF USB TTL so it's done.

Ok, thank you for the results, but I was going to make sure that modbus master stack sends a correct request over UART and the opposite side (PC) is able to receive it and  respond to master. This is why I asked you to install the Modbus slave SW on PC side just to record the Modbus log.
The RTS pin is not controlled by ESP32 if the HALF DUPLEX MODE is not set. So, your code is able to work in one direction.
Please use the echo rs485 example to check the RS485 interface connection instead of your code. The uart echo can be used to check USB-TTL to ESP32 connection.
See the readme.md of the example for more information.

I tried the ECHO RS485 code in Inspite of sending data from USB TTL to ESP32 I didn't receive any data on my ESP-IDF Serial monitor.

I tried the ECHO RS485 code in Inspite of sending data from USB TTL to ESP32 I didn't receive any data on my ESP-IDF Serial monitor.

To check UART interface you need to connect PC --> USB to TTL Adapter --> RX,TX pins of ESP32, build and run the uart echo and then send the string from PC. The string should be returned back to the terminal. If this does not work, please check your hardware.
In order to check the RS485: PC --> USB to RTS 485 Adapter A, B pins --> A, B pins RS485 Adapter --> RXD, TXD pins of ESP32. Then build and run  echo rs485 example, send the string from PC and check if it is returned back on PC terminal. If this do not work -> means the hardware do not work. If you use MAX485 adapter I would suggest to change it to ADM483 (3V) or just connect the VCC of MAX485 to 3.3V to use the correct level shifting.

The options above should work just fine on your side.

Hi, I'm also newbie
with modbus protocol I've used
Modbus master example and It' works
with certain devices, for example,
the refrigeration control datasheet looks
like this:

I don't understand the part of "it's necessary to start the CHECKSUM calcultation, writting any value at the address HEX 0500" since espressif modbus docs it's not mention that function.
Please help me to solve this issue.
Thank you in advance.

Hi @Kakomis,
I think your device is pretty custom and the behavior "it's necessary to start the CHECKSUM calculation, writing any value at the address HEX 0500" is custom functionality of device and does not have any relationship with the Modbus. As I understand the data of parameters is stored in nonvolatile memory of your device (type of parameter - N) and protected by checksum for whole structure of non-volatile parameters.  When you wrote the new data to this structure (changed any of the type N parameter) the device do not update the checksum automatically but calculates this manually once you write any value to the register 0x0500. This is my understanding.
The error ESP_ERR_TIMEOUT - means that device does not respond to your request during timeout.

Hi @alisitsyn
Thanks for your reply, I really appreciate it, Here is the code:
#include "string.h"
#include "esp_log.h"  // for modbus parameters structures
#include "mbcontroller.h"
#include "sdkconfig.h"
#define STR(fieldname) ((const char*)( fieldname ))
// Options can be used as bit masks or parameter limits
#define OPTS(min_val, max_val, step_val) { .opt1 = min_val, .opt2 = max_val, .opt3 = step_val }
static const char *TAG = "MASTER_TEST";
// Enumeration of modbus device addresses accessed by master device
enum {
MB_DEVICE_ADDR1 = 1 // Only one slave device used for the test (add other slave addresses here)
};
// Enumeration of all supported CIDs for device (used in parameter definition table)
enum {
CID_TEMP = 0,
CID_UNITS
};
mb_parameter_descriptor_t device_parameters[] = {
{   CID_SONDA_1,
STR("Pr1 temperature"),
STR("C"),
MB_DEVICE_ADDR1,
MB_PARAM_HOLDING,
512,
1,
0,
PARAM_SIZE_U16,
2,
OPTS( -40, 100, 1 ),
PAR_PERMS_READ },
{   CID_AUX_OUTPUT,
STR("Aux output"),
STR("."),
MB_DEVICE_ADDR1,
MB_PARAM_HOLDING,
643,
1,
0,
PARAM_SIZE_U16,
2,
OPTS( 0, 0, 0 ),
PAR_PERMS_READ },
};
// Calculate number of parameters in the table
uint16_t num_device_parameters = (sizeof(device_parameters) / sizeof(device_parameters[0]));
esp_err_t master_get_data(float pr1)
{
const mb_parameter_descriptor_t param_descriptor = NULL;
uint8_t temp_data[2] = {0}; // temporary buffer to hold maximum CID size
uint8_t type = 0;
// float pr1 = 0;
// Get the information for characteristic cid from data dictionary
esp_err_t err = mbc_master_get_cid_info(0, &param_descriptor);

if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) {
    err = mbc_master_get_parameter(param_descriptor->cid, (char*)param_descriptor->param_key, (uint8_t*)temp_data, &type);
    if (err == ESP_OK) {
        int16_t raw = temp_data[1] << 8 | temp_data[0];
        *pr1 = (float)raw / 10.0;
        ESP_LOGI(TAG, "Type: %d", type);
        return ESP_OK;
    } else {
        ESP_LOGE(TAG, "Characteristic #%d (%s) read fail, err = 0x%x (%s).",
                        param_descriptor->cid,
                        (char*)param_descriptor->param_key,
                        (int)err,
                        (char*)esp_err_to_name(err));
    }
} else {
    ESP_LOGE(TAG, "Could not get information for characteristic %d.", 0);
}

return -1;

}
void master_set_data(uint8_t units)
{
const mb_parameter_descriptor_t* param_descriptor = NULL;
// uint8_t temp_data = units;
// Get the information for characteristic cid from data dictionary
esp_err_t err = mbc_master_get_cid_info(1, &param_descriptor);

if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) {
    esp_err_t err1 = mbc_master_set_parameter(param_descriptor->cid, (char*)param_descriptor->param_key, &units, &type);
    if (err1 == ESP_OK) {
        ESP_LOGI(TAG, "Set parameter data successfully.");
    } else {
        ESP_LOGE(TAG, "Set data fail, type = %d, err = 0x%x (%s).", type, (int)err1, (char*)esp_err_to_name(err1));
    }
}else {
    ESP_LOGE(TAG, "Could not write information for characteristic %d.", param_descriptor->cid);
}
// ESP_ERROR_CHECK(mbc_master_destroy());

}
void init_modbus_comm()
{
mb_communication_info_t comm_info = {
.port = 2,                  // Serial port number
.mode = MB_MODE_RTU,        // Modbus mode of communication (MB_MODE_RTU or MB_MODE_ASCII)
.baudrate = 9600,           // Modbus communication baud rate
.parity = MB_PARITY_NONE,   // parity option for serial port
};
void* master_handler = NULL;

ESP_ERROR_CHECK(mbc_master_init(MB_PORT_SERIAL_MASTER, &master_handler));

ESP_ERROR_CHECK(mbc_master_setup((void*)&comm_info));

ESP_ERROR_CHECK(uart_set_pin(2, 9, 8, 10, UART_PIN_NO_CHANGE));

esp_err_t err = mbc_master_start();
if (err != ESP_OK) {
    ESP_LOGE(TAG, "mb controller start fail, err=%x.", err);
}

ESP_ERROR_CHECK(uart_set_mode(2, UART_MODE_RS485_HALF_DUPLEX));

vTaskDelay(5);

ESP_ERROR_CHECK(mbc_master_set_descriptor(&device_parameters[0], num_device_parameters));

ESP_LOGI(TAG, "Modbus master stack initialized...");

}
As you can see it's pretty simple like docs' one, and I this is the manual

X34.pdf

Hi @Kakomis ,
As I described above the data dictionary is incorrect. Should be fixed as below:
mb_parameter_descriptor_t device_parameters[] = {
{ CID_SONDA_1,
STR("Pr1 temperature"),
STR("C"),
MB_DEVICE_ADDR1,
MB_PARAM_HOLDING,
0x200,
1,
0,
PARAM_TYPE_U16, // <<<<< the critical change
PARAM_SIZE_U16,
OPTS( -40, 100, 1 ),
PAR_PERMS_READ },
{ CID_AUX_OUTPUT,
STR("Aux output"),
STR("."),
MB_DEVICE_ADDR1,
MB_PARAM_HOLDING,
0x283,
1,
0,
PARAM_TYPE_U16, // <<<<< the critical change
PARAM_SIZE_U16,
OPTS( 0, 0, 0 ),
PAR_PERMS_READ },
};

Hi @alisitsyn
I just update my code and I only can read but not write, However, with this:
{ CID_SONDA_1,
STR("Pr1 temperature"),
STR("C"),
MB_DEVICE_ADDR1,
MB_PARAM_HOLDING,
0x200,
1,
0,
PARAM_TYPE_U16, // <<<<< the critical change
PARAM_SIZE_U16,
OPTS( -40, 100, 1 ),
now, I get his error:
E (240198) MASTER_TEST: Characteristic #0 (Pr1 temperature) read fail, err = 0x108 (ESP_ERR_INVALID_RESPONSE).

Could you use the Modbus poll tool to recover log of what the slave returns as response to your read request? Setup your connection with slave in the menu connection. The log is available Menu - Display - Communication.

Ok, that error occurs randomly, indeed, manual says only uses  function 3 and 6

I have log verbosity selected, but it only shows me this when I try to write:
E (33615) MB_CONTROLLER_MASTER: mbc_master_set_parameter(146): Master set parameter failure, error=(0x107) (ESP_ERR_TIMEOUT).
E (33615) MASTER_TEST: Set data fail, type = 1, err = 0x107 (ESP_ERR_TIMEOUT).

I still need the whole log attached as a file and please try to use the tool to get response and later we can investigate communication with your slave and find issues. The read should work just fine because it uses the 0x03 command.

Hi @alisitsyn
I'm sorry I don't get this command 01 03 02 00 00 01 85 B2 since my test code looks like this:
void app_main(void)
{
while(true)
{
float temp;
if(master_get_data(&temp) == ESP_OK)
{
printf("Temp: %.1f °C\n", temp);
}
vTaskDelay(2000 / portTICK_PERIOD_MS);
}
}
I attach the output I got  it from GTK Term.
Once again, thank you for your help.
out.txt

After a while, I checked my connection and applied solder to the wires, now reading works.
logs from GTK Term:
logs.txt
Modbus Poll:
logs2.txt

@Kakomis,
I do not see the correct Modbus reply in your logs. I see some numbers returned in ASCII form as response instead of the correct Modbus response. Please check your connection.

Hi @alisitsyn
Here is the slave response. I just connected my device to pc with an usb to rs485 driver.
slave_log.txt

Hey, @alisitsyn I am grateful for your reply to my query yesterday on the expressive forum. Since now I have switched to RTU mode I am now getting a gibberish output for my serial request at the Hercules terminal. Since I am getting a timeout error for my set parameter I needed that output to understand what exactly am I doing wrong.
E (45960) MB_CONTROLLER_MASTER: mbc_master_set_parameter(134): Master set parameter failure, error=(0x107) (ESP_ERR_TIMEOUT).
I am getting this error although now I am able to establish communication with my energy meter. I am thankful to you for that. Can you also help me understand the above error, how can I resolve it and How can I get a readable output at the Hercules terminal for my serial request from my Master(Esp 32)?
Thank you

@VaibhavSingh9511,
The error description.
The error usually means that the slave do not respond to your request during response timeout or you need to increase slave response time in the master. Refer to [esp-modbus documenation]https://docs.espressif.com/projects/esp-modbus/en/latest/esp32/applications_and_references.html) for more information on how to use library.

I am now getting a gibberish output for my serial request at the Hercules terminal. Since I am getting a timeout error for my set parameter I needed that output to understand what exactly am I doing wrong.

You can use the ModbusPoll software  to debug your request and see the response from slave prior start working with esp32 modbus master. There is the Display communication traffic button. See the documentation for this software for more information.

Hi Kakomis,

Hi @alisitsyn Here is the slave response. I just connected my device to pc with an usb to rs485 driver. slave_log.txt

Sorry, I did not see your response just recently.
The slave log looks good for me. The small update in esp-modus wrapper can be used to communicate with your device.
If the issue still actual please see the answer here on how to implement the command 6 with esp-modbus library.

Hey @alisitsyn
So the required request that I have to send is something of this format 01 04 00 00 00 0A 70 0D, for the mentioned parameter in my code. I am getting a request from my master(esp32)    01 04 00 00 00 01 FA, what am I exactly missing here as there is something I am doing wrong with my CRC.
Can you please help me? I am attaching my communication traffic log and the link to my code below.
https://drive.google.com/drive/folders/1f0SdgaV3sBpndawrGtlOyr54XrxDcphh?usp=share_link
commdata.txt

I am getting a request from my master(esp32) 01 04 00 00 00 01 FA

It is because you still did not change the communication mode as was described recently. You can define the mode to RTU manually in the code:
// Modbus master initialization
static esp_err_t master_init(void)
{
    // Initialize and start Modbus controller
    mb_communication_info_t comm = {
            .port = MB_PORT_NUM,
            .mode = MB_MODE_RTU,
            .baudrate = MB_DEV_SPEED,
            .parity = MB_PARITY_NONE
    };
    void* master_handler = NULL;

    esp_err_t err = mbc_master_init(MB_PORT_SERIAL_MASTER, &master_handler);
    MB_RETURN_ON_FALSE((master_handler != NULL), ESP_ERR_INVALID_STATE, TAG,
..................

Check your port configuration parameters as well.
Your CID_INP_DATA_2 configuration looks ok, but the size of the CID should be 2 registers as below:
const mb_parameter_descriptor_t device_parameters[] = {
    // { CID, Param Name, Units, Modbus Slave Addr, Modbus Reg Type, Reg Start, Reg Size, Instance Offset, Data Type, Data Size, Parameter Options, Access Mode}
    { CID_INP_DATA_2, STR("Voltage 1st Phase"), STR("Volts"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 0, 2,
                    INPUT_OFFSET(input_data2), PARAM_TYPE_FLOAT,  PARAM_SIZE_U32, OPTS( 0, 300, 1 ), PAR_PERMS_READ_TRIGGER },
};

if you do everything correct you should have the master request 01 04 00 00 00 02 71 CB to read two registers from input register address = 0. Then your float value should be equal to<PHONE_NUMBER>38 = 0x4372570a.

Hello @alisitsyn,
So I have made all the changes as suggested and in fact, I am now getting the desired request from my master but then again I am still getting a timeout error and my read is failed.
I have attached all my configurations below.

![Screenshot (9)](https://user-images.githubusercontent.com/77339055/213441383-f975a5bf-b272-4cde-a33c-f5239f159de1.png)
 below please guide me.

Heyy @alisitsyn
So I have made all the configurations as suggested but there are still 2 problems:

So there's a bit of fluctuation in the voltage somewhere between 246V to 250V, And I am receiving values that are nowhere close to these values. There's only one value 242 which is somewhere close to my reading.

I am still getting a set parameter error failure although I have configured the response time from
the slave to react.

I am attaching a few images for your reference—Pl help.

I (540) MASTER_TEST: Error status is 0 I (540) MASTER_TEST: Characteristic #0 Voltage 1st Phase (Volts) value = (0x0000003d) read successful. E (1540) MB_CONTROLLER_MASTER: mbc_master_set_parameter(134): Master set parameter failure, error=(0x107) (ESP_ERR_TIMEOUT). I (2070) MASTER_TEST: Error status is 0 I (2070) MASTER_TEST: Characteristic #0 Voltage 1st Phase (Volts) value = (0x000000a4) read successful. E (3070) MB_CONTROLLER_MASTER: mbc_master_set_parameter(134): Master set parameter failure, error=(0x107) (ESP_ERR_TIMEOUT). I (3600) MASTER_TEST: Error status is 0 I (3600) MASTER_TEST: Characteristic #0 Voltage 1st Phase (Volts) value = (0x000000d7) read successful. E (4600) MB_CONTROLLER_MASTER: mbc_master_set_parameter(134): Master set parameter failure, error=(0x107) (ESP_ERR_TIMEOUT). I (5130) MASTER_TEST: Error status is 0 I (5130) MASTER_TEST: Characteristic #0 Voltage 1st Phase (Volts) value = (0x000000b8) read successful. E (6130) MB_CONTROLLER_MASTER: mbc_master_set_parameter(134): Master set parameter failure, error=(0x107) (ESP_ERR_TIMEOUT). I (6660) MASTER_TEST: Error status is 0 I (6660) MASTER_TEST: Characteristic #0 Voltage 1st Phase (Volts) value = (0x00000066) read successful. E (7660) MB_CONTROLLER_MASTER: mbc_master_set_parameter(134): Master set parameter failure, error=(0x107) (ESP_ERR_TIMEOUT). I (8190) MASTER_TEST: Error status is 0 I (8190) MASTER_TEST: Characteristic #0 Voltage 1st Phase (Volts) value = (0x00000014) read successful. E (9190) MB_CONTROLLER_MASTER: mbc_master_set_parameter(134): Master set parameter failure, error=(0x107) (ESP_ERR_TIMEOUT). I (9720) MASTER_TEST: Error status is 0 I (9720) MASTER_TEST: Characteristic #0 Voltage 1st Phase (Volts) value = (0x000000b8) read successful. E (10720) MB_CONTROLLER_MASTER: mbc_master_set_parameter(134): Master set parameter failure, error=(0x107) (ESP_ERR_TIMEOUT). I (11250) MASTER_TEST: Error status is 0 I (11250) MASTER_TEST: Characteristic #0 Voltage 1st Phase (Volts) value = (0x00000066) read successful.         E (12250) MB_CONTROLLER_MASTER: mbc_master_set_parameter(134): Master set parameter failure, error=(0x107) (ESP_ERR_TIMEOUT). I (12780) MASTER_TEST: Error status is 0 I (12780) MASTER_TEST: Characteristic #0 Voltage 1st Phase (Volts) value = (0x0000005c) read successful.         E (13780) MB_CONTROLLER_MASTER: mbc_master_set_parameter(134): Master set parameter failure, error=(0x107) (ESP_ERR_TIMEOUT). I (14310) MASTER_TEST: Error status is 0 I (14310) MASTER_TEST: Characteristic #0 Voltage 1st Phase (Volts) value = (0x0000008f) read successful.         E (15320) MB_CONTROLLER_MASTER: mbc_master_set_parameter(134): Master set parameter failure, error=(0x107) (ESP_ERR_TIMEOUT). I (15850) MASTER_TEST: Error status is 0 I (15850) MASTER_TEST: Characteristic #0 Voltage 1st Phase (Volts) value = (0x00000052) read successful.         E (16850) MB_CONTROLLER_MASTER: mbc_master_set_parameter(134): Master set parameter failure, error=(0x107) (ESP_ERR_TIMEOUT). I (17380) MASTER_TEST: Error status is 0 I (17380) MASTER_TEST: Characteristic #0 Voltage 1st Phase (Volts) value = (0x000000ae) read successful.         E (18380) MB_CONTROLLER_MASTER: mbc_master_set_parameter(134): Master set parameter failure, error=(0x107) (ESP_ERR_TIMEOUT). I (18910) MASTER_TEST: Error status is 0 I (18910) MASTER_TEST: Characteristic #0 Voltage 1st Phase (Volts) value = (0x00000033) read successful.         E (19910) MB_CONTROLLER_MASTER: mbc_master_set_parameter(134): Master set parameter failure, error=(0x107) (ESP_ERR_TIMEOUT). I (20440) MASTER_TEST: Error status is 0 I (20440) MASTER_TEST: Characteristic #0 Voltage 1st Phase (Volts) value = (0x00000085) read successful.         E (21440) MB_CONTROLLER_MASTER: mbc_master_set_parameter(134): Master set parameter failure, error=(0x107) (ESP_ERR_TIMEOUT). I (21970) MASTER_TEST: Error status is 0 I (21970) MASTER_TEST: Characteristic #0 Voltage 1st Phase (Volts) value = (0x00000071) read successful.         E (22970) MB_CONTROLLER_MASTER: mbc_master_set_parameter(134): Master set parameter failure, error=(0x107) (ESP_ERR_TIMEOUT). I (23500) MASTER_TEST: Error status is 0 I (23500) MASTER_TEST: Characteristic #0 Voltage 1st Phase (Volts) value = (0x000000a4) read successful.         E (24500) MB_CONTROLLER_MASTER: mbc_master_set_parameter(134): Master set parameter failure, error=(0x107) (ESP_ERR_TIMEOUT). I (25030) MASTER_TEST: Error status is 0 I (25030) MASTER_TEST: Characteristic #0 Voltage 1st Phase (Volts) value = (0x00000033) read successful.         E (26030) MB_CONTROLLER_MASTER: mbc_master_set_parameter(134): Master set parameter failure, error=(0x107) (ESP_ERR_TIMEOUT). I (26560) MASTER_TEST: Error status is 0 I (26560) MASTER_TEST: Characteristic #0 Voltage 1st Phase (Volts) value = (0x00000052) read successful.         E (27560) MB_CONTROLLER_MASTER: mbc_master_set_parameter(134): Master set parameter failure, error=(0x107) (ESP_ERR_TIMEOUT). I (28090) MASTER_TEST: Error status is 0 I (28090) MASTER_TEST: Characteristic #0 Voltage 1st Phase (Volts) value = (0x00000071) read successful.         E (29090) MB_CONTROLLER_MASTER: mbc_master_set_parameter(134): Master set parameter failure, error=(0x107) (ESP_ERR_TIMEOUT). I (29620) MASTER_TEST: Error status is 0 I (29620) MASTER_TEST: Characteristic #0 Voltage 1st Phase (Volts) value = (0x000000cd) read successful.         E (30620) MB_CONTROLLER_MASTER: mbc_master_set_parameter(134): Master set parameter failure, error=(0x107) (ESP_ERR_TIMEOUT). I (31150) MASTER_TEST: Error status is 0 I (31150) MASTER_TEST: Characteristic #0 Voltage 1st Phase (Volts) value = (0x0000001f) read successful.         E (32150) MB_CONTROLLER_MASTER: mbc_master_set_parameter(134): Master set parameter failure, error=(0x107) (ESP_ERR_TIMEOUT). I (32680) MASTER_TEST: Error status is 0 I (32680) MASTER_TEST: Characteristic #0 Voltage 1st Phase (Volts) value = (0x000000ec) read successful.         E (33680) MB_CONTROLLER_MASTER: mbc_master_set_parameter(134): Master set parameter failure, error=(0x107) (ESP_ERR_TIMEOUT). I (34210) MASTER_TEST: Error status is 0 I (34210) MASTER_TEST: Characteristic #0 Voltage 1st Phase (Volts) value = (0x0000003d) read successful.         E (35210) MB_CONTROLLER_MASTER: mbc_master_set_parameter(134): Master set parameter failure, error=(0x107) (ESP_ERR_TIMEOUT). I (35740) MASTER_TEST: Error status is 0 I (35740) MASTER_TEST: Characteristic #0 Voltage 1st Phase (Volts) value = (0x0000005c) read successful. E (36740) MB_CONTROLLER_MASTER: mbc_master_set_parameter(134): Master set parameter failure, error=(0x107) (ESP_ERR_TIMEOUT). I (37270) MASTER_TEST: Error status is 0 I (37270) MASTER_TEST: Characteristic #0 Voltage 1st Phase (Volts) value = (0x0000008f) read successful. E (38270) MB_CONTROLLER_MASTER: mbc_master_set_parameter(134): Master set parameter failure, error=(0x107) (ESP_ERR_TIMEOUT). I (38800) MASTER_TEST: Error status is 0 I (38800) MASTER_TEST: Characteristic #0 Voltage 1st Phase (Volts) value = (0x000000f6) read successful. E (39800) MB_CONTROLLER_MASTER: mbc_master_set_parameter(134): Master set parameter failure, error=(0x107) (ESP_ERR_TIMEOUT). I (40330) MASTER_TEST: Error status is 0 I (40330) MASTER_TEST: Characteristic #0 Voltage 1st Phase (Volts) value = (0x000000f6) read successful.         E (41330) MB_CONTROLLER_MASTER: mbc_master_set_parameter(134): Master set parameter failure, error=(0x107) (ESP_ERR_TIMEOUT). I (41860) MASTER_TEST: Error status is 0 I (41860) MASTER_TEST: Characteristic #0 Voltage 1st Phase (Volts) value = (0x00000033) read successful. E (42860) MB_CONTROLLER_MASTER: mbc_master_set_parameter(134): Master set parameter failure, error=(0x107) (ESP_ERR_TIMEOUT). I (43390) MASTER_TEST: Error status is 0 I (43390) MASTER_TEST: Characteristic #0 Voltage 1st Phase (Volts) value = (0x000000c3) read successful. E (44390) MB_CONTROLLER_MASTER: mbc_master_set_parameter(134): Master set parameter failure, error=(0x107) (ESP_ERR_TIMEOUT). I (44920) MASTER_TEST: Error status is 0 I (44920) MASTER_TEST: Characteristic #0 Voltage 1st Phase (Volts) value = (0x000000d7) read successful.         E (45920) MB_CONTROLLER_MASTER: mbc_master_set_parameter(134): Master set parameter failure, error=(0x107) (ESP_ERR_TIMEOUT). I (46450) MASTER_TEST: Error status is 0 I (46450) MASTER_TEST: Characteristic #0 Voltage 1st Phase (Volts) value = (0x000000d7) read successful.         E (47450) MB_CONTROLLER_MASTER: mbc_master_set_parameter(134): Master set parameter failure, error=(0x107) (ESP_ERR_TIMEOUT). E (47950) MASTER_TEST: Alarm is not triggered after 30 retries. I (47950) MASTER_TEST: Destroy master...

Heyy @alisitsyn
Thank you for your help. I was able to clear out my set parameter error. But I am still getting an integer output in the form of hexadecimal at my terminal. How can I get these values from my get parameter in the form of float up to 2 decimals?
Can you please help me with that?
`// User operation function to read slave values and check alarm
static void master_operation_func(void arg)
{
esp_err_t err = ESP_OK;
float value = 0;
bool alarm_state = false;
const mb_parameter_descriptor_t param_descriptor = NULL;
ESP_LOGI(TAG, "Start modbus test..");

for(uint16_t retry = 0; retry <= MASTER_MAX_RETRY && (!alarm_state); retry++) {
    // Read all found characteristics from slave(s)
    for (uint16_t cid = 0; (err != ESP_ERR_NOT_FOUND) && cid < MASTER_MAX_CIDS; cid++)
    {
        // Get data from parameters description table
        // and use this information to fill the characteristics description table
        // and having all required fields in just one table
        err = mbc_master_get_cid_info(cid, &param_descriptor);
        ///Print error status
        if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) {
            void* temp_data_ptr = master_get_param_data(param_descriptor);
            assert(temp_data_ptr);
            uint8_t type = 0;
            if ((param_descriptor->param_type == PARAM_TYPE_FLOAT) &&
                    (param_descriptor->cid == CID_INP_DATA_2)) {
               // Check for long array of registers of type PARAM_TYPE_FLOAT
                err = mbc_master_get_parameter(cid, (char*)param_descriptor->param_key,
                                                                        (uint8_t*)temp_data_ptr, &type);
                ESP_LOGI(TAG, "Error status is %u", err);
                if (err == ESP_OK) {
                    ESP_LOGI(TAG, "Characteristic #%d %s (%s) value = (0x%08x) read successful.",
                                             param_descriptor->cid,
                                             (char*)param_descriptor->param_key,
                                             (char*)param_descriptor->param_units,
                                             *(uint8_t*)temp_data_ptr);
                                             // Initialize data of test array and write to slave

                } else {
                    ESP_LOGE(TAG, "Characteristic #%d (%s) read fail_2, err = 0x%x (%s).",
                                            param_descriptor->cid,
                                            (char*)param_descriptor->param_key,
                                            (int)err,
                                            (char*)esp_err_to_name(err));
                }

            } else {
                    err = mbc_master_get_parameter(cid, (char*)param_descriptor->param_key,
                                                    (uint8_t*)&value, &type);
                if (err == ESP_OK) {
                    *(float*)temp_data_ptr = value;
                    if ((param_descriptor->mb_param_type == MB_PARAM_HOLDING) ||
                        (param_descriptor->mb_param_type == MB_PARAM_INPUT)) {
                        ESP_LOGI(TAG, "Characteristic #%d %s (%s) value = %f (0x%x) read successful.",
                                        param_descriptor->cid,
                                        (char*)param_descriptor->param_key,
                                        (char*)param_descriptor->param_units,
                                        value,
                                        *(uint32_t*)temp_data_ptr);
                        if (((value > param_descriptor->param_opts.max) ||
                            (value < param_descriptor->param_opts.min))) {
                                alarm_state = true;
                                break;
                        }
                    }
                } else {
                    ESP_LOGE(TAG, "Characteristic #%d (%s) read fail_3, err = 0x%x (%s).",
                                        param_descriptor->cid,
                                        (char*)param_descriptor->param_key,
                                        (int)err,
                                        (char*)esp_err_to_name(err));
                }
            }
            vTaskDelay(POLL_TIMEOUT_TICS); // timeout between polls
        }
    }
    vTaskDelay(UPDATE_CIDS_TIMEOUT_TICS); //
}`

My get_parameter is defined as
`/**

@brief Read parameter from modbus slave device whose name is defined by name and has cid.

   The additional data for request is taken from parameter description (lookup) table.

@param[in] cid id of the characteristic for parameter
@param[in] name pointer into string name (key) of parameter (null terminated)
@param[out] value pointer to data buffer of parameter
@param[out] type parameter type associated with the name returned from parameter description table.

@return

- esp_err_t ESP_OK - request was successful and value buffer contains

                     representation of actual parameter data from slave

- esp_err_t ESP_ERR_INVALID_ARG - invalid argument of function or parameter descriptor

- esp_err_t ESP_ERR_INVALID_RESPONSE - an invalid response from slave

- esp_err_t ESP_ERR_INVALID_STATE - invalid state during data processing or allocation failure

- esp_err_t ESP_ERR_TIMEOUT - operation timed out and no response from slave

- esp_err_t ESP_ERR_NOT_SUPPORTED - the request command is not supported by slave

- esp_err_t ESP_ERR_NOT_FOUND - the parameter is not found in the parameter description table

- esp_err_t ESP_FAIL - slave returned an exception or other failure

/
esp_err_t mbc_master_get_parameter(uint16_t cid, char name, uint8_t* value, uint8_t *type);`
Can you please have a look and guide me ?

I want to read the 1st phase voltage from my select MFM384-r-c energy meter and the datasheet mentions that my voltage of 1st phase is input type register hex address starting from 0X00, float type.
MFM384-R-C_Instruction_Manual.pdf

Thankyou @alisitsyn
I am now able to get the desired output from my slave. However, while requesting multiple parameters I am always facing a timeout error with my 2, 4, and even request. Whichever CID I put on an even position gives me a timeout error.
Can you help me with why this is happening and how should I resolve it?
Thankyou
`// Enumeration of all supported CIDs for device (used in parameter definition table)
enum {
CID_INP_DATA_0=0,
CID_INP_DATA_1,

CID_INP_DATA_2,
CID_HOLD_DATA_0,

CID_HOLD_TEST_REG,
CID_RELAY_P1,
CID_RELAY_P2,
CID_COUNT

};
// Example Data (Object) Dictionary for Modbus parameters:
// The CID field in the table must be unique.
// Modbus Slave Addr field defines slave address of the device with correspond parameter.
// Modbus Reg Type - Type of Modbus register area (Holding register, Input Register and such).
// Reg Start field defines the start Modbus register number and Reg Size defines the number of registers for the characteristic accordingly.
// The Instance Offset defines offset in the appropriate parameter structure that will be used as instance to save parameter value.
// Data Type, Data Size specify type of the characteristic and its data size.
// Parameter Options field specifies the options that can be used to process parameter value (limits or masks).
// Access Mode - can be used to implement custom options for processing of characteristic (Read/Write restrictions, factory mode values and etc).
const mb_parameter_descriptor_t device_parameters[] = {
// { CID, Param Name, Units, Modbus Slave Addr, Modbus Reg Type, Reg Start, Reg Size, Instance Offset, Data Type, Data Size, Parameter Options, Access Mode}
{ CID_INP_DATA_0, STR("Voltage 1st Phase"), STR("Volts"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 0, 2,
INPUT_OFFSET(input_data0), PARAM_TYPE_FLOAT,  PARAM_SIZE_U8, OPTS( 0, 300, 1 ), PAR_PERMS_READ_TRIGGER },
{ CID_INP_DATA_1, STR("Voltage 2nd Phase"), STR("Volts"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 2, 2,
                INPUT_OFFSET(input_data1), PARAM_TYPE_FLOAT,  PARAM_SIZE_U8, OPTS( 0, 300, 1 ), PAR_PERMS_READ_TRIGGER },

{ CID_INP_DATA_2, STR("Voltage 3rd Phase"), STR("Volts"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 4, 2,
                INPUT_OFFSET(input_data2), PARAM_TYPE_FLOAT,  PARAM_SIZE_U8, OPTS( 0, 300, 1 ), PAR_PERMS_READ_TRIGGER },

{ CID_HOLD_DATA_0, STR("CT Secondary"), STR("Ampere"), MB_DEVICE_ADDR1, MB_PARAM_HOLDING, 2, 2,
                HOLD_OFFSET(holding_data1), PARAM_TYPE_FLOAT,  PARAM_SIZE_U8, OPTS( 0, 5, 1 ), PAR_PERMS_READ_TRIGGER }

};
// Calculate number of parameters in the table
const uint16_t num_device_parameters = (sizeof(device_parameters)/sizeof(device_parameters[0]));
// The function to get pointer to parameter storage (instance) according to parameter description table
static void* master_get_param_data(const mb_parameter_descriptor_t* param_descriptor)
{
assert(param_descriptor != NULL);
void* instance_ptr = NULL;
if (param_descriptor->param_offset != 0) {
switch(param_descriptor->mb_param_type)
{
case MB_PARAM_HOLDING:
instance_ptr = ((void*)&holding_reg_params + param_descriptor->param_offset - 1);
break;
case MB_PARAM_INPUT:
instance_ptr = ((void*)&input_reg_params + param_descriptor->param_offset - 1);
break;
case MB_PARAM_COIL:
instance_ptr = ((void*)&coil_reg_params + param_descriptor->param_offset - 1);
break;
case MB_PARAM_DISCRETE:
instance_ptr = ((void*)&discrete_reg_params + param_descriptor->param_offset - 1);
break;
default:
instance_ptr = NULL;
break;
}
} else {
ESP_LOGE(TAG, "Wrong parameter offset for CID #%d", param_descriptor->cid);
assert(instance_ptr != NULL);
}
return instance_ptr;
}
// User operation function to read slave values and check alarm
static void master_operation_func(void arg)
{
esp_err_t err = ESP_OK;
float value = 0;
bool alarm_state = false;
const mb_parameter_descriptor_t param_descriptor = NULL;
ESP_LOGI(TAG, "Start modbus test..");

for(uint16_t retry = 0; retry <= MASTER_MAX_RETRY && (!alarm_state); retry++) {
    // Read all found characteristics from slave(s)
    for (uint16_t cid = 0; (err != ESP_ERR_NOT_FOUND) && cid < MASTER_MAX_CIDS; cid++)
    {
        // Get data from parameters description table
        // and use this information to fill the characteristics description table
        // and having all required fields in just one table
        err = mbc_master_get_cid_info(cid, &param_descriptor);
        ///Print error status
        if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) {
            void* temp_data_ptr = master_get_param_data(param_descriptor);
            assert(temp_data_ptr);
            uint8_t type = 0;
            if ((param_descriptor->param_type == PARAM_TYPE_FLOAT) &&
                    (param_descriptor->cid == CID_INP_DATA_0)) {
               // Check for long array of registers of type PARAM_TYPE_FLOAT
                err = mbc_master_get_parameter(cid, (char*)param_descriptor->param_key,
                                                                        (uint8_t*)temp_data_ptr, &type);
                if (err == ESP_OK) {
                    ESP_LOGI(TAG, "Characteristic #%d %s (%s) value = %f read successful.",
                                             param_descriptor->cid,
                                             (char*)param_descriptor->param_key,
                                             (char*)param_descriptor->param_units,
                                             *(float*)temp_data_ptr);
                                        } else {
                                            ESP_LOGE(TAG, "Characteristic #%d (%s) read fail_2, err = 0x%x (%s).",
                                            param_descriptor->cid,
                                            (char*)param_descriptor->param_key,
                                            (int)err,
                                            (char*)esp_err_to_name(err));
                                             }

            } else {
                    err = mbc_master_get_parameter(cid, (char*)param_descriptor->param_key,
                                                    (uint8_t*)&value, &type);
                if (err == ESP_OK) {
                    *(float*)temp_data_ptr = value;
                    if ((param_descriptor->mb_param_type == MB_PARAM_HOLDING) ||
                        (param_descriptor->mb_param_type == MB_PARAM_INPUT)) {
                        ESP_LOGI(TAG, "Characteristic #%d %s (%s) value = %f read successful.",
                                        param_descriptor->cid,
                                        (char*)param_descriptor->param_key,
                                        (char*)param_descriptor->param_units,
                                        value,
                                        *(uint32_t*)temp_data_ptr);
                        if (((value > param_descriptor->param_opts.max) ||
                            (value < param_descriptor->param_opts.min))) {
                                alarm_state = true;
                                break;
                        }
                    }
                } else {
                    ESP_LOGE(TAG, "Characteristic #%d (%s) read fail_3, err = 0x%x (%s).",
                                        param_descriptor->cid,
                                        (char*)param_descriptor->param_key,
                                        (int)err,
                                        (char*)esp_err_to_name(err));
                }
            }
            vTaskDelay(POLL_TIMEOUT_TICS); // timeout between polls
        }
    }
    vTaskDelay(UPDATE_CIDS_TIMEOUT_TICS); //
}

if (alarm_state) {
    ESP_LOGI(TAG, "Alarm triggered by cid #%d.",
                                    param_descriptor->cid);
} else {
    ESP_LOGE(TAG, "Alarm is not triggered after %d retries.",
                                    MASTER_MAX_RETRY);
}
ESP_LOGI(TAG, "Destroy master...");
ESP_ERROR_CHECK(mbc_master_destroy());

}
// Modbus master initialization
static esp_err_t master_init(void){
// Initialize and start Modbus controller
mb_communication_info_t comm = {
.port = MB_PORT_NUM,
.mode = MB_MODE_RTU, // <<<<<<<<<<<<<<<<<<<<<<<<<< RTU is here
.baudrate = MB_DEV_SPEED,
.parity = MB_PARITY_NONE,
};
void* master_handler = NULL;
esp_err_t err = mbc_master_init(MB_PORT_SERIAL_MASTER, &master_handler);
MB_RETURN_ON_FALSE((master_handler != NULL), ESP_ERR_INVALID_STATE, TAG,
                            "mb controller initialization fail.");
MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG,
                        "mb controller initialization fail, returns(0x%x).",
                        (uint32_t)err);
err = mbc_master_setup((void*)&comm);
MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG,
                        "mb controller setup fail, returns(0x%x).",
                        (uint32_t)err);

// Set UART pin numbers
err = uart_set_pin(MB_PORT_NUM, CONFIG_MB_UART_TXD, CONFIG_MB_UART_RXD,
                          CONFIG_MB_UART_RTS, UART_PIN_NO_CHANGE);
MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG,
        "mb serial set pin failure, uart_set_pin() returned (0x%x).", (uint32_t)err);

err = mbc_master_start();
MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG,
                        "mb controller start fail, returns(0x%x).",
                        (uint32_t)err);

// Set driver mode to Half Duplex
err = uart_set_mode(MB_PORT_NUM, UART_MODE_RS485_HALF_DUPLEX);
MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG,
        "mb serial set mode failure, uart_set_mode() returned (0x%x).", (uint32_t)err);

vTaskDelay(5);
err = mbc_master_set_descriptor(&device_parameters[0], num_device_parameters);
MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG,
                            "mb controller set descriptor fail, returns(0x%x).",
                            (uint32_t)err);
ESP_LOGI(TAG, "Modbus master stack initialized");
return err;

}
void app_main(void)
{
// Initialization of device peripheral and objects
ESP_ERROR_CHECK(master_init());
vTaskDelay(10);
master_operation_func(NULL);

}`
My response at the terminal is as Follow
I (410) MASTER_TEST: Modbus master stack initialized I (510) MASTER_TEST: Start modbus test.. I (570) MASTER_TEST: Characteristic #0 Voltage 1st Phase (Volts) value = 241.479996 read successful. E (1570) MB_CONTROLLER_MASTER: mbc_master_get_parameter(73): Master get parameter failure, error=(0x107) (ESP_ERR_TIMEOUT). E (1570) MASTER_TEST: Characteristic #1 (Voltage 2nd Phase) read fail_3, err = 0x107 (ESP_ERR_TIMEOUT). I (1610) MASTER_TEST: Characteristic #2 Voltage 3rd Phase (Volts) value = 241.339996 read successful. E (2610) MB_CONTROLLER_MASTER: mbc_master_get_parameter(73): Master get parameter failure, error=(0x107) (ESP_ERR_TIMEOUT). E (2620) MASTER_TEST: Characteristic #3 (CT Secondary) read fail_3, err = 0x107 (ESP_ERR_TIMEOUT).

@alisitsyn Any updates ??

Hey @alisitsyn I need one more help from you. I am only able to read around 8 parameters from the input type register although I am defining more  float input_data8; in the input structure, it is still giving me an invalid argument error.
Can you explain why is this happing ?? here my code
`// The macro to get offset for parameter in the appropriate structure
#define HOLD_OFFSET(field) ((uint16_t)(offsetof(holding_reg_params_t, field) + 1))
#define INPUT_OFFSET(field) ((uint16_t)(offsetof(input_reg_params_t, field) + 1))
#define COIL_OFFSET(field) ((uint16_t)(offsetof(coil_reg_params_t, field) + 1))
// Discrete offset macro
#define DISCR_OFFSET(field) ((uint16_t)(offsetof(discrete_reg_params_t, field) + 1))
#define STR(fieldname) ((const char*)( fieldname ))
// Options can be used as bit masks or parameter limits
#define OPTS(min_val, max_val, step_val) { .opt1 = min_val, .opt2 = max_val, .opt3 = step_val }
static const char *TAG = "MASTER_TEST";
// Enumeration of modbus device addresses accessed by master device
enum {
MB_DEVICE_ADDR1 = 1 // Only one slave device used for the test (add other slave addresses here)
};
// Enumeration of all supported CIDs for device (used in parameter definition table)
enum {
CID_HOLDING_1=0,
CID_INP_DATA_0,
CID_INP_DATA_1,
CID_INP_DATA_2,
CID_INP_DATA_3,
CID_INP_DATA_4,
CID_INP_DATA_5,
CID_INP_DATA_6,
CID_INP_DATA_7,
CID_INP_DATA_8,
};
// Example Data (Object) Dictionary for Modbus parameters:
// The CID field in the table must be unique.
// Modbus Slave Addr field defines slave address of the device with correspond parameter.
// Modbus Reg Type - Type of Modbus register area (Holding register, Input Register and such).
// Reg Start field defines the start Modbus register number and Reg Size defines the number of registers for the characteristic accordingly.
// The Instance Offset defines offset in the appropriate parameter structure that will be used as instance to save parameter value.
// Data Type, Data Size specify type of the characteristic and its data size.
// Parameter Options field specifies the options that can be used to process parameter value (limits or masks).
// Access Mode - can be used to implement custom options for processing of characteristic (Read/Write restrictions, factory mode values and etc).
const mb_parameter_descriptor_t device_parameters[] = {
// { CID, Param Name, Units, Modbus Slave Addr, Modbus Reg Type, Reg Start, Reg Size, Instance Offset, Data Type, Data Size, Parameter Options, Access Mode}
{ CID_HOLDING_1, STR("Bauderate"), STR("bps"), MB_DEVICE_ADDR1, MB_PARAM_HOLDING, 8, 1,
HOLD_OFFSET(holding_data0), PARAM_TYPE_FLOAT,  PARAM_SIZE_U8, OPTS( 0, 10, 1 ), PAR_PERMS_READ_TRIGGER },
{ CID_INP_DATA_0, STR("Voltage 1st Phase"), STR("Volts"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 0, 2,
                INPUT_OFFSET(input_data0), PARAM_TYPE_FLOAT,  PARAM_SIZE_U8, OPTS( 0, 300, 1 ), PAR_PERMS_READ_TRIGGER },

{ CID_INP_DATA_1, STR("Voltage 2nd Phase"), STR("Volts"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 2, 2,
                INPUT_OFFSET(input_data1), PARAM_TYPE_FLOAT,  PARAM_SIZE_U8, OPTS( 0, 300, 1 ), PAR_PERMS_READ_TRIGGER },

{ CID_INP_DATA_2, STR("Voltage 3rd Phase"), STR("Volts"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 4, 2,
                INPUT_OFFSET(input_data2), PARAM_TYPE_FLOAT,  PARAM_SIZE_U8, OPTS( 0, 300, 1 ), PAR_PERMS_READ_TRIGGER },

{ CID_INP_DATA_3, STR("Average Voltage LN"), STR("Volts"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 6, 2,
                INPUT_OFFSET(input_data3), PARAM_TYPE_FLOAT,  PARAM_SIZE_U8, OPTS( 0, 300, 1 ), PAR_PERMS_READ_TRIGGER },

{ CID_INP_DATA_4, STR("Voltage 12"), STR("Volts"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 8, 2,
                INPUT_OFFSET(input_data4), PARAM_TYPE_FLOAT,  PARAM_SIZE_U8, OPTS( 0, 300, 1 ), PAR_PERMS_READ_TRIGGER },

{ CID_INP_DATA_5, STR("Voltage 23"), STR("Volts"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 10, 2,
                INPUT_OFFSET(input_data5), PARAM_TYPE_FLOAT,  PARAM_SIZE_U8, OPTS( 0, 300, 1 ), PAR_PERMS_READ_TRIGGER },

{ CID_INP_DATA_6, STR("Voltage 31"), STR("Volts"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 12, 2,
                INPUT_OFFSET(input_data6), PARAM_TYPE_FLOAT,  PARAM_SIZE_U8, OPTS( 0, 300, 1 ), PAR_PERMS_READ_TRIGGER },

{ CID_INP_DATA_7, STR("Avg. Voltage LL "), STR("Volts"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 14, 2,
                INPUT_OFFSET(input_data7), PARAM_TYPE_FLOAT,  PARAM_SIZE_U8, OPTS( 0, 300, 1 ), PAR_PERMS_READ_TRIGGER },

{ CID_INP_DATA_8, STR("Average Current"), STR("A"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 22, 2,
                INPUT_OFFSET(input_data8), PARAM_TYPE_FLOAT,  PARAM_SIZE_U8, OPTS( 0, 300, 1 ), PAR_PERMS_READ_TRIGGER },

};`
The changes I have made are in the input_reg_params_t of the line #define INPUT_OFFSET(field) ((uint16_t)(offsetof(input_reg_params_t, field) + 1))
This is the structure of input type register
#pragma pack(push, 1) typedef struct {     uint8_t discrete_input0:1;     uint8_t discrete_input1:1;     uint8_t discrete_input2:1;     uint8_t discrete_input3:1;     uint8_t discrete_input4:1;     uint8_t discrete_input5:1;     uint8_t discrete_input6:1;     uint8_t discrete_input7:1;     uint8_t discrete_input_port1:8; } discrete_reg_params_t; #pragma pack(pop)
I am not able to build code and I am getting a error of something like this
`C:/Users/Admin/Master_Comm/main/master.c:104:34: error: 'input_reg_params_t' has no member named 'input_data8'; did you mean 'input_data0'?
104 |                     INPUT_OFFSET(input_data8), PARAM_TYPE_FLOAT,  PARAM_SIZE_U8, OPTS( 0, 300, 1 ), PAR_PERMS_READ_TRIGGER },
|                                  ^~~~~~~~~~~
C:/Users/Admin/Master_Comm/main/master.c:104:21: note: in expansion of macro 'INPUT_OFFSET'
104 |                     INPUT_OFFSET(input_data8), PARAM_TYPE_FLOAT,  PARAM_SIZE_U8, OPTS( 0, 300, 1 ), PAR_PERMS_READ_TRIGGER },
|                     ^~~~~~~~~~~~
ninja: build stopped: subcommand failed.

The terminal process "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -Command ninja " terminated with exit code: 1.
`

Can you please help me @alisitsyn

Hey @alisitsyn I need one more help from you. I am only able to read around 8 parameters from the input type register although I am defining more  float input_data8; in the input structure, it is still giving me an invalid argument error.
Can you explain why is this happing ?? here is my code
// The macro to get offset for parameter in the appropriate structure
#define HOLD_OFFSET(field) ((uint16_t)(offsetof(holding_reg_params_t, field) + 1))
#define INPUT_OFFSET(field) ((uint16_t)(offsetof(input_reg_params_t, field) + 1))
#define COIL_OFFSET(field) ((uint16_t)(offsetof(coil_reg_params_t, field) + 1))
// Discrete offset macro
#define DISCR_OFFSET(field) ((uint16_t)(offsetof(discrete_reg_params_t, field) + 1))

#define STR(fieldname) ((const char*)( fieldname ))
// Options can be used as bit masks or parameter limits
#define OPTS(min_val, max_val, step_val) { .opt1 = min_val, .opt2 = max_val, .opt3 = step_val }

static const char *TAG = "MASTER_TEST";

// Enumeration of modbus device addresses accessed by master device
enum {
    MB_DEVICE_ADDR1 = 1 // Only one slave device used for the test (add other slave addresses here)
};

// Enumeration of all supported CIDs for device (used in parameter definition table)
enum {
    CID_HOLDING_1=0,
    CID_INP_DATA_0,
    CID_INP_DATA_1,
    CID_INP_DATA_2,
    CID_INP_DATA_3,
    CID_INP_DATA_4,
    CID_INP_DATA_5,
    CID_INP_DATA_6,
    CID_INP_DATA_7,
    CID_INP_DATA_8,
};

// Example Data (Object) Dictionary for Modbus parameters:
// The CID field in the table must be unique.
// Modbus Slave Addr field defines slave address of the device with correspond parameter.
// Modbus Reg Type - Type of Modbus register area (Holding register, Input Register and such).
// Reg Start field defines the start Modbus register number and Reg Size defines the number of registers for the characteristic accordingly.
// The Instance Offset defines offset in the appropriate parameter structure that will be used as instance to save parameter value.
// Data Type, Data Size specify type of the characteristic and its data size.
// Parameter Options field specifies the options that can be used to process parameter value (limits or masks).
// Access Mode - can be used to implement custom options for processing of characteristic (Read/Write restrictions, factory mode values and etc).
const mb_parameter_descriptor_t device_parameters[] = {
    // { CID, Param Name, Units, Modbus Slave Addr, Modbus Reg Type, Reg Start, Reg Size, Instance Offset, Data Type, Data Size, Parameter Options, Access Mode}
    { CID_HOLDING_1, STR("Bauderate"), STR("bps"), MB_DEVICE_ADDR1, MB_PARAM_HOLDING, 8, 1,
                    HOLD_OFFSET(holding_data0), PARAM_TYPE_FLOAT,  PARAM_SIZE_U8, OPTS( 0, 10, 1 ), PAR_PERMS_READ_TRIGGER },

    { CID_INP_DATA_0, STR("Voltage 1st Phase"), STR("Volts"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 0, 2,
                    INPUT_OFFSET(input_data0), PARAM_TYPE_FLOAT,  PARAM_SIZE_U8, OPTS( 0, 300, 1 ), PAR_PERMS_READ_TRIGGER },

    { CID_INP_DATA_1, STR("Voltage 2nd Phase"), STR("Volts"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 2, 2,
                    INPUT_OFFSET(input_data1), PARAM_TYPE_FLOAT,  PARAM_SIZE_U8, OPTS( 0, 300, 1 ), PAR_PERMS_READ_TRIGGER },

    { CID_INP_DATA_2, STR("Voltage 3rd Phase"), STR("Volts"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 4, 2,
                    INPUT_OFFSET(input_data2), PARAM_TYPE_FLOAT,  PARAM_SIZE_U8, OPTS( 0, 300, 1 ), PAR_PERMS_READ_TRIGGER },

    { CID_INP_DATA_3, STR("Average Voltage LN"), STR("Volts"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 6, 2,
                    INPUT_OFFSET(input_data3), PARAM_TYPE_FLOAT,  PARAM_SIZE_U8, OPTS( 0, 300, 1 ), PAR_PERMS_READ_TRIGGER },

    { CID_INP_DATA_4, STR("Voltage 12"), STR("Volts"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 8, 2,
                    INPUT_OFFSET(input_data4), PARAM_TYPE_FLOAT,  PARAM_SIZE_U8, OPTS( 0, 300, 1 ), PAR_PERMS_READ_TRIGGER },

    { CID_INP_DATA_5, STR("Voltage 23"), STR("Volts"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 10, 2,
                    INPUT_OFFSET(input_data5), PARAM_TYPE_FLOAT,  PARAM_SIZE_U8, OPTS( 0, 300, 1 ), PAR_PERMS_READ_TRIGGER },

    { CID_INP_DATA_6, STR("Voltage 31"), STR("Volts"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 12, 2,
                    INPUT_OFFSET(input_data6), PARAM_TYPE_FLOAT,  PARAM_SIZE_U8, OPTS( 0, 300, 1 ), PAR_PERMS_READ_TRIGGER },

    { CID_INP_DATA_7, STR("Avg. Voltage LL "), STR("Volts"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 14, 2,
                    INPUT_OFFSET(input_data7), PARAM_TYPE_FLOAT,  PARAM_SIZE_U8, OPTS( 0, 300, 1 ), PAR_PERMS_READ_TRIGGER },

    { CID_INP_DATA_8, STR("Average Current"), STR("A"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 22, 2,
                    INPUT_OFFSET(input_data8), PARAM_TYPE_FLOAT,  PARAM_SIZE_U8, OPTS( 0, 300, 1 ), PAR_PERMS_READ_TRIGGER },
};

The changes I have made are in the input_reg_params_t of the line #define INPUT_OFFSET(field) ((uint16_t)(offsetof(input_reg_params_t, field) + 1))
This is the structure of input type register
#pragma pack(push, 1)
typedef struct
{
    float input_data0; // 0
    float input_data1; // 2
    float input_data2; // 4
    float input_data3; // 6
    uint16_t data[150]; // 8 + 150 = 158
    float input_data4; // 158
    float input_data5;
    float input_data6;
    float input_data7;
    float input_data8;
    uint16_t data_block1[150];
} input_reg_params_t;
#pragma pack(pop)

I am not able to build code and I am getting a error of something like this
C:/Users/Admin/Master_Comm/main/master.c:104:34: error: 'input_reg_params_t' has no member named 'input_data8'; did you mean 'input_data0'?
  104 |                     INPUT_OFFSET(input_data8), PARAM_TYPE_FLOAT,  PARAM_SIZE_U8, OPTS( 0, 300, 1 ), PAR_PERMS_READ_TRIGGER },
      |                                  ^~~~~~~~~~~
C:/Users/Admin/Master_Comm/main/master.c:104:21: note: in expansion of macro 'INPUT_OFFSET'
  104 |                     INPUT_OFFSET(input_data8), PARAM_TYPE_FLOAT,  PARAM_SIZE_U8, OPTS( 0, 300, 1 ), PAR_PERMS_READ_TRIGGER },
      |                     ^~~~~~~~~~~~
ninja: build stopped: subcommand failed.

 *  The terminal process "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -Command ninja " terminated with exit code: 1.

@VaibhavSingh9511,
Please make attention to below aspects:

All the float parameters reflect the input registers with the float type but in your data dictionary the parameter size field is initialized incorrectly.

{ CID_INP_DATA_3, STR("Average Voltage LN"), STR("Volts"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 6, 2,
                    INPUT_OFFSET(input_data3), PARAM_TYPE_FLOAT,  PARAM_SIZE_U8 /* the error is here*/ , OPTS( 0, 300, 1 ), PAR_PERMS_READ_TRIGGER },

For each parameter of PARAM_TYPE_FLOAT the size should be initialized accordingly = PARAM_SIZE_FLOAT or PARAM_SIZE_U32 = 4 bytes.

The compilation error says that it does not find the  appropriate field in the parameter structure. Please make sure you do the changes of the parameter structure in the correct place. In the regular examples the parameters structure is defined in the modbus  example common component which is shared between all the examples. Use idf.py fullclean; idf.py build; commands after your changes to make sure the code reflected the changes in the common components.

Heyy @alisitsyn

Please make sure you do the changes of the parameter structure in the correct place. In the regular examples the parameters structure is defined in the modbus example common component which is shared between all the examples.

So I am making changes in the modbus_params.h file
After using idf.py fullclean; idf.py build; commands it's still giving me a error
C:/Users/Admin/Master_Comm/main/master.c:128:34: error: 'input_reg_params_t' has no member named 'input_data8'; did you mean 'input_data0'?
  128 |                     INPUT_OFFSET(input_data8), PARAM_TYPE_FLOAT,  PARAM_SIZE_FLOAT, OPTS( 0, 300, 1 ), PAR_PERMS_READ_TRIGGER },

@VaibhavSingh9511,
Where is the modbus_params.h defined in your project? The problem is the compiler do not find the where the changed  include file is. Please take a look to this line in the cmake file which define the location of the parameters structure. Please send the whole project here as a zip file.

@alisitsyn

Where is the modbus_params.h defined in your project? it's in this path C:\Users\Admin\Master_Comm\managed_components\espressif__esp-modbus\test\mb_example_common\include

I am attaching the link for my whole project. Please have a look
https://drive.google.com/drive/folders/1f0SdgaV3sBpndawrGtlOyr54XrxDcphh?usp=share_link

Please follow the steps below:

Rename your component folder managed_components to components.
Change your  CMakeLists.txt file as below:

# The following lines of boilerplate have to be in your project's CMakeLists
# in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)

#set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/protocols/modbus/mb_example_common)

# Include parameters from common modbus folder
set(MB_PARAMS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/components/espressif__esp-modbus/test/mb_example_common")
list(APPEND EXTRA_COMPONENT_DIRS "${MB_PARAMS_DIR}")

include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(Master_Comm)

Recompile your project using idf.py fullclean; idf.py build.
The project is able to be compiled correctly.

Hello @alisitsyn, Thank you for your response earlier. I got a response for all 27 parameters described in the character dictionary. However, I am still finding an issue with completely understanding the working of this example. like if we look in main .c  or operational function that sends the request and gets the data:
for (uint16_t cid = 0; (err != ESP_ERR_NOT_FOUND) && cid < MASTER_MAX_CIDS; cid++)
        {
            // Get data from parameters description table
            // and use this information to fill the characteristics description table
            // and having all required fields in just one table
            err = mbc_master_get_cid_info(cid, &param_descriptor);
            /// Print error status
            if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL))
            {
                void* temp_data_ptr = master_get_param_data(param_descriptor);
                assert(temp_data_ptr);
                uint8_t type = 0;
                if ((param_descriptor->param_type == PARAM_TYPE_FLOAT) &&
                    (param_descriptor->cid == CID_HOLDING_1))
                {
                    // Check for long array of registers of type PARAM_TYPE_FLOAT
                    err = mbc_master_get_parameter(cid, (char*)param_descriptor->param_key,
                                                   (uint8_t*)temp_data_ptr, &type);

                    if (err == ESP_OK)
                    {
                        ESP_LOGI(TAG, "Characteristic #%d %s (%s) value = (0x%08x) read successful.",
                                 param_descriptor->cid,
                                 (char*)param_descriptor->param_key,
                                 (char*)param_descriptor->param_units,
                                 *(uint32_t*)temp_data_ptr);

                    }
                    else
                    {
                        ESP_LOGE(TAG, "Characteristic #%d (%s) read fail_2, err = 0x%x (%s).",
                                 param_descriptor->cid,
                                 (char*)param_descriptor->param_key,
                                 (int)err,
                                 (char*)esp_err_to_name(err));

It's quite obvious that the mbc_master_get_parameter function sends the request on RS 485 and gets the readings from the slave and prints it in logI below. I guess this whole function is responsible for sending requests and receiving the data over RS 485 communication. So if we look closer into this function in   esp_modbus_master.c we get:
/**
 * Get parameter data for corresponding characteristic
 */
esp_err_t mbc_master_get_parameter(uint16_t cid, char* name, uint8_t* value, uint8_t* type)
{
    esp_err_t error = ESP_OK;
    MB_MASTER_CHECK((master_interface_ptr != NULL),
                    ESP_ERR_INVALID_STATE,
                    "Master interface is not correctly initialized.");

    MB_MASTER_CHECK((master_interface_ptr->get_parameter != NULL),
                    ESP_ERR_INVALID_STATE,
                    "Master interface is not correctly initialized.");

    error = master_interface_ptr->get_parameter(cid, name, value, type);

    MB_MASTER_CHECK((error == ESP_OK),
                    error,
                    "Master get parameter failure, error=(0x%x) (%s).",
                    error, esp_err_to_name(error));
    return error;
}

Here the master is able to send a request after  **error = master_interface_ptr->get_parameter(cid, name, value, type);**
is executed. The get_parameter function is defined as
iface_get_parameter get_parameter;      /*!< Interface get_parameter method */
and typedef esp_err_t (*iface_get_parameter)(uint16_t, char*, uint8_t*, uint8_t*);        /*!< Interface get_parameter method */
What I am unable to understand is how and when exactly the master sends a request and when is it receiving data and storing it in a buffer. As my ultimate goal is to send one request to the slave and receive multiple responses
from the slave.
For all my 27 Parameters my master is sending 27 requests to the slave and every time it is rewritten the variable where the data from the slave is stored. I want to modify it in such a way that I am able to send a range of registered addresses in a single request and get data from my slave to all those register in a single buffer.
Can you please help me understand how the above code sends requests and how is it receiving data from the slave ? It would be really helpful to me.
Thankyou

Heyy @alisitsyn  any updates on the above ??

Hi @VaibhavSingh9511 ,
Sorry for the delay with answer.
The mbc_master_get_parameter() calls the registered method for appropriate type of port (TCP, SERIAL) in the concrete modbus controller class.

What I am unable to understand is how and when exactly the master sends a request and when is it receiving data and storing it in a buffer. As my ultimate goal is to send one request to the slave and receive multiple responses
from the slave.

master fills the request fields then sends the request to slave device here. The functions below this line form the actual request buffer and generate the EV_MASTER_FRAME_TRANSMIT event then sends the data here using registered port send method for concrete type of port.
Once master received the response from slave it executes the response handler function on EV_MASTER_EXECUTE event here. This function is actually responsible for checking of the response and mapping. It actually transfers the data from slave response to appropriate memory location.
The past processing of the received slave data can be performed here, where we can check the type of parameter and transfer the received data to appropriate storage.

For all my 27 Parameters my master is sending 27 requests to the slave and every time it is rewritten the variable where the data from the slave is stored. I want to modify it in such a way that I am able to send a range of registered addresses in a single request and get data from my slave to all those register in a single buffer.

Hope I understand your project correctly. If you need to get several registers (contiguous data) from each slave and store them in appropriate location in master (slave related) you just need to add the parameters with type  of PARAM_TYPE_ASCII to the data dictionary for each slave address (UID).
Hope the above will help with your project. Let me know if you have issues.

How to set const mb_parameter_descriptor_t device_parameters[] = {} for control relay module.
https://www.aliexpress.us/item/3256802169722248.html?spm=a2g0o.productlist.main.17.531c6487KNdnHL&algo_pvid=804e0979-f08e-4011-98cc-a509817a3b99&algo_exp_id=804e0979-f08e-4011-98cc-a509817a3b99-8&pdp_npi=4%40dis!USD!5.00!0.99!!!5.00!0.99!%402140dcab17273628304062689e0b84!12000020266054187!sea!US!0!ABX&curPageLogUid=YaAVF5s0juuQ&utparam-url=scene%3Asearch|query_from%3A
Thank you so much!