Forum: PC Hard- und Software RTS Timing bei USB zu TTL Adaptern


von Georg P. (perthil)


Lesenswert?

Ich benötige einen zusätzlichen Ausgang der vor dem Senden gesetzt wird, 
und wollte dazu den RTS Pin benutzen, den ja die meisten USB zu TTL 
Adapter haben. Jetzt habe ich festgestellt, dass das RTS Signal immer 
mindestens 1ms auf dem selben Pegel bleibt. Ich kann also maximal 500Hz 
erzeugen.

Das habe ich mit einem CH340 Klon und einem FTDI FT232BL probiert, und 
beide machen diese 1ms.

Deshalb ist meine Vermutung, dass das irgendwo im Treiber eingestellt 
ist. Ich benutzte Ubuntu 22.04.2 LTS. Das Programm, das ich zum testen 
verwende, ist in Python (3.10.6) geschrieben und benutzt pyserial in der 
Version 3.5:
1
import serial
2
3
port = serial.Serial("/dev/ttyUSB1", 40000, stopbits=serial.STOPBITS_ONE, timeout=0)
4
5
print(serial.VERSION)
6
7
while True:
8
    port.rts = True
9
    port.rts = False

Kann man dieses Timing irgendwo einstellen?

Dass Python so langsam ist, glaube ich nicht, das Programm läuft auf 
einem Ryzen 5 5625U mit bis zu 4.3GHz.

Vielleicht kann mir hier ja jemand weiterhelfen.

von Irgend W. (Firma: egal) (irgendwer)


Lesenswert?

Linux und erst recht USB sind von Hause aus nicht echtzeitfähig.
Du hast da einfach gewisse Latenzen, bevor so ein einzelnes USB-Paket 
überhaupt abgesendet wird. 1ms ist schon eher bestcase und du musst 
damit rechnen das da auch mal sporadisch bis zu 100ms Pause oder so drin 
sind. Für irgendwas mit einem definierten Timing ist USB einfach nicht 
vorgesehen und daher ungeeignet.

- Beitrag "USB Latenz im Millisekundenbereich?"
- https://wiki.archlinux.org/title/mouse_polling_rate
(mouse/hid ist zwar andere Richtung, dass grundlegende Verhalten ist 
aber ähnlich)

Wenn du was genaues brauchst, nehme einen µC und verwenden den in dem du 
dann z.B. per USB sagst "mach 100 Impulse von 0,5ms im Abstand von 1 
ms". Dann kannst du dich da auch drauf verlassen (aber nicht darauf wann 
die 100 Impulse wirklich anfangen).

von C-hater (c-hater)


Lesenswert?

Georg P. schrieb:

> Jetzt habe ich festgestellt, dass das RTS Signal immer
> mindestens 1ms auf dem selben Pegel bleibt.
[...]
> Kann man dieses Timing irgendwo einstellen?

Einstellen kannst du das garnicht. Du könntest höchstens einen anderen 
USB-Serial-Adapter verwenden, nämlich einen, der mittels HighSpeed 
kommunizieren kann (selten und teuer). Damit hast du dann eine Latenz 
von 250µs, also ein Viertel von dem der üblichen FullSpeed-Adapter.

So weit die Theorie. In der Praxis ist es aber oft so, dass 
minderweitertige Treiber, Firmwares und teildefekte oder ungeeignete 
Hardware dafür sorgen, dass sich so ein Buszyklus (der eigentlich dafür 
da ist, zumindest die genannten Latenzen zu garantieren) auch mal 
verschluckt. Am wahrscheinlichsten bei der Anmeldung neuer Geräte am 
Bus.

Das sollte zwar nicht so sein, passiert aber in der Praxis doch recht 
häufig. Man ist also gut beraten, nicht darauf zu setzen, dass die 
Zykluszeit (und damit die Latenzen) wirklich konstant und 
unerschütterlich stabil ist.

Zusammenfassend: dein Ansatz ist eine ganz schlechte Idee. Dafür ist USB 
schlicht nicht gedacht. Das ist auf hohen Durchsatz optimiert, nicht auf 
geringe Latenzen.

von Georg P. (perthil)


Lesenswert?

Danke, ich dachte mir schon, dass es am USB liegt.

Eigentlich wollte ich ja einen Break senden, aber das dauert ja noch 
länger. Unter Linux wohl mindestens 0,25s. Das Protokoll das ich habe 
startet immer mit einem Break und hat 8N1. Die Pakete sind meist nur 4 
Bytes lang. Das sind dann gerade Mal 4 Pakete pro Sekunde.

Ich habe auch schon probiert die Baudrate zu ändern, aber das ist auch 
sehr langsam.

Ein Portpin war noch frei, also dachte ich, vielleicht ist es damit 
besser. Ist es auch, aber ich dachte es wäre noch schneller.

Ich dachte auch daran ein Paritybit für den Break anzuhängen, aber da 
dazu auch die Konfiguration der Schnittstelle geändert werden muss, ist 
es wohl dasselbe wie beim Ändern der Baudrate.

Eine Möglichkeit wäre jetzt noch den Break in einem zusätzlichen 
Datenbit zu senden, also 9N1 statt 8N1. Gibt es USB-Adapter die so etwas 
können? Bis jetzt habe ich nichts gefunden.

Vermutlich bleibe ich dann bei der Lösung mit dem RTS. Ist bis jetzt das 
schnellste und benötigt keine Sonderlösung.

VG

von C-hater (c-hater)


Lesenswert?

Georg P. schrieb:

> Eigentlich wollte ich ja einen Break senden, aber das dauert ja noch
> länger. Unter Linux wohl mindestens 0,25s. Das Protokoll das ich habe
> startet immer mit einem Break und hat 8N1.

Hört sich irgendwie stark nach DMX an...

Und natürlich ist ein Break nicht zwingend mindestens 250ms lang. Wie 
lang der ist, hängt von der Baudrate ab, auf die die Schnittstelle 
konfiguriert ist.

von Thomas Z. (usbman)


Lesenswert?

Baudrate und Status Leitungen werden über USB via Control Requests 
eingestellt, das wird bei Fullspeed nicht wesentlich schneller, da für 
Controll Requests nur 10% der gesammten Bandbreite vorgesehen ist. Das 
passt schon ganz gut zu 1 Request pro ms.

von Georg P. (perthil)


Lesenswert?

C-hater schrieb:
> Und natürlich ist ein Break nicht zwingend mindestens 250ms lang. Wie
> lang der ist, hängt von der Baudrate ab, auf die die Schnittstelle
> konfiguriert ist.

Ich weiß manche Controller machen einfach ein paar Bits länger.

Aber in meinem Fall macht pyserial das so. Hängt wohl mit termios
zusammen. Soweit ich gelesen habe ruft pyserial tcsendbreak() aus 
termios auf. Und das macht irgendwas zwischen 0.25 und 0.5s. Wenn man 
eine Zeit übergibt, dann steht in der Beschreibung: If duration is not 
zero, it sends zero-valued bits for some implementation-defined length 
of time.

Also nichts genaues weiß man nicht.

Leider bezieht sich alles was ich im Netz gefunden habe auf 
tcsendbreak().
Und ich möchte dafür auch nicht selbst irgendwas machen, es sollte schon 
mit Standardhardware funktionieren.

Bei mir war der Break jedenfalls immer ziemlich lang. Aber auch das muss 
ja über USB und wird dann wohl nicht schneller sein als der RTS.

P.S. Ist kein DMX, ist was in Anlehnung an LIN selbst gemachtes.
Da kann man noch was anpassen. Ich hatte auch Mal die Idee ein Byte auf
zwei 6Bit Werte aufzuteilen, dann muss aber die Baudrate hoch und mehr 
als die eingestellten 40kBaud sollen es nicht werden, sonst wird wohl 
der Empfänger (AVR) überlastet.

Danke nochmals,

VG

von Harald K. (kirnbichler)


Lesenswert?

Georg P. schrieb:
> Ich benötige einen zusätzlichen Ausgang der vor dem Senden gesetzt wird,
> und wollte dazu den RTS Pin benutzen, den ja die meisten USB zu TTL
> Adapter haben.

Und was genau soll dieser Ausgang machen? Etwa einen RS485-Treiber 
ansteuern? Dafür haben die meisten USB-Seriell-Bridges dedizierte 
Steuerausgänge, die sie vollautomatisch in Hardware ansteuern, sobald 
sie senden. Per Software an irgendwelchen Leitungen rumwackeln muss man 
da gar nicht.

Und wenn Du einen längeren Impuls brauchst, häng' da halt ein Monoflop 
dran.

von Georg P. (perthil)


Angehängte Dateien:

Lesenswert?

Der Impuls soll den Anfang eines Datenpakets markieren.
Das mache ich normalerweise mit einem Break-Signal.

Ich habe einen Bus, wo das so passiert, und diesen will ich jetzt
mit dem PC verbinden. Dazu würde ich gerne dasselbe Protokoll benutzen, 
und nicht wieder irgendwas neues machen. Da das mit dem Break vom PC aus 
noch viiieeel langsamer ist, suche ich nach einer anderen Möglichkeit 
dafür.

Die Ziele sind, dass es mit Standard USB-UART-Wandlern funktioniert, 
dass es hinreichend schnell ist (also die 40kBaud gut ausnutzt), und 
dass die Änderungen am Protokoll möglichst klein sind.

Da noch ein Portpin frei ist, schien mir das mit dem RTS-Ausgang eine 
gute Lösung zu sein. Den haben die meisten Adapter.

Da, wie man auf dem angehängten Screenshot sieht, die Daten schon kurz 
nach dem Setzen des RTS gesendet werden, sich Daten und Steuersignale 
wohl überlappen, kann man damit immerhin 500 Datenpakete pro Sekunde 
schicken.
Das ist schon Mal deutlich mehr als bei Benutzung des Breaks.

Die eigentliche Frage war jetzt, ob man das noch ein bisschen 
beschleunigen kann. Sieht aber wohl nicht so aus.

VG

von Harald K. (kirnbichler)


Lesenswert?

Georg P. schrieb:
> Der Impuls soll den Anfang eines Datenpakets markieren.

Und der "Impuls" soll während des Datenpaketes dann irgendwann aufhören?

Wie lange vor dem Beginn des Datenpaketes soll denn Dein "Impuls" 
beginnen?


Mit der von mir vorgeschlagenen Kombination aus der 
RS485-Treibersteuerung und gegebenenfalls einem Monoflop (retriggerbar) 
bekommst Du ein Signal, das während des gesamten Datenpakets aktiv ist, 
und das sehr knapp vor dem Beginn des Datenpakets aktiv wird.

Das Monoflop ist nur dazu da, um etwaige kurze Pausen zwischen den 
einzelnen gesendeten Bytes zu überbrücken.

Du kannst ja, falls das Oszillogramm da oben mit einem FT232 o.ä. 
erstellt wurde, zusätzlich noch das Signal TXDEN einblenden. Das ist 
beim FT232RL üblicherweise auf CBUS2.

Andere USB-UARTs haben auch derartige Signale.


Was ist das für ein Protokoll? 40 kBaud ist eine sehr ungewöhnliche 
Baudrate; ist das was selbstgebratenes?

von Georg P. (perthil)


Lesenswert?

Harald K. schrieb:
> Und der "Impuls" soll während des Datenpaketes dann irgendwann aufhören?
>
> Wie lange vor dem Beginn des Datenpaketes soll denn Dein "Impuls"
> beginnen?
>
Es reicht eine Flanke um zu erkennen, dass jetzt ein neues Datenpaket 
kommt. Die soll natürlich möglichst lang genug vor den Daten kommen, 
damit der Portinterrupt immer vor dem seriellen Receiverinterrupt kommt. 
Zurückgesetzt kann er dann irgendwann werden. Laut Messung scheint das 
zu passen, ich habe es aber noch nicht probiert.

> Mit der von mir vorgeschlagenen Kombination aus der
> RS485-Treibersteuerung und gegebenenfalls einem Monoflop (retriggerbar)
> bekommst Du ein Signal, das während des gesamten Datenpakets aktiv ist,
> und das sehr knapp vor dem Beginn des Datenpakets aktiv wird.
>
> Das Monoflop ist nur dazu da, um etwaige kurze Pausen zwischen den
> einzelnen gesendeten Bytes zu überbrücken.
>
> Du kannst ja, falls das Oszillogramm da oben mit einem FT232 o.ä.
> erstellt wurde, zusätzlich noch das Signal TXDEN einblenden. Das ist
> beim FT232RL üblicherweise auf CBUS2.
>
> Andere USB-UARTs haben auch derartige Signale.
>
Ja, das wäre auch eine Lösung, nur von den beiden Adaptern die ich hier 
habe hat keiner dieses Signal herausgeführt, RTS aber schon. Falls ich 
einen eigenen USB-Seriell-Wandler machen muss, wäre das wohl die beste 
Lösung (wenn es nicht zu knapp vor den Daten kommt, siehe oben). Aber 
wie gesagt, ich wollte was von der Stange nehmen.

> Was ist das für ein Protokoll? 40 kBaud ist eine sehr ungewöhnliche
> Baudrate; ist das was selbstgebratenes?
>
Ja, es ist was selbstgebratenes.

von Harald K. (kirnbichler)


Lesenswert?

Georg P. schrieb:
> Es reicht eine Flanke um zu erkennen, dass jetzt ein neues Datenpaket
> kommt. Die soll natürlich möglichst lang genug vor den Daten kommen,
> damit der Portinterrupt immer vor dem seriellen Receiverinterrupt kommt.

Wenn Du das von mir vorgeschlagene Steuersignal verwendest, hast Du bei 
Deinen 40 kBaud etwa 250 µsec Zeit, nämlich die Dauer für das Senden 
eines Bytes. Das belegt auf der Leitung zehn Bitzeiten (bei 8n1, nämlich 
ein Start-, ein Stop- und acht Datenbits).

Deine empfangende UART löst ihren Rx-Interrupt natürlich erst dann aus, 
wenn sie das Zeichen auch empfangen hat. Das Steuersignal aber wird vor 
dem Beginn der Übertragung des Startbits gesetzt.


Warum muss ein Datenpaket bei Deinem Protokoll angekündigt werden? Was 
ist der tiefere Sinn davon?

von Purzel H. (hacky)


Lesenswert?

Wenn ich ein spezielles Timing, zB fuer kurze Reaktionszeit bei hohem 
Durchsatz will, lagere ich diese Funktionalitaet auf einen AVR aus, 
welcher dann per USB am PC angeschlossen ist. Der USB bringt die hohen 
Blocklaengen bei hoher Geschwindigkeit, der AVR macht das Timing. Muss 
halt etwas buffern.
zB einen schnellen ADC an einem schnellen Bus per kurzen Packeten 
angeschlossen, auf einen PC bringen. Die kurzen Packete werden einzeln 
quitiert.

von Georg P. (perthil)


Lesenswert?

Harald K. schrieb:
> Warum muss ein Datenpaket bei Deinem Protokoll angekündigt werden? Was
> ist der tiefere Sinn davon?

Zum synchronisieren, z.B. wenn der Empfänger abgeschaltet war.

Der Busmaster fragt zyklisch Adressen ab, aber nicht alle Empfänger
sind aktiv, sie können zwischendurch schlafen gehen, wenn nichts zu tun 
ist. Nach dem Aufwachen müssen sie erkennen können, wann ein Telegramm 
beginnt. Für den Anschluss zum PC soll dasselbe Protokoll verwendet 
werden (evtl. mit kleinen Änderungen). In diesem Fall ist der PC der 
Busmaster und der Empfänger hat eine vom PC unabhängige Versorgung, so 
dass auch hier eine Synchronisation notwendig sein kann.

VG

von Georg P. (perthil)


Lesenswert?

Purzel H. schrieb:
> Wenn ich ein spezielles Timing, zB fuer kurze Reaktionszeit bei hohem
> Durchsatz will, lagere ich diese Funktionalitaet auf einen AVR aus,

Wie ich schon geschrieben habe würde ich gerne "normale" USB zu UART ICs 
verwenden und mir nicht noch eine Baustelle aufmachen. Sollte es gar 
nicht funktionieren kann ich das ja immer noch.

VG

von Harald K. (kirnbichler)


Lesenswert?

Georg P. schrieb:
> Zum synchronisieren, z.B. wenn der Empfänger abgeschaltet war.

Das macht man üblicherweise mit einem sinnvoll aufgebauten Protokoll - 
erst wenn ein Paket mit funktionierender Prüfsumme empfangen wird, wird 
es akzeptiert. Pakete werden durch Pausen separiert.

Sieh Dir Modbus/RTU an, da wird so ein Verfahren verwendet.

Was passiert bei Deinem "Protokoll", wenn ein Empfänger während des 
Sendend eingeschaltet wird? Er erkennt (fälschlich) das 
Paketbeginnsignal und decodiert falsche Daten.

Wie auch immer:

Das Steuersignal der USB-Seriell-Bridge ist für Deinen Zweck ausreichend 
lange vor Beginn des Pakets aktiv, allerdings wird es erst nach 
vollständigem Senden des Paketes wieder inaktiv. Wenn Deine Empfänger 
nur auf eine Flanke des Signales reagieren, ist das aber kein Problem.

von Michael X. (Firma: vyuxc) (der-michl)


Lesenswert?

Schau dir den FT232R genauer an, insbesondere den Pin CBUS2. Eventuell 
tut es die Hardware von selber was du brauchst.

von Harald K. (kirnbichler)


Lesenswert?

Michael X. schrieb:
> Schau dir den FT232R genauer an, insbesondere den Pin CBUS2.

Davon rede ich hier die ganze Zeit.

von Georg P. (perthil)


Lesenswert?

Harald K. schrieb:
> Das macht man üblicherweise mit einem sinnvoll aufgebauten Protokoll -
> erst wenn ein Paket mit funktionierender Prüfsumme empfangen wird, wird
> es akzeptiert. Pakete werden durch Pausen separiert.
>
Bei dem Protokoll das ich habe wird der Paketanfang durch einen Break
signalisiert. Da ich das Protokoll auch für den PC-Anschluss verwenden 
will muss ich das also irgendwie anders kenntlich machen. Zusätzliche 
Pausen möchte ich eigentlich aus Durchsatzgründen nicht haben.

> Was passiert bei Deinem "Protokoll", wenn ein Empfänger während des
> Sendend eingeschaltet wird? Er erkennt (fälschlich) das
> Paketbeginnsignal und decodiert falsche Daten.
Dann wartet der Empfänger bis er einen Break erkennt. Erst danach werden 
Daten akzepiert. Prüfsumme gibt es natürlich zuätzlich.

Wie ich schon Mal geschrieben habe, ist das Protokoll an das 
LIN-Bus-Protokoll angelehnt. Da wird es so gemacht. Da das im Fahrzeug 
schon lange verwendet wird, sollte es wohl funktionieren. Die 
Spezifikation dafür kann man sich bei https://www.lin-cia.org/standards/ 
runterladen.

von Georg P. (perthil)


Lesenswert?

Wie ich schon geschrieben habe, haben die Adapter die ich hier habe das 
RS485 Signal (TXDEN) nicht.
Ich habe einen mit dem FT232BL, der Chip hat das Signal, aber es ist 
nicht herausgeführt.
Die anderen sind irgendwelche CH340 Kopien, da habe ich kein Datenblatt 
davon, sie sind zwar im selben Gehäuse wie der CH340, haben aber eine 
komplett andere Pinbelegung.

Außerdem habe ich schon genug Baustellen, da muss ich nicht noch einen 
USB zu seriell Adapter selber machen. Nur wenn es gar nicht anders geht. 
Aber das mit dem RTS sieht ja ganz gut aus. Ich bin gerade am Testen.

Danke für die vielen Vorschläge.

VG

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.