Singhal
Singhal

Reputation: 1

modbus_read_register - Error connection timed out

We are using libmodbus library to read register values from energy meter EM6400 which supports Modbus over RTU. We are facing the following two issues.

1) We are facing an issue with modbus_read_registers API, this API returns -1 and the error message is:

ERROR Connection timed out: select.

After debugging the library, we found this issue is due to the echo of request bytes in the response message. read() API call in _modbus_rtu_recv returns request bytes first followed by response bytes. As a result, length_to_read is calculated in compute_data_length_after_meta() based on the request bytes instead of response bytes (which contains the number of bytes read) and connection timed out issue occurs. We tried to use both 3.0.6 and 3.1.2 libmodbus versions but same issue occurs in both the versions.

2) modbus_rtu_set_serial_mode (ctx, MODBUS_RTU_RS485) returns "BAD file descriptor".

Please confirm if there is any API call missing or any parameter is not set correctly.

Our sample code to read register value is as follows.

int main()
{

    modbus_t *ctx;
    uint16_t tab_reg[2] = {0,0};
    float avgVLL = -1;;
    int res = 0;
    int rc;
    int i;
    struct timeval response_timeout;
    uint32_t tv_sec = 0;
    uint32_t tv_usec = 0;
    response_timeout.tv_sec = 5;
    response_timeout.tv_usec = 0;

    ctx = modbus_new_rtu("/dev/ttyUSB0", 19200, 'E', 8, 1);
    if (NULL == ctx)
    {
                    printf("Unable to create libmodbus context\n");
                    res = 1;
    }
    else
    {
        printf("created libmodbus context\n");
        modbus_set_debug(ctx, TRUE);
        //modbus_set_error_recovery(ctx, MODBUS_ERROR_RECOVERY_LINK |MODBUS_ERROR_RECOVERY_PROTOCOL);
        rc = modbus_set_slave(ctx, 1);
        printf("modbus_set_slave return: %d\n",rc);
        if (rc != 0)
        {
                        printf("modbus_set_slave: %s \n",modbus_strerror(errno));
        }

        /* Commented - Giving 'Bad File Descriptor' issue
        rc = modbus_rtu_set_serial_mode(ctx, MODBUS_RTU_RS485);
        printf("modbus_rtu_set_serial_mode: %d \n",rc);

        if (rc != 0)
        {
                        printf("modbus_rtu_set_serial_mode: %s \n",modbus_strerror(errno));
        }
        */

        // This code is for version 3.0.6
        modbus_get_response_timeout(ctx, &response_timeout); 
        printf("Default response timeout:%ld sec %ld usec \n", response_timeout.tv_sec, response_timeout.tv_usec );

        response_timeout.tv_sec = 60;
        response_timeout.tv_usec = 0;

        modbus_set_response_timeout(ctx, &response_timeout); 
        modbus_get_response_timeout(ctx, &response_timeout); 
        printf("Set response timeout:%ld sec %ld usec \n", response_timeout.tv_sec, response_timeout.tv_usec );


        /* This code is for version 3.1.2
        modbus_get_response_timeout(ctx, &tv_sec, &tv_usec); 
        printf("Default response timeout:%d sec %d usec \n",tv_sec,tv_usec );

        tv_sec = 60;
        tv_usec = 0;

        modbus_set_response_timeout(ctx, tv_sec,tv_usec); 
        modbus_get_response_timeout(ctx, &tv_sec, &tv_usec); 
        printf("Set response timeout:%d sec %d usec \n",tv_sec,tv_usec );
        */

        rc = modbus_connect(ctx);
        printf("modbus_connect: %d \n",rc);

        if (rc == -1) {
                        printf("Connection failed: %s\n", modbus_strerror(errno));
            res = 1;
        }

        rc = modbus_read_registers(ctx, 3908, 2, tab_reg);
        printf("modbus_read_registers: %d \n",rc);

        if (rc == -1) {
                        printf("Read registers failed:  %s\n", modbus_strerror(errno));
            res = 1;
        }

        for (i=0; i < 2; i++) {
            printf("reg[%d]=%d (0x%X)\n", i, tab_reg[i], tab_reg[i]);
        }

        avgVLL = modbus_get_float(tab_reg);

        printf("Average Line to Line Voltage = %f\n", avgVLL);

        modbus_close(ctx);
        modbus_free(ctx);
    }
}

Output of this sample is as follows:

created libmodbus context
modbus_set_slave return: 0
modbus_rtu_set_serial_mode: -1 
modbus_rtu_set_serial_mode: Bad file descriptor 
Default response timeout:0 sec 500000 usec 
Set response timeout:60 sec 0 usec 
Opening /dev/ttyUSB0 at 19200 bauds (E, 8, 1)
modbus_connect: 0 
[01][03][0F][44][00][02][87][0A]
Waiting for a confirmation...
ERROR Connection timed out: select
<01><03><0F><44><00><02><87><0A><01><03><04><C4><5F><43><D4><C6><7E>modbus_read_registers: -1 
Read registers failed:  Connection timed out
reg[0]=0 (0x0)
reg[1]=0 (0x0)
Average Line to Line Voltage = 0.000000

Upvotes: 0

Views: 9006

Answers (1)

jonasberg
jonasberg

Reputation: 1933

Issue 1) is probably a hardware issue, with "local echo" enabled in your RS-485 adapter. Local echo is sometimes used to confirm sending of data bytes on the bus. You need to disable it, or find another RS-485 adapter.

I have written about this in the documentation of my MinimalModbus Python library: Local Echo

It lists a few common ways to disable local echo in RS-485 adapters.

Upvotes: 0

Related Questions