Entwickler-Ecke

Sonstiges (Delphi) - Com Daten auswerten


chiron - Mo 23.02.09 13:30
Titel: Com Daten auswerten
Hallo.

Ich benutzte Delphi 6 und greife mit der TComPort Komponente Version 3.10 auf die serielle Schnittstelle zu.

Die gesendeten Daten kann ich auch ohne Probleme in einer Memo Box anzeigen. Gerne möchte ich diese Daten aber in einem Array speichern bzw. dann daraus später ein x-T Diagramm zeichnen. Mein Problem ist nun, dass ich den string lese mit ComPort1.Readstr und er da natürlich auch noch #$D und #$A liest. Diese möchte ich klar nicht in dem Array haben damit ich ein einfaches Integer array deklarieren kann. Weiss vielleicht jemand einen Ansatz wie ich das Problem lösen kann?
Hat vielleicht jemand einen Beispiel Quelltext in dem er auch schonmal auf deisen Weg Daten weiterverarbeitet hat?

Für Tips wäre ich sehr Dankbar.

Gruss
Markus


Nersgatt - Mo 23.02.09 13:40

Hallo,

mit LeftStr kannst Du die 2 überzähligen Zeichen abschneiden und mit StrToInt einen String in einen Integer umwandeln.

Gruß,
Jens


jaenicke - Mo 23.02.09 13:46

user profile iconchiron hat folgendes geschrieben Zum zitierten Posting springen:
Mein Problem ist nun, dass ich den string lese mit ComPort1.Readstr und er da natürlich auch noch #$D und #$A liest. Diese möchte ich klar nicht in dem Array haben damit ich ein einfaches Integer array deklarieren kann.
Das sind doch genau die Trennzeichen, die du brauchst um die Daten zu trennen. Geh zeichenweise durch den empfangenen String und trenne an den Zeilenumbruchzeichen.
Für eine ähnliche Frage habe ich mal ein wenig Code geschrieben, vielleicht hilft die der ein wenig:
http://www.delphipraxis.net/post996232.html#996232

// EDIT:
Crossposts solltest du verlinken. Sonst kann man nicht schauen ob vielleicht schon woanders jemand das geschrieben hat, was man selbst schreiben will, und man macht sich ggf. unnötig Mühe. Gerne gesehen sind sie trotzdem nicht, aber bei Verlinkung geduldet.
http://forum.delphi-treff.de/showthread.php?t=25935


chiron - Mo 23.02.09 14:53

Danke für die schnelle Hilfe.
ich habe es jetzt so gemacht, das ich mit die Stellen mit dem 'Müll' drin gelöscht habe.
Wenn ich mit F8 das Programm durchsteppe klappt alles einwandfrei und die Werte werden im Array gespeichert.

Im Run Modus meckert er vonwegen keine gültige Integervariable. Ich denke ich muss es dann so machen wie in dem Quelltext von dir beschrieben. Kannst du mich grad auf die für mich Interessanten Stellen verweisen? Oder ist all das nötig, auch mit der anderen Klasse (TMySimpleParser)?


jaenicke - Mo 23.02.09 15:05

Da du nicht mehrere verschiedene Quellen hast usw. ist eigentlich nur die Methode Parse (und die zugehörigen Methoden SkipTrash und GetTextLength) wirklich interessant. Die könntest du aber auch ohne Klasse benutzen. In deinem Fall sähe das dann ca. so aus:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
var
  TextLen: Integer;
begin
  Data := Text;
  DataPointer := 1;
  SetLength(Entries, 0);
  SkipTrash;
  while DataPointer < Length(Data) do
  begin
    SetLength(Entries, Length(Entries) + 1);
    TextLen := GetTextLength(False);
    Entries[High(Entries)] := StrToInt(Copy(Data, DataPointer, TextLen));
    DataPointer := DataPointer + TextLen;
    SkipTrash;
  end;
Wobei Entries bei dir ja ein array of Integer wäre.


chiron - Mo 23.02.09 15:40

Der Befehl "SkipTrash" kennt mein Delphi nicht.

