stephane / libmodbus

A Modbus library for Linux, Mac OS, FreeBSD and Windows
http://libmodbus.org
GNU Lesser General Public License v2.1
3.42k stars 1.74k forks source link

modbus_read_registers #535

Closed viktor-morin closed 4 years ago

viktor-morin commented 4 years ago

I'm running following code on Linux:

#include <stdio.h>
#include <modbus.h>

int main(void)
{
  modbus_t *ctx;
  uint16_t tab_reg[64];
  int rc;
  int i;

  ctx = modbus_new_tcp("127.0.0.1", 502);
  if (modbus_connect(ctx) == -1)
  {
    printf("Connection failed: %d \n", -1);
    modbus_free(ctx);
    return -1;
  }

  rc = modbus_read_registers(ctx, 20000, 10, tab_reg);
  if (rc == -1)
  {
    printf("Error reading register %d \n", rc);
    return -1;
  }

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

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

Result:

Error reading register -1

I want to read from register 20000 Using a C# client called EasyModbus Client (Free Software), I get it to work: https://imgur.com/zQfxd28

What's wrong?

karlp commented 4 years ago

try using the recommended code from the documentation to get better errors. You might also like to turn on verbose debug to see what's sent/received and compare.

rc = modbus_read_registers(ctx, 20000, 10, tab_reg);
if (rc == -1) {
    fprintf(stderr, "%s\n", modbus_strerror(errno));
    return -1;
}
viktor-morin commented 4 years ago

using that example, errno isnt defined.

karlp commented 4 years ago

then include errno.h, errno is a global...

viktor-morin commented 4 years ago

Updated the code to follwing:

if (rc == -1)
{
    printf("Error reading register %d \n", rc);
    fprintf(stderr, "%s\n", modbus_strerror(errno));
    return -1;
}

Get following output:

Error reading register -1 Connection timed out

Again, it works with other clients like https://imgur.com/zQfxd28

mhei commented 4 years ago

Repeating that a C# client works for this Modbus Server does not help very much. I doubt that this C# client runs in the same environment (Linux) as your libmodbus-based program, does it?

So now that you have a human-readable error message for the reason, check libmodbus documentation how you could play with libmodbus' API to address this issue, e.g. enable debugging, modify timeouts... I'd also recommend to use Wireshark to inspect the TCP data flow...

karlp commented 4 years ago

(is your target device actually running on 127.0.0.1?)

viktor-morin commented 4 years ago

I was running on Linux WSL (Windows Subsystem Linux), but to make sure that wasnt an issue I connected a Raspberry Pi. I still get same error:

Error reading register -1 Connection timed out

And I have verified it works from other clients, and that I can ping the device from Linux. So its clear to me that there is something, probably a settings or similar I have to change? But usually when you follow an example provided by the lib itself, they tend to work without additional configuration.

I will see if I can find anything in the documentation regarding this. I also tried to increaste the timeout since that's what the error indicated (even when it dosnt feel like that's the issue)

modbus_set_response_timeout(ctx, 5, 0);

viktor-morin commented 4 years ago

Uploaded picture from WireShark: https://imgur.com/tOWaWcd, and the log itself: https://www.dropbox.com/s/awmnho9da9b0d7c/modbus.pcapng?dl=0

viktor-morin commented 4 years ago

Solved my problem by using another lib

JoelStienlet commented 4 years ago

ctx = modbus_new_tcp("127.0.0.1", 502); here the library is asked to open a TCP connection to locahost. But the wireshark screenshot (log link broken) shows two machines:

netomx commented 3 years ago

What library did you use? I have some issues that I need to try to send some registers, and I need to send them several times.