Recent

Author Topic: Easy way to send / receive raw binary data bytes on a Serial / COM port?  (Read 4270 times)

741

  • New Member
  • *
  • Posts: 27
Hi

Is there a package like AsyncFree or AsyncPro for Lazarus?

I had thought TLazSerial was the easiest solution - but I have to Tx/Rx raw binary data.

Regards
Stephen

jamie

  • Hero Member
  • *****
  • Posts: 7774
Re: Easy way to send / receive raw binary data bytes on a Serial / COM port?
« Reply #1 on: January 21, 2024, 03:55:02 pm »
You are after my heart "LM741"  :D

There are a couple of sources, SERIAL unit and or LazSerial component you can install.


What exactly is the issue here? You can't bit bang an IO pin so easy in windows, although you can do it via the standard method of control API but still, you won't get the response time if it needs to be critical.
« Last Edit: January 21, 2024, 03:59:07 pm by jamie »
The only true wisdom is knowing you know nothing

MarkMLl

  • Hero Member
  • *****
  • Posts: 8572
Re: Easy way to send / receive raw binary data bytes on a Serial / COM port?
« Reply #2 on: January 21, 2024, 04:00:47 pm »
Is there a package like AsyncFree or AsyncPro for Lazarus?

I had thought TLazSerial was the easiest solution - but I have to Tx/Rx raw binary data.

Serial.pp is OK if you're happy managing your own threads etc., I use it routinely for bench equipment.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12905
  • FPC developer.
Re: Easy way to send / receive raw binary data bytes on a Serial / COM port?
« Reply #3 on: January 21, 2024, 04:03:27 pm »
I use tcomport.

ccrause

  • Hero Member
  • *****
  • Posts: 1117
Re: Easy way to send / receive raw binary data bytes on a Serial / COM port?
« Reply #4 on: January 21, 2024, 05:06:43 pm »
Is there a package like AsyncFree or AsyncPro for Lazarus?
Several options, some are listed here: https://wiki.freepascal.org/Hardware_Access#Serial_Communication

Quote
I had thought TLazSerial was the easiest solution - but I have to Tx/Rx raw binary data.
Yes, TLazSerial does not expose the ReadBuffer function of the underlying Synapse library.  You can always copy your binary data into and out of strings, but it will smell like a hack.  Or use SynaSer, but then you have to handle blocking reads in your code.

I usually work with the serial unit, but it may be a little too low level for some. Else try some of the other options.

jamie

  • Hero Member
  • *****
  • Posts: 7774
Re: Easy way to send / receive raw binary data bytes on a Serial / COM port?
« Reply #5 on: January 21, 2024, 05:38:32 pm »
If you don't checkmark the "RcvLineCRLF" property then the String contains RAW data which translates to a Dynamic Array at the end, since strings and hold anything, including #0 chars.

 If you do use the CRLF options then the data is split between those incoming line endings.
The only true wisdom is knowing you know nothing

avra

  • Hero Member
  • *****
  • Posts: 2592
    • Additional info
Re: Easy way to send / receive raw binary data bytes on a Serial / COM port?
« Reply #6 on: January 23, 2024, 08:53:58 pm »
If you are interested in file transfer over serial connection you need something like XMODEM, YMODEM or ZMODEM from ancient modem era.

I have not tested this one based on LazSerial:    ;D
https://github.com/ivang78/xmodem
ct2laz - Conversion between Lazarus and CodeTyphon
bithelpers - Bit manipulation for standard types
pasettimino - Siemens S7 PLC lib

Jurassic Pork

  • Hero Member
  • *****
  • Posts: 1290
Re: Easy way to send / receive raw binary data bytes on a Serial / COM port?
« Reply #7 on: January 24, 2024, 04:36:33 pm »
Hello,
I had thought TLazSerial was the easiest solution - but I have to Tx/Rx raw binary data.
When you receive a packet of data how do you know that you have received the end of the packet ? size ? timeout ? end sequence ? other thing ?

Friendly, J.P
Jurassic computer : Sinclair ZX81 - Zilog Z80A à 3,25 MHz - RAM 1 Ko - ROM 8 Ko

CCRDude

  • Hero Member
  • *****
  • Posts: 615
Re: Easy way to send / receive raw binary data bytes on a Serial / COM port?
« Reply #8 on: January 24, 2024, 05:07:22 pm »
That's totally up to the protocol you use.
The serial connection on itself is just a stream.

It has already been mentioned that sometimes a CRLF is used as a separator, but since you mention raw binary data, it depends on whether you have control over the sender.

* You could send the length first, then the raw data, so on the receiving end, you will first read the length, then the according number of bytes.
* You could define a magic, but then you need to escape that magic if it appears within the actual data.
...

Or you don't have control, in which case the documentation of the sender will hopefully include some kind of protocol definition that helps you recognize the end.

741

  • New Member
  • *
  • Posts: 27
Re: Easy way to send / receive raw binary data bytes on a Serial / COM port?
« Reply #9 on: January 28, 2024, 06:44:31 pm »
Thanks for all the ideas.

