How to properly define multiple Modbus register areas?

Nikostpn
Posts: 13
Joined: Mon Jan 25, 2021 5:46 pm

How to properly define multiple Modbus register areas?

Postby Nikostpn » Tue Jan 10, 2023 5:20 pm

Hi,

I'm having issues with defining multiple separate Modbus holding register areas using the serial slave example. I get the following error:
"MB_CONTROLLER_SLAVE: mbc_slave_set_descriptor(217): mb incorrect descriptor or already defined."

Here is how I define the areas in the main app:
  1. #define MB_REG_HOLDING_START_AREA0          (40263)
  2. #define MB_REG_HOLDING_START_AREA1          (40267)
  3. #define MB_REG_HOLDING_START_AREA2          (40291)
  4. #define MB_REG_HOLDING_START_AREA3          (40293)
  5. #define MB_REG_HOLDING_START_AREA4          (40389)
  6. #define MB_REG_HOLDING_START_AREA5          (40907)
  7. #define MB_REG_HOLDING_START_AREA6          (40931)
  8. #define MB_REG_HOLDING_START_AREA7          (40933)
  9. #define MB_REG_HOLDING_START_AREA8          (41027)
  10.  
  11. static void setup_reg_data(void)
  12. {
  13.     // Define initial state of parameters
  14.     holding_reg_params.reg263= 0;
  15.  
  16.     holding_reg_params.reg267 = 0;
  17.  
  18.     holding_reg_params.reg291 = 0;
  19.  
  20.     holding_reg_params.reg293 = 0;
  21.  
  22.     holding_reg_params.reg389 = 0;
  23.  
  24.     holding_reg_params.reg907 = 0;
  25.  
  26.     holding_reg_params.reg931 = 0;
  27.  
  28.     holding_reg_params.reg1027 = 0;
  29. }
  30.  
  31.     reg_area.type = MB_PARAM_HOLDING; // Set type of register area
  32.     reg_area.start_offset = MB_REG_HOLDING_START_AREA0;
  33.     reg_area.address = (void*)&holding_reg_params.reg263;
  34.     reg_area.size = sizeof(float) << 1;
  35.     ESP_ERROR_CHECK(mbc_slave_set_descriptor(reg_area));
  36.     reg_area.type = MB_PARAM_HOLDING; // Set type of register area
  37.     reg_area.start_offset = MB_REG_HOLDING_START_AREA1;
  38.     reg_area.address = (void*)&holding_reg_params.reg267;
  39.     reg_area.size = sizeof(float) << 1;
  40.     ESP_ERROR_CHECK(mbc_slave_set_descriptor(reg_area));
  41.     reg_area.type = MB_PARAM_HOLDING;
  42.     reg_area.start_offset = MB_REG_HOLDING_START_AREA2;
  43.     reg_area.address = (void*)&holding_reg_params.reg291;
  44.     reg_area.size = sizeof(float) << 1;
  45.     ESP_ERROR_CHECK(mbc_slave_set_descriptor(reg_area));
  46.     reg_area.type = MB_PARAM_HOLDING;
  47.     reg_area.start_offset = MB_REG_HOLDI    NG_START_AREA3;
  48.     reg_area.address = (void*)&holding_reg_params.reg293;
  49.     reg_area.size = sizeof(float) << 1;
  50.     ESP_ERROR_CHECK(mbc_slave_set_descriptor(reg_area));
  51.      reg_area.type = MB_PARAM_HOLDING;
  52.     reg_area.start_offset = MB_REG_HOLDING_START_AREA4;
  53.     reg_area.address = (void*)&holding_reg_params.reg389;
  54.     reg_area.size = sizeof(float) << 1;
  55.     ESP_ERROR_CHECK(mbc_slave_set_descriptor(reg_area));
  56.     reg_area.type = MB_PARAM_HOLDING;
  57.     reg_area.start_offset = MB_REG_HOLDING_START_AREA5;
  58.     reg_area.address = (void*)&holding_reg_params.reg907;
  59.     reg_area.size = sizeof(float) << 1;
  60.     ESP_ERROR_CHECK(mbc_slave_set_descriptor(reg_area));
  61.     reg_area.type = MB_PARAM_HOLDING;
  62.     reg_area.start_offset = MB_REG_HOLDING_START_AREA6;
  63.     reg_area.address = (void*)&holding_reg_params.reg931;
  64.     reg_area.size = sizeof(float) << 1;
  65.     ESP_ERROR_CHECK(mbc_slave_set_descriptor(reg_area));
  66.     reg_area.type = MB_PARAM_HOLDING;
  67.     reg_area.start_offset = MB_REG_HOLDING_START_AREA7;
  68.     reg_area.address = (void*)&holding_reg_params.reg933;
  69.     reg_area.size = sizeof(float) << 1;
  70.     ESP_ERROR_CHECK(mbc_slave_set_descriptor(reg_area));
  71.     reg_area.type = MB_PARAM_HOLDING;
  72.     reg_area.start_offset = MB_REG_HOLDING_START_AREA8;
  73.     reg_area.address = (void*)&holding_reg_params.reg1027;
  74.     reg_area.size = sizeof(float) << 1;
  75.     ESP_ERROR_CHECK(mbc_slave_set_descriptor(reg_area));
  76.     reg_area.type = MB_PARAM_HOLDING;
  77.  
  78.  
  79.     setup_reg_data(); // Set values into known state
