Autor |
Beitrag |
Martello
      
Beiträge: 131
WIN 2000
TP, C, Delphi 1.0, Turbo Delphi 2006, Delphi 7
|
Verfasst: Di 15.06.10 23:42
Ich möchte 4 mal in der Sekunde GPS-Daten aus einem UBLOX via RS232 einlesen. Diese Strings kommen schön regelmäßig alle 250 ms, und damit habe ich ja auch gleich einen exakten Taktgeber für mein Delphi-Progrämmchen, von dem ich leider nicht weiß, ob ich es je zum Laufen kriege...
Ich habe Cport erfolgreich installiert und studiere nun erst mal die mitgelieferte Hilfe. Weißt jemand - rein zufällig - von ein paar passenden Delphi-Zeilen, die an einem Comport lauschen und regelmäßig Stringsendungen unbekannter Länge (die Längen der $GPRMC-Strings variieren leider) nach Delphi transportieren?
M.
|
|
Martok
      
Beiträge: 3661
Erhaltene Danke: 604
Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
|
Verfasst: Di 15.06.10 23:51
Das ist zufällig mal was, was ich so auch massenweise verbaut hab
Du brauchst also erstmal ein TComPort. Damit verdrahtest du ein TComDataPacket (Packet.ComPort zuweisen). Dieses benötigst du, damit du eben diese unbekannt langen Pakete einfach zerschnipselt kriegst.
Dem DataPacket musst du jetzt sagen, wie die Pakete terminiert sind. StartString bleibt für NMEA leer, StopString ist das ZeilenEnde, also #13#10.
Delphi-Quelltext 1:
| ComDataPacket.StopString := #13#10; |
Nachdem du den ComPort dann zugewiesen, Baudrate und Parität richtig eingestellt und geöffnet hast, bekommst du für jedes Paket ein ComDataPacket.OnPacket Ereignis, und kannst dort die Pakete zerlegen, Prüfsummenchecken etc (hier ggf. auch gucken, ob das Paket überhaupt ein RMC ist  )
Alles klar? Damit sollte man das eigentlich gebaut kriegen.
_________________ "The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Mi 16.06.10 00:47
@Martok: NMEA-Datensätze fangen IMMER mit einem $ an. könnte man theoretisch also als Startstring angeben.
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
Martello 
      
