Who worked with the library libmodbus please tell me . I want to send the packet to the device that receives the data using the MODBUS protocol.

I will give a piece of code with the structure of the package itself:

struct input_t { union { uint16_t raw[9]; struct { uint16_t mode; float position; float time; float ampl; float velocity; } __attribute__((packed)); }; static constexpr int addr = 1; static constexpr int count = sizeof(raw) / 2; }; 

In the main part of the application, it is enough for me to simply send this package via COM PORT via RTU:

 modbus_t* ctx; input_t ifield; output_t ofield; std::cout << "Sizeof input : " << sizeof(input_t) << std::endl; std::cout << "Sizeof output: " << sizeof(output_t) << std::endl; //ctx = modbus_new_tcp("192.168.0.3", 502); ctx = modbus_new_rtu("COM4", 115200, 'N', 8, 1); if( ctx == NULL ) { std::cout << "Unable to create the libmodbus context"; return -1; } modbus_set_slave(ctx, 1); modbus_set_debug(ctx, FALSE); std::cout << "Connect: " << modbus_connect(ctx) << std::endl; uint16_t tab_reg[64]; if (ctx ==NULL) printf("%s\n","check null not ok" ); int a = modbus_read_registers(ctx, input_t::addr, input_t::count, ofield.raw); std::cout << a << std::endl; std::cout << *ofield.raw << std::endl; ifield.mode = 3; ifield.position = -9; ifield.time = 6; int b = modbus_write_registers(ctx, output_t::addr, output_t::count, ofield.raw); std::cout << a << std::endl; modbus_close(ctx); modbus_free(ctx); return 0; 

In this program, the connection to this port and to the slave is correct. Errors occur on the packet sending and register reading functions. With what can this be related?

  • what mistakes though? - goldstar_labs
  • error code -1, Unknown error. - jNX
  • Did you check the device connection with anything other than your code? - goldstar_labs
  • one
    in general, for all functions, check the return code and errno, -1 returns modbus_read_registers and the error code in errno, it will become clearer though - goldstar_labs
  • one
    To the @goldstar_labs comment, you can add the following: use the modbus_strerror function. For example: if (modbus_...(ctx) == -1) fprintf(stderr, modbus_strerror(errno)); - Embedder

1 answer 1

The solution to this problem may not be obvious and it was solved by tying all functions. I hope that someone when it helps. The solution is the following, it was only necessary to set the timeout. Although the documentation for using this library is libmodbus , it is said that these variables are set by default. Below is the code of the working program about the RTU protocol, for the windows operating system, for nix-like systems, you will only need to change the port from COMX to / dev / ttyUSBX.

Package structure:

 struct massage { union { uint16_t raw[9]; struct { uint16_t mode; float position; float time; float ampl; float velocity; } __attribute__((packed)); }; static constexpr int addr = 256 ; static constexpr int count = sizeof(raw) / 2; }; 

The main function for receiving and transmitting data over RTU:

 ctx = modbus_new_rtu("COM4", 19200, 'N', 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_PROTOCOL); rc = modbus_set_slave(ctx, 1); modbus_get_response_timeout(ctx, &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); 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, massage::addr, massage::count, out.raw); rc = modbus_write_registers(ctx, massage::addr, massage::count, out.raw); modbus_close(ctx); modbus_free(ctx); }