What am I doing wrong? It specifically complains on the reg293 reg_area, so it's okay with the first 3. Each register in the program is just a single float register in my definition.

Thank you in advance!

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

Re: How to properly define multiple Modbus register areas?

Postby ESP_alisitsyn » Thu Jan 12, 2023 10:49 am

Hi @Nikostpn,

Unfortunately you define the areas incorrectly. Actually I do not see the structure holding_reg_params and my guess about your structure may be incorrect. Please provide the holding_reg_params structure for more information.

Code: Select all

    reg_area.type = MB_PARAM_HOLDING; // Set type of register area
    reg_area.start_offset = MB_REG_HOLDING_START_AREA0;
    reg_area.address = (void*)&holding_reg_params.reg263;
    reg_area.size = sizeof(float) << 1;
    // This call registers the register area in the memory from &holding_reg_params.reg263 with length = 4 (sizeof float) * 2 (registers 263, 264, 265, 266) = 8 bytes!. So, the &holding_reg_params.reg267 corresponds to registers 265, 266 in this area.
    ESP_ERROR_CHECK(mbc_slave_set_descriptor(reg_area));
    reg_area.type = MB_PARAM_HOLDING; // Set type of register area
    reg_area.start_offset = MB_REG_HOLDING_START_AREA1;
    reg_area.address = (void*)&holding_reg_params.reg267;
    reg_area.size = sizeof(float) << 1;
    // Here you starting to register the new area starting from memory address &holding_reg_params.reg267, but its already registered in previous area. This causes the error!
You can define the first register area with length

Code: Select all

        reg_area.address = (void*)&holding_reg_params.reg263;
	reg_area.size = sizeof(float); // 4 bytes in the memory starting from &holding_reg_params.reg263
, or just add :

Code: Select all

    holding_reg_params.reg263 = 0;
 	      holding_reg_params.reg265 = 0; // add the field to keep registers 265, 266 into your holding_reg_params structure (uint16_t).
    holding_reg_params.reg267 = 0;
Also please note that the modbus registers in the esp-modbus defined as zero based. So, the PLC holding register 40263 is defined as 263 :

#define MB_REG_HOLDING_START_AREA0 263

Please refer to https://docs.espressif.com/projects/esp ... ata-access, for more information on how to configure the register areas in the modbus slave.

Nikostpn
Posts: 13
Joined: Mon Jan 25, 2021 5:46 pm

Re: How to properly define multiple Modbus register areas?

Postby Nikostpn » Tue Jan 17, 2023 4:02 pm

Hi ESP_alisitsyn,

Thank you for your answer! I was able to resolve this. My issues were that I was linking the wrong modbus_params.h file -- since I went off the serial slave example, the esp-modbus stuff was automatically copied over as a component into my project once I started changing it, but the CMakeLists.txt file was still linking the component that was in my esp-idf; and yes, I was incorrectly defining the Modbus register areas ('4xxxx' instead of just 'xxxx'). I didn't see your message until now so I was changing the register areas until they worked, but possibly a more verbose example in the docs would do good.

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

Re: How to properly define multiple Modbus register areas?

Postby ESP_alisitsyn » Wed Jan 18, 2023 10:40 am

Hi Nikostpn,

It is good that the issue is solved.
I didn't see your message until now so I was changing the register areas until they worked, but possibly a more verbose example in the docs would do good.
I will think about verbose example in the updated documentation to make it clearer.

Who is online

Users browsing this forum: Bing [Bot], Majestic-12 [Bot] and 120 guests