Well, I might be tempted to use the fact that "the String contains RAW data which translates to a Dynamic Array at the end"

I'll need to re-read something on how that works first though - and I agree with the point "you can always copy your binary data into and out of strings, but it will smell like a hack.".

Basically it's partly down to convenience and expediency for now - I am converting an existing Delphi project which worked reasonably well. I'd need a way to invoke/populate a list of available COM ports, and that seems to be straightforward with LazSerial.


With 'AsyncFree" an event would occur when "some bytes" had arrived. I do not know what sets the way buffers are flushed etc, although there was a user-defined buffer size. For instance if the remote device sends 100 bytes, waits a second, then sends 100 more bytes, I never knew for sure how the data would be bunched by the USB/serial drivers.

The far side is a USB capable PIC. I'm reading and writing a protocol which is 'binary' - it is not ASCII.

It's ages since I used the project, but I think the protocol defines the packet length in the first 2 bytes.

741

  • New Member
  • *
  • Posts: 27
Re: Easy way to send / receive raw binary data bytes on a Serial / COM port?
« Reply #10 on: January 28, 2024, 07:33:13 pm »
Um... Just started some research on how to treat the 'ansistring' type as a byte array and it is not clear to me. This is what I've gathered so far -

In TLazSerial we find
{$H+}
...
   function ReadData: string;

According to Lazarus Help:
   "If the switch is on {$H+}, AND there is a maximum length (the size) specifier, the declaration is a short string declaration".
   "If no size and code page specifier are present, the above declaration can declare an ansistring OR a short string"
   
But - there is no length specifier. Here is ReadData:

Code: Pascal  [Select][+][-]
  1.    function TLazSerial.ReadData: string;
  2.    begin
  3.      result:='';
  4.      if FSynSer.Handle=INVALID_HANDLE_VALUE then
  5.        ComException('can not read from a closed port.');
  6.      if FRcvLineCRLF then
  7.          result:=FSynSer.RecvString(0)
  8.      else
  9.          result:=FSynSer.RecvPacket(0);  //<---I'll be wanting this option
  10.    end;
       
   
In LazSynaSer:   
   function Recvstring(timeout: integer): AnsiString; virtual;   
   function RecvPacket(Timeout: Integer): AnsiString; virtual; 

   
Back in Help:
   "Ansistrings are strings that have no length limit, and have a code page associated with them2. They are reference counted and are guaranteed to be null terminated.""
   "Internally, an ansistring is treated as a pointer"
   "The null-termination does not mean that null characters (char(0) or #0) cannot be used: the null-termination is not used internally, but is there for convenience when dealing with external routines that expect a null-terminated string"
   "When an ansistring is declared, the Free Pascal compiler initially allocates just memory for a pointer, not more."
   
   The Length function must be used to get the length of an ansistring: the length is not stored at character 0 of the ansistring. The construct
    L:=ord(S[0]);
   which was valid for Turbo Pascal shortstrings, is no longer correct for Ansistrings. The compiler will warn if such a construct is encountered.       

   Ansistrings can be typecast to PChar or Pointer types:

   Var P : Pointer; 
       PC : PChar; 
       S : AnsiString; 

   begin 
     S :='This is an ansistring'; 
     PC:=Pchar(S); 
     P :=Pointer(S);
     ...

cdbc

  • Hero Member
  • *****
  • Posts: 2818
    • http://www.cdbc.dk
Re: Easy way to send / receive raw binary data bytes on a Serial / COM port?
« Reply #11 on: January 28, 2024, 07:53:18 pm »
Hi
Well, look for a property "RcvLineCRLF" or "LineCRLF" in TLazSerial.
It determines, if to read a string terminated by crlf og just read the buffered data...
Q) There is no "TLazSerial.ReadPacket" ?!?
If not, can you surface such a method from protected?!?
Regards Benny
If it ain't broke, don't fix it ;)
PCLinuxOS(rolling release) 64bit -> KDE6/QT6 -> FPC Release -> Lazarus Release &  FPC Main -> Lazarus Main

jamie

  • Hero Member
  • *****
  • Posts: 7774
Re: Easy way to send / receive raw binary data bytes on a Serial / COM port?
« Reply #12 on: January 28, 2024, 08:00:37 pm »
use a RawByteString to store the return.

The length of the string is marked outside of the characters within the string.

So using a Pchar(MyRawByteString) and a known length of the string will signal the end of the string.

#0 characters can exist within the string.

So the index value for Pchar needs to be one less than the Length(MyRawString);

of course, if Length returns 0 and you do subtract one in code you can simply test for <=0 etc.
The only true wisdom is knowing you know nothing

741

  • New Member
  • *
  • Posts: 27
Re: Easy way to send / receive raw binary data bytes on a Serial / COM port?
« Reply #13 on: January 28, 2024, 08:08:00 pm »
OK thank you, I will look up "RawByteString", which is new to me.

 

TinyPortal © 2005-2018