espressif / esp-modbus

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

ESP32 Modbus Communication Issue: Temperature Data Consistently Reads Zero Despite Successful Transactions (IDFGH-12723) #58

Closed herryliq closed 2 months ago

herryliq commented 2 months ago

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:

  1. Communication Status:
  1. Temperature Reading:
  1. Log Insights:
  1. Potential Issue Areas:

the log as follows:

D (9422) MB_PORT_COMMON: eMBMasterRTUReceive: Port exit critical␛[0m D (9422) MB_PORT_COMMON: 8666597: Packet data received successfully (0).␛[0m D (9432) POLL receive buffer: 04 02 01 36 ␛[0m D (9432) MB_PORT_COMMON: 8666597:EV_MASTER_FRAME_SENT␛[0m D (9442) POLL sent buffer: 04 00 00 00 01 ␛[0m D (9442) MB_PORT_COMMON: 8666597:EV_MASTER_EXECUTE␛[0m D (9452) MB_PORT_COMMON: 8666597:set event EV_ERROR_OK␛[0m D (9452) MB_PORT_COMMON: 8666597:EV_MASTER_ERROR_PROCESS␛[0m D (9462) MB_PORT_COMMON: vMBMasterCBRequestSuccess: Callback request success.␛[0m D (9472) MB_PORT_COMMON: Transaction (8666597), processing time(us) = 136362␛[0m D (9472) MB_PORT_COMMON: eMBMasterWaitRequestFinish: returned event = 0x80␛[0m D (9482) MB_CONTROLLER_MASTER: mbc_serial_master_get_parameter: Good response for get cid(0) = ESP_OK␛[0m ␛[0;32mI (9492) MASTER_TEST: Characteristic #0 Temperature (Celsius) value = (0x0) read successful.␛[0m ␛[0;32mI (10002) MASTER_TEST: mbc_master_get_cid_info: (param_key:1061160556), (mb_slave_addr:1)␛[0m D (10002) MB_PORT_COMMON: xMBMasterRunResTake:Take MB resource (500 ticks).␛[0m D (10002) MB_PORT_COMMON: xMBMasterRunResTake:Take MB resource (500 ticks).␛[0m D (10012) MB_PORT_COMMON: 9356874:EV_MASTER_FRAME_TRANSMIT␛[0m D (10012) POLL transmit buffer: 04 00 00 00 01 ␛[0m D (10022) MB_PORT_COMMON: eMBMasterRTUSend: Port enter critical.␛[0m D (10022) MB_PORT_COMMON: eMBMasterRTUSend: Port exit critical␛[0m D (10032) MB_PORT_COMMON: xMBMasterPortSerialSendRequest default␛[0m D (10042) MB_PORT_COMMON: vMBMasterPortTimersRespondTimeoutEnable Respond enable timeout.␛[0m D (10042) MB_MASTER_SERIAL: MB_TX_buffer sent: (9) bytes.␛[0m D (10052) MB_PORT_COMMON: xMBPortSerialWaitEvent, UART event: 1 ␛[0m D (10052) MB_MASTER_SERIAL: MB_uart[2] event:␛[0m D (10062) MB_MASTER_SERIAL: uart rx break.␛[0m D (10062) MB_PORT_COMMON: xMBPortSerialWaitEvent, UART event: 0 ␛[0m D (10072) MB_MASTER_SERIAL: MB_uart[2] event:␛[0m D (10072) MB_MASTER_SERIAL: Data event, len: 7.␛[0m D (10082) MB_MASTER_SERIAL: Received data: 8(bytes in buffer)␛[0m D (10082) MB_MASTER_SERIAL: Timeout occured, processed: 8 bytes␛[0m D (10092) MB_PORT_COMMON: 9356874:EV_MASTER_FRAME_RECEIVED␛[0m D (10102) MB_PORT_COMMON: xMBMasterPortSerialGetResponse default␛[0m D (10102) MB_PORT_COMMON: eMBMasterRTUReceive: Port enter critical.␛[0m D (10112) MB_PORT_COMMON: eMBMasterRTUReceive: Port exit critical␛[0m D (10112) MB_PORT_COMMON: 9356874: Packet data received successfully (0).␛[0m D (10122) POLL receive buffer: 04 02 01 36 ␛[0m D (10132) MB_PORT_COMMON: 9356874:EV_MASTER_FRAME_SENT␛[0m D (10132) POLL sent buffer: 04 00 00 00 01 ␛[0m D (10142) MB_PORT_COMMON: 9356874:EV_MASTER_EXECUTE␛[0m D (10142) MB_PORT_COMMON: 9356874:set event EV_ERROR_OK␛[0m D (10152) MB_PORT_COMMON: 9356874:EV_MASTER_ERROR_PROCESS␛[0m D (10152) MB_PORT_COMMON: vMBMasterCBRequestSuccess: Callback request success.␛[0m D (10162) MB_PORT_COMMON: Transaction (9356874), processing time(us) = 138536␛[0m D (10172) MB_PORT_COMMON: eMBMasterWaitRequestFinish: returned event = 0x80␛[0m D (10172) MB_CONTROLLER_MASTER: mbc_serial_master_get_parameter: Good response for get cid(0) = ESP_OK␛[0m ␛[0;32mI (10182) MASTER_TEST: Characteristic #0 Temperature (Celsius) value = (0x0) read successful.␛[0m

the source code was base from sample mb-master

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},

` static void master_operation_func(void arg) { esp_err_t err = ESP_OK; float value = 0; uint8_t temp_data[4]={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);
        ESP_LOGI(TAG, "mbc_master_get_cid_info: (param_key:%d), (mb_slave_addr:%d)", param_descriptor->param_key, param_descriptor->mb_slave_addr);

        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;
            {
                err = mbc_master_get_parameter(cid, (char*)param_descriptor->param_key,
                                                    (uint8_t*)&value, &type);                                              
                if (err == ESP_OK) {
                    ESP_LOGI(TAG, "Characteristic #%d %s (%s) value = (0x%" PRIx32 ") read successful.",
                                    param_descriptor->cid,
                                    (char*)param_descriptor->param_key,
                                    (char*)param_descriptor->param_units,
                                    *(uint32_t*)temp_data); 
                } 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));
                }
            }
            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());

}

`

alisitsyn commented 2 months ago

@herryliq ,

The issue happens because your code above is incorrect.

  1. Initialization of the temporary data pointer. This is where the data is designed to be stored.
    void* temp_data_ptr = master_get_param_data(param_descriptor); // initializes the temp_data_ptr to the &input_reg_params.input_data0.
  2. Get response from slave and returned data.
    err = mbc_master_get_parameter(cid, (char*)param_descriptor->param_key,
                                                    (uint8_t*)&value, &type);   // sends request and handle response, then saves the input data into data instance pointed by third parameter (&value)
  3. Your modified code below prints the uint32_t value from the temp_data[] which is not initialized and is printed as 0x00000000.
    ESP_LOGI(TAG, "Characteristic #%d %s (%s) value = (0x%" PRIx32 ") read successful.",
                                    param_descriptor->cid,
                                    (char*)param_descriptor->param_key,
                                    (char*)param_descriptor->param_units,
                                    *(uint32_t*)temp_data); 

    if you change the line above to below code, you will be able to get actual data received from slave.

    ESP_LOGI(TAG, "Characteristic #%d %s (%s) value = (0x%" PRIx32 ") read successful.",
                                    param_descriptor->cid,
                                    (char*)param_descriptor->param_key,
                                    (char*)param_descriptor->param_units,
                                    *(uint32_t*)&value); 

    Please see the documentation pages the function mbc_master_get_parameter description

alisitsyn commented 2 months ago

The issue is duplicate with https://github.com/espressif/esp-idf/issues/13705

herryliq commented 2 months ago

The issue is duplicate with https://github.com/espressif/esp-idf/issues/13705