Recent

Author Topic: Linux, Lazarus and the Serial Port  (Read 9737 times)

HatForCat

  • Sr. Member
  • ****
  • Posts: 281
Linux, Lazarus and the Serial Port
« on: January 02, 2017, 12:10:02 am »
Finally bit the bullet and dropped windows and Delphi. I am now using Mint and Lazarus and liking them both.

I have converted several Delphi-5 programs over to Linux-Lazarus and all good. But one of those programs needs to read and write data to an Arduino via the USB and serial port.

I am having trouble getting the Lazarus code to find any Com ports as it did on windows. The Synaser call to display all available comports shows nothing.

Any thoughts on how to make Mint see the USB-Arduino as a comport of some sort so I can transfer data both ways?

Is the USBTTY0 etc opened directly by FPC or what? If so, can you point me at some example code.

Thanks


Acer-i5, 2.6GHz, 6GB, 500-SSD, Mint-19.1, Cinnamon Desktop, Lazarus 1.8.4, SQLite3 -- Retired after 40+years programming, still cannot stop.

mig-31

  • Full Member
  • ***
  • Posts: 244
Re: Linux, Lazarus and the Serial Port
« Reply #1 on: January 02, 2017, 09:48:43 am »
Hi,

it's normal, that it shows nothing.

In terminal (Konsole in KDE, i don't the terminal emulation program in Cinnamon nad Mate) command

dmesg |grep tty

It should be something ttyUSBx or ttyACMx
Lazarus 2.0.0 - CentOS 7.x, Mageia 6.1

HatForCat

  • Sr. Member
  • ****
  • Posts: 281
Re: Linux, Lazarus and the Serial Port
« Reply #2 on: January 02, 2017, 06:34:14 pm »
dmesg |grep tty

Thanks, that shows this...

Code: [Select]
[    0.000000] console [tty0] enabled
[ 4452.717761] usb 3-2.4.4: ch341-uart converter now attached to ttyUSB0

But how do I get the Lazarus program to see it?

I had to do this sudo chmod a+rw /dev/ttyUSB0 for the Arduino-IDE to see it, but it hasn't helped with Lazarus.
Acer-i5, 2.6GHz, 6GB, 500-SSD, Mint-19.1, Cinnamon Desktop, Lazarus 1.8.4, SQLite3 -- Retired after 40+years programming, still cannot stop.

kupferstecher

  • Sr. Member
  • ****
  • Posts: 251
Re: Linux, Lazarus and the Serial Port
« Reply #3 on: January 03, 2017, 10:53:08 am »
But how do I get the Lazarus program to see it?

Thats not  easy under Linux. The Synaser Function for showing the portname - as far as I know - doesn't work under Linux.
But anyways of course you still can connect to any available port.

The following should work:
Code: Pascal  [Select]
  1.   Serial:=TBlockSerial.Create;
  2.   Serial.Connect(PortNr);
  3.   Serial.Config(baud, bits, parity, stop, softflow, hardflow);
  4.   sleep(100);
  5.   if Serial.LastError = 0 then begin
  6.     connected := True;
  7.     WriteLn('ComPort: Verbindung erfolgreich');
  8.   end else begin
  9.     Connected:= false;
  10.   end;
  11.  
  12.  Serial.SendByte(DataByte);
  13.  


PS: To allow port communication something like
$ sudo adduser username dialout
in the command line is required once if you didn't do so before.

Hopestation

  • Full Member
  • ***
  • Posts: 157
Re: Linux, Lazarus and the Serial Port
« Reply #4 on: January 03, 2017, 11:14:52 am »
I asked the same question in 2011 and got the following, abbreviated solution :

unit Main01;

{$mode objfpc}{$H+}

........

interface

uses
  Classes, Controls, Dialogs, ExtCtrls, FileUtil, Forms, Graphics, Registry,
  StdCtrls, Synaser, SysUtils;

type

  { TForm1 }

  private
    { private declarations }
  public
    { public declarations }
  end;

var
  Form1             : TForm1;
  ser1              : TBlockSerial;
  Line              : String;

implementation
uses Unit2;

{$R *.lfm}

{ TForm1 }

procedure TForm1.BtnRunClick(Sender: TObject);
Var
  reg: TRegistry;
  L  : TStringList;
  n: integer;
  Str1, Str2: String;
begin
  L := TStringList.Create;
  reg := TRegistry.Create;
  try
    {$IFNDEF VER100}
    reg.Access := KEY_READ;
    {$ENDIF}
    reg.RootKey := HKEY_LOCAL_MACHINE;
    reg.OpenKeyReadOnly('HARDWARE\DEVICEMAP\SERIALCOMM');//, false);
    reg.GetValueNames(L);
    for n := 0 to l.Count - 1 do
    begin
      Str1 := L[n];
      Str2 := reg.ReadString(L[n]);
      Memo1.Lines.Add(Str1 + ': ' + Str2);
      end;
    end;
  finally
    reg.Free;
    L.Free;
  end;
end;

END.

I have used it regularly since.

mig-31

  • Full Member
  • ***
  • Posts: 244
Re: Linux, Lazarus and the Serial Port
« Reply #5 on: January 03, 2017, 03:04:00 pm »
There is code example.
Code: Pascal  [Select]
  1. SerialPort:=TBlockSerial.Create;
  2. with SerialPort do begin
  3.         Connect('/dev/ttyUSB0');
  4.         Config(9600,8,'N',SB1,False,False);
  5.         if LastError<>0 then begin
  6.            writeln('Can''t to connect.  Error description: '+LastErrorDesc);
  7.            Free;
  8.         end;
  9.  end;    
  10.  
« Last Edit: January 04, 2017, 09:50:30 am by mig-31 »
Lazarus 2.0.0 - CentOS 7.x, Mageia 6.1

HatForCat

  • Sr. Member
  • ****
  • Posts: 281
Re: Linux, Lazarus and the Serial Port
« Reply #6 on: January 03, 2017, 11:11:40 pm »
Thanks everyone, as a newbie to Linux, I have had to go back a few saved images after finger-trouble. :)

