Confirmation Receiving Partial Echo of Transmission

146 views
Skip to first unread message

Jake Reher

unread,
May 8, 2015, 7:08:43 PM5/8/15
to libm...@googlegroups.com
Hello,

I am attempting to send a series of commands at 5ms intervals to an RS485-RTU device via a laptop and usb->RS485 converter. The slave will actually accept the write commands, execute them, and sends back the confirmation. The problem that I am experiencing is that what is coming back to the libmodbus debug messages as the confirmation contains a partial echo of the transmission. It might be important to note that this is completely repeatable. Every time the program is executed, the confirmation responses are always the same.

The wiring is properly attached and is grounded to the slave. I am using BAUD=115200, stop bits =1, parity = N. I put the output of the program below and a sample of the code:

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

int main(int argc, char **argv) { 

const char *device = "/dev/ttyUSB1";
modbus_t *TMC;
int ret;

// Create the serial device
TMC = modbus_new_rtu(device, 115200, 'N', 8, 1);
// STANDARD ERROR CATCHING CODE OMITTED

modbus_set_debug(TMC, TRUE);

// Set the slave address
ret = modbus_set_slave(TMC, 0x1F);
// STANDARD ERROR CATCHING CODE OMITTED

// SET SERIAL MODE TO RS485
modbus_rtu_set_serial_mode(TMC, MODBUS_RTU_RS485);
// Set RTS MODE
modbus_rtu_set_rts(TMC, MODBUS_RTU_RTS_UP);

// Connect to the modbus
if (modbus_connect(TMC) == -1) {
// STANDARD ERROR CATCHING CODE OMITTED
}

uint16_t startup[1];
startup[0] = 1;
ret = modbus_write_registers(TMC, 0x0001, 1, startup);
// STANDARD ERROR CATCHING CODE OMITTED

uint16_t frequency[1];
frequency[0] = 1000;
for (int i = 0; i<5; i++) {
modbus_write_registers(TMC, 0x0002, 1, frequency);
usleep(50000);
}


modbus_close(TMC);
modbus_free(TMC);
return 0;
}




Sending request using RTS signal

ERROR CRC received 0x200 != CRC calculated 0x53B7

Invalid CRC

Sending request using RTS signal

The responding slave 1 isn't the requested slave 31

Response not from requested slave

Response not from requested slave

Sending request using RTS signal

ERROR CRC received 0x153 != CRC calculated 0x7050

Invalid CRC

Invalid CRC

Sending request using RTS signal

The responding slave 183 isn't the requested slave 31

Response not from requested slave

Response not from requested slave

Sending request using RTS signal

ERROR CRC received 0x2612 != CRC calculated 0x843C

Invalid CRC

Invalid CRC

Sending request using RTS signal

Opening /dev/ttyUSB1 at 115200 bauds (N, 8, 1)

[1F][10][00][01][00][01][02][00][01][E7][E1]

Waiting for a confirmation...

<1F><10><00><01><00><01><02><00>

[1F][10][00][02][00][01][02][00][00][26][12]

Waiting for a confirmation...

<01><E7><E1><1F><10>

Request for slave 1 ignored (not 31)

[1F][10][00][02][00][01][02][00][00][26][12]

Waiting for a confirmation...

<00><01><00><01><53>

[1F][10][00][02][00][01][02][00][00][26][12]

Waiting for a confirmation...

<B7><1F><10><00><02>

Request for slave 183 ignored (not 31)

[1F][10][00][02][00][01][02][00][00][26][12]

Waiting for a confirmation...

<00><01><02><00><00><26><12>

[1F][10][00][02][00][01][02][00][00][26][12]

Waiting for a confirmation...

<1F><10><00><02><00><01><A3><B7>


Is there anyone who has seen this type of behavior when using libmodbus? I would imagine that the software would not be requesting a read while the transmission is still taking place, are there any settings in libmodbus rtu that I might be missing to cause this on the software end?

Thanks in advance!

Chuck Watson

unread,
May 9, 2015, 8:41:00 AM5/9/15
to libm...@googlegroups.com

Slow down. 5ms is much more  than RS485 can handle in general.

 

Slow your interval to 1 second and verify if everything works correctly. Then start testing by shortening the interval.

 

However, the bigger the RS485 network (cable length, cable type, number of devices, etc.), the slower the response rate will be able to be.

 

Chuck Watson BS, CEM, CMVP

Direct USA 724-799-1529

www.EnergyChaser.com

--
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.

image001.gif

Jake Reher

unread,
May 9, 2015, 3:40:45 PM5/9/15
to libm...@googlegroups.com
Thanks for the quick reply Chuck,

I apologize, there was a typo in the original statement on the timing, I meant to say 50ms intervals. In any event, we tried the same loop at 1s intervals as suggested and the confirmation packets were identical. This led us to believe that the serial line was populating the receive buffer while the transmission was still taking place, or holding onto an echo in the buffer before the slave has responded.

We actually were able to solve this issue today by changing the source code in modbus-rtu.c (we are using libmodbus 3.1.2). Specifically, moved the _modbus_rtu_flush declaration above _modbus_rtu_send, and we call the _modbus_rtu_flush immediately after the write process to clear the buffer of the echo. Everything works like a charm with this modification.

static int _modbus_rtu_flush(modbus_t *);

static ssize_t _modbus_rtu_send(modbus_t *ctx, const uint8_t *req, int req_length)
{
#if defined(_WIN32)
    modbus_rtu_t *ctx_rtu = ctx->backend_data;
    DWORD n_bytes = 0;
    return (WriteFile(ctx_rtu->w_ser.fd, req, req_length, &n_bytes, NULL)) ? (ssize_t)n_bytes : -1;
#else
#if HAVE_DECL_TIOCM_RTS
    modbus_rtu_t *ctx_rtu = ctx->backend_data;
    if (ctx_rtu->rts != MODBUS_RTU_RTS_NONE) {
        ssize_t size;

        if (ctx->debug) {
            fprintf(stderr, "Sending request using RTS signal\n");
        }

        _modbus_rtu_ioctl_rts(ctx->s, ctx_rtu->rts == MODBUS_RTU_RTS_UP);
        usleep(_MODBUS_RTU_TIME_BETWEEN_RTS_SWITCH);

        size = write(ctx->s, req, req_length);

        usleep(ctx_rtu->onebyte_time * req_length + _MODBUS_RTU_TIME_BETWEEN_RTS_SWITCH);
        _modbus_rtu_ioctl_rts(ctx->s, ctx_rtu->rts != MODBUS_RTU_RTS_UP);

+++++   _modbus_rtu_flush(ctx);

        return size;
    } else {
#endif
        return write(ctx->s, req, req_length);
#if HAVE_DECL_TIOCM_RTS
    }
#endif
#endif
}


Reply all
Reply to author
Forward
0 new messages