Recent

Author Topic: How to disable the LineBuffer of LazSerial/Synapse  (Read 16934 times)

tetrastes

  • Hero Member
  • *****
  • Posts: 762
Re: How to disable the LineBuffer of LazSerial/Synapse
« Reply #15 on: February 23, 2022, 12:12:42 am »
One more solution, though I think it's not good:
Every time when you want to read from port
- Connect
- Config
- wait for new 25 bytes
- read
- CloseSocket
 :-\

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: How to disable the LineBuffer of LazSerial/Synapse
« Reply #16 on: February 23, 2022, 01:37:55 am »
Based on reading the source code, *Ex functions use the internal buffer which is causing your problem. When you need the latest data, use WaitingData to find how many bytes are waiting. And use RecvBuffer to read them.

If the number of bytes is more than what you need, read them all and use only the part at the end of the buffer.

tetrastes

  • Hero Member
  • *****
  • Posts: 762
Re: How to disable the LineBuffer of LazSerial/Synapse
« Reply #17 on: February 23, 2022, 09:18:30 am »
I think the problem is not in internal buffer (property LineBuffer). RecvBuffer tries to read N bytes from port (i.e port's internal input buffer), if there are more than N bytes in port's internal buffer, they remain in it. The *Ex functions read all available bytes from port to LineBuffer, clearing port's internal input buffer, and then try to read N bytes from LineBuffer,  if there are more than N bytes in LineBuffer, they remain in LineBuffer. To my mind they are preferably, as they clean port's internal input buffer.
This is simply double buffering. In any case you cannot avoid buffering, cause modern OSes cannot read data from ports immediately as they arrive.
Quote
use WaitingData to find how many bytes are waiting. And use RecvBuffer to read them.
This is simply manually doing the same, what *Ex functions do in RecvPacket.
« Last Edit: February 23, 2022, 09:26:48 am by tetrastes »

tetrastes

  • Hero Member
  • *****
  • Posts: 762
Re: How to disable the LineBuffer of LazSerial/Synapse
« Reply #18 on: February 23, 2022, 09:48:41 am »
Based on reading the source code, *Ex functions use the internal buffer which is causing your problem. When you need the latest data, use WaitingData to find how many bytes are waiting. And use RecvBuffer to read them.

If the number of bytes is more than what you need, read them all and use only the part at the end of the buffer.

In this case you have to check that this part is 25 bytes of full last data, not 15 from previous and 10 from the last. RecvPacket does it for you, as it has timeout.

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: How to disable the LineBuffer of LazSerial/Synapse
« Reply #19 on: February 23, 2022, 08:17:54 pm »
@tetrastes, some of *Ex functions will not read the actual serial port if LineBuffer has enough to satisfy the request. As for your second point, WaitingData gives you the number of bytes available. It is simple to get the most recent complete 25 bytes.

tetrastes

  • Hero Member
  • *****
  • Posts: 762
Re: How to disable the LineBuffer of LazSerial/Synapse
« Reply #20 on: February 23, 2022, 09:34:48 pm »
@tetrastes, some of *Ex functions will not read the actual serial port if LineBuffer has enough to satisfy the request.
Yes, and what? Think and you will see that reading directly from port you will read the same bytes from port's internal input buffer.

Quote
As for your second point, WaitingData gives you the number of bytes available. It is simple to get the most recent complete 25 bytes.
I didn't write that it is very difficult. I wrote that you have to check it, and you may use RecvPacket for this, instead of reinventing the wheel.
And I wrote that because
Quote
If the number of bytes is more than what you need, read them all and use only the part at the end of the buffer.
is not enough.

« Last Edit: February 23, 2022, 09:44:56 pm by tetrastes »

Muso

  • Sr. Member
  • ****
  • Posts: 362
Re: How to disable the LineBuffer of LazSerial/Synapse
« Reply #21 on: February 23, 2022, 09:42:23 pm »
Thanks to you both.
But now I am a bit confused. What exactly should I do, omit the *Ex functions or not?

tetrastes

  • Hero Member
  • *****
  • Posts: 762
Re: How to disable the LineBuffer of LazSerial/Synapse
« Reply #22 on: February 23, 2022, 09:51:43 pm »
Thanks to you both.
But now I am a bit confused. What exactly should I do, omit the *Ex functions or not?

I think that you know my answer already: not.  ;)

Muso

  • Sr. Member
  • ****
  • Posts: 362
Re: How to disable the LineBuffer of LazSerial/Synapse
« Reply #23 on: March 03, 2022, 07:57:50 pm »
I am a bit desperate meanwhile because I cannot resolve the issue and it seems there is a bug in synaser/LazSerial:

To summarize:
- I need to readout data from sensors
- According to the datasheet, the sensors should send every 1.7 seconds 25 bytes. Tests revealed however, that some sensors send every 2.0, some even only every 2.2 seconds. So I cannot use a fixed readout timer.
- I read now every 2.5 seconds and do this:
 
Code: Pascal  [Select][+][-]
  1.  // we want the latest/last data
  2.   while serSensor.WaitingData > 24 do
  3.    k:= serSensor.RecvBuffer(@dataArray[0], 25);
  4.   // attempt to completely empty the buffer by reading the remaining bytes
  5.   while serSensor.WaitingData > 0 do
  6.    serSensor.RecvByte(100);

I do the latter because I debugged that after about 5 minutes, after the last 25 byte readouts, there are 22 or 19 bytes left.

The problem is now that after about an hour, WaitingData tells me it has no bytes to be read, but when I nevertheless readout 25 bytes, I get 25 bytes and their checksum is correct.
Therefore, hour by hour I don't get the current sensor data but some older data.

I have no idea how to fix this.