I am currently back at just before I installed Lazarus, but will get it reinstalled tomorrow. The code examples will be a great help, thanks to you all.

Good to know I am not alone. :)
Acer-i5, 2.6GHz, 6GB, 500-SSD, Mint-19.1, Cinnamon Desktop, Lazarus 1.8.4, SQLite3 -- Retired after 40+years programming, still cannot stop.

kupferstecher

  • Sr. Member
  • ****
  • Posts: 251
Re: Linux, Lazarus and the Serial Port
« Reply #7 on: January 04, 2017, 11:09:13 am »
I asked the same question in 2011 and got the following, abbreviated solution
[...]
uses [...] Registry,

'Registry' sounds a lot like windows.

I'd be also interested in an easy solution to list the available ports under Linux (within the program, not using the shell).

EDIT:
I found code on the German Lazarus board:
http://www.lazarusforum.de/viewtopic.php?p=72837#p72837
« Last Edit: January 04, 2017, 11:17:51 am by kupferstecher »

krolikbest

  • Jr. Member
  • **
  • Posts: 88
Re: Linux, Lazarus and the Serial Port
« Reply #8 on: January 04, 2017, 12:07:54 pm »
I'd suggest really TLazSerial. You can test it on both platforms: Win and Linux.
Here some thread:
http://forum.lazarus.freepascal.org/index.php?topic=20481.0

HatForCat

  • Sr. Member
  • ****
  • Posts: 281
Re: Linux, Lazarus and the Serial Port
« Reply #9 on: January 04, 2017, 10:40:43 pm »
I found code on the German Lazarus board:
http://www.lazarusforum.de/viewtopic.php?p=72837#p72837

Now, that looks interesting. Thanks.
Acer-i5, 2.6GHz, 6GB, 500-SSD, Mint-19.1, Cinnamon Desktop, Lazarus 1.8.4, SQLite3 -- Retired after 40+years programming, still cannot stop.

HatForCat

  • Sr. Member
  • ****
  • Posts: 281
Re: Linux, Lazarus and the Serial Port
« Reply #10 on: January 04, 2017, 10:42:15 pm »
I'd suggest really TLazSerial. You can test it on both platforms: Win and Linux.

I'll give it a try but I have no more windows anything -- really. Yipppeeee!
Acer-i5, 2.6GHz, 6GB, 500-SSD, Mint-19.1, Cinnamon Desktop, Lazarus 1.8.4, SQLite3 -- Retired after 40+years programming, still cannot stop.

mig-31

  • Full Member
  • ***
  • Posts: 244
Re: Linux, Lazarus and the Serial Port
« Reply #11 on: January 05, 2017, 10:28:37 am »
I have no more windows anything -- really. Yipppeeee!
Sounds good, no Windows  ;)
Lazarus 2.0.0 - CentOS 7.x, Mageia 6.1

krolikbest

  • Jr. Member
  • **
  • Posts: 88
Re: Linux, Lazarus and the Serial Port
« Reply #12 on: January 05, 2017, 12:26:40 pm »
TLazSerial works on Raspbian, at least for me :)

Jurassic Pork

  • Hero Member
  • *****
  • Posts: 753
Re: Linux, Lazarus and the Serial Port
« Reply #13 on: January 05, 2017, 12:33:44 pm »
hello,
have a look in the GetSerialPortNames function of synaser.pas (modified version) ot TLazserial package :

Code: Pascal  [Select]
  1. {$IFDEF MSWINDOWS}
  2. function GetSerialPortNames: string;
  3. var
  4.   reg: TRegistry;
  5.   l, v: TStringList;
  6.   n: integer;
  7. begin
  8.   l := TStringList.Create;
  9.   v := TStringList.Create;
  10.   reg := TRegistry.Create;
  11.  
  12.   try
  13. {$IFNDEF VER100}
  14. {$IFNDEF VER120}
  15.     reg.Access := KEY_READ;
  16. {$ENDIF}
  17. {$ENDIF}
  18.     reg.RootKey := HKEY_LOCAL_MACHINE;
  19.     reg.OpenKey('\HARDWARE\DEVICEMAP\SERIALCOMM\', false);
  20.     reg.GetValueNames(l);
  21.     for n := 0 to l.Count - 1 do
  22. // Modif J.P  03/2013
  23.       v.Add(Pchar(reg.ReadString(l[n])));
  24.     Result := v.CommaText ;
  25.   finally
  26.     reg.Free;
  27.     l.Free;
  28.     v.Free;
  29.   end;
  30. end;
  31. {$ENDIF}
  32. {$IFNDEF MSWINDOWS}
  33. // Modif J.P   03/2013
  34. function GetSerialPortNames: string;
  35. var
  36.   Index: Integer;
  37.   Data: string;
  38.   TmpPorts: String;
  39.   sr : TSearchRec;
  40.  
  41.   procedure ScanForPorts( const ThisRootStr : string); // added by PDF
  42.   var theDevice : String;
  43.   var FD : Cint;
  44.   var Ser : TSerialStruct;
  45.   begin
  46.     if FindFirst( ThisRootStr, $FFFFFFFF, sr) = 0 then
  47.     begin
  48.       repeat
  49.         if (sr.Attr and $FFFFFFFF) = Sr.Attr then
  50.         begin
  51.           data := sr.Name;
  52.           index := length(data);
  53.           theDevice := '/dev/' + data;
  54. // try to open the device
  55.        FD := fpopen(thedevice,O_RdWr or O_NonBlock or O_NoCtty);
  56.        if FD > 0 then
  57.           begin
  58. // try to get serial info from the device
  59.            if fpioctl( FD,TIOCGSERIAL, @Ser) <> -1 then
  60.              begin
  61. // device is serial if type is not unknown
  62.               if (Ser.typ <> 0)  then
  63.                TmpPorts := TmpPorts + '  ' + theDevice;
  64.                fpclose(FD);
  65.              end;
  66.            end;
  67.         end;
  68.       until FindNext(sr) <> 0;
  69.     end;
  70.   end;
  71.  
  72. begin
  73.   try
  74.     TmpPorts := '';
  75.     ScanForPorts( '/dev/rfcomm*');
  76.  //   ScanForPorts( '/dev/pts/*');
  77.     ScanForPorts( '/dev/ttyUSB*');
  78.     ScanForPorts( '/dev/ttyS*');
  79.     ScanForPorts( '/dev/ttyAM*'); // for ARM board
  80.     FindClose(sr);
  81.   finally
  82.     Result:=TmpPorts;
  83.   end;
  84. end;
  85. {$ENDIF}

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

HatForCat

  • Sr. Member
  • ****
  • Posts: 281
Re: Linux, Lazarus and the Serial Port
« Reply #14 on: January 08, 2017, 04:43:01 pm »
Thanks everyone,

The German code mentioned by kupferstecher works fine.

JP your code looks quite similar but in English so will give it a try.
Acer-i5, 2.6GHz, 6GB, 500-SSD, Mint-19.1, Cinnamon Desktop, Lazarus 1.8.4, SQLite3 -- Retired after 40+years programming, still cannot stop.