Ich habe mir jetzt versucht in dem string die positionen raus zusuchen. Mit PosEx. Hat auch einwandfrei im "Step" Betrieb mit F8 funktioniert. Er sicht sich immer zwischen zwei positionen den richtigen Wert raus. Gehe ich in den Run Betrieb meckert er wieder. Kein Integerwert bla,bla...

Programmieren kann so frustrierend sein... :-(


jaenicke - Mo 23.02.09 15:42

user profile iconchiron hat folgendes geschrieben Zum zitierten Posting springen:
Der Befehl "SkipTrash" kennt mein Delphi nicht.
Der ist ja auch dabei bei dem Quelltext von mir. :lol: ;-)

Zeig man den Quelltext beim Empfangen, wie machst du das?


Nersgatt - Mo 23.02.09 15:42

Ich vermute, dass da manchmal Daten ankommen, die Du so nicht erwartest ;-)
Ich würde es mal mit TryStrToInt probieren und mir anschauen, wie der String aussieht, wenn es fehlschlägt.


chiron - Mo 23.02.09 15:53


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
for n:= 1 to 10 do
   begin
      ComPort1.Readstr(str,8);
      Pos1:= Pos('w1',str);
      Pos2:= PosEx('w2',str,Pos1+1);
      str2:= Copy(str,Pos1+1,Pos2-Pos1 -1);
      ar [n]:=strtoint (str2);
      application.processmessages;
  end;
Ich schicke vom Mikrocontroller z.B. w1200w2 und alles was zwischen w1 und w2 steht will ich rausfiltern. Habe das jetzt mal grad temporär so eingestellt.

Moderiert von user profile iconNarses: Delphi-Tags hinzugefügt


jaenicke - Mo 23.02.09 15:55

Du prüfst aber gar nicht, ob die Positionen überhaupt gültig sind (> 0), außerdem stimmt Pos1 + 1 ja nicht, weil w1 zwei Buchstaben sind.
Zudem wartest du nicht, dass Daten kommen, sondern liest einfach immer 8 Zeichen. :shock:


chiron - Mo 23.02.09 15:59

Ok. Momentan sende ich immer einen Wert zwischen 100 und 200. Null wird er erstmal nicht.
Aber wenn das funzt schreibe ich das noch ein..

Wie kann ich denn warten dass Daten kommen? Also syntaxmäßig? Hättest du einen Quelltextvorschlag für mich? :-)


jaenicke - Mo 23.02.09 16:11

Gibt es da nicht ein Ereignis OnRxChar oder so? Jedenfalls gibt es eins, das dir anzeigt, dass und wie viel angekommen ist.


Jens Hartmann - Mo 23.02.09 17:33

Was Sebastian meint sollte ungefähr so aus sehen.

Mit dieser Procedure, fragt´s du deine Schnittstelle ab

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
procedure TForm1.ComPort1RxChar(Sender: TObject; Count: Integer);
var
  Date : String;
begin
  ComPort1.ReadStr(Date, Count);
  Buffer:=Buffer+Date;
  
  Bufferverarbeitung;           

end;


chiron - Di 24.02.09 10:09

Ok danke. Das klappt auch alles soweit. Unter dieser Procedur schreibe ich alles wie es gerade kommt in ein Memo. Dort wird es auch korrekt angezeigt.
Den string den Jens als 'Date' deklariert hat möchte ich gerne in Integerwerte umwandeln. Jedoch ist halt das Problem das ich mir nur die Werte aus String ziehen will und nicht so Kram wie #$D etc. Diese Werte kommen halt irgendwie undefiniert und er meckert beim strtoint.

Danke nochmals für eure Hilfe. In anderen Foren ist man nicht so freundlich... :-)


jaenicke - Di 24.02.09 10:44

user profile iconchiron hat folgendes geschrieben Zum zitierten Posting springen:
Jedoch ist halt das Problem das ich mir nur die Werte aus String ziehen will und nicht so Kram wie #$D etc. Diese Werte kommen halt irgendwie undefiniert und er meckert beim strtoint.
Genau aus dem Grund habe ich SkipTrash implementiert, das überspringt einfach solche Zeichen.

