Recent

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

Aruna

  • Hero Member
  • *****
  • Posts: 748
Re: Linux, Lazarus and the Serial Port
« Reply #30 on: October 17, 2025, 04:03:26 am »
...
Good luck, and I hope this helps you get started!
Thanks, it works just fine.
From your code, just for getting the friendly names:
I’m glad it’s working for you. And I have something new for you to test!

The attached ZIP file includes the Arduino sketch blinkspeed.ino. Please compile and upload it to your device, then TEST IT FIRST using the Arduino Serial Console. Feel free to make any adjustments you like. Try typing in dseligo or MarkMLI into the serial console  :D

Once that’s done, run the Lazarus code. The attached screenshots should be self-explanatory.

This setup demonstrates bi-directional serial communication — sending data from Lazarus to the Arduino and reading data back from the Arduino board into Lazarus.

Good luck, and happy hacking!  😎
« Last Edit: October 17, 2025, 04:30:25 am by Aruna »

CM630

  • Hero Member
  • *****
  • Posts: 1527
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: Linux, Lazarus and the Serial Port
« Reply #31 on: October 17, 2025, 10:30:10 am »
Лазар 4,2 32 bit (sometimes 64 bit); FPC3,2,2

ccrause

  • Hero Member
  • *****
  • Posts: 1080

Aruna

  • Hero Member
  • *****
  • Posts: 748
Re: Linux, Lazarus and the Serial Port
« Reply #33 on: October 20, 2025, 10:57:08 pm »
Some updates done in https://wiki.freepascal.org/Hardware_Access#Serial_Communication
Hello CM360,  I’ve noticed that much of the example code in the wiki tends to make sense mainly to more seasoned or experienced developers. For newcomers, it can be confusing and even discouraging when examples assume prior knowledge.

A few beginner-friendly explanations or simpler examples would make a huge difference in helping new users feel confident and included. Adding a few simpler examples or extra explanations for beginners would really help make the wiki more welcoming and easier to learn from. Some examples are so cryptic and way beyond a newbie level. This is just my two cents, the kind of thing 'I' would have loved to see in the wiki back when I was a beginner and clueless newbie. What follows are not criticisms, but genuine concerns that I’m pointing out along with suggestions on how they could be improved (if you wish and the community agree, of course).

This is the kind of example where a newcomer to Lazarus / Free Pascal on Linux can easily get confused, because at first glance, it looks like Windows COM-port code due to the name GetComFriendlyName, but it’s actually Linux-specific and relies on the udevadm command-line tool. Rename the function to something clearer, such as: Function GetLinuxSerialDeviceFriendlyName(PortName: String): String; That immediately signals “Linux-only” and avoids Windows COM confusion.

Here’s the same code, but heavily commented and explained line-by-line, with all the pitfalls and confusing parts for newcomers clearly pointed out:
Code: Pascal  [Select][+][-]
  1. {$IfDef Linux}  
  2. // The following function is *only compiled on Linux systems*.
  3. // This avoids build errors on non-Linux platforms.
  4. Function GetComFriendlyName(PortName: String): String;
  5. var
  6.   RunOutput: string = '';   // Will hold the text output from the 'udevadm' command.
  7.   StartPos: integer = 0;    // Used to locate where the friendly name begins in the output.
  8.   EndPos: integer = 0;      // Used to locate where the friendly name ends in the output.
  9. begin
  10.   Result := '';  
  11.   // Always initialize Result to an empty string in case the function fails.
  12.   // This ensures that callers don’t receive garbage data.
  13.  
  14.   // The following line runs the Linux shell command `udevadm info -q property <device>`
  15.   // Example: udevadm info -q property /dev/ttyUSB0
  16.   // It stores all the command output text into the variable RunOutput.
  17.   //
  18.   // ⚠️ POTENTIAL PITFALLS FOR NEWCOMERS:
  19.   //  - RunCommand is part of the Free Pascal unit `Process`, not `SysUtils`.
  20.   //    You must include `Process` in your "uses" clause or you’ll get “Identifier not found: RunCommand”.
  21.   //  - 'udevadm' must exist on your system (it normally does on most Linux systems).
  22.   //  - If you pass a wrong device name like '/dev/ttyFAKE0', RunCommand still "succeeds"
  23.   //    but RunOutput may be empty or contain an error message.
  24.   if not RunCommand('udevadm info -q property ' + PortName, RunOutput) then
  25.     exit;
  26.   // If the command fails entirely (returns false), the function exits immediately
  27.   // leaving Result = '', which indicates no friendly name could be found.
  28.  
  29.   // Now we search for the text "ID_MODEL_FROM_DATABASE=" inside the output.
  30.   // This field usually contains the *human-readable device model name*,
  31.   // such as "FT232 USB UART" or "Arduino Uno".
  32.   StartPos := Pos('ID_MODEL_FROM_DATABASE=', RunOutput);
  33.  
  34.   if (StartPos = 0) then
  35.     exit;  
  36.   // If that substring is not found, exit — no friendly name is available.
  37.  
  38.   // Move StartPos past the "ID_MODEL_FROM_DATABASE=" label
  39.   // so that it points directly to the beginning of the *actual friendly name text*.
  40.   StartPos := StartPos + Length('ID_MODEL_FROM_DATABASE=');
  41.  
  42.   // Find the position of the next newline character (#10)
  43.   // after the start of the friendly name. This marks where the name ends.
  44.   EndPos := Pos(#10, RunOutput, StartPos + 1);
  45.  
  46.   // Copy just the friendly name portion from RunOutput into Result.
  47.   Result := Copy(RunOutput, StartPos, EndPos - StartPos);
  48. end;
  49. {$EndIf}
  50.  

Confusing Aspects for Newcomers
  • Function name (GetComFriendlyName) sounds Windows-related   The term “COM” is used on Windows (e.g., COM1, COM2). On Linux, serial devices are /dev/ttyUSB0, /dev/ttyACM0, etc. So a beginner might assume this works on Windows, it does not.
  • Missing unit in “uses”   The function requires Process for RunCommand. If you forget it, you’ll get Identifier not found: RunCommand.
  • Doesn’t handle missing or invalid devices gracefully   If /dev/ttyUSB0 doesn’t exist, you just get an empty result, no error message. Newcomers might think the code “does nothing.”
  • Case sensitivity of Linux /dev/ttyUSB0 ≠ /dev/TTYUSB0. Linux paths are case-sensitive, unlike Windows.
  • Command availability   udevadm may not be in the user’s PATH on some embedded or minimal systems. The function will silently fail if it’s not installed.
  • Hardcoded property name   It assumes the field ID_MODEL_FROM_DATABASE exists. Some devices may not have that property (e.g., some cheap adapters). Then you’ll get an empty string.
  • Not cross-platform   Wrapped in {$IfDef Linux}, so this will not compile or work on Windows or macOS. Beginners might not realize this and try to use it universally.

Suggestions for Beginners

Rename the function to something clearer, such as:
Function GetLinuxSerialDeviceFriendlyName(PortName: String): String;
That immediately signals “Linux-only” and avoids Windows COM confusion.

Add error feedback, for example:

if RunOutput = '' then
  Result := 'Device not found or udevadm unavailable';

Show debug output during testing:
WriteLn('udevadm output:', LineEnding, RunOutput);

Remember to add Process in your uses clause:
uses SysUtils, Process;

I hope this will be taken in the same spirit it is said in. I have been there, done that, printed the T-shirts. Why make life difficult when together we can learn and build amazing stuff?

And the attached image hopefully will make you all smile  :) 



« Last Edit: October 21, 2025, 01:22:57 am by Aruna »

mas steindorff

  • Hero Member
  • *****
  • Posts: 560
Re: Linux, Lazarus and the Serial Port
« Reply #34 on: October 20, 2025, 11:33:35 pm »
Hi Aruna
I think what you have done is great but I suggest comments for other OS somehow be filtered. 

As an example you can get the "GetComFriendlyName" out of the windows registry for Windows 10+. This function call in the 2002 synaser.pas was something like GerSerialPortRegNames().  I do not know if it migrated into the latest Lazarus library but to say it does not exist for a OS requires the creator of the example to be an expert of (at least) the all of the major OS.
Perhaps we we label the examples that use OS dependent calls with what OS they have been tested with and note the differences and or weaknesses of the OS separately. Then a guru can come in later and add a separate tip or fix for the OS they know about.
I guess the trick is to direct the gurus to that wiki page. 
MAS
windows 10 &11, Ubuntu 21+ IDE 3.4 general releases

Aruna

  • Hero Member
  • *****
  • Posts: 748
Re: Linux, Lazarus and the Serial Port
« Reply #35 on: October 21, 2025, 01:25:28 am »
Hi Aruna
I think what you have done is great but I suggest comments for other OS somehow be filtered. 

As an example you can get the "GetComFriendlyName" out of the windows registry for Windows 10+. This function call in the 2002 synaser.pas was something like GerSerialPortRegNames().  I do not know if it migrated into the latest Lazarus library but to say it does not exist for a OS requires the creator of the example to be an expert of (at least) the all of the major OS.
Perhaps we we label the examples that use OS dependent calls with what OS they have been tested with and note the differences and or weaknesses of the OS separately. Then a guru can come in later and add a separate tip or fix for the OS they know about.
I guess the trick is to direct the gurus to that wiki page. 
MAS
Hi MAS, thank you for the kind words. I have removed the offending line. I said that because of the '{$IfDef Linux}  which will prevent any other non-Linux OS from running that code. Apologies if that caused any confusion.
'

mas steindorff

  • Hero Member
  • *****
  • Posts: 560
Re: Linux, Lazarus and the Serial Port
« Reply #36 on: October 21, 2025, 01:40:12 am »
Sorry, should have said  "comments in example code on wiki for beginners".  What is commented and done in the source code should follow /reflect "good programming".
OPP is all about isolation and reusability of code so comments about OS differences, in my mind, should be limited to the calls that use each target OS.  Document the function and what is suppose to do but move the OS tutor comments out on to a wiki page somewhere so the code (or it's comments) do not go obsolete as fast. 
windows 10 &11, Ubuntu 21+ IDE 3.4 general releases

 

TinyPortal © 2005-2018