Recent

Author Topic: Accessing Virtual Comports from several Units  (Read 4928 times)

docwat

  • New Member
  • *
  • Posts: 40
Accessing Virtual Comports from several Units
« on: May 06, 2015, 06:42:04 pm »
Hi,

I wish to access a virtual COM3 port from multiple Lazarus Units but cannot think round the best method to avoid port clashes.

I have previously avoided this problem by only running one form at once but I now wish to keep form1 running with forms 2,3 and 4 superimposed;

In form 1 I use SDPOSerial1  and in form2 I try Unit1.Form1.SDPOserial1 which works when sending data to the virtual port/usb. But any response provides the unit1.form1.dataAvailable  function=true- but the unit1.form1.SDPOSerial.ReadData returns nothing whilst the returned data reaches the serial in buffer and is displayed when I return to Form1 and read SDPOSerial1.

Is there a proper way to manage multiple unit access to a  single virtual com port  or to open new sessions using Serial(2-n) sessions without COM3 contentions?

My application is communication to a CANBUS network from several points in a complex program.

I seem to have a blind spot on this one !

Any suggestions ?

Very many thanks,

docwat.


tr_escape

  • Sr. Member
  • ****
  • Posts: 432
  • sector name toys | respect to spectre
    • Github:
Re: Accessing Virtual Comports from several Units
« Reply #1 on: May 06, 2015, 07:08:47 pm »
Hello,

You have to think Serial Port is like as a single file and there is a one handle.
If some object / process / thread holds you can't hold again.

But you can create some global functions for manage your com port object.

Could you please much more explain what is your needs?

Best regards

 

serbod

  • Full Member
  • ***
  • Posts: 142