Beiträge: 131
WIN 2000
TP, C, Delphi 1.0, Turbo Delphi 2006, Delphi 7
|
Verfasst: Sa 19.06.10 23:16
Martok hat folgendes geschrieben : |
Nachdem du den ComPort dann zugewiesen, Baudrate und Parität richtig eingestellt und geöffnet hast, bekommst du für jedes Paket ein ComDataPacket.OnPacket Ereignis, und kannst dort die Pakete zerlegen, Prüfsummenchecken etc (hier ggf. auch gucken, ob das Paket überhaupt ein RMC ist ) |
Ich habe die bei Cport mitgelieferten Beispiele ein wenig studiert: Zum folgenden habe ich ein paar Fragen:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57:
| program ModTest; {$APPTYPE CONSOLE}
uses SysUtils, CPort, Windows, SyncObjs;
var ComPort: TComPort; Events: TComEvents; Answer, Data: string; Step: Integer; Event: TEvent;
function CtrlHandler(CtrlType: LongWord): Boolean; begin Event.SetEvent; Result := True; end;
begin Event := TEvent.Create(nil, True, False, ''); SetConsoleCtrlHandler(@CtrlHandler, True); try ComPort.Port := 'COM1'; ComPort.Events := []; ComPort.FlowControl.ControlDTR := dtrEnable; ComPort.FlowControl.ControlRTS := rtsEnable; ComPort.Open; ComPort.WriteStr('AT'#13#10); Answer := ''; Step := 0; repeat Events := [evRxChar]; ComPort.WaitForEvent(Events, Event.Handle, 5000); if evRxChar in Events then begin ComPort.ReadStr(Data, ComPort.InputCount); Answer := Answer + Data; if Pos('OK', Answer) > 0 then Break; end; Inc(Step) until (Events = []) or (Step = 20); finally ComPort.Free; end; except on E: Exception do WriteLn('Error: ' + E.Message); end; Event.Free; end. |
Mit ist nicht klar, woher Comport.InputCount kommt. Zählt da im Hintergrund jemand mit? Aber was zählt er?
Macht TComPortPacket ähnliches, nämlich Datenpakete erkennen und schnüren?
M.
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Sa 19.06.10 23:53
Das wird in der Komponente ein Property sein, was vom Betriebssystem abfragt, wieviele Zeichen im Systempuffer für den COM-Port zwischengespeichert sind. Die Zeile kopiert also im Wesentlichen den System-Puffer in deine Data-Variable.
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
Martok
      
Beiträge: 3661
Erhaltene Danke: 604
Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
|
Verfasst: Sa 19.06.10 23:55
Hi,
wenn ich das Richtig in Erinnerung hab, dann enthält InputCount die Anzahl der Bytes, die im EingangsPuffer angekommen sind, seit man das letzte mal was gelesen hat.
Damit macht der folgendes:
- AT hinschicken
- Warten, bis ein Event auftritt, das wenigstens ein Zeichen da ist
- gesamten Buffer einsammeln
- Wenn das nicht das Ende (OK) war, weiter bei 2.
Generell sollte man aber Blocking Calls vermeiden, wenn man sie nicht braucht.
Ich sammel z.B. mit diesen Kompos Messwerte etc ein, da ist das Paketorientiert schon wesentlich besser. Zumal man dafür ja grade die Packet-Komponente kriegt, die genau das macht: sie guckt sich jedes Zeichen im Stream an, und erkennt, ob da ein Paket anfängt oder zuende ist, und gibt dir per Event Signal davon.
_________________ "The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."
|
|
Martello 
      
Beiträge: 131
WIN 2000
TP, C, Delphi 1.0, Turbo Delphi 2006, Delphi 7
|
Verfasst: So 20.06.10 11:07
Martok hat folgendes geschrieben : | Ich sammel z.B. mit diesen Kompos Messwerte etc ein, da ist das Paketorientiert schon wesentlich besser. Zumal man dafür ja grade die Packet-Komponente kriegt, die genau das macht: sie guckt sich jedes Zeichen im Stream an, und erkennt, ob da ein Paket anfängt oder zuende ist, und gibt dir per Event Signal davon. |
Um ehrlich zu sein: Ich bin noch ziemlich weit davon entfernt, irgendwann den ersten String eingelesen zu haben
Das Beispiel mit dem Modem ist auch nur zum Lernen.
Ich stelle mir das ungefähr so vor: Im Hintergrund läuft ständig ein Teil (Thread ?), das aus dem Datenstrom der Schnittstelle (Byte für Byte, Stream?) genau die Strings herausholt, die zwischen dem definierten Anfangs- und dem Endzeichen (TComDataPacket) stehen.
Eigentlich geht es nicht einfacher zu machen, als genau diesen wunderbaren Service (DataPacket) zu nutzen. Mein Problem ist nur, dass ich trotzdem im Moment noch zuweit davon entfernt bin, es so hinschreiben zu können, dass es auch funktioniert 
|
|
Martok
      
Beiträge: 3661
Erhaltene Danke: 604
Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
|
Verfasst: So 20.06.10 13:38
Hin schreiben könnte ich das auch nicht aus dem Stand.
Muss das unter TD Explorer laufen, oder warum so kompliziert? Normalerweise wären da nur eine handvoll Eigenschaften im Inspektor zu setzen
Das Setup für die ComPort-Komponente selbst ist ja schon im Beispiel oben drin.
ComPortPacket hat ein Property ComPort (oder nur Port? Bin grad nicht sicher), welchem du nur die Port-Komponente zuweisen musst. Dann noch Paktegrenzen einstellen und das Ereignis ComPortPacket.OnPacket zuweisen.
Martello hat folgendes geschrieben : | Ich stelle mir das ungefähr so vor: Im Hintergrund läuft ständig ein Teil (Thread ?), das aus dem Datenstrom der Schnittstelle (Byte für Byte, Stream?) genau die Strings herausholt, die zwischen dem definierten Anfangs- und dem Endzeichen (TComDataPacket) stehen. |
Ich glaube, so wird das auch gemacht. Müsste ich aber auch den CPort-Source lesen 
_________________ "The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."
|
|
Martello 
      
Beiträge: 131
WIN 2000
TP, C, Delphi 1.0, Turbo Delphi 2006, Delphi 7
|
Verfasst: So 20.06.10 18:26
Martok hat folgendes geschrieben : |
ComPortPacket hat ein Property ComPort (oder nur Port? Bin grad nicht sicher), welchem du nur die Port-Komponente zuweisen musst. Dann noch Paketgrenzen einstellen und das Ereignis ComPortPacket.OnPacket zuweisen. |
Kann es sein, dass ich es nur noch nicht gewohnt bin, Code "herzuklicken", anstatt ihn - wie früher üblich - "hinzuschreiben"?
Ich habe aus der CPortLib zwei Elemente auf Form1 gezogen.
Dannach habe ich im Inspektor Start- und Stop-String eingetragen. Anschließend habe ich dort unter "Ereignisse" rechts neben COMPORT "Comport1" eingetragen. Schließlich habe ich links neben OnPacket ein oder zweimal mit der Maus klick gemacht und es erschien - einfach so aus dem Nichts - "ComDataPacket1Packet".
Ich habe weiterhin ein Edit1 erklickt und die Zuweisung "edit1.txt:=str;" eingetragen.
Nachdem der Compiler nicht meckert bin ich nun auf alles gefasst. Allerdings habe ich Moment gar keinen RS232-Sender zuhause
Kann es sein, dass diese paar Klicks alles gewesen sein sollen?  Oder bin ich einfach nur viel zu naiv, für sowas?
M.
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33:
| unit Unit1;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, CPort, StdCtrls;
type TForm1 = class(TForm) ComPort1: TComPort; ComDataPacket1: TComDataPacket; Edit1: TEdit; procedure ComDataPacket1Packet(Sender: TObject; const Str: String); private public end;
var Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.ComDataPacket1Packet(Sender: TObject; const Str: String); begin edit1.text:=str; end;
end. |
|
|
Martok
      
Beiträge: 3661
Erhaltene Danke: 604
Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
|
Verfasst: Mo 21.06.10 00:06
Martello hat folgendes geschrieben : | Kann es sein, dass ich es nur noch nicht gewohnt bin, Code "herzuklicken", anstatt ihn - wie früher üblich - "hinzuschreiben"? |
Ach, also Delphi gibt es jetzt seit 20 Jahren, da kann man sich schon mal so langsam dran gewöhnen  Seh ja sogar ein Delphi 1 bei dir im Profil
Martello hat folgendes geschrieben : | Kann es sein, dass diese paar Klicks alles gewesen sein sollen? Oder bin ich einfach nur viel zu naiv, für sowas? |
Naiv eher nicht. Aber du machst noch nicht lange Delphi, kann das sein? Was ist so dein Background?
Anyway: Jetzt bau ich doch auch mal was, und schreib die Schritte mit. Das Ergebnis gibt im Anhang
- ComPort und ComPortPacket aufs Formular werfen, Namen lass ich der Einfachheit halber mal auf Standard.
- ComPort1 auswählen und im OI die Eigenschaften Parity, BaudRate und DataBits einstellen (Port kommt später)
- ComDataPacket1 auswählen und im Objektinspektor(Eigenschaften) der Eigenschaft ComPort die ComPort1 zuweisen.
- StopString soll #13#10 werden, das kann man aber so nicht im OI einstellen-> Doppelklick auf das Formular, um FormCreate zu erzeugen. Hier folgendes schreiben:
Delphi-Quelltext 1: 2: 3: 4:
| procedure TForm1.FormCreate(Sender: TObject); begin ComDataPacket1.StopString:= #13#10; end; |
- Da wir den Port zur Laufzeit ändern wollen,brauchen wir dafür ein Control. Hier gibt uns die CPortLib TComComboBox in die Hand, die wir gleich mal aufs Forumlar packen...
- ... und ComComboBox1 wie auch schon beim Packet ComPort auf ComPort1 setzen und, da wir den Port ändern wollen, die gleich drunter liegende Eigenschaft ComProperty auf cpPort setzen
- Achja, das Packet-Event sollte man auch setzen; also Doppelklick unter Ereignisse von ComDataPacket1 auf OnPacket, Code erzeugen lassen
- Ich will die Daten mal in ein Memo werfen, dazu folgendes:
Delphi-Quelltext 1: 2: 3: 4:
| procedure TForm1.ComDataPacket1Packet(Sender: TObject; const Str: String); begin Memo1.Lines.Add(Str); end; |
- Bleibt noch das Eigentliche Port auf/zu machen. Dazu 2 Buttons, die jeweils ComPort1.Open/Close aufrufen.
- Und das Einfachste zum Schluss: da wir auch wissen wollen, was grade passiert, gibts auch TComLed, die bestimmte Status-Sachen durch "LED-artiges" blinken anzeigen kann.
- ComLed1 ComPort zuweisen, Kind auf lkBlueLight, LedSignal auf lsConn.
- ComLed2 ComPort zuweisen, Kind auf lkGreenLight, LedSignal auf lsRx.
- Empfangsseite fertig
- Um was zu senden, ein Edit und noch ein Button und folgender Code im OnClick desselben:
Delphi-Quelltext 1: 2: 3: 4:
| procedure TForm1.Button3Click(Sender: TObject); begin ComPort1.WriteStr(Edit1.Text+#13#10); end; |
Martello hat folgendes geschrieben : | Allerdings habe ich Moment gar keinen RS232-Sender zuhause  |
Ich grad auch nicht, deswegen ist das Programm hier auch ungetestet. Sollte aber tun.
Einloggen, um Attachments anzusehen!
_________________ "The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."
|
|
Martello 
      
Beiträge: 131
WIN 2000
TP, C, Delphi 1.0, Turbo Delphi 2006, Delphi 7
|
Verfasst: Mo 21.06.10 14:05
Martok hat folgendes geschrieben : |
Ach, also Delphi gibt es jetzt seit 20 Jahren, da kann man sich schon mal so langsam dran gewöhnen Seh ja sogar ein Delphi 1 bei dir im Profil
Naiv eher nicht. Aber du machst noch nicht lange Delphi, kann das sein? Was ist so dein Background? |
Der erste Rechner wurde noch selbst gelötet, ein Z80-Prozessor, Laufwerk war ein Casettenrecorder, das Keyboard hatte nur 16 Tasten. Aber bald darauf kam IBM auf die Welt, CP/M und Borlands TurboPascal 1.0. Als es dort später objektorientiert wurde, TP 5.5, hatte ich keine Lust auf diesen Overhead nur für Mäuse und Rechteckfenster (es war aber kein Neid auf Bill Gates Rechtecke). Noch heute schreibe ich Konsolen-Anwendungen in TurboPascal, nicht objektorientiert. Meine Schilderungen hier im Forum mit dem "Geklicke" sind schon auch ein wenig ironisch  Natürlich schätze ich Delphi und diese Art zu programmieren; mein Problem besteht nur darin, dass ich es viel zu lange nicht ernst genommen habe.
Die folgenden Punkte 1 bis 3 hatte ich erfolgreich absolviert. Im Objekt-Inspektor konnte ich aber auch #13#10 eintragen, dort wird nach einem Stopstring gefragt (dein Punkt 4).
Wg. Einstellungen der Portparameter war ich zunächst zufrieden, die am Anfang einmal zu wählen (zur Entwurfszeit definieren). Gedanken darüber habe ich mir also schon gemacht...
Die Punkte 7 und 8 hatte ich auch erledigt, allerdings ein Edit1 gewählt, kein Memo. So schlecht war ich also gar nicht  , aber es war und ist immer noch viel zu sehr Stochern im Ungewissen.
Ich bin gespannt auf Deinen Code im Anhang. Und auch wenn er nicht von mir selbst ist, war ich immerhin in dieser Richtung unterwegs....
Als nächstes organisiere ich nun einen RS232-Sender und melde mich dann wieder. Erst mal vielen herzlichen Dank.
M.
- ComPort und ComPortPacket aufs Formular werfen, Namen lass ich der Einfachheit halber mal auf Standard.
- ComPort1 auswählen und im OI die Eigenschaften Parity, BaudRate und DataBits einstellen (Port kommt später)
- ComDataPacket1 auswählen und im Objektinspektor(Eigenschaften) der Eigenschaft ComPort die ComPort1 zuweisen.
- StopString soll #13#10 werden, das kann man aber so nicht im OI einstellen-> Doppelklick auf das Formular, um FormCreate zu erzeugen. Hier folgendes schreiben:
Delphi-Quelltext 1: 2: 3: 4:
| procedure TForm1.FormCreate(Sender: TObject); begin ComDataPacket1.StopString:= #13#10; end; |
- Da wir den Port zur Laufzeit ändern wollen,brauchen wir dafür ein Control. Hier gibt uns die CPortLib TComComboBox in die Hand, die wir gleich mal aufs Forumlar packen...
- ... und ComComboBox1 wie auch schon beim Packet ComPort auf ComPort1 setzen und, da wir den Port ändern wollen, die gleich drunter liegende Eigenschaft ComProperty auf cpPort setzen
- Achja, das Packet-Event sollte man auch setzen; also Doppelklick unter Ereignisse von ComDataPacket1 auf OnPacket, Code erzeugen lassen
- Ich will die Daten mal in ein Memo werfen, dazu folgendes:
Delphi-Quelltext 1: 2: 3: 4:
| procedure TForm1.ComDataPacket1Packet(Sender: TObject; const Str: String); begin Memo1.Lines.Add(Str); end; |
- Bleibt noch das Eigentliche Port auf/zu machen. Dazu 2 Buttons, die jeweils ComPort1.Open/Close aufrufen.
- Und das Einfachste zum Schluss: da wir auch wissen wollen, was grade passiert, gibts auch TComLed, die bestimmte Status-Sachen durch "LED-artiges" blinken anzeigen kann.
- ComLed1 ComPort zuweisen, Kind auf lkBlueLight, LedSignal auf lsConn.
- ComLed2 ComPort zuweisen, Kind auf lkGreenLight, LedSignal auf lsRx.
- Empfangsseite fertig
- Um was zu senden, ein Edit und noch ein Button und folgender Code im OnClick desselben:
Delphi-Quelltext 1: 2: 3: 4:
| procedure TForm1.Button3Click(Sender: TObject); begin ComPort1.WriteStr(Edit1.Text+#13#10); end; |
|
|
Martello 
      
Beiträge: 131
WIN 2000
TP, C, Delphi 1.0, Turbo Delphi 2006, Delphi 7
|
Verfasst: Mi 23.06.10 15:26
Martok hat folgendes geschrieben : |
[*]Da wir den Port zur Laufzeit ändern wollen,brauchen wir dafür ein Control. Hier gibt uns die CPortLib TComComboBox in die Hand, die wir gleich mal aufs Forumlar packen...
[*]... und ComComboBox1 wie auch schon beim Packet ComPort auf ComPort1 setzen und, da wir den Port ändern wollen, die gleich drunter liegende Eigenschaft ComProperty auf cpPort setzen
|
Hallo Martok,
ich habe mittlerweile einen RS232--> USB-Konverter erworben und mein Progrämmchen läuft somit auch auf Notebooks. Dort heißt der Port "com12" oder "com13", je nach Buchse,
allerdings funktioniert die ComProperty (=cpPort) nicht zur Laufzeit. Auch auf dem Rechner, auf dem ich es entwickelt habe, muss der Port im Objekt-Inspektor voreingestellt werden.
Was könnte da noch fehlen?
M.
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Mi 23.06.10 15:35
Schau mal, inwiefern Du vor/nach dem Wechseln den Port neu öffnen musst. Wäre zumindest durchaus vorstellbar.
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
|