espressif / esp-modbus

ESP-Modbus - the officially suppported library for Modbus protocol (serial RS485 + TCP over WiFi or Ethernet).
Apache License 2.0
83 stars 46 forks source link

How to output detailed instruction logs? (IDFGH-12822) #63

Open yel-best opened 1 month ago

yel-best commented 1 month ago

Hi My Friend.

1. I am currently doing modbus connection with some PLC devices. I need to see some detailed logs. For example, the sent message "01 03 A0 80 00 01 A7 E2" and then the received message "01 03 02 03 E8 B8 FA", I need to print to the console for output,I have been searching for a long time but I have not found how to open this part of the log.

2. In addition, the example does not seem to explain how to convert the value. For example, I have a float & u16 type value. How should I extract it for subsequent logic? I now use a very stupid way to do it, and I will *(uint16_t ) temp_data_ptr** for forced conversion, do you have any other suggestions?

 if (TEST_VERIFY_VALUES(param_descriptor, (uint16_t *)temp_data_ptr) == ESP_OK)
  {
      ESP_LOGI(TAG, "Characteristic #%d %s (%s) value = %u (0x%" PRIx16 ") read successful.",
               (int)param_descriptor->cid,
               (char *)param_descriptor->param_key,
               (char *)param_descriptor->param_units,
               *(uint16_t *)temp_data_ptr,
               *(uint16_t *)temp_data_ptr);
  }

uint16_t test_v =   *(uint16_t *)temp_data_ptr,

I assign the value to test_vand then I bring test_v into my business logic. There seems to be some problems and it doesn't feel optimal.

alisitsyn commented 1 month ago

@yel-best ,

  1. I am currently doing modbus connection with some PLC devices. I need to see some detailed logs. For example, the sent message "01 03 A0 80 00 01 A7 E2" and then the

The logging for Modbus can be enabled in menuconfig setting the log verbosity. This enables the logging of sent/received PDU frames. The ADU frame logging is removed from the port layer because the log might get cluttered. It is also possible to remove some messages from log.

In addition, the example does not seem to explain how to convert the value.

The code you are looking for is not good example because it is test code and it should not be described for user. This uses the macro which is an analog of template function in CPP to be able to use the same scenario for all types of parameters from data dictionary.

The example of mapping in the data dictionary is described here. Once the characteristics are defined you can read and write the described parameter using the functions mbc_master_get_parameter, mbc_master_set_parameter.

It is selection of user how to store the data and how to save it but the API provides the methods to read/write data over modbus and store them as instructed.

mb_parameter_descriptor_t device_parameters[] = {
      { CID_HOLD_U16_AB, STR("U16_AB"), STR("--"), MB_DEVICE_ADDR1, MB_PARAM_HOLDING,
              HOLD_REG_START(holding_u16_ab), HOLD_REG_SIZE(holding_u16_ab),
              0, PARAM_TYPE_U16_AB, (HOLD_REG_SIZE(holding_u16_ab) << 1),
              OPTS( 0, USHRT_MAX, 0 ), PAR_PERMS_READ_WRITE_TRIGGER },
...
}
...
uint16_t my_data = 0;
...
esp_err_t err = mbc_master_set_parameter(CID_HOLD_U16_AB, "U16_AB", (uint8_t *)&my_data, &type);
if (err == ESP_OK) {
    ESP_LOGI(TAG, "Set parameter data successfully.");
} else {
    ESP_LOGE(TAG, "Set data fail, err = 0x%x (%s).", (int)err, (char*)esp_err_to_name(err));
}

assign the value to test_v and then I bring test_v into my business logic. There seems to be some problems and it doesn't feel optimal.

The temp_data_ptr in this case gets the pointer to parameter instance in the parameter structure void *temp_data_ptr = master_get_param_data(param_descriptor); ).

Th example with the parameters stored in data structures and the code saves the data to the appropriate field of the structure as defined in data dictionary.

