AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Sonstige Fragen zu Delphi Delphi ApdCOMPort: Daten gehen bei großen Datenmengen verloren
Thema durchsuchen
Ansicht
Themen-Optionen

ApdCOMPort: Daten gehen bei großen Datenmengen verloren

Ein Thema von Carsten1234 · begonnen am 6. Mai 2009 · letzter Beitrag vom 29. Mai 2009
Antwort Antwort
Seite 1 von 3  1 23      
Carsten1234

Registriert seit: 9. Apr 2008
Ort: Vechelde
178 Beiträge
 
Delphi 8 Professional
 
#1

ApdCOMPort: Daten gehen bei großen Datenmengen verloren

  Alt 6. Mai 2009, 15:20
Hallo zusammen,

ich habe mit der aktuellsten Version das Problem, dass mir offensichtlich Daten im Buffer verloren gehen oder überschrieben werden.
Vorab:
Über einen Virtual COM Port Treiber wird ein Gerät via USB angeschlossen. Schicke ich Daten an das Gerät, erfolgt von diesem eine Rückmeldung in einer bestimmten Art und Weise. Die ersten drei Zeichen, der sog. Kopfblock, enthält u.a. die Datenlänge. Diese wiederum bestimmt die Länge der nachfolgenden Daten.
In rudimentären Grundroutinen lesen ich zunächst die den Kopfblock aus und anhand der im Kopfblock übertragenen Länge anschliessend den Datenblock selbst.
Bsp. (stark vereinfacht):
Delphi-Quellcode:

const
  HEADBLOCKSIZE = 3;
  DATABLOCKSIZE = 4096;

var
  Head_Block = array[1..HEADBLOCKSIZE] of char;
  Data_Block = array[1..DATABLOCKSIZE] of char;

procedure GetHeadBlock;
begin
  repeat
    Application.ProcessMessages;
  until (TimeoutFlag) or (ApdComPort.InBuffUsed >= HEADBLOCKSIZE);
  if (not TimeoutFlag) then
  begin
    ApdComPort.GetBlock(Head_Block, HEADBLOCKSIZE);
  end;
end;

procedure GetDataBlock(ASize: word);
begin
  repeat
    Application.ProcessMessages;
  until (TimeoutFlag) or (ApdComPort.InBuffUsed >= ASize);
  if (not TimeoutFlag) then
  begin
    ApdComPort.GetBlock(Head_Block, ASize);
  end;
end;
Vorher wurde ein Timer gesetzt, der nach max. 3 Sek. anspringt und das TimeOutFlag auf TRUE setzt, so dass die Endlosschleife unterbrochen wird.
Diese (grob skizzierten) Routinen arbeiten eigentlich auch ganz wunderprächtig, so lange die Datenmenge zw. PC und Gerät rel. klein ist.

Nun sollen aber auch größere Datenmengen (Dateien) in Blöcke zu max. 4kB vom PC zum Gerät übertragen werden. Dazu wird über eine while not (EoF(...)) do die zu übertragene Datei in 4kB-Häppchen zerlegt und via ApdComPort.PutBlock an das Gerät übertragen.
Nachdem ein 4kB-Block übertragen wurde, warte ich über die beiden Routinen oben die Rückmeldung vom Gerät ab. Der Kopfblock bestimmt wieder die Länge der Rückmeldung und im Datenblock wiederum steht die Rückmeldung.
Leider kommt es mitunter und zu immer anderen Zeitpunkten vor, dass die Daten im InBuffer völlig zerschossen sind, wobei jedoch kurioserweise ein Mitschnitt auf dem USB-Port angibt, dass die Daten noch korrekt vom Gerät an die PC-Schnittstelle kommen. Der Mitschnitt bzw. die Hardware dazu ist ein Gerät, dass quasi in das USB-Kabel zw. Gerät und PC gehängt wird.
Ferner hatte ich festgestellt, dass es eine deutliche Besserung bringt, wenn ich in der while not (EoF(...)) do ein Delay von 30..40ms einbaue. De facto scheint es also irgendwo ein Buffer Overflow zu geben (meine Mutmassung).
Das PDF-Handbuch zu AsyncPro beschreibt diesbzgl. auf S. 31ff ein "eventually overflow the PC's input buffer and data would be lost".
Ein Hardware Flow Control scheidet auf jeden Fall aus, doch auch ein Software Flow Control sowohl über die Einstellungen bei ApdCOMPort als auch in den COM-Port Einstellungen über den Gerätemanager bringen nix. Ebenso wenig bringt ein 'Flushen' der beiden Buffer.