After hours of debugging I also found out that when I have after
Code: Pascal  [Select][+][-]
  1. while serSensor.WaitingData > 24 do
  2.    k:= serSensor.RecvBuffer(@dataArray[0], 25);
e.g. 22 bytes left and readout 25, I get 25 bytes and their checksum is OK.

So my problem is that I cannot rely on WaitingData since it reports me often wrong info.

Can I flush the buffer somehow? Or is there a way to readout bytes until I get an error, that there are really no bytes? If so, how can I do this assuring that the COM connection is not closed?

tetrastes

  • Hero Member
  • *****
  • Posts: 762
Re: How to disable the LineBuffer of LazSerial/Synapse
« Reply #24 on: March 04, 2022, 09:51:01 am »
You have to read docs and sources carefully:
Code: Pascal  [Select][+][-]
  1.     {:Waits until the allocated buffer is filled by received data. Returns number
  2.      of data bytes received, which equals to the Length value under normal
  3.      operation. If it is not equal, the communication channel is possibly broken.
  4.  
  5.      This method not using any internal buffering, like all others receiving
  6.      methods. You cannot freely combine this method with all others receiving
  7.      methods!}
  8.     function RecvBuffer(buffer: pointer; length: integer): integer; virtual;
  9.  
Thus:
1. You combine RecvBuffer with RecvByte, which uses LineBuffer.
2. RecvBuffer has nothing to do with the result of WaitingData, unless you put it in length parameter. It waits for length (in your case 25) bytes and returns after receiving them all or after some timeout, which may be even infinite. In Windows it calls WaitForSingleObject(FHandle, FDeadlockTimeout), and by default FDeadlockTimeout = 30000(ms). In Unixes this timeout is leaved for OS default, as I understand it.

P.S. It seems to me that you try to reinvent the wheel...
« Last Edit: March 04, 2022, 10:07:44 am by tetrastes »

Muso

  • Sr. Member
  • ****
  • Posts: 362
Re: How to disable the LineBuffer of LazSerial/Synapse
« Reply #25 on: March 04, 2022, 01:45:15 pm »
P.S. It seems to me that you try to reinvent the wheel...

OK, but how should I do it right? Do you have a code example for me? I am working on this for days, and cannot get it to work.

I think If I can every 2.5 seconds readout date from the serial port, and NOT the LineBuffer, I should be happy. I am on Windows 10.

In my desperation I tried out this:
Code: Pascal  [Select][+][-]
  1. while serSensor.WaitingData > 24 do
  2.    k:= serSensor.RecvBuffer(@dataArray[0], 25);
  3.   // attempt to completely empty the buffer by reading the remaining bytes
  4.   while serSensor.WaitingData > 0 do
  5.    serSensor.RecvBuffer(@wasteArray[0], 1);
  6.   while serSensor.WaitingDataEx > 0 do
  7.    serSensor.RecvByte(100);

But still the same result.

Can I omit the result of WaitingData and just do this?:
Code: Pascal  [Select][+][-]
  1. k:= serSensor.RecvBuffer(@dataArray[0], 25);

tetrastes

  • Hero Member
  • *****
  • Posts: 762
Re: How to disable the LineBuffer of LazSerial/Synapse
« Reply #26 on: March 04, 2022, 02:22:22 pm »
I think If I can every 2.5 seconds readout date from the serial port, and NOT the LineBuffer, I should be happy. I am on Windows 10.

Well, not reinventing the wheel...

Code: Pascal  [Select][+][-]
  1. var
  2. s, t: AnsiString;   // to be precise
  3.  
  4. begin
  5.    s := '';
  6.    repeat
  7.        t := serSensor.RecvPacket(100);   // Choose appropriate timeout
  8.        s := s + t;
  9.    until t = '';
  10. end;
« Last Edit: March 04, 2022, 02:38:39 pm by tetrastes »

Muso

  • Sr. Member
  • ****
  • Posts: 362
Re: How to disable the LineBuffer of LazSerial/Synapse
« Reply #27 on: March 04, 2022, 03:48:38 pm »
Code: Pascal  [Select][+][-]
  1.        t := serSensor.RecvPacket(100);   // Choose appropriate timeout

OK, but this returns a string and I need a array of bytes. How to I readout the bytes from the AnsiString?
(This questions might sound beginner-like, in this respect I am a beginner because up to now I only had to deal with strings, this is my first task where I get a byte array from a serial port.)

tetrastes

  • Hero Member
  • *****
  • Posts: 762
Re: How to disable the LineBuffer of LazSerial/Synapse
« Reply #28 on: March 04, 2022, 07:50:48 pm »
OK, but this returns a string and I need a array of bytes. How to I readout the bytes from the AnsiString?
(This questions might sound beginner-like, in this respect I am a beginner because up to now I only had to deal with strings, this is my first task where I get a byte array from a serial port.)

AnsiString is already an array of bytes (well, chars) with some stuff, so the base is
Code: Pascal  [Select][+][-]
  1. some_byte := byte(some_string[i]);
and so on...
There are too many variants depending on what you need.
« Last Edit: March 04, 2022, 08:13:00 pm by tetrastes »

Muso

  • Sr. Member
  • ****
  • Posts: 362
Re: How to disable the LineBuffer of LazSerial/Synapse
« Reply #29 on: March 04, 2022, 08:19:04 pm »
Code: Pascal  [Select][+][-]
  1. var
  2. s, t: AnsiString;   // to be precise
  3. begin
  4.    s := '';
  5.    repeat
  6.        t := serSensor.RecvPacket(100);   // Choose appropriate timeout
  7.        s := s + t;
  8.    until t = '';
  9. end;

I tried this but this kills the serial connection immediately.  serSensor.LastError becomes 9997.

 

TinyPortal © 2005-2018