libmodbus
libmodbus copied to clipboard
RTU slave responds to requests with different slave address
I am using libmodbus 3.1.6 and have the situation, that my modbus RTU slave application answers to requests for address 1, even though it has address 10.
Debug output:
Waiting for an indication...
<01><04><75><4A><00><01><0A><10>
Request for slave 1 ignored (not 10)
[01][04][02][36][FD][6F][11]
Waiting for a confirmation...
ERROR Connection timed out: select
<01><04><75><4B><00><01><5B><D0>Confirmation to ignore
[01][04][02][4B][FC][8F][81]
Waiting for an indication...
<01><04><75><44><00><02><2B><D2>
Request for slave 1 ignored (not 10)
[01][04][04][00][00][E2][B2][33][51]
Waiting for a confirmation...
ERROR Connection timed out: select
<01><04><75><46><00><01><CA><13>Confirmation to ignore
[01][04][02][69][98][96][CA]
Waiting for an indication...
<01><04><75><47><00><01><9B><D3>
Request for slave 1 ignored (not 10)
[01][04][02][79][D8][9A][FA]
Waiting for a confirmation...
So we can see that the request for slave 1 is ignored. However, the device on the other end of the line still receives data. I tried it with a proprietary device and with modpoll: Receiving data is possible, without regard for the modbus address.
Here is the relevant part of the code (error checking omitted for brevity):
ctx = modbus_new_rtu("/dev/ttyUSB0", 9600, 'N', 8, 1);
modbus_connect(ctx);
modbus_set_slave(ctx, 10);
I have seen that this was also asked on the mailing list, but no responses.
From reading the libmodbus source, I believe this happens because _modbus_rtu_check_integrity
returns 0
which gets propagated up in _modbus_receive_msg
, which’s return code is unused in the remaining part of the RTU code – but that is just my limited understanding of the code base.
Suggested fix: I changed this code in modbus-rtu.c
:
/* Following call to check_confirmation handles this error */
return 0;
to:
/* Following call to check_confirmation handles this error */
return -1;
And now my application only answers to requests for slave address 1. However, I did not opened a PR because I am not sure if I misunderstood either how to use libmodbus correctly or how slave addresses are supposed to work. Furthermore, I am not sure if this introduces any side-effects.
I had a similar issue. modbus_receive
returns message length. So if slave ID doesn't match, then you just get 0 (empty message), so you could detect this case, I guess.
The solution is just check returned message length. If it's positive (>0) you can process the message.
int rc = 0;
ctx = modbus_new_rtu("/dev/ttyUSB0", 115200, 'N', 8, 1);
modbus_set_slave(ctx, 0xF0);
modbus_rtu_set_serial_mode(ctx, MODBUS_RTU_RS232);
modbus_connect(ctx);
mb_mapping = modbus_mapping_new(MODBUS_MAX_READ_BITS, 0, MODBUS_MAX_READ_REGISTERS, 0);
while(1) {
rc = modbus_receive(ctx, query);
if (rc > 0) {
print_query(query, MODBUS_RTU_MAX_ADU_LENGTH);
}
}