Fragen:
1) Ist meine Mutmassung bzgl. Buffer overflow richtig?
2) Hat jemand noch eine gute Idee, das Problem in den Griff zu bekommen?

Dank vorab und Gruß, Carsten
  Mit Zitat antworten Zitat
Benutzerbild von user0815
user0815

Registriert seit: 5. Okt 2007
331 Beiträge
 
Delphi XE2 Professional
 
#2

Re: ApdCOMPort: Daten gehen bei großen Datenmengen verloren

  Alt 6. Mai 2009, 16:32
Hast Du zum testen dazu mal die ApdDataPacket Komponente eingesetzt ?

Rechtsklick drauf und man kann die StartCond + EndCond setzen oder auch erstmal jeden String akzeptieren.
Evtl. den TimeOut auf 0 Stellen.
Ausgabe über das Event "ApdDataPacket1StringPacket"
  Mit Zitat antworten Zitat
Carsten1234

Registriert seit: 9. Apr 2008
Ort: Vechelde
178 Beiträge
 
Delphi 8 Professional
 
#3

Re: ApdCOMPort: Daten gehen bei großen Datenmengen verloren

  Alt 6. Mai 2009, 17:30
Zitat von user0815:
Hast Du zum testen dazu mal die ApdDataPacket Komponente eingesetzt ?

Rechtsklick drauf und man kann die StartCond + EndCond setzen oder auch erstmal jeden String akzeptieren.
Evtl. den TimeOut auf 0 Stellen.
Ausgabe über das Event "ApdDataPacket1StringPacket"
Damit hatte ich es noch nicht versucht. Allerdings hatte ich noch vergessen zu erwähnen, dass ich sowohl den Log- als auch Trc-Mitschnitt aktiviert hatte und dort die Daten korrekt auftauchen.

Gruß, Carsten
  Mit Zitat antworten Zitat
Trigger2003

Registriert seit: 14. Jun 2006
36 Beiträge
 
Delphi 12 Athens
 
#4

Re: ApdCOMPort: Daten gehen bei großen Datenmengen verloren

  Alt 6. Mai 2009, 17:51
Was ich noch nicht erkennen kann:

Was hält denn den Sender (PC) davon ab, nach Senden der ersten 4K sofort den nächsten Datenblock zu übertragen, für den Du eigentlich doch nicht unmittelbar Platz hast (-> Overflow). Eine Art von Quittung, Handshake o.Ä. kann ich im Beispielcode nicht erkennen. Das würde auch erklären, warum sich die Situation mit Delays zwischen den Datenblocks bessert, weil das dem Empfänger Zeit verschafft, einen vollständigen Datenblock erstmal zu verarbeiten und den benötigten Empfangspuffer wieder freizugeben.

Ich denke, ohne eine Art Protokoll (positive oder negative Rückmeldung) wird es kaum sauber hinzukriegen sein. So in der Art des uralten XModem- oder ZModem-Protokolls..

Oder habe ich da was falsch verstanden?
  Mit Zitat antworten Zitat
taveuni

Registriert seit: 3. Apr 2007
Ort: Zürich
534 Beiträge
 
Delphi 11 Alexandria
 
#5

Re: ApdCOMPort: Daten gehen bei großen Datenmengen verloren

  Alt 6. Mai 2009, 17:55
Jetzt mal ohne genau Deinen Code zu analysieren.
Wir arbeiten seit Jahren mit AsyncPro.

Allerdings empfangen wir im TriggerAvail.
Beispiel:

Delphi-Quellcode:
procedure TSickLMxDevice.TriggerAvail(CP: TObject; Count: Word);
var
  buffer : array [0..4095] of byte;
  crcBuffer : array[0..4095] of byte;
  i: Integer;
  dataLength : word;
  tmpBufferSize : Integer;
const
  minRXTelegramLength = 8;
begin
  try
    TApdComPort(CP).GetBlock(buffer, Count);
Kannst Du Dich da mal reinhängen und überprüfen ob der buffer dann immer
das gewünschte enthält? Falls ja machst Du was falsch.
  Mit Zitat antworten Zitat
Carsten1234

Registriert seit: 9. Apr 2008
Ort: Vechelde
178 Beiträge
 
Delphi 8 Professional
 
#6

Re: ApdCOMPort: Daten gehen bei großen Datenmengen verloren

  Alt 6. Mai 2009, 18:22
Zitat von Trigger2003:
Was ich noch nicht erkennen kann:

Was hält denn den Sender (PC) davon ab, nach Senden der ersten 4K sofort den nächsten Datenblock zu
(...)
Oder habe ich da was falsch verstanden?
Das Problem ist, dass es weder ein Hardware noch Software Flow Control mit dem Gerät gibt. Der PC (mein Programm) wartet in den genannten Schleifen max. 3 Sek. auf eine Rückmeldung bzw. darauf, dass Daten im InBuffer von ApdCOMPort liegen. Die Rückmeldung vom Gerät soll quasi (im übertragenen Sinne) der Handshake sein und das Zeichen dafür, dass vom Gerät die Daten verarbeitet wurden.
Ich vermute daher kein Overflow im Gerät, sondern im UART, der eine gewisse Zeit benötigt, die Daten zu verarbeiten.
  Mit Zitat antworten Zitat
Trigger2003

Registriert seit: 14. Jun 2006
36 Beiträge
 
Delphi 12 Athens
 
#7

Re: ApdCOMPort: Daten gehen bei großen Datenmengen verloren

  Alt 6. Mai 2009, 18:29
Fragen über Fragen zum besseren Verständnis:

Wer schickt denn jetzt wem (Nutz-)Daten? PC an Gerät oder umgekehrt? Beide? Ist da schon irgendein Protokoll mit Quittungsblocks implementiert/dokumentiert? Dein OP klingt ja so, aber in dem Fall vermisse ich eine Art Prüfsumme. Bei einem Block-orientierten Protokoll benötigst Du eigentlich keine Flow-Control, weil ja der Quittungsblock die erneute Empfangsbereitschaft melden soll.

Schreibst Du die Routinen für beide Seiten oder nur für die PC-Seite? Mit anderen Worten: Kannst Du den Aufbau des Protokolls beeinflussen?

Ist das "Gerät" irgendeine Blackbox (Meßgerät o.Ä.), die aufgezeichnete Daten/Meßwerte/wasauchimmer seriell (RS232/RS485) über einen USB-Schnittstellenwandler abliefert oder hat das Gerät ein echtes USB-Interface, das dann durch den VirtualComPort-Treiber wie eine zusätzliche RS232 erscheint? Mit welcher Baudrate wird übertragen (wg. Timings)?

Im ersten Fall würde ich mit einer "echten" RS232 testen, um Fehler im virtuellen ComPort-Treiber auszuschließen. Nach meiner Erfahrung ist die RS232-Emulation durch den Treiber keineswegs 100% kompatibel, gerade was das Zeitverhalten der Statusregister angeht.
  Mit Zitat antworten Zitat
Benutzerbild von Chemiker
Chemiker

Registriert seit: 14. Aug 2005
1.859 Beiträge
 
Delphi 11 Alexandria
 
#8

Re: ApdCOMPort: Daten gehen bei großen Datenmengen verloren

  Alt 6. Mai 2009, 19:48
Hallo Carsten1234,

wie user0815 bereits ausgeführt hat, bittet sich für Deine Aufgabe das ApdDataPacket an. Die Buffer-Verwaltung sollte man der Komponente überlassen. Wahrscheinlich wird schon der Buffer wieder beschrieben, wenn Dein Programm grade den Buffer ausliest.

Bis bald Chemiker
wer gesund ist hat 1000 wünsche wer krank ist nur einen.
  Mit Zitat antworten Zitat
Carsten1234

Registriert seit: 9. Apr 2008
Ort: Vechelde
178 Beiträge
 
Delphi 8 Professional
 
#9

Re: ApdCOMPort: Daten gehen bei großen Datenmengen verloren

  Alt 7. Mai 2009, 07:14
Zitat von Trigger2003:
Fragen über Fragen zum besseren Verständnis:
(...)
Im ersten Fall würde ich mit einer "echten" RS232 testen, um Fehler im virtuellen ComPort-Treiber auszuschließen. Nach meiner Erfahrung ist die RS232-Emulation durch den Treiber keineswegs 100% kompatibel, gerade was das Zeitverhalten der Statusregister angeht.
Na, dann versuche ich mal Licht ins Dunkle zu bringen.
Bei dem Gerät handelt es sich um ein Gerät mit echter USB-Schnittstelle, wird allerdings wie bereits geschrieben via einem Virtual COM Port Treiber mit dem PC (Windows) verbunden. Die Erklärung, warum das so gemacht wird und nicht mit echtem USB würde den Rahmen sprengen.
Die Baudrate liegt bei 9600Baud, wobei die Einstellung keinen Einfluss auf die tatsächliche Geschwindigkeit hat, da die max. Übertragungsrate immer bei ~140kB/s liegt. Ob das jetzt nun schnell bzw. zu schnell für den UART und/oder den Treiber ist, kann ich nicht beurteilen.
Ich schreibe nur das Programm auf PC-Seite, für die Firmware ist eine andere Inhouse-Abteilung zuständig. Einfluss auf mögl. Änderungen im Gerät hätte ich aber, da alles, also auch die Hardwareentwicklung Inhouse geschieht.

