Forum: PC-Programmierung Lazarus + Synaser


von Tony B. (Gast)


Lesenswert?

Hallo liebes Forum! (=

Ich hab schon seit Ewigkeiten nach einer Möglichkeit gesucht, um per 
RS232 zwischen PC un AtMega8 eine Kommunikation aufzubauen!

Da ich aber meine Kontrolloberfläche auf dem PC selbst gestalten möchte 
wollte ich kein übliches Panel(damit funzt es ohne Probleme) sondern ein 
eigenes Program, und da ich in Lazarus schon einige Erfahrung habe, 
wollte ich das einfach nutzen.
Kurzer hand hab ich mir Synaser besorgt und mal so durch die Proceduren 
und Funktionen gestöbert und auch schnell etwas gefunden, leider hab ich 
Probleme damit etwas vom µC zu empfangen. Senden geht ohne Probleme!

Der Syntax in Lazarus habt Ihr hier einmal!
1
 
2
unit Unit1; 
3
4
{$mode objfpc}{$H+}
5
6
interface
7
8
uses
9
  Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
10
  StdCtrls, synaser;
11
12
  var
13
  serv:TBlockSerial;
14
15
type
16
17
  { TForm1 }
18
19
  TForm1 = class(TForm)
20
    Button1: TButton;
21
    Button2: TButton;
22
    Button3: TButton;
23
    Edit1: TEdit;
24
    Edit2: TEdit;
25
    Edit3: TEdit;
26
    Label1: TLabel;
27
    Label2: TLabel;
28
    Label3: TLabel;
29
    Label4: TLabel;
30
    procedure Button1Click(Sender: TObject);
31
    procedure Button2Click(Sender: TObject);
32
    procedure Button3Click(Sender: TObject);
33
    procedure empfang;
34
  private
35
    { private declarations }
36
  public
37
    { public declarations }
38
  end; 
39
40
var
41
  Form1: TForm1; 
42
43
implementation
44
45
{ TForm1 }
46
47
procedure TForm1.empfang;
48
var
49
timeout : integer;
50
signal : string;
51
52
53
begin
54
Timeout := 4000;
55
signal := serv.Recvstring(timeout);
56
edit2.text := signal;
57
end;
58
59
procedure TForm1.Button1Click(Sender: TObject);
60
begin
61
  serv.free;
62
  ShowMessage('ComPort muss freigeschalten werden! Jetzt freischalten?');
63
  sleep(1000);
64
  close;
65
end;
66
67
procedure TForm1.Button2Click(Sender: TObject);
68
var
69
portnr : string;
70
parity : char;
71
baud,bits,stop : integer;
72
softflow : boolean;
73
hardflow : boolean;
74
75
begin
76
serv:=TBlockSerial.create;
77
portnr := 'COM1';
78
parity := 'N';
79
baud := 4800;
80
bits := 8;
81
stop := 1;
82
softflow := false;
83
hardflow := false;
84
85
try
86
  serv.Connect(portnr);
87
  serv.Config(baud, bits, parity, stop, softflow, hardflow);
88
  ShowMessage('Verbindung erfolgreich')
89
except;
90
91
end;
92
end;
93
94
procedure TForm1.Button3Click(Sender: TObject);
95
var
96
befehl, data : string;
97
98
const
99
CR = #$0d;
100
begin
101
  befehl := edit1.text;
102
  data   := befehl+CR;
103
  serv.SendString(data);
104
end;
105
106
107
initialization
108
  {$I Unit1.lrs}
109
110
end.

Ich wollte einfach mal wissen, warum ich in mein Edit2feld keinen Text 
bekomme.
Der µC ist mit Bascom gecoded, hier benutze ich den Print befehl ohne 
';' dahinter (Das hat zur Folge das nach jedem String durch PRINT 
automatisch ein CRLF gesendet wird...)


Bitte helft mir, hab noch rein gar nichts brauchbares im Netz gefunden!

Danke schonmal!! (=

Lg

von Wegstaben V. (wegstabenverbuchsler)


Lesenswert?

.. und ein einfaches Terminal-Programm funktioniert, d.h. es zeigt das 
an was vom uC gesendet wird?

von Tony B. (Gast)


Lesenswert?

Wegstaben Verbuchsler schrieb:
> .. und ein einfaches Terminal-Programm funktioniert, d.h. es zeigt das
> an was vom uC gesendet wird?

Ja, das is ja das mekrwürdige. =(

Mit einem einfachen I/O Terminal unter Windows, kann ich senden und 
empfangen ohne Probleme, ohne Datenverlust und in astreiner 
Geschwindigkeit!

Fällt euch vielleicht irgendwo mein Fehler auf? (=


Wäre echt Spitze!!

Lg

von GeraldB (Gast)


Lesenswert?

Ich wundere mich, daß du was senden konntest. Der COM-Port wurde 
überhaupt nicht (richtig?) geöffnet.

Mach mal folgende Änderungen:

Bei der Klassendeklaration von TForm1 :
1
private
2
    connected: Boolean;

Ändere die procedure TForm1.Button2Click folgendermaßen :
1
begin
2
  if connected then
3
  begin
4
    ShowMessage('Verbindung ist bereits vorhanden');
5
    exit;
6
  end;
7
  serv:=TBlockSerial.create;
8
  portnr := 'COM1';
9
  parity := 'N';
10
  baud := 4800;
11
  bits := 8;
12
  stop := SB1;
13
  softflow := false;
14
  hardflow := false;
15
  serv.Connect(portnr);
16
  sleep(1000);
17
  serv.Config(baud, bits, parity, stop, softflow, hardflow);
18
  sleep(1000);
19
  if serv.LastError = 0 then
20
  begin
21
    connected := True;
22
    ShowMessage('Verbindung erfolgreich');
23
  end
24
  else
25
  ShowMessage('Verbindung konnte nicht hergestellt werden');
26
end;
Die Funktion serv.Config ist bei Dir unerkannt abgebrochen, da ihr über 
den Parameter stop ein ungültiger Wert übergeben wurde. Und da das in 
diversen Beispielen angegebene Konstrukt mit try/except hier nicht 
funktioniert, wurde Dir ein geöffneter und konfigurierter COM-Port 
vorgegaukelt.

PS: Hast Du eigentlich das Buch über Lazarus?
Mitlerweile in der 2. Auflage vom C&L-Verlag
-> Lazarus: Klassenbibliothek und IDE (http://www.cul.de/lazarus2.html)

Der Titel der 1. Auflage war:
Lazarus: Arbeiten mit IDE und Klassenbibliotheken

Dort wird ein korrektes Beispiel gezeigt.

von Tony B. (Gast)


Lesenswert?

Hey GeraldB (=

Ich danke Dir für deinen Ausführlichen Post!!
Ich hab das alles mal ergänzt/ korrigiert!
Es funktionierte leider weiterhin nur das Senden. Ich hab jedoch (wenn 
auch nicht sehr elegant) jetzt eine Möglichkeit des Empfangens gefunden.

Ich hab jetzt In jede SendeProcedure noch folgendes angehängt:
1
if serv.CanRead(2000) then
2
  signal := serv.Recvstring(5000);
3
  memo1.Lines.add(signal);

Jetzt empfange ich alles Korrekt! (=
Senden funktioniert auch ohne Probleme!

Ich hätte nur mal noch eine Frage:
Das Problem ist ja jetzt dass es nur dann empfängt, wenn ich etwas 
gesendet habe.
Aus diesem Grund wollte ich einen Timer erstellen der alle 2sek (2000ms) 
Quasi diese EmpfangsSyntax durchläuft, sodass ich alles immer empfangen 
kann. Ich hab selbstverständlich auf den "Verbinden" Button (mit COM 
verbinden und Configurieren) erst Timer1.Enabled := true; gelegt, da 
sonst eine fehler meldung kommt, wenn man sich nicht innerhalb von 2 
sekunden verbunden hat.

Aber irgendwie geht das nicht klar.

Muss ich da irgendwas beachten?

Danke schonmal! (=

von GeraldB (Gast)


Lesenswert?

In dem Beispiel im o.a. Buch wird auch mit einem Timer gearbeitet.
Für Dein Programm angepaßt sieht das dann so aus:
1
procedure TForm1.Timer1Timer(Sender: TObject);
2
var
3
  signal : string;
4
5
begin
6
  if not connected then exit;
7
  signal := serv.Recvstring(Timer1.Interval div 2);
8
  if serv.LastError <> 0 then exit;
9
  Edit2.Text := signal;
10
end;
Zum Timer-Interval steht nichts dabei, daher kann es wohl auf 1000 
bleiben. Da erst das Vorhandensein der Verbindung abgefragt wird, 
braucht der Timer auch nicht aus-/einschaltet werden.

von Marcel B. (mikroseven)


Lesenswert?

Hallo, zusammen!

Danke fur diesen Beitrag.
War auch auf suche nach Lazarus-Atmega Komunication.

M.f.G. Der Marcel

von Marcel B. (mikroseven)


Lesenswert?

Hi,

kan Jemand "synaser" erklaren?

Bin mir icht sicher was ich dafur brauche.

Kann ich den genaue Component bekommen von jemand, oder ein Link?

M.f.G.

von Huhu (Gast)


Lesenswert?

Marcel B. schrieb:
> oder ein Link?

http://synapse.ararat.cz/doku.php/download

Da ist auch alles beschrieben...

von Marcel B. (mikroseven)


Angehängte Dateien:

Lesenswert?

Vielen Dank, Uhu!

Hatte bereits den selbe Seite gefunden und bin gestartet.



- Alle Ordner/Dateien werden gefunden von den LAZARUS-IDE.

- Nur Fehlermeldung, aber ich denke ich muss mall nachsehen weil das
  Beispiel ist in Deutsch und meine LAZARUS ist in Englisch
  Zum Beispiel TForm.empfang...


Fur die geinteresierten, schau mall mein Projeckten an!
Der Robotor wird noch gesteuert mit Turbo Pascal 7.0 und ein ISA-Slot 
mit verschiedene 82c55a Chips. Muchte gerne zu Lazarus und Arduino ( 
mikroPascal ).



https://www.facebook.com/SurroundingMars/

http://europakade.nl/motion-control-and-robots

M.f.G.

von Marcel B. (mikroseven)


Lesenswert?

Uberigens:

RS232 Kommunication habe ich schon functionieren mit ein 
PC-USART-Terminal.

Ich Sende zu Arduino, und den LCD zeciht es an.
Es wird auch zuruck gesendet und den PC-USART-Terminal zeicht das 
Gleiche an.

Hardware funcioniert!

von Marcel B. (mikroseven)


Lesenswert?

Abend!

Mall eben im /synapse40/source/demo  rumgekuckt aber ich verstehe nicht 
was ich kann anwenden als funcionierendes Demo fur RS232.

Jemand ein Hinweis?

M.f.G.

von W.S. (Gast)


Lesenswert?

Tony B. schrieb:
> Kurzer hand hab ich mir Synaser besorgt

Erwartest du, daß hier irgend jemand dieses/diesen Synaser kennt?

Du brauchst nen Comport-Anschluß für dein Delphi/Lazarus-Projekt. Sowas 
wie ne Komponente TComPort oder wie auch immer das im konkreten Falle 
heißen mag.

Dann solltest du dir sowas wie
procedure TForm1.empfang;
...
begin
Timeout := 4000;
signal := serv.Recvstring(timeout);
...

komplett verkneifen. Genau SO macht man so etwas überhaupt nicht. Hast 
du dir nie einen Gedanken gemacht darüber, wie ein GUI-Programm unter 
egal welchem OS eigentlich funktioniert?

Mein Rat: verpasse deinem Programm einen Timer, setze den auf 50..100 ms 
und erledige deine Input-Aufgaben in der OnTimer-Methode:

procedure Timer.OnTimer
..
if ComPort.CharAvailable
then
begin
  Ch:= ComPort.GetTheChar;
  Verarbeite(Char);
end;

So etwa geht sowas.

W.S.

von mikroSeven (Gast)


Lesenswert?

Hi.

Bevor ich auf diesem Forum ankamm, habe ich mit 5spdo und lazser 
rumgebastellt.

Ich glaube ich gehe besser dorthin zuruck und steige nochmall "frish" 
hinein.

Da ist richtig ein component im Lazarus IDE compileert/-rebuild.

M.f.G.

von mikroSeven (Gast)


Angehängte Dateien:

Lesenswert?

For mehere jahren schon angefangen mit Delphi.
Hier mein funcionierendes Programm, aber ohne RobotArm konnekted.

( funktioniert jetzt noch mit TurboPAscal 7.0 und ISA-Slot )

von Schorsch X. (bastelschorsch)


Lesenswert?

Synaser ist eigentlich recht einfach und funktioniert. Im Prinzip:

uses
  ...
  synaser;

var
  ser:TBlockSerial;
  s:string;
...
  ser:=TBlockserial.Create;
  ser.Connect('COM1');
  ser.Config(115200,8,'N',SB1,false,false);
...
  ser.SendString(text);
...
  if (ser.WaitingData <> 0) then begin
    s := ser.RecvPacket(5000);
  end;

von Marcel B. (mikroseven)


Lesenswert?

Vielen Dank!

Werde nachste Wcohe weitergehn.

Mein Deutsch ist ja nicht Perfekt aber ich hoffe trotzdem es ist fur 
euch Allen zu begreifen!

M.f.G. Der Marcel

von Marcel B. (mikroseven)


Lesenswert?

Hallo,  Schorsch X.

Dat hort mir was bekanter an.
So etwas anliches geht's in meine Arduino.

M.f.G.

von Marcel B. (mikroseven)


Lesenswert?

Moi moi!

habe Erfolg!

Ich 'use' lazaSerial und Synaser.
Hingefughtes Beilspiel "sertest" bestudiert, was rumgebastelt und jetzt 
kan ein String hochzuladen werden zu Arduino/LCD.


Die wichtigste Sachen:

  Serial.Device := EditDevice.Text; { com setting aus editbox }
  Serial.Open;



  str:='(564,129)el';      { el wende ich an im Arduino als delimiter }
  Serial.WriteData(Str);






M.f.G.

: Bearbeitet durch User
von Marcel B. (mikroseven)


Angehängte Dateien:

Lesenswert?

Got some significant progress!

Value of 3 ScrollBars is sended by RS232 to my Arduino.
At 3 LedBars, the values are displayed as (0-255) values.
( gonna be in 0 to 8 led's later as is it showing an 
audio-level-indicater )

In Lazarus the refresh rate is 10/sec. Only the value of the last 
changed Scrollbar is sended to Arduino. At my Lazarus INIT al of the 3 
wil be sended!

I'm using

1 byte as LedbarNumber and

3 bytes as LedBarValue.

The string 'el' (end-line) is added as delimiter.


I'm very happy I got this far programming RS232.

Next step is to controll my robotArm by PC-RS232-Arduino!


Fortunately I got the major part for controlling my robotArm allready
coded in TurbuPascal7.0 and the control is done by ISA/ 82c55a.

The whole ForWard/BackWard-Kinematics, stepperControl and overal 
mathematics for Interpolation/Integral/Differential for creating a path 
in 3d.

http://europakade.nl/motion-control-an-robots/robot-arm

https://www.youtube.com/playlist?list=PL7iWs5bvJdxs91kCZUV9P6KuG4mvriLgJ

von Mathias (Gast)


Lesenswert?

Ich arbeite auch mit Lazarus und synaser, dabei funktioniert die 
Kommunikation mit meinem Arduino hervorragend.

von Marcel B. (mikroseven)


Lesenswert?

Hallo, Mathias!

Geht jetzt besser, aber...kann besser glaube ich.


Kannst du vieleicht etwas von deine Code posten?

Nur die Code schliesslich angewend vor das Senden und dem Empfang.

Ein wenig Erklarung:

Ich sende jetzt immer mit ein Bestimmte Lange des Strings.
z.B. ich sende ADC-Werten von Arduino-ADC zu pc. Bereich
0 bis 1023. Jeder bracht dabei 1, 2, 3 oder 4 Platzen in dem String.
8 ADC's machen 32 Platzen ( char's ) und ein AnfangCharacter . 
ADC-Werten werden mit intToStringWithZeros immer 4
 4Characters Plats einnehemn.

Der Arduino sendet 4 ADC's macht das z.B.
ADC1:= 58;
ADC2:= 659
ADC3:= 303;
ADC4:= 8;

// macht
stOut:= 'D0058065903030008';
uart1_write_text('stOut');

Aber ich will folgendes machen.

stOut:= 'D58,659,303,8';


Da muss, ich zb 58 Speichern im entfangADC1 bis ich ein ','
begegne und dan 659 im entfangADC2...u.s.w...

Am Lazarus krieg ich das nicht hin leider.

Ich glaube, das muss auch anders:


if SerialA.synser.waitingData = cStIn

Konstante cStin habe ich weil ich beim orginalcode immer
die gleiche lange entfange.

von Marcel B. (mikroseven)


Lesenswert?

Hallo W.S.

Sie haben gepostet:

procedure Timer.OnTimer
..
if ComPort.CharAvailable
then
begin
  Ch:= ComPort.GetTheChar;
  Verarbeite(Char);
end;


So etwas suchte ich, nicht ganze string entfangen im Lazarus aber
die Character nach einander und die speicheren in ein String.

Werde nach Wochenende damit anfangen/versuchen.

Da muss ich auch das Senden des Arduino auch anderen:
nicht ein ganze String senden aber einzele Character. ( doch? oder? )

Schones Wochenende!

von Marcel B. (mikroseven)


Angehängte Dateien:

Lesenswert?

( hier mall eben was ich soweit habe. rechtunter seht mann die werden 
von 8 ADC's ( je x und y) und 4 Buttons ( je f ). L ist fur Erweiterung 
und jetzt nicht im betrieb. ganz rechtsunter den lange string ist das 
Entfangene String, erste Character ist nur ein Kontrollzahler. )

von Heinz B. (Firma: Privat) (hbrill)


Lesenswert?

Hallo,
hatte das Problem auch. Zwar nicht mit Lazarus
sondern mit anderen Programmiersprachen.

Das Problem ist, wenn der Arduino (AVR u. a.)
einen String sendet, daß er kein NullByte hinter
den String hängt. Da die meisten Windows-Programmiersprachen
aber ein Nullbyte am Stringende erwarten, können sie
den Arduino-String nicht erkennen.

Abhilfe : einfach (z.B. in Bascom) am Ende des
zu sendenden Strings ein Chr$(0) dranhängen.

von W.S. (Gast)


Angehängte Dateien:

Lesenswert?

Marcel B. schrieb:
> So etwas suchte ich,

Dann guck dir den Anhang an. Läuft in Delphi 6 und 10 - den Port nach 
Lazarus hab ich zwar auch, aber grad nicht greifbar. Installiere dir das 
als Komponente und gut isses.

Zum Benutzen installierst du dir einfach einen Timer zum Pollen des 
Comports (oder nen separaten Thread, geht ja auch) und eine Listbox zum 
Anzeigen.
Prinzip:
Tasten--> via Comport senden;
Empfangen vom Comport--> via Timer in die Listbox stopfen
Das Folgende stammt aus dem STM32Prog-Projekt (hier im Forum zu finden), 
hab das Ganze vor einiger Zeit auch nach Lazarus portiert, aber das D10 
Programm sieht dank Skin netter aus.
1
LaberBox: TListBox;
2
LiBoTimer: TTimer;
3
....
4
5
procedure TMainForm.LaberBoxKeyDown(Sender: TObject; var Key: Word;
6
  Shift: TShiftState);
7
var
8
  ctl  : boolean;
9
  i    : integer;
10
  S    : AnsiString;
11
begin
12
  ctl:=  ssCtrl  in Shift;
13
14
  if ctl and (Key = $2D)   // einfg, also CTL_INS
15
  then
16
  begin
17
    S:= '';
18
    for i:= 0 to LaberBox.Count-1 do
19
    if LaberBox.Selected[i]
20
    then S:= S + #13#10 + LaberBox.Items[i];
21
    Clipboard.AsText:= S;
22
    Key:= 0;
23
  end;
24
25
end;
26
27
procedure TMainForm.LaberBoxKeyPress(Sender: TObject; var Key: Char);
28
var
29
  B : byte;
30
  i : integer;
31
begin
32
  B:= ord(Key);
33
  if B = 1         // CTRL_A  alles markieren
34
  then
35
  begin
36
    LaberBox.SelectAll;
37
    Key:= #0;
38
    exit;
39
  end;
40
41
42
  ComPort.WriteB(B);
43
  if B = 13 then ComPort.WriteB(10);
44
  for i:= 0 to LaberBox.Count-1 do LaberBox.Selected[i]:= false;
45
end;
46
47
48
procedure TMainForm.OnLiBoTimer(Sender: TObject);
49
var
50
  i : integer;
51
  j : integer;
52
  S : String;
53
  C : Char;
54
begin
55
  if not TerminalBox.Visible then exit;
56
  while LaberBox.Count>200 do LaberBox.Items.Delete(0);
57
58
  if LaberBox.Count=0
59
  then begin
60
         LaberBox.AddItem('Terminal '+IntToStr(ComPort.Baud) + ' baud',nil);
61
         LaberBox.AddItem('',nil);
62
       end;
63
64
  i:= ComPort.InCount;
65
  if i=0 then exit;
66
  S:= LaberBox.Items[LaberBox.Count-1];
67
  while i>0 do
68
  begin
69
    C:= Char(ComPort.ReadB);
70
    if C=#13
71
    then begin
72
           LaberBox.Items[LaberBox.Count-1]:= S;
73
           LaberBox.AddItem('',nil);
74
           S:= LaberBox.Items[LaberBox.Count-1];
75
         end
76
    else begin
77
           if C=#9
78
           then begin
79
                  j:= (length(S) or 7)+1;
80
                  while length(S)<j do S:= S+' ';
81
                end
82
           else if C=#8
83
           then begin
84
                  if length(S) > 0
85
                  then Setlength(S, length(S)-1);
86
                end
87
           else begin
88
                  if C>=' ' then S:= S+C;
89
                end;
90
         end;
91
    dec(i);
92
  end;
93
  LaberBox.Items[LaberBox.Count-1]:= S;
94
  LaberBox.ItemIndex:= LaberBox.Count-1;
95
end;

W.S.

von Marcel B. (mikroseven)


Lesenswert?

Danke!

Leider diese Woche noch nicht programmiert.

Bis bald.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.