Re: Accessing Virtual Comports from several Units
« Reply #2 on: May 06, 2015, 08:51:39 pm »
You can use DataPort components ( https://github.com/serbod/dataport ) - it thread-safe wrapper for Ararat Synapse library. It allow use of single serial port by multiple forms, but only one form can get events notifications, and you must use DataPort.Peek() for retrieving data without deleting it.

Good way is create some public class/object that represent remote device or devices, interact with single serial port, send commands and parse replies. Other forms works with that object and you don't need to care about synchronization between forms. Don't allow direct interaction with one serial port from multiple source modules, it will be hard to manage.

docwat

  • New Member
  • *
  • Posts: 40
Re: Accessing Virtual Comports from several Units
« Reply #3 on: May 06, 2015, 11:26:24 pm »
Many thanks IDUA,

I would like to get data from some three units passed via com3/usb  to a CANBUS network controller.

in Unit 1, I test communications with the CANBUS:

procedure TForm1.CAN_TST_ButtonClick(Sender: TObject);

var i:Integer;
    Dat:Boolean;
begin
    Can_Tst_Display.Text:='';
    for i:=1 to 5 do
      begin
      Delay(10);
         if SDPOSerial1.Active=False then SDPOSerial1.Active:=True;
      end;
    SDPOSerial1.WriteData('S4'+ Chr($0D));
    SDPOSerial1.WriteData('O'+ Chr($0D));
    SDPOSerial1.WriteData('V'+ Chr($0D));
    i:=0;
    repeat
        begin
        delay(1);
        i:=i+1;
        end;
    Until (SDPOSerial1.DataAvailable) OR (i>50);
    if SDPOSerial1.DataAvailable then Can_Tst_Display.Text:=SDPOSerial1.ReadData;
    SDPOSerial1.WriteData('C'+ Chr($0D));

    SDPOSerial1.Active:=False;
    SDPOSerial1.Close;

end; 

This works fine.   From Unit2 I test communications with a hardware ADC module and displays 'Gotcha' to prove that data has been returned which is the desired 'GOOD'

But the received data is invisible to the   Label18.Caption:=Unit1.Form1.SDPOSerial1.ReadData; code and it remains in the com3 input buffer until it is read again in Unit1

Procedure TForm2.Button8Click(Sender: TObject);

var i:Integer;

begin

     Unit1.Form1.SDPOSerial1.Active:=True;
     Unit1.Form1.SDPOSerial1.ReadData;
     Unit1.Form1.SDPOSerial1.WriteData('S4'+ Chr($0D));
     Unit1.Form1.SDPOSerial1.WriteData('O'+ Chr($0D));
     Unit1.Form1.SDPOSerial1.WriteData('t60015A' + Chr($0D));
     Unit1.Form1.SDPOSerial1.WriteData('m61000000' + Chr($0D));
     Unit1.Form1.SDPOSerial1.WriteData('M00000000' + Chr($0D));


     i:=0;
     repeat
        begin
        delay(1);
        i:=i+1;
        end;
     Until (Unit1.Form1.SDPOSerial1.DataAvailable) OR (i>50);

    if Unit1.Form1.SDPOSerial1.DataAvailable then
    Begin
    Label18.Caption:=Unit1.Form1.SDPOSerial1.ReadData;
    {Label18.Caption:='GOTCHA'; }
    end else

    Label18.Caption:='FAIL';
    Unit1.Form1.SDPOSerial1.WriteData('C'+ Chr($0D));
    Unit1.Form1.SDPOSerial1.Close;

My ultimate need is to communicate with the CANBUS from anywhere within my code from CONFIGURATION,CALIBRATION and WEIGHING activities.  I cannot understand why the  Unit1.Form1.SDPOSerial1.ReadData; does not access the IN buffer whilst the DataAvailable event is read ?

There may be many ways to accomplish accessing COM3 throughout the host program running under Win8.1 32 bit but I have not found the answer.

I greatly appreciate your help in this matter.

docwat

                     

docwat

  • New Member
  • *
  • Posts: 40
Re: Accessing Virtual Comports from several Units
« Reply #4 on: May 07, 2015, 12:07:36 am »
Hi  tr_escape,

Very many thanks for you comments.

Yes, I was wondering whether it would be better to achieve global access to functions which encapsulate the COMPORT component.   I think it would be much more easily managed than my back referencing to the unit to use the Sdpo component.

I am still not sure why my Uni11.Form1,SdpoSerial1.ReadData failed but that is the penalty for being lazy!

I greatly appreciate to helpful comment.

Regards,

Docwat

docwat

  • New Member
  • *
  • Posts: 40
Re: Accessing Virtual Comports from several Units
« Reply #5 on: May 07, 2015, 12:15:49 am »
Hi serbod,

'Good way is create some public class/object that represent remote device or devices, interact with single serial port, send commands and parse replies.'

Yes, I think that looks like the way forward.  Perhaps creating a dummy form named CAN_LINK and writing a range of Public Functions to deal with the specifics of my communications will be best.

I am most grateful for the very helpful responses from this forum which clarify what must be done !

Regards,

docwat


Jurassic Pork

  • Hero Member
  • *****
  • Posts: 1228
Re: Accessing Virtual Comports from several Units
« Reply #6 on: May 07, 2015, 12:30:16 am »
hello,
have a look to my component Tlazserial here
you can use the event OnRxRead and if your received datas are binaries you can use a code like this :
Code: [Select]
procedure TFMain.SerialRxData(Sender: TObject);
var S,HexaS : string;
    i : integer;
begin
  S := Serial.ReadData;
  for I := 1 to Length(S) do begin
    HexaS := HexaS + InttoHex(Ord(S[I]),2)+ ' ';
  end;
Memo.lines.Add(HexaS);
end;         

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

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11453
  • FPC developer.
Re: Accessing Virtual Comports from several Units
« Reply #7 on: May 07, 2015, 10:11:26 am »
If the trick is that you shouldn't send a second before the answer to the first was received (or a timeout passed), you need a simple state machine that manages the serial, and basically program asynchronously.



 

TinyPortal © 2005-2018