05-12-2010 07:03 AM
06-21-2011 01:38 PM
I have a similar issue... I think I tracked down the problem, and I'm surprised no one has noticed it yet.
In MB Serial Receive.vi, it reads the buffer byte by byte. When it finds a byte that matches its slave address (or 0, for broadcasts), it starts to read other bytes, until it has a message with a matching CRC. Basically, the only thing that delimits the end of a message is the CRC.
Thing is, if the master sends a message to another slave, or if a slave replies to the master, and that message happens to contain a byte that matches this slave address, it will try to read a message from that byte. But it will never get a matching CRC, so it will eventually timeout.
What it SHOULD do: Even if the message is addressed to another slave, read it until you find a CRC match, but don't process it.
Example:
Slave1 is a device, Slave2 is a labview app using this library.
Master -> Slave1: 01 ... CRC1
Slave1 -> Master: 01 ... 02 ... CRC2 (at this point, Slave2 reads "02 ... CRC2", but CRC2 doesn't match because it didn't start the right time. So it keeps reading until it times out)
Master -> Slave2: 02 ... CRC3
(Slave2 probably has something like "02 ... CRC2 02 ... CRC3" in its message at this point, but it still waits for more bytes to make a valid CRC)
06-22-2011 02:31 AM
You are right, it does time out whenever it sees a number that matches a slave address. The modbus RTU timeout does not seem to be correctly calculated either (1.5 characters). However I don't know how to improve this serial slave, without consuming a tremendous amount of CPU.
08-16-2011 03:17 PM
I tried fixing the problem by having the slave listen to all messages, even those not addressed to him, and stop listening once it finds a matching CRC.
But I thought: "What if 2 bytes in a message happen to match the CRC of the previous bytes? Bleh, that'll never happen..."
I tested: The master first sends a msg to slave 1, slave 1 replies. (LabVIEW is slave 2) That very first reply... was:
01 10 07 D6 00 01 E1 45
The CRC-16 of that msg is 0, obviously, but the CRC-16 of this message is also 0: (according to MB CRC-16.vi, anyway)
01 10 07 D6 00 01 E1
So it stopped listening after "E1", and considered "45 ... <whatever the next message was>" to be a message intended to slave #45(hex).
So the only way out of this is to effectively detect the end of a message by detecting a "silence" of at least 3.5 characters... I have no idea how to modify the current code for that, though.
08-16-2011 03:46 PM
One way around that might be to send a fixed numbers of registers to the slave each time. This way the number of bytes should be consistent between messages. Then you could wait until the bytes at port reached that value. Then read the data and decode the modbus info. Recalculate the CRC inside labview code to verify it matches the CRC in the message. Might be helpful to use an opc server as a slave on a computer. Then use portmon to watch the data transfer to see how it is handled.
08-16-2011 03:49 PM - edited 08-16-2011 03:51 PM
The problem is with messages that are addressed to OTHER slaves on the bus (and their replies to the master). I have no control over the content of these messages. Well, we can control the master, but it has to send specific messages to the other device it communicates with.
And as said earlier, if I just ignore these messages (like the code was doing in the first place), there's no way to know when a message should start.
08-17-2011 02:07 AM
The timing seems to be the key. First the message needs to be buffered, in an array, 1 character per index. Knowing the BaudRate, you can calculate the '3.5 character time' and maybe determine the message's start and end. Then look for the correct slave nr. and CRC.
08-17-2011 08:27 AM
I just stumbled on this:
http://iatips.com/modbus_rtu.html#char35
It basically suggests that you can know the length of each message, depending on the function, instead of using a strict 3.5 chars timeout.
08-17-2011 09:20 AM
After reading this article, I agree that network switches etc. (for Modbus IP) or other factors might influence the 3.5 char pause.
However this would mean rewriting the existing Modbus slave, having to process each byte that is read, look for a slave nr, length, then calculate full message lenght, and then check CRC.
08-17-2011 09:33 AM
Yep... exactly...
I'm already knee deep in MB Serial Receive.vi, so I guess I'll give it a try.
If anyone has a better suggestion for debugging it: I had to plant a named notifier in there to throw out some strings that I can read from my test program 😕 I think the VI is dynamically called, and has to be reentrant, so I couldn't figure out how to probe wires in there.