...
#pragma pack(push, 1)
typedef struct
{
#if CONFIG_FMB_EXT_TYPE_SUPPORT
    uint16_t holding_u16_ab[2];
    uint16_t holding_u16_ba[2];
} holding_reg_params_t;
#pragma pack(pop)
...
// This structure keeps the values that can be accessed from Modbus master
holding_reg_params_t holding_reg_params = { 0 };
....
mb_parameter_descriptor_t device_parameters[] = {
      { CID_HOLD_U16_AB, STR("U16_AB"), STR("--"), MB_DEVICE_ADDR1, MB_PARAM_HOLDING,
              HOLD_REG_START(holding_u16_ab), HOLD_REG_SIZE(holding_u16_ab),
              HOLD_OFFSET(holding_u16_ab), PARAM_TYPE_U16_AB, (HOLD_REG_SIZE(holding_u16_ab) << 1),
              OPTS( 0, USHRT_MAX, 0 ), PAR_PERMS_READ_WRITE_TRIGGER },
...
}

const mb_parameter_descriptor_t* param_descriptor = NULL;
...
esp_err_t err = mbc_master_get_cid_info(cid, &param_descriptor); // get characteristic descriptor from data dictionary
...
void *temp_data_ptr = master_get_param_data(param_descriptor); // <<<< gets the pointer to the parameter instance as defined by offset HOLD_OFFSET(holding_u16_ab) in data dictionary.
...
// Send the data of the parameter stored in the holding_reg_params.holding_u16_ab to the slave.
esp_err_t err = mbc_master_set_parameter(CID_HOLD_U16_AB, "U16_AB", (uint8_t *)temp_data_ptr, &type);
if (err == ESP_OK) {
    ESP_LOGI(TAG, "Set parameter data successfully.");
} else {
    ESP_LOGE(TAG, "Set data fail, err = 0x%x (%s).", (int)err, (char*)esp_err_to_name(err));
}
yel-best commented 1 month ago

Hi, Friend

Thank you very much for your answer. Based on your tips, I have a new understanding of the way to read data using modbus, but I encountered another problem. I wonder if you can help me.

My current environment

Currently I want to use modbus 485 to read device data and display it on an LCD screen using lvgl UI. I also use esp-idf WIFI & MQTT for data transfer. Currently I have no problem using lvgl UI, but when I After adding modbus, some exceptions will appear. I don’t know whether it is caused by a memory error or insufficient storage space. The prompts are as follows.

I don’t understand why I’m using the largestN16R8version, and why there are still some memory exceptions and creation failures. Is it because my esp-idf setting causes moudbus to have some impact on lvgl? I don’t know if anyone has found similar problems. question

Guru Meditation Error: Core  / panic'ed (Cache disabled but cached memory region accessed). 
MMU entry fault error occurred while accessing the address 0x43ffef00 (invalid mmu entry)

Core  0 register dump:
PC      : 0x40378340  PS      : 0x00060f34  A0      : 0x82022ba8  A1      : 0x3fcbba40
0x40378340: _UserExceptionVector at E:/MyProject/IoT/esp/esp-idf/components/freertos/FreeRTOS-Kernel/portable/xtensa/xtensa_vectors.S:621

A2      : 0x3c12a900  A3      : 0x3fcbba70  A4      : 0x00000049  A5      : 0x0000006f
A6      : 0x00000000  A7      : 0x00000010  A8      : 0x82022add  A9      : 0xffffef03
A10     : 0x3c12a900  A11     : 0x3fcbba70  A12     : 0x00000049  A13     : 0x0000006f
A14     : 0xffffffff  A15     : 0x0000ffff  SAR     : 0x00000020  EXCCAUSE: 0x00000007
EXCVADDR: 0xffffef00  LBEG    : 0x42024ea4  LEND    : 0x42024ecb  LCOUNT  : 0x00000000

If you have time, I hope you can give me some help or suggestions, thanks

It's been bothering me for a week and I don't know what to do 🥲

alisitsyn commented 1 month ago

I can not help you to identify the reason for the issue having just the information above. Ican give you some recommendations:

yel-best commented 1 month ago
  • IRAM_ATTR

Ok, I'll check it out. I think it's caused by insufficient stack space. Is there any way to get more stack space? for example, changing some settings

What I can determine so far is that when I use LVGL + modbus at the same time, there will be a problem of failure to create the moubus task. It is most likely due to insufficient memory.

alisitsyn commented 4 weeks ago

@yel-best ,

The latest master now supports the user error handler function to expose the modbus buffers.

Please take a look to the documentation.

Have you been able to resolve your issue?

yel-best commented 3 weeks ago

Have you been able to resolve your issue?

wow,thank you for your support. I have been able to solve my data format problem, but I will continue to test it and hope to provide you with more case help through testing. 😄