![]() |
ApdCOMPort: Daten gehen bei großen Datenmengen verloren
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:
Vorher wurde ein Timer gesetzt, der nach max. 3 Sek. anspringt und das TimeOutFlag auf TRUE setzt, so dass die Endlosschleife unterbrochen wird.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; 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 ![]() 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 |
Re: ApdCOMPort: Daten gehen bei großen Datenmengen verloren
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" |
Re: ApdCOMPort: Daten gehen bei großen Datenmengen verloren
Zitat:
Gruß, Carsten |
Re: ApdCOMPort: Daten gehen bei großen Datenmengen verloren
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? |
Re: ApdCOMPort: Daten gehen bei großen Datenmengen verloren
Jetzt mal ohne genau Deinen Code zu analysieren.
Wir arbeiten seit Jahren mit AsyncPro. Allerdings empfangen wir im TriggerAvail. Beispiel:
Delphi-Quellcode:
Kannst Du Dich da mal reinhängen und überprüfen ob der buffer dann immer
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); das gewünschte enthält? Falls ja machst Du was falsch. |
Re: ApdCOMPort: Daten gehen bei großen Datenmengen verloren
Zitat:
Ich vermute daher kein Overflow im Gerät, sondern im UART, der eine gewisse Zeit benötigt, die Daten zu verarbeiten. |
Re: ApdCOMPort: Daten gehen bei großen Datenmengen verloren
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. |
Re: ApdCOMPort: Daten gehen bei großen Datenmengen verloren
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 |
Re: ApdCOMPort: Daten gehen bei großen Datenmengen verloren
Zitat:
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 |
Re: ApdCOMPort: Daten gehen bei großen Datenmengen verloren
Zitat:
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 |
Alle Zeitangaben in WEZ +1. Es ist jetzt 03:28 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz