Recent

Author Topic: TLazSerial : serial port component for Lazarus (windows and linux).  (Read 356945 times)

Jurassic Pork

  • Hero Member
  • *****
  • Posts: 1235
Re: TLazSerial : serial port component for Lazarus (windows and linux).
« Reply #420 on: April 25, 2023, 12:29:28 pm »
Hello,
I'm trying to read data from serial port. In every package has '#' as a first mark and '&' as an end mark but after the end mark there is also 16-bit CRC. With Lazserial it is easy to use "RecvTerminated" but how to get CRC in same package?
Can you show us three data frames (as you received them).
And have you CRLF between data frames ?
Friendly, J.P
« Last Edit: April 25, 2023, 12:57:40 pm by Jurassic Pork »
Jurassic computer : Sinclair ZX81 - Zilog Z80A à 3,25 MHz - RAM 1 Ko - ROM 8 Ko

tetrastes

  • Hero Member
  • *****
  • Posts: 517
Re: TLazSerial : serial port component for Lazarus (windows and linux).
« Reply #421 on: April 25, 2023, 01:53:06 pm »
I'm trying to read data from serial port. In every package has '#' as a first mark and '&' as an end mark but after the end mark there is also 16-bit CRC. With Lazserial it is easy to use "RecvTerminated" but how to get CRC in same package?

Code: Pascal  [Select][+][-]
  1. var
  2.   s: AnsiString;
  3.   CRCHi, CRCLo: byte;
  4. . . .
  5.   s := port.RecvTerminated(100, '&');
  6.   CRCHi := port.RecvByte(10);
  7.   CRCLo := port.RecvByte(10);
  8.   s := s + '&' + chr(CRCHi) + chr(CRCLo);    // If this is really needed

EDIT: Sorry, I forgot that "The resulting string is returned without this termination string!", corrected.
« Last Edit: April 25, 2023, 02:35:17 pm by tetrastes »

Noobie

  • New member
  • *
  • Posts: 8
Re: TLazSerial : serial port component for Lazarus (windows and linux).
« Reply #422 on: April 25, 2023, 05:42:00 pm »
Hello,
I'm trying to read data from serial port. In every package has '#' as a first mark and '&' as an end mark but after the end mark there is also 16-bit CRC. With Lazserial it is easy to use "RecvTerminated" but how to get CRC in same package?
Can you show us three data frames (as you received them).
And have you CRLF between data frames ?
Friendly, J.P

Hi J.P

There is no CRLF between frames.
Here is few examples:

#MASTER;WNER;OBC;169;TD;1;4;0;17.8;92;0;&84B6
#MASTER;TBAR;67.5;TD;7;9;N;22.0;15.8;1;&D407
#TBAR,MASTER,55,RECPT;&088B



tetrastes

  • Hero Member
  • *****
  • Posts: 517
Re: TLazSerial : serial port component for Lazarus (windows and linux).
« Reply #423 on: April 25, 2023, 08:55:07 pm »
Here is few examples:

#MASTER;WNER;OBC;169;TD;1;4;0;17.8;92;0;&84B6
#MASTER;TBAR;67.5;TD;7;9;N;22.0;15.8;1;&D407
#TBAR,MASTER,55,RECPT;&088B

For me "16-bit CRC" is real 16-bit CRC (2 bytes), but you have 4-byte string. Then
Code: Pascal  [Select][+][-]
  1. s := port.RecvTerminated(100, '&');
  2. s := s + '&' + port.RecvBufferStr(4, 10);

BosseB

  • Sr. Member
  • ****
  • Posts: 470
Re: TLazSerial : serial port component for Lazarus (windows and linux).
« Reply #424 on: April 25, 2023, 09:50:21 pm »
Normally when dealing with CRC16 over ascii transmission data the CRC16 is calculated over the complete telegram including the start and end markers, then the CRC16 is added as ASCII HEX representation, which is 4 characters, by the sender after the end marker.
.
The receiving end must localize the start and end of the telegram, then calculate the CRC16 over these bytes and finally compare to the transmitted CRC.
I always convert the received 4-char hex string to a word type variable (or uint16 if you like).
That can then be directly compared to the calculated CRC16 over the received telegram.
If different then discard the telegram.

I have just completed an electricity meter HAN interface app, which will run on an RPiZero W device communicating with the meter using 115200 baud. And I have used the built-in Free-pascal serial unit functionality.
This makes it not depend on the masses of stuff that Synapse brings along and is easily portable to Windows and what have you....
--
Bo Berglund
Sweden

mas steindorff

  • Hero Member
  • *****
  • Posts: 540
Re: TLazSerial : serial port component for Lazarus (windows and linux).
« Reply #425 on: April 25, 2023, 10:42:02 pm »
...
There is no CRLF between frames.
Here is few examples:

#MASTER;WNER;OBC;169;TD;1;4;0;17.8;92;0;&84B6
#MASTER;TBAR;67.5;TD;7;9;N;22.0;15.8;1;&D407
#TBAR,MASTER,55,RECPT;&088B
just to clarify...
you have shown each frame on a separate line. so it was all one line and you when in front of each "#" and press enter?
if not, then there was either a CR or LF char that your capture software as "decoded" for you to show 3 lines
windows 10 &11, Ubuntu 21+ IDE 3.4 general releases

tetrastes

  • Hero Member
  • *****
  • Posts: 517
Re: TLazSerial : serial port component for Lazarus (windows and linux).
« Reply #426 on: April 25, 2023, 10:47:50 pm »
This makes it not depend on the masses of stuff that Synapse brings along and is easily portable to Windows and what have you....

There is no need in "the masses of stuff" of Synapse for serial communications, synaser and synautil (they use synafpc in addition, but I always comment it out) are enough.
« Last Edit: April 25, 2023, 10:53:57 pm by tetrastes »

Noobie

  • New member
  • *
  • Posts: 8
Re: TLazSerial : serial port component for Lazarus (windows and linux).
« Reply #427 on: April 26, 2023, 08:09:13 am »
...
There is no CRLF between frames.
Here is few examples:

#MASTER;WNER;OBC;169;TD;1;4;0;17.8;92;0;&84B6
#MASTER;TBAR;67.5;TD;7;9;N;22.0;15.8;1;&D407
#TBAR,MASTER,55,RECPT;&088B
just to clarify...
you have shown each frame on a separate line. so it was all one line and you when in front of each "#" and press enter?
if not, then there was either a CR or LF char that your capture software as "decoded" for you to show 3 lines

Sorry, my bad. Of course it is like #MASTER;WNER;OBC;169;TD;1;4;0;17.8;92;0;&84B6#MASTER;TBAR;67.5;TD;7;9;N;22.0;15.8;1;&D407#TBAR,MASTER,55,RECPT;&088B  etc.

mas steindorff

  • Hero Member
  • *****
  • Posts: 540
Re: TLazSerial : serial port component for Lazarus (windows and linux).
« Reply #428 on: April 26, 2023, 08:15:59 pm »
In that case, no terminator (no CR LF ), I would treat the stream as binary using the x.WaitingData along with the x.RecvBuffer(@yourFIFO, x.WaitingData) in a loop / thread to move the stream into local memory.  Then you can check to see if you have a full frame by checking to see if your buffer has a "&" and 4 more bytes.   
This is about what I do but in my case, the number of bytes is a value sent shortly after the header "#" is sent.
Another option is to start a timer each time you receive the "#" that should be adequate to receive the rest of the frame but only if yours is a slow device that has large time gaps between frames (like 500ms). 
Mas
windows 10 &11, Ubuntu 21+ IDE 3.4 general releases

Jurassic Pork

  • Hero Member
  • *****
  • Posts: 1235
Re: TLazSerial : serial port component for Lazarus (windows and linux).
« Reply #429 on: April 27, 2023, 07:05:04 am »
Hello,
Sorry, my bad. Of course it is like #MASTER;WNER;OBC;169;TD;1;4;0;17.8;92;0;&84B6#MASTER;TBAR;67.5;TD;7;9;N;22.0;15.8;1;&D407#TBAR,MASTER,55,RECPT;&088B  etc.
You can try this:
I have modified the example project sertest of my component LazSerial :
1 - To calculate CRC16 XModem (it seems that it is the type of CRC of your frames) :
Code: Pascal  [Select][+][-]
  1. function CRC16(Buffer: String): string;  // CRC16 XMODEM
  2. const
  3.   Initial = $0000;
  4.   Polynom = $1021;   // 0001 0000 0010 0001  (0, 5, 12)
  5. var
  6.   i,j: Integer;
  7.   crc: Cardinal;
  8. begin
  9. crc:=Initial;
  10. for i:=1 to Length(Buffer) do begin
  11.   crc:=crc xor (ord(buffer[i]) shl 8);
  12.   for j:=0 to 7 do begin
  13.     if (crc and $8000)<>0 then crc:=(crc shl 1) xor Polynom
  14.     else crc:=crc shl 1;
  15.     end;
  16.   end;
  17. crc :=crc and $ffff;
  18.   CRC16 := IntToHex(crc ,4);
  19. end;    
         
2 - Simulate your frames :
Code: Pascal  [Select][+][-]
  1. procedure TFMain.Timer2Timer(Sender: TObject);
  2. const  StaticInc: Integer = 0;
  3.           Frame : Array[0..2] of string = ('MASTER;WNER;OBC;169;TD;1;4;0;17.8;92;0;',
  4.                                    'MASTER;TBAR;67.5;TD;7;9;N;22.0;15.8;1;',
  5.                                    'TBAR,MASTER,55,RECPT;');
  6. var
  7.   Str: String;
  8. begin
  9.    Str := Frame[StaticInc Mod 3];
  10.    Str := '#' + Str + '&' + CRC16(Str) ;
  11.    Serial.WriteData(Str);
  12.    inc(StaticInc);
  13. end;      
3 - Receive your frames and extract data and crc :
Code: Pascal  [Select][+][-]
  1. procedure TFMain.SerialRxData(Sender: TObject);
  2. var Str : string;
  3. var calcCRC : string;
  4. var data : string; // frame without # & and crc
  5. var crc : string;  // crc received
  6. begin
  7.   try  // adjust timeout if necessary
  8.     Str :=  Serial.SynSer.RecvTerminated(100,'&'); // Synchronize with &
  9.     crc :=  Serial.SynSer.RecvBufferStr(4,100); // crc = 4 chars after &
  10.   except
  11.     exit;  // if timeOut exit  (wait for frames)
  12.   end;
  13.   if pos('#',Str) = 0 then Exit; // if frame not whole exit  (frame lost)
  14.   data := Copy(Str,2,length(Str) -1);  // remove #
  15.   calcCRC := CRC16(data); // calculate CRC
  16.   Memo.Lines.BeginUpdate;
  17.   Memo.Lines.Add('data: ' + data + ' -> ' + crc + ' - CalcCRC: ' + calcCRC  );
  18.   Memo.Lines.EndUpdate;
  19.   Memo.SelStart := Length(Memo.Lines.Text)-1;
  20.   Memo.SelLength:=0;
  21. end;          
           

Seems to be OK with a 2 seconds frame frequency. I don't know if it is working with continuous frames.
Friendly, J.P
Jurassic computer : Sinclair ZX81 - Zilog Z80A à 3,25 MHz - RAM 1 Ko - ROM 8 Ko

Noobie

  • New member
  • *
  • Posts: 8
Re: TLazSerial : serial port component for Lazarus (windows and linux).
« Reply #430 on: April 28, 2023, 02:57:08 pm »
Hello,
Sorry, my bad. Of course it is like #MASTER;WNER;OBC;169;TD;1;4;0;17.8;92;0;&84B6#MASTER;TBAR;67.5;TD;7;9;N;22.0;15.8;1;&D407#TBAR,MASTER,55,RECPT;&088B  etc.
You can try this:
Thank you J.P! Works well.

BeaglePi

  • New Member
  • *
  • Posts: 32
Re: TLazSerial : serial port component for Lazarus (windows and linux).
« Reply #431 on: August 08, 2023, 08:40:04 am »
Hi - I'm afraid that I'm back with an old problem.  I need to use two tLazSerial components in one program. 

One speaks to an Arduino Mega on COM4 at 115200 Baud.  The Arduino replies with the output from a laser.  A question to the Arduino might be: @E121!    The response would be 112 numbers and letters in a fromatted string.

The other tLazSerial communicates with a USB RS485 converter that connects to Alicat mass flow controllers.  It runs at 9600 Baud on COM6.  A question sent to this might be 'A'+#13.  It will reply with a string of numbers and a gas identifier.

All other comms parameters are as usual - 8 databits, no parity, 1 stop bit etc.

The problem is that I cannot use both serial components; only one will work at a time and they will quickly lock up if I try to run both.

Here is my test code with one serial stream commented out and the tLazSerial component deleted.  The timer is set to tick every 2 seconds.

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, ExtCtrls,
  9.   LazSerial;
  10.  
  11. type
  12.  
  13.   { TForm1 }
  14.  
  15.   TForm1 = class(TForm)
  16.     LazSerial2: TLazSerial;
  17.     Memo1: TMemo;
  18.     Timer1: TTimer;
  19.     procedure FormCreate(Sender: TObject);
  20.     procedure Timer1Timer(Sender: TObject);
  21.   private
  22.  
  23.   public
  24.  
  25.   end;
  26.  
  27. var
  28.   Form1: TForm1;
  29.  
  30. implementation
  31.  
  32. {$R *.lfm}
  33.  
  34. { TForm1 }
  35.  
  36. procedure TForm1.FormCreate(Sender: TObject);
  37. begin
  38.  // lazSerial1.Open;
  39. //  lazSerial1.Active:= true ;
  40.   lazSerial2.Open;
  41.   lazSerial2.Active:= true ;
  42. end;
  43.  
  44. procedure TForm1.Timer1Timer(Sender: TObject);
  45. begin
  46. //  lazSerial1.WriteData('@E121!');
  47.  
  48. //  while lazSerial1.DataAvailable do
  49. //    memo1.Lines.add  (lazSerial1.ReadData) ;
  50.  
  51.   lazSerial2.WriteData('A' + #13 );
  52.  
  53.   while lazSerial2.DataAvailable do
  54.     memo1.Lines.add  (lazSerial2.ReadData) ;
  55. end;
  56.  
  57. end.            
  58.  
  59.  


In this case on the Alicats are being talked to.  If I replace lazSerial1 and uncomment the code, it stops working. 

I've tried numerous variants, with separate timers for each component and with time gaps between the calls, but the outcome is the same.

Any suggestions would be gratefully received before I resort to running two programs and IPC.

Thanks


af0815

  • Hero Member
  • *****
  • Posts: 1356
Re: TLazSerial : serial port component for Lazarus (windows and linux).
« Reply #432 on: August 08, 2023, 08:57:41 am »
I use sometimes more than 2 LazSerial. My way:  Drop 2 LazSerial on the form and create the OnRXData Event. Only in this Event read the Data and add it to the meno. Do not read it in a timer, use the Event and store the read data, then read it in the timer if you need it there. With this way of working i can use a lot of LazSerials at one time. On slow devices you read sometimes only chunks of data and have to concat the data up to your end of data, by yourself. 
regards
Andreas

Scalabr

  • New Member
  • *
  • Posts: 22
Re: TLazSerial : serial port component for Lazarus (windows and linux).
« Reply #433 on: August 08, 2023, 01:42:14 pm »
Is there a chance to use TLazSerial and HidApi on the same project?

Jurassic Pork

  • Hero Member
  • *****
  • Posts: 1235
Re: TLazSerial : serial port component for Lazarus (windows and linux).
« Reply #434 on: August 08, 2023, 02:15:37 pm »
hello,
BeaglePi and af0815 what is your O.S ?
it seems that there is a problem on windows when there are two lazserial components : the received buffer of the second Tlazserial component is wrong -> return byte 00 while waitingData number is good. On linux no problem . I have modified the sertest project to have two lazserial components (see attachment). Send simulator data on first port , receive on second port (with null modem cable between the two ports).
Scalabr -> no idea i don't know HidApi
[EDIT] it's OK now  on windows. error in my baud speed parameter of the second TLazserial component  :-[ 

Friendly, J.P 

« Last Edit: August 08, 2023, 06:29:20 pm by Jurassic Pork »
Jurassic computer : Sinclair ZX81 - Zilog Z80A à 3,25 MHz - RAM 1 Ko - ROM 8 Ko

 

TinyPortal © 2005-2018