2
votes

I am new to Modbus protocol. I want to read data from RS485. I have written C code using Libmodbus library but unable to read data getting error connection timed out. I am here using modbus slave running on windows machine from here I am connecting from USB to serial cable from COM port of windows machine. To the RS485 port of Linux machine where I run the below C code there.

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <stdbool.h>

#include <modbus.h>


int main()
{
  modbus_t *ctx = 0;

  //
  // create a libmodbus context for RTU
  // doesn't check if the serial is really there
  //
  ctx = modbus_new_rtu("/dev/ttyS2", 115200, 'N', 8, 1);

  if (ctx == 0) {

    fprintf(stderr, "Unable to create the libmodbus context\n");
    return -1;

  } else {
    struct timeval old_response_timeout;
    struct timeval response_timeout;

    // enable debug
    modbus_set_debug(ctx, true);

    // initialize timeouts with default
    modbus_get_response_timeout(ctx, &old_response_timeout);
    response_timeout = old_response_timeout;

    // set the message and charcater timeout to 2 seconds
    response_timeout.tv_sec = 2;
    modbus_set_response_timeout(ctx, &response_timeout);
    modbus_set_byte_timeout(ctx, &response_timeout);

  }

  // try to connet to the first DZT on the line
  // assume that line address is 1, the default
  // send nothing on the line, just set the address in the context
  if(modbus_set_slave(ctx, 1) == -1) {
    fprintf(stderr, "Didn't connect to slave/n");
    return -1;
  }

  // establish a Modbus connection
  // in a RS-485 context that means the serial interface is opened
  // but nothing is yet sent on the line
  if(modbus_connect(ctx) == -1) {

    fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno));
    modbus_free(ctx);
    return -1;

  } else {

    int nreg = 0;
    uint16_t tab_reg[32];
   // uint16_t
    fprintf(stderr, "Connected\n");

    //
    // read all registers in DVT 6001
    // the function uses the Modbus function code 0x03 (read holding registers).
    //
    nreg = modbus_read_registers(ctx,0,5,tab_reg);
    
    //printf(tab_reg);
    if (nreg == -1) {

       fprintf(stderr, "Error reading registers: %s\n", modbus_strerror(errno));
       modbus_close(ctx);
       modbus_free(ctx);

       return -1;

    } else {
       int i;

       // dump all registers content

       fprintf (stderr, "Register dump:\n");
       for(i=0; i < nreg; i++)
         printf("reg #%d: %d\n", i, tab_reg[i]);


       modbus_close(ctx);
       modbus_free(ctx);

       return 0;
    }
  }
}

Error is as follows

Opening /dev/ttyS2 at 115200 bauds (N, 8, 1)
Connected
[01][03][00][00][00][05][85][C9]
Waiting for a confirmation...
ERROR Connection timed out: select
Error reading registers: Connection timed out
1

1 Answers

1
votes

The first thing I would check is the serial communication hardware. Is there any other device you could try connecting to both of the computers to make sure each computer's serial port is working? That would help verify that the serial port is correctly installed and configured on each computer. USB to serial converts are notoriously finicky and difficult to get working.

The next thing I would check is the baud rate and serial port settings on each machine. The RS-232 and RS-485 serial communication protocols do not auto-negotiate / auto-detect the speed of a connection so both devices need to have the same connectivity settings.

You may also want to try a slower baud rate than 115200. While higher baud rates allow for more bandwidth and throughput there is a greater chance for errors. I would start out with the 19200 baud and go from there once you get it working.

Also, what user are you running this program under? You may need to execute the program via sudo or as a user with elevated permissions.