We are still working on migrating to the new Bosch Connected Industry Online Portal. Stay tuned! Click here for the latest updates.
12-08-2021 02:37 AM
Hello,
I have the following problem with a unit that I programmed for a device connected with RS485.
I am using an EL6022 and the matching Peripheral version 2.0.5.0. I am only using the first channel and it is configured as RS485 in the OES parameters.
I open the channel like this:
_parCfg.iSerialStream.Open(OpconSerialBaudRate.BAUD_9600, OpconSerialDataFrame.FRAME_8E1, OpconSerialHandShakeType.NO_HANDSHAKE);
I successfully send 14 bytes to the device and the device responds according to its protocol documentation. In order to receive the response, I use:
_parCfg.iSerialStream.Read(ADR(_receiveBuffer), 23, _bytesRead, _timeout);
When the Read() method returns OK, the value in _bytesRead is only 22 though, this is my problem. I checked the Input variables of the serial terminal and I can see that the 23rd byte that the device sent me actually sits in the Data In 0 with Input length set to 1. So the device seems to work correctly, the Beckhoff terminal seems to work correctly, but the EL6022 peripheral seems unable to read more than 22 bytes, which is probably because that's how much data the serial terminal catches with its input variables in a single go.
I tried different handshake mechanisms in the Open() parameter but they seem to have no effect (... are they even used with RS485 in general?). I also made sure that the device's parameters are matching the baud rate and parity settings. But could not get the 23 byte response to work correctly with the Nexeed objects.
The device supports another protocol that only has a 19 byte response. If I use this one then the message fits into the buffer and the entire communication works. So it does not seem to be a problem of the device and probably not in my application either.
Are there any known solutions to this problem? I am curious what the root cause is and how to eliminate it, because I really want to use the 23 byte version of the protocol.
Solved! Go to Solution.
12-08-2021 01:13 PM - edited 12-08-2021 01:17 PM
you must call the method Read() until all data has been read
example:
_ret := _parCfg.iSerialStream.Read( ADR(_readArray) + _curReadLen, SIZEOF(_readArray) - _curReadLen, _readBytes, _readTimeout );
IF ( _ret <> RUNNING )
THEN
IF( _ret = OK )
THEN
_curReadLen := _curReadLen + _readBytes;
IF( _readTimeout )
THEN
// set detailed error number
ELSE
IF ( check end sign )
THEN
//end read data
END_IF
END_IF
ELSE
// get error from socket
_lastError := _parCfg.iSerialStream.LastError;
END_IF
END_IF
12-09-2021 02:15 AM
So, I understand that you're saying this behavior is intentional.
If that is the case then I suggest to update the documentation of the Read() method to make this more clear. There are two points that made me believe that it will read the data contineously:
First of all it says that is reading data from the stream. I understand that a stream is basically a representation of a potentially limitless data source, and since I provide it with a buffer, I can read as much as I want in a single call. If it had said "Read a portion of data from the stream, according to the limit of the packet size (stream implementation specific)" or something like that, I would have been more cautious.
The second point is the documentation of the DataLen parameters. It is suggesting that it specifies how much data I will read, but in reality it is _only_ the size of the buffer from pData. Or does it serve any other function as well? It certainly is not the exact number of bytes that will be read, which lead to my example.
Anyway, thanks for clearing it up. I will change my object and give it a try. I am sure it will work since I saw the missing byte already in the IO image. I just didn't feel like this was the right solution haha.
01-28-2022 06:53 AM
Does the same logic actually apply to to Write() as well? If yes, how do I know whether a write timeout occured?
01-30-2022 09:12 PM
For Write() you no need this.