Zum Protokoll (sofern man das so nennen will):
Im sog. Kopfblock, den ersten drei Bytes, steht als erstes Byte die sog. Befehlsfamilie, Byte 2 und Byte 3 bestimmen die Länge des nachfolgenden Datenblocks.

Schicke ich nun einen 4K-Häppchen an das Gerät, erzeuge ich ebenfalls diesen "Overhead" vorne dran, in dem ich die Befehlsfamilie und die Länge des nachfolgenden Datenblocks schicke. Im Pseudocode: "Gerät, jetzt kommen Binärdaten mit der Länge 4096 Bytes". Genau genommen schicke ich also 3 + 4096 Bytes. Wenn das Gerät die Daten empfangen hat, bekomme ich eine Antwort vom Gerät in derselben eben genannten Weise. Das erste Byte liefert mir wieder die Befehlsfamilie und Byte 2 und Byte 3 die Länge des Datenblock.
Wurden die von mir geschickten Daten vom Gerät korrekt empfangen und verstanden, ist die Datenlänge 1 und ich muss nur auf das ersten Byte des Datenblocks schauen, wobei dieses Byte einen bestimmten Wert für OK haben muss. Ist die gelieferte Länge > 1, liegt eine Fehlermeldung seitens des Geräts vor und die Bytes des Datenblock ab Position 2 bis {geschickte Datenlänge} liefern den Fehlercode (z.B. Gerät hat Daten nicht korrekt empfangen od. ähnl.).

Wir haben, wie weiter oben geschrieben, mal einen Datenlogger in die USB-Leitung gehängt. Über diesen sehen wir, dass bis zum Abbruch meinerseits das Gerät immer mit OK geantwortet hat. Ferner bietet ja ApdCOMPort ein Logging und Tracing und auch hier sind die vom Gerät empfangenen Daten noch i.O. Markant ist allerdings, dass alles sauber durchläuft, wenn ich zw. dem Versenden meines Datenpakets und dem Warten auf eine Antwort ein Delay von 30..40ms einbaue. Zudem ist dieser Effekt auch recht neu, nämlich erst seitdem die Übertragungsgeschwindigkeit aufgebohrt wurde.
Was jedoch wiederum gg. einen Fehler in meinen beiden Routinen spricht ist die Tatsache, dass über diese Routinen ALLE Kommunikationen mit dem Gerät laufen, also z.B. auch das Auslesen von Werten, Lesen und Schreiben von Konfig-Daten im Gerät usw.. Als dies läuft fehlerfrei, allerdings sind hier die übertragenen Datenmengen auch überschaubar klein (max. einmalig 1kB/Befehl). Ferner tritt der Effekt auch nicht bereits nach dem ersten übertragenen 4k-Block auf, sondern später, allerdings zu unterschiedlichen Zeitpunkten. Mal sind bereits 200kB übertragen, beim nächsten Mal 600kB, 1MB, .... Ich kann also noch nicht mal sagen, dass der Fehler immer nach xkB auftritt.
Und Debuggen ist auch nicht möglich, da es dann nicht mehr zeitkritisch ist und alles sauber durchläuft.

Zum Treiber:
Wird das Gerät erstmalig mit dem PC verbunden und Windows kennt das Gerät noch nicht, wird die INF-Datei angefordert. Diese INF-Datei stammt vom Chiphersteller, dessen Chip im Gerät werkelt. Was da dann genau abgeht bei der Treiberinstallation, vermag keiner so richtig zu sagen. Wir gehen allerdings davon aus, dass ein windowseigener Virtual COM Port Treiber installiert wird.

Gruß, Carsten
  Mit Zitat antworten Zitat
Carsten1234

Registriert seit: 9. Apr 2008
Ort: Vechelde
178 Beiträge
 
Delphi 8 Professional
 
#10

Re: ApdCOMPort: Daten gehen bei großen Datenmengen verloren

  Alt 7. Mai 2009, 07:27
Zitat von taveuni:
Kannst Du Dich da mal reinhängen und überprüfen ob der buffer dann immer
das gewünschte enthält? Falls ja machst Du was falsch.
Das habe ich getan und bekomme schon nach rel. kurzer Zeit eine Exception, die da lautet:
Im Projekt ist eine Exception der Klasse EOutputBufferToSmall mit der Meldung 'Output buffer too small for small for block' aufgetreten.

Die Größen:
InSize:= 16384;
OuSize:= 16384;

Gruß, Carsten
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 3  1 23      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 01:13 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz