libmodbus icon indicating copy to clipboard operation
libmodbus copied to clipboard

Modbus ASCII issue,

Open Ashis-Github opened this issue 6 years ago • 11 comments

Please read the following carefully before submitting this new issue.

  • Please ensure, that you are really reporting a bug. When in doubt, post a message on https://groups.google.com/forum/#!forum/libmodbus or send an email to [email protected]

  • Please do not open issues to ask questions about using libmodbus. Use the mailing list for this as there are many more people reading that list, who could help you.

  • When using libmodbus from a distribution (Debian, Fedora...), please report the bug first in the bug tracker of the distribution. The reason for doing so is that the package maintainer should have a chance to look at the issue first as it might be a packaging error. If/when the package maintainer comes to the conclusion that is really an upstream bug, then he/she will usually report it here by himself/herself. This is because he/she is interested in staying in the notification chain to decide about a backport as soon as a bugfix is available. Otherwise you (distribution user) will be asked to do so explicitely.

When you get here and you are still convinced that you want report a bug:

  • Use a clear and decriptive title for the issue to identify

  • Which version of libmodbus are you using? you can obtain this information from your package manager or by running pkg-config --modversion libmodbus. You can provide the sha1 of the commit if you have fetched the code with git.

  • Which operating system are you using?

  • Describe the exact steps which reproduce the problem in as many details as possible. For example, the software/equipement which runs the Modbus server, how the clients are connected (TCP, RTU, ASCII) and the source code you are using.

  • Enable the debug mode, libmodbus provides a function to display the content of the Modbus messages and it's very convenient to analyze issues (http://libmodbus.org/docs/latest/modbus_set_debug.html).

Good bug reports provide right and quick fixes!

Finally, thank you very much for using libmodbus and taking the time to file a good bug report. Doing so signals your respect for the developers.

The following template helps you to address the points above. Please delete everything up to and including the following line which starts with ---.


libmodbus version

OS and/or distribution

<e.g. Windows, Linux... version>

Environment

<e.g. CPU architecture, 32 vs. 64 bit...>

Description

<...>

Expected behaviour

<...>

Actual behaviour

<...>

Steps to reproduce the behavior (commands or source code)

<...>

libmodbus output with debug mode enabled

<...>

Ashis-Github avatar Mar 14 '18 05:03 Ashis-Github

I'm using libmodbus for ASCII. I'm able to send the request but i'm not getting any response. Can you please help. here is my code below.

modbus_t *ctx = modbus_new_ascii("COM4", 9600, 'N', 8, 1);
int retVal = modbus_set_slave(ctx, 1);
if (retVal == -1)
{
	// no error
}
retVal = modbus_connect(ctx);
if (retVal == -1)
{
	// no error
}

uint16_t tab_reg[32];
memset(tab_reg, 0, 1 * sizeof(tab_reg));

retVal = modbus_read_registers(ctx, 25,1, tab_reg);
if (retVal == -1)
{
	// retrun -1 always
}

Ashis-Github avatar Mar 14 '18 05:03 Ashis-Github

What does the documentation for modbus_read_registers say? What would a negative value for parameter number 3 mean?

karlp avatar Mar 14 '18 09:03 karlp

  1. My appology, this is type error.@karlp
  2. While sending this info to slave, I have monitored the port(COM4), it looks like timeout error. Can anyone suggest why it's that. Did I miss anything.
  3. It throws MODBUS_EXCEPTION_GATEWAY_TARGET exception. what's this mean.

Ashis-Github avatar Mar 14 '18 10:03 Ashis-Github

most likely the remote device doesn't understand you and ignored you. You are either using the wrong protocol, wrong wiring (on the other side of your gateway) or have the wrong configuration of your gateway/port/device itself. I don't believe you have any issue that can be resovled with libmodbus tickets though.

karlp avatar Mar 14 '18 16:03 karlp

By considering your input i have sent the same Ascii frame to the same remote device by using some other external modus send tool. Im getting respnse in this way. So here we can't say this is the problem with remote device or any configuration issue.

Ashis-Github avatar Mar 15 '18 02:03 Ashis-Github

I would guess you didn't send the same frame then :) if you turn on libmodbus' debug, you can see the bytes sent and received printed out. You can compare that with what your other tool has done.

karlp avatar Mar 15 '18 09:03 karlp

I have send the same request(:010300190001E3) using libmodbus dll from my client code. I have used some external tool to monitor that particular port, I'm getting response i.e. :0103020903 and status is always success. But in the libmodbus dll client code I'm getting always return value -1. That means device sending response. But my libmodbus dll is unable to handle this response. Correct me if I'm wrong. If something I can look into the dll code, pls let me know.

Ashis-Github avatar Mar 19 '18 06:03 Ashis-Github

Hi guys,

I have a similar problem in Modbus Ascii. In short, modbus_connect works correctly, but a subsequent call to modbus_write_bit yields -1.

The debug mode told that the library have received the confirmation incorrectly. After looking into the error, I have found that the problem originate from _modbus_receive_msg in modbus.c. _modbus_receive_msg somehow reads a wrong massage from a serial port (and sometime incomplete) An external tool confirms that a device sends back right confirmation.

A quick workaround for this would be to change

while (length_to_read != 0) { rc = ctx->backend->select(ctx, &rset, p_tv, length_to_read); if (rc == -1) {

in modbus.c line 386 to

while (length_to_read != 0) { rc = ctx->backend->select(ctx, &rset, p_tv, 1); if (rc == -1) {

I don't know how or why this works and the previous one doesn't. The error only happened in windows. Maybe something about windows' API?

KorlaMarch avatar Aug 21 '18 10:08 KorlaMarch

@Ashis-Github where did you get modbus_ascii function from, i have been trying it here and i couldn't get anything. Can you help me out here. Thank you!

Moinelly avatar Dec 25 '18 11:12 Moinelly

@Ashis-Github @Moinelly I would like to know, where there modbus_ascii function, the latest libmodbus, I did not find.

DLFenFen avatar Aug 23 '21 02:08 DLFenFen

Hi guys,

I have a similar problem in Modbus Ascii too in 2022! I think the library in Windows have received the confirmation incorrectly indeed.

The library uses win32_ser_select to receive a msg from a serial port and win32_ser_read to read the msg from win32_ser.buf. win32_ser_select may receive some bytes according to length_to_read in modbus.c and _modbus_ascii_recv (calls win32_ser_read)read character by character to convert each character into byte, but when reading character from the win32_ser.buf, memcpy starts with the same source address(win32_ser.buf[0]) every time(in modbus-serial.c, line 111). That means if win32_ser_select receives data ':01', _modbus_ascii_recv may convert it to ':::' wrongly. That's the problem.

@KorlaMarch 's quick workaround works since win32_ser_select always receives one character now. Another way to avoid this problem is to add a pointer to struct win32_ser to save the position every time the libarary calls win32_ser_read. I have no idea which is better...

Add pos in modbus-serial-private.h

struct win32_ser {
    /* File handle */
    HANDLE fd;
    /* Receive buffer */
    uint8_t buf[PY_BUF_SIZE];
    /* Received chars */
    DWORD n_bytes;
    /* win32_ser_read position */
    uint8_t* pos;
};

change pos in win32_ser_read

int win32_ser_read(struct win32_ser *ws, uint8_t *p_msg,
                   unsigned int max_len)
{
    unsigned int n = ws->n_bytes;
    if (max_len < n) {
        n = max_len;
    }
    if (ws->pos - ws->buf > PY_BUF_SIZE || ws->pos -ws->buf < -PY_BUF_SIZE) {
        assert(0);
        ws->pos = ws->buf;
    }
    if (n > 0) {
        memcpy(p_msg, ws->pos, n);
    }
    ws->n_bytes -= n;
    ws->pos += n;
    return n;
}

reset pos when receiving new message

if (ReadFile(ws->fd, &ws->buf, max_len, &ws->n_bytes, NULL)) {
    /* Check if some bytes available */
    if (ws->n_bytes > 0) {
        /* Some bytes read */
	ws->pos = ws->buf;
        return 1;
    } else {
        /* Just timed out */
        return 0;
    }
} else {

blackpencil2019 avatar Jan 19 '22 08:01 blackpencil2019