Hallo Zusammen :) Ich habe ein C++ Programm geschrieben um einen Sensor unter Linux auszulesen. Es handelt sich um den CHR-6dm, der per USB angeschlossen wird, aber per serieller Schnittstelle (/dev/ttyUSB0) ausgelesen. Es handelt sich um einen USB Serial Converter: Future Technology Devices International, Ltd FT232 USB-Serial (UART) IC Ich kann über diese Schnittstelle mit dem CHR-6dm kommunizieren, was auch schon sehr gut klappt. Im Prinzip geht es mir nur darum, möglichst schnell Daten auszulesen. Dies ist von 20-300Hz möglich: "The CHR-6dm is factory-configured to broadcast angles and angular rates at 200 Hz over a TTL UART at 115200 baud. The serial protocol uses 8 data bits, 1 stop bit, and no parity." Der Sensor schickt mir genau 39 Byte die ich lesen möchte. Ich öffne also eine serielle Verbindung: // Seriell Schnittstelle öffnen und konfigurieren int fd_seriell = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK); int flags = fcntl(fd_seriell, F_GETFL); flags = ( O_DIRECT | O_FSYNC | O_RSYNC | O_DSYNC); if (fd_seriell == -1) perror("open_port: Unable to open serial port "); else fcntl(fd_seriell, F_SETFL, 0); leselaenge = 39; setzeOptionen(&fd_seriell); und konfiguriere sie: http://nopaste.immersight.de/?3ad970837b6016ae#JIN32+w5cj4O6EhvYbu8beE6u+2dB//u0T7NkLi+Qig= Die Zeit zwischen dem Lesen von der Schnittstelle messe ich dabei. Das Gerät ist auf 300 Hz eingestellt uns sendet mir damit alle 5,5ms 39 Byte. read((*p_fd_seriell),&stream,leselaenge);//Stream lesen Das Ergebnis ist leider nicht zufriedenstellend. Anstatt alle 5,5ms einen Wert auszulesen, ergibt sich dieses komische Muster: http://nopaste.immersight.de/?d00eb0eb88bf16d7#Z5esix5wkbu1+993riyPpYDuYtWa6m5Bxk8FEGKV60Y= Als hässliche Lösung habe ich das nun so gemacht. Vor dem Read setze ich den Thread einfach 3ms schlafen: boost::this_thread::sleep(boost::posix_time::microseconds(3000)); Dann ergibt sich ein regelmäßiges Muster wie ich es gerne hätte (der Beweis dass es geht): http://nopaste.immersight.de/?95e44e07fbf177f3#BmXWN2Lj2QGzd1B9NeObSuUPIfUp4YRjUNiZMxT3AHQ= Ich frage mich warum der read-Aufruf nicht einfach wartet bis wieder 39 Byte vorhanden sind. Wie kann denn in 3 mal nacheinander in 0.05ms etwas ausgelesen werden? Vielen Dank schonmal im Voraus! :)
warum mit O_NONBLOCK? ich würde es blockierend in einem Thread mit read machen. Wo sieht man denn den code vom auslesen?
Durch O_NONBLOCK kehrt der read-Aufruf immer sofort zurück, unabhängig davon, ob was da ist und wieviel. Fabske Eksbaf schrieb: > int flags = fcntl(fd_seriell, F_GETFL); > flags = ( O_DIRECT | O_FSYNC | O_RSYNC | O_DSYNC); Es ist wenig sinnig, die Flags zu lesen und dann den gelesenen Wert zu verwerfen und komplett zu überschreiben. Da sollte ein |= verwendet werden, sonst werden einige der schon gesetzten Flags mit dieser Operation wieder gelöscht, unter anderem z.B. das oben gesetzte O_NONBLOCK. Und O_DIRECT ist generell eine etwas dubiose Option. Ich denke allerdings nicht, daß die bei Schnittstellen überhaupt eine Wirkung hat. Die ist eher dafür gedacht, beim Zugriff auf Dateien den Festplatten-Cache zu umgehen. Ähnliches gilt für diese *_SYNC-Flags.
Aha, jemand liest also meinen Quellcode! ;) Genau Rolf, weil wenn ich die flags einkommentiere liest er mir gar nix mehr aus :( nur noch -1 (Hab nun die Ausgabe um eine Angabe der gelesenen Byte erweitert): http://nopaste.immersight.de/?686db1250afb625e#6NWiaMZWAFtZIGjmx4e95II0POgXguego7ELLHNrB+A= Und das liegt am O_NDELAY und O_NONBLOCK. Hab das nun rausgeworfen. Ich hatte es nur alles reingemacht um damit zu experimentieren. Natürlich will ich eigentlich einen blockierenden Aufruf haben der 4 MilliSekunden blockiert (sollte) und mir dadurch einen super Takt liefert. (Diese Kode läuft in einem eigenen Thread!). Es ergibt sich nun das Bild vom Anfang, das Lesen dauert einfach immer unterschiedlich lange: http://nopaste.immersight.de/?5a40863665485dd0#1z84uxEzXxHnjDgX6ImBSpSaCAOLHF/BwCyH4vg5v5Q=
Tja wieder jemand der gemerkt hat das USB nicht wirklich echtzeitfähig ist. Echtzeitfähig bedeutet : die Zeit einer Bestimmten Operation ist deterministisch (Berechenbar bzw. Abschätzbar). Dies ist bei USB nicht der Fall. Da sind zuviele Puffer und FIFOs und Treiber, Caches, Betriebsystemeigenarten usw. dazwischen. Du kannst das Verhalten jedoch optimieren: 1. Stell im Gerätemanager unter Einstellungen unter Erweitert beim FTDI Device die Puffer auf 64 Bytes und die Wartezeit auf 1ms. 2. Spendier dem Ding einen eigenen USB Controller an dem kein anderes Gerät hängt also nicht nur einen anderen USB Port, Denn intern ist zumeist nur ein USB Controller da, der die 480MBit mit einem internen HUB auf die ganzen onboard Ports aufteilt (so kann es nicht zu kappeleien zwischen Devices kommen). 3. Versuch dem USB Service Prozess oder was auch immer mehr Priorität zu geben 4. Versuch das System sowenig wie möglich mit anderem Krempel zu belaßten. Ansonsten nimm nen Echtzeitbetreibstystem und eine echte RS232
Naja, da Windows an sich erst mal gar nicht echtzeitfähig ist, ist es in dem Fall auch egal, was USB macht. USB ist halt auch gar nicht dafür konzipiert. Umgekehrt hilft aber auch ein Echtzeit OS mit USB da wenig.
Christian R. schrieb: > Naja, da Windows an sich erst mal gar nicht echtzeitfähig ist, ist es in > dem Fall auch egal, was USB macht. Da es allerdings gar nicht um Windows geht, ist auch egal, ob dieses echtzeitfähig ist. > USB ist halt auch gar nicht dafür konzipiert. Das ist für sehr vieles nicht konzipiert, wofür es heute eingesetzt wird.
Rolf Magnus schrieb: > Da es allerdings gar nicht um Windows geht, ist auch egal, ob dieses > echtzeitfähig ist. Hach, Tatsache. Mea culpa. Naja, ändert aber nichts am Sachverhalt. Auch ein Standard-Linux ist nicht echtzeitfähig.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.