Forum: Mikrocontroller und Digitale Elektronik Effiziente Datenübertragung (low-latency) von PC zu Mikrocontroller


von Timo L. (Gast)


Lesenswert?

Hallo,

ich arbeite derzeit an einem Projekt bei dem ich in von einem PC (Linux, 
low-latency-Kernel) mit bei einem Takt von 1.25 kHz 256 Byte pro 
Nachricht an einen Mikrocontroller (TI TMS320F28377D) per virtuelle 
serielle Schnittstelle (USB2-Adapter) schicke. Der Taktgeber ist hierbei 
eine Industrie-Kamera deren Jitterverhalten ich im Griff habe (avg=0.8 
ms, std.dev=60µs). Wenn ich mit 10 Bit rechne komme ich im Schnitt auf 
eine Datenrate von 3.2 Mbit/s. Laut Doku erreicht der TI bei einer USB2 
"High-Speed" Anbindung theoretisch bis zu 12 Mbit/s, d.h. es sollte 
prinzipiell mit der Hardware möglich sein.

Auf der PC-Seite habe ich die serielle Schnittstelle per ttyAMC0 mit 
Parametern für eine Binärübertragung geöffnet und sende die Daten in 
einem C-Program mit hoher Prozesspriorität "sudo -E nice -19" jeden Takt 
in einer per "write(fd,buffer,len)" gefolgt von einem "tcdrain(fd)" alle 
1250 Hz raus. Inhaltlich passt die Datenübertragung. Ich habe hierfür in 
meinen Datenpaketen eine Sequenznummer untergebracht, die der PC 
hochzählt und die ich auf der Mikrocontroller-Seite prüfe und mit einem 
Zähler dort abgleiche.

Allerdings ist die Performanz schlechter als erwartet. Ich habe auf der 
PC-Seite ein Histogram über einige Minuten gebildet stelle fest, dass 
ich im Schnitt ca. 500µs für die Übertragung der 256 Bytes (10 Bit) mit 
worst-case-Spitzen bis zu 2000 µs erhalte. Beim Average komme ich daher 
nur auf rund 1 Mbit/s, d.h. mehr als Faktor 3 unter dem, was ich 
erreichen will.

Um den Flaschenhals zu finden, habe ich beide Seiten untersucht. Die 
Mikrocontroller-Seite sieht gut aus, da ich für das Auslesen und 
Entpacken der 256 Bytes lediglich 60-70 µs benötige. Ich vermute daher, 
dass der Sender bzw. die Übertragung auf der PC-Seite den Engpass 
darstellt.

Seht ihr eine Möglichkeit wie ich das Ganze PC-seitig beschleunigen 
kann?
Meine erste Überlegung war, dass ich die Hardware nicht als serielle 
Schnittstelle fahre, sonder per libusb/bulktransfer anspreche. Seht ihr 
eine Alternative? Die Datenpakete kann ich leider nicht deutlich 
vergrößern, da ich low-latency sein will und sie möglichst schnell 
Zeitnah zum Takt von der PC-Seite versenden möchte.

Allgemein frage ich mich, was für eine Übertragungstechnologie für 
meinen Anwendungsfall low-latency, 1.25 Khz/256 Bytes sinnvoll ist.

Ich würde mich freuen, wenn ihr mir mit Anregungen helfen könnt.

Vielen Dank und schönen Gruß

von Sven B. (scummos)


Lesenswert?

Der cdc_acm-Treiber ist für größere Datenraten Schrott. Er erreicht 
weder die ideale Datenrate noch funktioniert er korrekt; kann sein, dass 
manche Pakete bei hoher Last einfach aus dem Datenstrom gedropt werden, 
ohne dass Host oder Device das mitbekommen.

Nimm lieber libusb, damit bist du viel flexibler und es ist kein 
besonders großer Aufwand für so eine einfache Anwendung.

Ob du damit deine Specs erreichst, kann ich dir nicht sagen, aber ich 
würde sagen entweder es geht damit oder die Lösung ist prinzipiell nicht 
geeignet.

: Bearbeitet durch User
von Auch Karl, ein anderer (Gast)


Lesenswert?

Bulk endpoints haben kein definiertes Zeitverhalten. Wenn du das 
brauchst, musst du auf einen isochronen endpoint gehen. Das ist aber mit 
den üblichen Standard Geräteklassen glaub ich nicht drin.

von blub (Gast)


Lesenswert?

Probiers mit ethernet

von Thomas Z. (usbman)


Lesenswert?

Timo L. schrieb:
> Laut Doku erreicht der TI bei einer USB2
> "High-Speed" Anbindung theoretisch bis zu 12 Mbit/s, d.h. es sollte
> prinzipiell mit der Hardware möglich sein.

das riecht aber nicht nach HS sondern FS sprich USB1 speed.

Damit sind die Bulkpakete jeweils 64 byte. Pro Usb Frame musst du also 5 
Pakete übertragen um auf die 256b bei 1.25kHz kommen. Alles im Rahmen.
Was ich nicht verstehe wo kommen die 3.2MBit her? weil 256b bei 1.25kHz
sind ja gerade mal 320kBit also Faktor 10 weniger.

3.2MBit per serial ist sportlich ich würde sagen 1 MBit ist eher drin. 
was sich ja wohl mit deinen Ergebnissen deckt.

die Serielle Verbindung ist übrigens auch eine Bulk Verbindung.

Wie sehen die Deskriptoren aus?

Thomas

von Dergute W. (derguteweka)


Lesenswert?

blub schrieb:
> Probiers mit ethernet

Seh' ich auch so.

Gruss
WK

von Hmmm (Gast)


Lesenswert?

Alternativ eine PCI(e)-RS422/485-Karte, um Dir die USB-Latenz zu 
ersparen.

von c-hater (Gast)


Lesenswert?

Timo L. schrieb:

> Meine erste Überlegung war, dass ich die Hardware nicht als serielle
> Schnittstelle fahre, sonder per libusb/bulktransfer anspreche.

Das wird rein garnix bringen. CDC-ACM benutzt ja auch schon bulk-Kanäle.

> Seht ihr
> eine Alternative?

Wenn überhaupt, dann isochrone Transfers. Die können eine Bandbreite und 
eine Latenz garantieren (allerdings keine fehlerfreie Übertragung).

Das Problem wird aber (neben der fehlenden Fehlerkontrolle) auch damit 
sein: die garantierte Latenz ist relativ groß und paßt nicht zu deinen 
Latenzforderungen.

Oder anders ausgedrückt: USB taugt wohl nicht für deinen Zweck.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

c-hater schrieb:
> Das wird rein garnix bringen. CDC-ACM benutzt ja auch schon bulk-Kanäle.

Aber der hostseitige CDC-ACM-Treiber enthält Puffer/FIFOs und die 
Paketierung lässt sich nicht wirklich kontrollieren. Über ein eigenes 
USB-Protokoll und libusb kann man genau steuern welche Daten wann in ein 
Paket verpackt und abgeschickt werden. Damit könnte das schon gehen.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.