Du könntest den Quelltext so übernehmen oder schauen wie der funktioniert und es selbst machen. ;-)


chiron - Mo 02.03.09 18:05

Habe mich nochmal dran gegeben und versucht den verlinkten Quelltext in mein Programm mal zu übernehmen.
Bei der Prozedur skiptrash die Werte #13,#10,#32 sind das die Werte die übersprungen werden sollen? In meinem Fall müsste ich dann ja #$D und #$A hinschreiben?!

Habe keine extra Klasse erzeugt sonder weitestgehend alles hineingeschreiben was in der Klasse TMySimpleParser steht ausser die Procedur TMySimpleParser.Parse. Oder muss die auch noch rein für mein Vorhaben?

Du schreibst weiter (in diesem Threat ein paar Einträge vorher) das bei dem Beispielquelltext ENTRIES in meinem Fall ein array of integer wäre. Dann verstehe ich aber folgende Zeile nicht: SetLength (Entries, 0); Was wird denn hier in welchen Platz es Arrays rein geschrieben?

Danke und Gruss :-)


jaenicke - Mo 02.03.09 18:13

user profile iconchiron hat folgendes geschrieben Zum zitierten Posting springen:
Habe mich nochmal dran gegeben und versucht den verlinkten Quelltext in mein Programm mal zu übernehmen.
Bei der Prozedur skiptrash die Werte #13,#10,#32 sind das die Werte die übersprungen werden sollen? In meinem Fall müsste ich dann ja #$D und #$A hinschreiben?!
#$D ist doch das selbe wie #13, nur dass 13 dezimal und D hexadezimal dargestellt ist, aber es ist ja trotzdem der selbe Zahlenwert. ;-)

user profile iconchiron hat folgendes geschrieben Zum zitierten Posting springen:
Habe keine extra Klasse erzeugt sonder weitestgehend alles hineingeschreiben was in der Klasse TMySimpleParser steht ausser die Procedur TMySimpleParser.Parse. Oder muss die auch noch rein für mein Vorhaben?
Parse ist ja das wo alles passiert, wobei du davon nicht viel brauchst, solange du verstanden hast, wie du das machen musst.

user profile iconchiron hat folgendes geschrieben Zum zitierten Posting springen:
Du schreibst weiter (in diesem Threat ein paar Einträge vorher) das bei dem Beispielquelltext ENTRIES in meinem Fall ein array of integer wäre. Dann verstehe ich aber folgende Zeile nicht: SetLength (Entries, 0); Was wird denn hier in welchen Platz es Arrays rein geschrieben?
SetLength setzt die Länge des Arrays wie eigentlich schon der Name sagt (oder zumindest die Hilfe, wenn der Name nicht sprechend genug ist)...


Jens Hartmann - Mo 02.03.09 18:56

Hallo nochmal,

Zitat:

Mit dieser Procedure, fragt´s du deine Schnittstelle ab

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
procedure TForm1.ComPort1RxChar(Sender: TObject; Count: Integer);
var  Date : String;
begin  
ComPort1.ReadStr(Date, Count);  
Buffer:=Buffer+Date;    
Bufferverarbeitung;     
end;


Als kleinen Tipp noch am Rande, die Componente hat noch diverse andere Abfragen, ich habe meine Abfrage z.B geändert.

Wenn Du folgende Funktion verwendets, kannst du einen START und einen STOP Sting angeben, womit die Möglichkeit besteht nur gewisse Datenteile zu lesen.

Die dafür benötigte Komponente (TCOMDATAPacket) ist bei TCOMPort4Beta auch dabei:



Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
{Daten von COM-Schnittestelle lesen}

procedure TForm1.ComDataPacket1Packet(Sender: TObject; const Str: string);
begin
  Buffer := Str;
  if Pos(':', Buffer) = 1 then
  begin
  DataMB256plus:=Buffer;
  DatenverarbeitungVSTMB256plus;
  Bufferverarbeitung;
  end;
end;


Jens Hartmann - Mi 04.03.09 21:07

Hallo Chiron,

auf deine anfrage per E-Mail, will ich Dir sicherlich gerne helfen. Also, mit dem DataPacket, ließt man Daten von der Schnittstelle, wo man z.B. einen Start String abwarten kann.

