Recent

Author Topic: Reading and sending data in sequence, COM port.  (Read 7641 times)

dawid75_75

  • New Member
  • *
  • Posts: 14
Reading and sending data in sequence, COM port.
« on: December 03, 2016, 10:10:44 am »
Hello everyone :)
I have to solve some problem. I would like to implement that algorithm in Lazarus:
1) send a command to the COM port;
2) wait for response;
3) some function which uses data from response;
4) send next command to the COM port;
5) wait for response;
6) another function which uses data from response
and so on.
This sequence could be called every 1 sec by Timer in OnTimer event.
What's important - every command, response data and function which uses rersponse data is different!

Something like using UART polled mode in MCU.
I don't know how to do it in Lazarus when everything about COM port is set in procedures.

Do you have any ideas? :)
BR,
Dawid.

BlueIcaro

  • Hero Member
  • *****
  • Posts: 792
    • Blog personal
Re: Reading and sending data in sequence, COM port.
« Reply #1 on: December 03, 2016, 10:21:12 am »

derek.john.evans

  • Guest
Re: Reading and sending data in sequence, COM port.
« Reply #2 on: December 03, 2016, 10:39:54 am »
The Serial unit (which comes with FreePascal) works for me. I wrapped it in a TStream based class, so I have code which works for either TCP or COM.

https://sourceforge.net/p/cobado/code/HEAD/tree/server/ucobadoserial.pas




derek.john.evans

  • Guest
Re: Reading and sending data in sequence, COM port.
« Reply #3 on: December 03, 2016, 11:10:46 am »
BTW: I found this tool helped with serial development.
https://sourceforge.net/projects/com0com/

dawid75_75

  • New Member
  • *
  • Posts: 14
Re: Reading and sending data in sequence, COM port.
« Reply #4 on: December 03, 2016, 01:59:45 pm »
BlueIcaro - I've tested TLazSerial. I don't have any problem with establishing connection with COM port.

As I wrote - I would like to send data on COM port -> wait for response -> do sth with incoming data -> send next data -> and so on...

Geepster - it is COM emulator, isn't it? It would help me with testing software, wouldn't it?

And one more question - do you have example of using class you sent a link? And I can't see something like 'Write' function, just 'Read'.

Thank all of you for answers :)
« Last Edit: December 03, 2016, 02:05:14 pm by dawid75_75 »

Edson

  • Hero Member
  • *****
  • Posts: 1301
Re: Reading and sending data in sequence, COM port.
« Reply #5 on: December 03, 2016, 05:39:50 pm »
As I wrote - I would like to send data on COM port -> wait for response -> do sth with incoming data -> send next data -> and so on...
Does your serial device generate prompt?
If so, you need to detect when the prompt appears and then, do something and send the next command. You can do it by polling or by events, if your serial object can generates events.
Lazarus 2.2.6 - FPC 3.2.2 - x86_64-win64 on Windows 10

dawid75_75

  • New Member
  • *
  • Posts: 14
Re: Reading and sending data in sequence, COM port.
« Reply #6 on: December 03, 2016, 05:45:28 pm »
How can I do it by polling? I mean, how to implement polling in Lazarus?

Edson

  • Hero Member
  • *****
  • Posts: 1301
Re: Reading and sending data in sequence, COM port.
« Reply #7 on: December 03, 2016, 07:08:15 pm »
Well, it's easy. Something like this:

Code: Pascal  [Select][+][-]
  1. //This will block your program, until prompt appears
  2. while not PromptArrived() do begin  //wait forever
  3.   delay(500);  
  4. end
  5. //The prompt has arrived
  6. ...
  7.  

You can improve this by:

Code: Pascal  [Select][+][-]
  1. while not PromptArrived() and not Timeout() do begin  //wait forever
  2.   delay(500);
  3.    Application.ProcessMessages;  //be carefully with this
  4. end
  5. //The prompt has arrived or there is timeout.
  6. ...
  7.  
Lazarus 2.2.6 - FPC 3.2.2 - x86_64-win64 on Windows 10

derek.john.evans

  • Guest
Re: Reading and sending data in sequence, COM port.
« Reply #8 on: December 03, 2016, 10:16:18 pm »
Geepster - it is COM emulator, isn't it? It would help me with testing software, wouldn't it?
And one more question - do you have example of using class you sent a link? And I can't see something like 'Write' function, just 'Read'.

Yep. The com0com will install virtual COM ports in pairs. Each pair is connected to each other. So you end up with COM8 and COM9. You run a server on one port and a client on the other. The difference between a server and a client is which one remains in a "read locked" state. ie: Waiting for requests.

RE: Why no write method. If you look at the code for SerWrite(), you will see it uses the function WriteFile(). THandleStream also uses this command, so there was no need to override the Write method for the TStream.

RE: Example. Here is the TSerialStream unit again:

Code: Pascal  [Select][+][-]
  1. unit SerialStream;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, Serial, SysUtils;
  9.  
  10. type
  11.  
  12.   TSerialStream = class(THandleStream)
  13.   public
  14.     constructor Create(const ADevice: string; const ABaud: integer;
  15.       const AByteSize: integer = 8; const AParity: TParityType = NoneParity;
  16.       const AStopBits: integer = 1);
  17.     destructor Destroy; override;
  18.   public
  19.     function Read(var ABuffer; ACount: longint): longint; override;
  20.   end;
  21.  
  22. implementation
  23.  
  24. constructor TSerialStream.Create(const ADevice: string; const ABaud, AByteSize: integer;
  25.   const AParity: TParityType; const AStopBits: integer);
  26. begin
  27.   inherited Create(SerOpen(ADevice));
  28.   if Handle = 0 then begin
  29.     raise Exception.Create('Unable to open serial device');
  30.   end;
  31.   SerSetParams(Handle, ABaud, AByteSize, AParity, AStopBits, []);
  32. end;
  33.  
  34. destructor TSerialStream.Destroy;
  35. begin
  36.   SerClose(Handle);
  37.   inherited;
  38. end;
  39.  
  40. function TSerialStream.Read(var ABuffer; ACount: longint): longint;
  41. begin
  42.   Result := SerReadTimeout(Handle, byte(ABuffer), ACount, High(longint));
  43. end;
  44.  
  45. end.
  46.  


Here is a basic server which just reads a string message and returns it as uppercase.
Code: Pascal  [Select][+][-]
  1. program Server;
  2.  
  3. uses
  4.   SerialStream;
  5.  
  6. {$R *.res}
  7.  
  8. var
  9.   GServerStream: TSerialStream;
  10.   GData: string;
  11. begin
  12.   GServerStream := TSerialStream.Create('COM8', 2400);
  13.   while True do begin
  14.     GData := GServerStream.ReadAnsiString;
  15.     GServerStream.WriteAnsiString(upcase(GData));
  16.   end;
  17. end.  
  18.  

Here is a client:

Code: Pascal  [Select][+][-]
  1. program Client;
  2. uses SerialStream;
  3.  
  4. {$R *.res}
  5.  
  6. var
  7.   GClientStream: TSerialStream;
  8.  
  9. begin
  10.   GClientStream := TSerialStream.Create('COM9', 2400);
  11.   while True do begin
  12.     GClientStream.WriteAnsiString('This is an example of remoting the uppercase function via RS232');
  13.     WriteLn(GClientStream.ReadAnsiString);
  14.   end;
  15. end.    
  16.  

You will run into a number of problems like, what happens when the server is not responding? ie: timeouts. You can write your own timeouts or adjust the timeouts for the handle via Windows functions.

Apart from that, its pretty easy. WriteAnsiString/ReadAnsiString can also handle binary data. Use SetString() to convert a record to a string, and send it via WriteAnsiString().

For speed incompatible devices, you may require echoing, or some other handshaking. I used echoing because the TRS80 only has 3 RS232 wires and is very slow compared to the PC, so, each byte needed to "hold" the PC to prevent the PC from sending too fast.

Jurassic Pork

  • Hero Member
  • *****
  • Posts: 1228
Re: Reading and sending data in sequence, COM port.
« Reply #9 on: December 03, 2016, 11:17:25 pm »
hello,
Hello everyone :)
I have to solve some problem. I would like to implement that algorithm in Lazarus:
1) send a command to the COM port;
2) wait for response;
3) some function which uses data from response;
dawid75 , how do you know if you have received the whole response ? the length of frame response ? an end frame character ? the max time to have the response ?


Friendly, J.P
« Last Edit: December 03, 2016, 11:19:47 pm by Jurassic Pork »
Jurassic computer : Sinclair ZX81 - Zilog Z80A à 3,25 MHz - RAM 1 Ko - ROM 8 Ko

 

TinyPortal © 2005-2018