Open herryliq opened 2 weeks ago
Hi @herryliq ,
Thanks for the issue. As per your information above I can guess about the misconfiguration of the example you are using. The code tries to display the float value (length = 4 bytes) of characteristic CID_INP_DATA_0
but your data dictionary is configured incorrectly to read just one register (2 byes) from slave:
{CID_INP_DATA_0,STR("Temperature"),STR("Celsius"),1, // << read data from slave address 1
MB_PARAM_INPUT, // << read input registers
0x0000,1, // << this means read one register from address 0x0000 from slave (2 bytes)
INPUT_OFFSET(input_data0), // << means pack the read data into parameter `input_data0`
PARAM_TYPE_FLOAT, PARAM_SIZE_FLOAT, // <<< the packet value will be mapped into device memory as of type float 4 bytes
OPTS(-40,80,0.1),PAR_PERMS_READ},
The example uses the float values but if you need to read the 2 bytes values you need to modify the type of input_data0
here to PARAM_TYPE_U16
and modify the code here to display the correct unsigned 16 bit value instead of float and uint32_t. When the code tries to print the incorrectly set float value it usually prints it as 0.00
.
Please read the readme.md file for example carefully and take a look to mapping examples in the documentation here. Also, please investigate the mapping table of your slave or check if the mapping areas in your slave configured correctly.
Please verify the above and let me know if you still have issues.
thanks. UPDATED: See more information about this fail here
Thank for your response. In the file managed_components\espressif__esp-modbus\freemodbus\common\esp_modbus_master.c, the function mbc_master_get_parameter is implemented as follows:
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).",
(int)error, esp_err_to_name(error));
return error;
}
In this code snippet, the mbc_master_get_parameter function is responsible for calling another function to actually perform the parameter retrieval. The master_interface_ptr->get_parameter function is called with the provided parameters cid, name, value, and type.
However, the conversion or mapping of the parameter value from hexadecimal to decimal does not seem to be explicitly handled in this function. It's likely that the conversion or mapping is performed inside the master_interface_ptr->get_parameter function or its related functions.
The master_interface_ptr->get_parameter function ultimately calls the mbc_serial_master_get_parameter function located in managed_components\espressif__esp-modbus\freemodbus\serial_master\modbus_controller\mbc_serial_master.c. In this function, the actual Modbus communication and data handling take place, but the specific conversion or mapping of the parameter value is not immediately apparent from the provided code snippets.
static esp_err_t mbc_serial_master_get_parameter(uint16_t cid, char* name,
uint8_t* value_ptr, uint8_t *type)
{
MB_MASTER_CHECK((name != NULL),
ESP_ERR_INVALID_ARG, "mb incorrect descriptor.");
MB_MASTER_CHECK((type != NULL),
ESP_ERR_INVALID_ARG, "type pointer is incorrect.");
esp_err_t error = ESP_ERR_INVALID_RESPONSE;
mb_param_request_t request ;
mb_parameter_descriptor_t reg_info = { 0 };
error = mbc_serial_master_set_request(name, MB_PARAM_READ, &request, ®_info);
if ((error == ESP_OK) && (cid == reg_info.cid)) {
// Send request to read characteristic data
error = mbc_serial_master_send_request(&request, value_ptr);
if (error == ESP_OK) {
ESP_LOG_BUFFER_HEX_LEVEL("POLL receive buffer", (void*)value_ptr, 2, ESP_LOG_INFO);
ESP_LOGD(TAG, "%s: Good response for get cid(%u) = %s. reg size=%d, reg start = %d",
__FUNCTION__, (unsigned)reg_info.cid, (char*)esp_err_to_name(error), request.reg_size, request.reg_start);
} else {
ESP_LOGD(TAG, "%s: Bad response to get cid(%u) = %s",
__FUNCTION__, (unsigned)reg_info.cid, (char*)esp_err_to_name(error));
}
// Set the type of parameter found in the table
*type = reg_info.param_type;
} else {
ESP_LOGE(TAG, "%s: The cid(%u) not found in the data dictionary.",
__FUNCTION__, (unsigned)reg_info.cid);
error = ESP_ERR_INVALID_ARG;
}
return error;
}
Therefore, could you please provide a brief explanation of whether automatic value mapping processing will be performed and its related implementation logic?
automatic value mapping into the parameter set as INPUT_OFFSET(input_data0) is not performed. The mapping is performed as below:
The handling of input response from slave is performed from main FSM by executing appropriate command handler function (xMasterFuncHandlers).
The final mapping of data from slave response is performed in read/write handler methods example read handler for input registers.
The conversion of data for characteristic according to type is performed here.
Thanks for your feedback. I checked the version of the esp-modbus component I'm using and found it to be v1.0.13. However, there are some differences between v1.0.13 and the master version.
Is the 'Map Value With Response Value' feature a new addition in version 1.0.15
@herryliq ,
No, the latest update includes Modbus extended types for mapping but the mapping was implemented in v1.0.13 as well. The functions esp_err_t mbc_master_set_parameter(uint16_t cid, char* name, uint8_t* value, uint8_t* type)
, esp_err_t mbc_master_get_parameter(uint16_t cid, char* name, uint8_t* value, uint8_t* type)
work the same as it was before for the basic types.
[!NOTE] The basic mapping of the response values is a part of function handler functions.
@herryliq , Could you give me some feedback? As per discussion above is the issue resolved on your side?
Answers checklist.
IDF version.
5.1.1
Espressif SoC revision.
ESP WROOM-32
Operating System used.
Windows
How did you build your project?
VS Code IDE
If you are using Windows, please specify command line type.
PowerShell
Development Kit.
espressif32
Power Supply used.
USB
What is the expected behavior?
Issue Summary:
I am experiencing an issue with reading temperature data via Modbus using an ESP32 microcontroller. The temperature values are consistently reported as zero, despite successful communications without any error codes.
Detailed Description:
What is the actual behavior?
I can receive the buffer from device, but can not map to the real value though by function mbc_master_get_parameter.
Steps to reproduce.
The follows is my device_parameters define. {CID_INP_DATA_0,STR("Temperature"),STR("Celsius"),1,MB_PARAM_INPUT,0x0000,1,INPUT_OFFSET(input_data0),PARAM_TYPE_FLOAT,PARAM_SIZE_FLOAT,OPTS(-40,80,0.1),PAR_PERMS_READ},
The source code is use modbus master sample as follows: https://github.com/espressif/esp-idf/blob/b3f7e2c8a4d354df8ef8558ea7caddc07283a57b/examples/protocols/modbus/serial/mb_master/main/master.c#L313
Debug Logs.
More Information.
No response