In deinem Fall musst Du einfach nur die Komponente COMdataPacket auf deine Form ziehen. Diese mit deiner COM Komponente verbinden, und unter StartString '156' und unter StopString '245' eintragen.
Zitat:

Dein Daensatz
#$A’156’#$D#$A’176’#$D#$A’220’#$D#$A’245’#$D


Der Datensatz ist getrennt durch #13#10 das heiß, das u jetzt nur noch eine Abfrage durchführen musst, die in etwa so aus sehen müsste.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
Laenge:=Length(Buffer);
I:=1;
  while I < Laenge+1 do
    begin
      Daten:=Daten+Buffer[I];
        IF Buffer[I] =#13 then
          begin
              z.B. MyArray füllen.
            end;
          end;
      INC(I);
    end;
Buffer:='';
end;


chiron - Mo 09.03.09 17:51

Hey, habe es hin bekommen.
Funktioniert alles einwandfrei. Zwar nicht ganz so wie du meintest Jens aber dein Ansatz hat mir sehr geholfen.

Viele Dank und Grüße


chiron - Di 31.03.09 15:02

Hallo

Habe nochmal eine Frage bezüglich der ComPort Komponente.
Und zwar möchte ich gerne an den Mikrocontroller über die RS-232 was senden.
Der MC benötigt eine Zahl im ASCI Format.

Ich kann ja mit dem befehl: ComPort1.WriteStr(100) was senden. (z.B. den Wert 100)
Kann er dann nur einen String senden? Habe es auch schon mit dieser Syntax versucht:
ComPort1.WriteStr(#100). Raute Zeichen = ASIC Format??

Oder gibt es noch andere Befehle für das senden im ASCI Format an die RS-232?


jaenicke - Di 31.03.09 15:07

#100 sollte das Zeichen mit dem Zahlenwert 100 senden. Was es noch für Möglichkeiten bei der Komponente gibt, weiß ich so erstmal nicht.

Klappt das damit nicht?


Jens Hartmann - Di 31.03.09 15:49

Zitat:
ComPort1.WriteStr(#100). Raute Zeichen = ASIC Format??


Also, das ist aufjedenfall richtig, das du somit das ASCII Zeichen mit dem Zahlenwert 100 senden tust. Soll heißen, du sendest ein "d".

Hier mal eine Ascii Tabelle
http://de.wikipedia.org/wiki/ASCII-Tabelle#ASCII-Tabelle

Gruß Jens


chiron - Di 31.03.09 15:49

der Mikrocontroller empfängt wohl was jedoch anscheinend nicht das richtige.
In meinem MC Programm habe ich 2 verschiedene Schleifen. Bei einem übertragenen Wert von #100
soll die eine Schleife abgearbeitet werden und bei einem Wert von #200 die andere.
Nur irgendwie wirft er dann innerhalb der Schleifen alle Parameter über den Haufen und steuert undefiniert.
Wenn Delphi den Wert richtig im ASCI Format überträgt muss ich halt nochmal mein MC Programm überprüfen.


jaenicke - Di 31.03.09 15:54

Naja, was heißt Zahl im Asci Format? Eine Zahl ist eine Zahl und ein Zeichen hat ggf. einen bestimmten Zahlenwert als Asciicode.

Soll am µC die Zeichenkette 100 als mehrere Asciizeichen hintereinander ankommen oder die Zahl 100 / 200? Und soll die Zahl in einem einzelnen Byte stehen?


chiron - Di 31.03.09 16:14

der wert wird im MC in eine Byte variable geschrieben.
Die Zahl 100/200 als ganzes soll ankommen. Also nicht als Zeichenkette.


jaenicke - Di 31.03.09 16:15

Dann sollte WriteStr mit #100 genau das richtige sein. Oder Moment: benutzt du Delphi 2009? Da ist ein Zeichen zwei Byte groß.


chiron - Di 31.03.09 16:25

ne ich benutze Delphi 6.
hmm... dann liegt´s wohl an meinem MC Programm, das das vielleicht mit den Variablen Typen durcheinander kommt.