AIX test libmodbus 3.1.2

66 views
Skip to first unread message

Fabrice

unread,
Oct 28, 2015, 6:29:00 PM10/28/15
to libmodbus
Hi,

We used to work with libmodbus-2.1.0.
We are working to port the app to libmodbus-3.1.2

During the built-in test, we got this error

7/7 Disable byte timeout: OK
[00][1D][00][00][00][06][FF][03][00][6F][00][01]
Waiting for a confirmation...
ERROR Connection timed out: select
<00>Bytes flushed (10)
1/2 Too small byte timeout (3ms < 5ms): OK
Bytes flushed (0)
[00][1E][00][00][00][06][FF][03][00][6F][00][01]
Waiting for a confirmation...
ERROR Connection timed out: select
<00>Bytes flushed (10)
2/2 Adapted byte timeout (7ms > 5ms):
Line 560: assertion error for 'rc == 1':

Any idea what's wrong ?
Thanks


Stéphane Raimbault

unread,
Oct 29, 2015, 4:46:11 AM10/29/15
to libm...@googlegroups.com
Hi,

I already applied a fix https://github.com/stephane/libmodbus/commit/d69c8cf for this test but it's included in v3.1.2 :/

Which OS do you use?

--
Vous recevez ce message, car vous êtes abonné au groupe Google Groupes "libmodbus".
Pour vous désabonner de ce groupe et ne plus recevoir d'e-mails le concernant, envoyez un e-mail à l'adresse libmodbus+...@googlegroups.com.
Pour obtenir davantage d'options, consultez la page https://groups.google.com/d/optout.

Olivier Barthelemy

unread,
Oct 29, 2015, 5:27:08 AM10/29/15
to libm...@googlegroups.com
I am not sure if it is related, but I have had an issue where a serial line that was probably not properly shielded added some 00 at the start of the answer frames sent from a slave device to the PC master. (If your serial line only has one stop byte for exemple, you only need one 'parasite spike' to change no signal to a 00 byte in RS232. That's how i interpreted it)

I don't remember the exact executon scenario, but libmodbus was not handling this well, only clearing one byte from the receive buffer at each 'select timeout', so until the whole input frame was cleared, the following answer frames, even if tey didn't have that starting 00, were badly interpreted, because libmodbus thought the begun at the part of the first erroneous frame that was not cleared yet. This caused about 10 'unanswered frames' after each erroneous 00

Not being able to fix the hardware cause in that case, i ended up modifying libmodbus to ignore all 00 in the input buffer when it is expecting the reception of the start of a new frame. This solved the issue for me, and as far as i know, it doesn't break any compliance to the modbus standard, since no modbus slave answer will ever start by 00.

--
Geovariances

Olivier BARTHELEMY Software development engineer
Geovariances, 49bis avenue Franklin Roosevelt - 77215 AVON CEDEX - FRANCE
| www.geovariances.com
Keep posted about Geovariances                  

Fabrice

unread,
Oct 29, 2015, 8:16:21 PM10/29/15
to libmodbus
I am using AIX
with up to date v3.1.2

Stéphane Raimbault

unread,
Nov 2, 2015, 8:37:40 AM11/2/15
to libm...@googlegroups.com
Olivier,

I don't think it's the same problem than Fabrice's, anyway do you propose to only remove the leading 00 in Modbus RTU reception or to drop the full frame in your case?

Olivier Barthelemy

unread,
Nov 2, 2015, 9:05:41 AM11/2/15
to libmodbus
In my case, i only had an occasional 00 byte, or 0x80 added to my first byte (slave number), but the rest of the frame was ok, so i just filtered that and my error rate decreased a lot.

Here is my ugly modif of v3.0.5:

***************
*** 363,368 ****
--- 366,435 ----
          tv.tv_usec = ctx->response_timeout.tv_usec;
          p_tv = &tv;
      }
+     
+     /******** MODIF **************************/
+     /* First loop to ignore bytes before what could be a valid master or slave number */
+     while(slave_number_found == 0){
+       rc = ctx->backend->select(ctx, &rfds, p_tv, 1);
+       if (rc == -1) {
+             _error_print(ctx, "select");
+             if (ctx->error_recovery & MODBUS_ERROR_RECOVERY_LINK) {
+                 int saved_errno = errno;
+                 if (errno == ETIMEDOUT) {
+                     _sleep_and_flush(ctx);
+                 } else if (errno == EBADF) {
+                     modbus_close(ctx);
+                     modbus_connect(ctx);
+                 }
+                 errno = saved_errno;
+             }
+             return -1;
+       }
+       rc = ctx->backend->recv(ctx, msg, 1);
+       if (rc == 0) {
+           errno = ECONNRESET;
+           rc = -1;
+       }
+       if (rc == -1) {
+           _error_print(ctx, "read");
+           if ((ctx->error_recovery & MODBUS_ERROR_RECOVERY_LINK) &&
+               (errno == ECONNRESET || errno == ECONNREFUSED ||
+                errno == EBADF)) {
+               int saved_errno = errno;
+               modbus_close(ctx);
+               modbus_connect(ctx);
+               /* Could be removed by previous calls */
+               errno = saved_errno;
+           }
+           return -1;
+       }
+       if(msg[0]==ctx->slave || msg[0]==0x80 || msg[0]==ctx->slave+0x80){
+         //slave number found
+         slave_number_found = 1;
+         //1 less byte to read later
+         msg_length++;
+         length_to_read--;
+         //The DSP sometimes returns 0x80 or 0x80+slavenumber in the first byte,
+         //but this 0x80 is not counted for the crc of the frame, so replace it before CRC calculation by the slave number
+         if(msg[0] >= 0x80)
+           msg[0] = ctx->slave;
+         if(ctx->debug)
+           printf("<%.2X>", msg[0]);
+         //get out of the loop
+         break;
+       }else{
+         if (ctx->debug)
+           printf("(%.2X)",msg[0]);
+       }
+     }
+     /* if we have not exited, slave found */
+     
+     /******** END OF MODIF **************************/
  
      while (length_to_read != 0) {
          rc = ctx->backend->select(ctx, &rfds, p_tv, length_to_read);


In modbus.c, before the normal select that waits for the answer frame, i added an other select in a while loop, that will discard the input while it is not the slave number i expect an answer from.
In a more general case, where you could be waiting for an answer from multiple slaves, only the starting 00 can be ignored without risk in my opinion
Reply all
Reply to author
Forward
0 new messages