Modbus master and endianness

rtborg
Posts: 67
Joined: Wed Oct 23, 2019 6:15 am

Modbus master and endianness

Postby rtborg » Thu Apr 28, 2022 12:41 pm

For a Modbus network that contains a mixture of big-endian and little-endian slaves, is there a way specify endianness for each mb_parameter_descriptor_t and process the data accordingly?

If not, what would be a good way of doing the conversion in user code?

Thanks

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

Re: Modbus master and endianness

Postby ESP_alisitsyn » Mon May 09, 2022 3:56 pm

@rtborg ,

It is possible to add support for the other four options for FLOAT format.

I was discussing about this here: viewtopic.php?f=2&t=23040&hilit=modbus+floating
https://github.com/espressif/esp-modbus/issues/3

The new float type defines can be added here:
https://github.com/espressif/esp-modbus ... ster.h#L32

In order to add support for different format of float for each CID you need to implement byte swapping of the float value in the code:
https://github.com/espressif/esp-modbus ... ter.c#L557 (this is an example for tcp master).

Code: Select all

# define __beswap_32(x) \
    (__extension__							      \
     ({ uint32_t __bsx = (x);					      \
        ((((__bsx) >> 16) & 0xffff) | (((__bsx) & 0xffff) << 16)); }))

Code: Select all

// Set parameter value for characteristic selected by name and cid
static esp_err_t mbc_tcp_master_set_parameter(uint16_t cid, char* name, uint8_t* value, uint8_t *type)
{
    MB_MASTER_CHECK((name != NULL), ESP_ERR_INVALID_ARG, "mb incorrect descriptor.");
    MB_MASTER_CHECK((value != NULL), ESP_ERR_INVALID_ARG, "value pointer is incorrect.");
    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 };
    uint8_t* pdata = NULL;

    error = mbc_tcp_master_set_request(name, MB_PARAM_WRITE, &request, &reg_info);
    if ((error == ESP_OK) && (cid == reg_info.cid)) {
        pdata = calloc(1, (reg_info.mb_size << 1)); // alloc parameter buffer
        if (!pdata) {
            return ESP_ERR_INVALID_STATE;
        }
        // Transfer value of characteristic into parameter buffer
        error = mbc_tcp_master_set_param_data((void*)pdata, (void*)value,
                                              reg_info.param_type, reg_info.param_size);
        if (error != ESP_OK) {
            ESP_LOGE(TAG, "fail to set parameter data.");
            free(pdata);
            return ESP_ERR_INVALID_STATE;
        }
        // Send request to write characteristic data
        error = mbc_tcp_master_send_request(&request, pdata);
        if (error == ESP_OK) {
            ESP_LOGD(TAG, "%s: Good response for set cid(%u) = %s",
                                    __FUNCTION__, (unsigned)reg_info.cid, (char*)esp_err_to_name(error));
        } else {
            ESP_LOGD(TAG, "%s: Bad response to set cid(%u) = %s",
                                    __FUNCTION__, reg_info.cid, (char*)esp_err_to_name(error));
        }
        free(pdata);
        // Set the type of parameter found in the table
        *type = reg_info.param_type;
        if ((reg_info.param_type == PARAM_TYPE_FLOAT_BYTE_SWAP) 
                && (reg_info.param_size == 4)) {
            	// Fix endianess for FLOAT_BYTE_SWAP here <<<<<<<<<<<<<<<<<<<
            	*(uint32_t*)value_ptr = __beswap_32(*(uint32_t*)value_ptr);
        }
    } else {
        ESP_LOGE(TAG, "%s: The requested cid(%u) not found in the data dictionary.",
                                    __FUNCTION__, reg_info.cid);
        error = ESP_ERR_INVALID_ARG;
    }
    return error;
}
Once these changes are added to the stack, you can use the new float type(s) in the object dictionary of master to process the data of your slave specifically.

The same can be done for the serial master port. It requires an update of the stack code and I plan to add this support in the next patch version of the component.
If not, what would be a good way of doing the conversion in user code?
It is also possible to convert the float as required using parameter instance address in user code using the macro similar to below
https://github.com/espressif/esp-modbus ... mmon.h#L60

Who is online

Users browsing this forum: arunbm123 and 101 guests