Hallo,
ich stehe vor folgendem Problem:
Ich habe eine Windowsanwendung, die über einen COM Port Befehle an ein
Steuergerät schickt und über den selben COM Port daraufhin eine Antwort
erhält.
Die Befehle bestehen im Schnitt aus 10-12 Bytes. Bei der eingestellten
Geschwindigkeit von 115200 Baud sollte also ein Befehl in ziemlich genau
1ms über die Leitung rauschen.
Es gibt 3 Möglichkeiten das Steuergerät zu verbinden:
1) direkt den nativen COM Port des PC mit dem USART (über Pegelwandler)
des Steuergerätes verbinden
2) mangels nativem COM Port ein USB-auf-Seriell Kabel verwenden
(virtueller COM Port)
3) über Bluetooth (SPP), ebenfalls virtueller COM Port
In allen 3 Fällen sieht die Windows Anwendung nur einen COM Port und
weiß ja nicht, was sich dahinter befindet.
Nun mein Problem:
Bei Lösung 1) geschieht die Übertragung auch wirklich in ca. 1ms.
Bei Lösung 2) brauchen die 11 Bytes schon immerhin 10ms. Zwischen jedem
Byte ist eine Pause von fast 1ms!
Und bei Lösung 3) dauert der Vorgang schon 30-40ms! Rießige Pausen
zwischen den Bytes...
Gemessen wurde das mit einem Logiktester (Intronix Logicport).
Normalerweise würde ich jetzt die Schuld auf die Treiber schieben, die
der Anwendung den COM Port vorgaukeln.
Allerdings hab ich einen Gegenversuch mit HTerm gemacht, indem ich den
Befehl per Hand eintippe und abschicke.
In allen 3 Fällen dauert die Übertragung 1ms. Also kanns der Treiber ja
doch irgendwie...
Wisst ihr vielleicht ob man da was dagegen tun kann? Gibt es alternative
Treiber für Bluetooth Dongles und USB-Seriell Adapter?
Oder kann man im System irgendwas konfigurieren? Immerhin klappts ja bei
HTerm...
Ist bisl ärgerlich soviel Zeit für den Request zu verbraten wenn die
Verarbeitung in der ECU und die Antwort zusammen nur ca. 3-4ms
benötigen...
Viele Grüße,
Karlo
Ich denke das liegt am FIFO den die meisten USB-UART-Adapter
standardmäßig nutzen. Die senden dann erst nach einem Timeout die Daten
aus dem Fifo wenn sie längere Zeit keine weiteren Daten bekommen.
Geht mal auf den USB-UART im Gerätemanager und stell unter Erweitert den
Fifo mal um.
Bluetooth müsste ich nachlesen, bei USB sieht das eher danach aus das
die Anwendung nicht ein ganzes Paket, sondern mehrere schickt.
Falls da ein FTDI USB->Seriell-Wandler drin hängt:
http://www.ftdichip.com/Support/Documents/AppNotes/AN232B-04_DataLatencyFlow.pdf
(Latenz ist sowohl über die FTD2XX, als auch über den Gerätemanager
einstellbar)
Welche Sprache/ Bibliothek wird verwendet?
Werden die Befehle zeichenweise gesendet?
Sinnvoll ist blockweise Übertragung (Win32Api: WriteFile(), evtl.
OVERLAPPED)
Hallo,
Danke für die Antworten erstmal.
Welche Lib genutzt wird kann ich nicht sagen, ich habe die Anwendug
bereits fertig erhalten und hab auch keinen Quellcode dazu.
Werd mal der Reihe nach eure Vorschläge abarbeiten :-)
Mich wunderts halt nur, dass HTerm das ganze komplett auf einmal raus
schicken kann, die Anwendung aber nicht...
Viele Grüße,
Karlo
Rumspielen mit den Werten des Buffers oder deaktivieren des Buffers
ändert leider garnichts am Timing. Es ist kein Unterschied zu erkennen,
sowohl bei dem Adapter als auch beim USB Dongle.
Hat noch jemand ne Idee wie sich die Anwendung bewegen lässt, sich so
wie HTerm zu verhalten?
Viele Grüße,
Karlo
>Hat noch jemand ne Idee wie sich die Anwendung bewegen lässt, sich so>wie HTerm zu verhalten?
offensichtlich ist das Programm selber ja "schlecht" programmiert
warum wendest du dich nicht an den Entwickler?
Wie bereits vermutet, wird die Anwendung die Befehle als einzelne
Schreibzugriffe auf dem Port ausgeben.
Ohne Zugriff auf den Entwickler/ Quelltext könntest Du nur eine
Adapter-Anwendung schreiben, die über einen virtuellen Com-Port (z.B.
http://com0com.sourceforge.net/) die Daten eines kpl. Befehls einliest
und dann sinnvoll über den gewünschten Port ausgibt.
Daß es bei sinnvoller Ausgabetechnik funktioniert, hast Du ja mit hterm
getestet.
Hallo Karlo,
das liegt wohl an Deinem Treiber.
Bei einem virtuellen COM-Port versucht man ja eine möglichst hohe
Übertragungsrate zu erreichen. Das aber ist nur möglich, wenn volle
Pakete (entsprechend Deiner Endpunkt-Puffer) versendet werden.
Angenommen Deine Endpunkte sind 64 Byte groß, dann muss der PC Treiber
immer auf 64 Byte warten, um sicherzustellen, dass er auch alles
entgegennimmt (ReadFile(a,b,c,64) o.ä.).
Wenn Deine Anwendung also nur 10 Bytes versendet, dann wartet der
Treiber theoretisch ewig, was aber dadurch vermieden wird, indem nach
z.B. 10 ms die Daten vom Treiber weitergegeben werden - und zwar egal
wieviele es sind.
Man könnte den Treiber auch so erstellen, dass er die Daten Byte-weise
entgegen nimmt (ReadFile(a,b,c,1)). Was aber eher selten passiert, denn
dann hat man das Problem, dass die ganze Geschichte wesentlich
verlangsamt wird. Darum nutzen viele Treiber die Lösung mit vollem
Puffer (64 Byte) und dem Timeout.
Gruß Potter
Das heißt, die Anwendung wird (wahrscheinlich) nicht einen 11 Byte
langen Frame an den Treiber weiterreichen sondern immer nur 1 Byte, d.h.
der "Senden" Befehl wird 11 mal ausgeführt?
Dann hab ich wohl wirklich ohne Quelltext keinen Einfluss auf das
Verhalten...
Die Lösung mit dem com0com hört sich gut an, wär aber ein wenig
Overkill. So schlimm ist das mit dem Timing auch nicht, sind eher so
Feinheiten (die sich aber bekanntlich aufsummieren können :-)).
Ich habe mal den Support angeschrieben, falls noch jemanden was
einfällt, gerne her damit :-)
Viele Grüße,
Karlo