Forum: PC-Programmierung SerialPort in .NET bei hohen Baudraten performant auslesen


von Traubensaft .. (increasingcurrant)


Lesenswert?

Hi,

ich bastele momentan an einem CAN -> PC Interface. Ich verwende dazu 
einen STM32 (CAN -> UART), einen FT232RL (UART -> USB @1.5MBaud) und die 
SerialPort-Klasse des .NET-Frameworks.

Mein Problem: der Flaschenhals des Systems scheint aktuell die 
SerialPort-Instanz bzw. irgendein Buffer zu sein. Wenn ich das Kabel vom 
CAN-Bus trenne liest mein Programm weiterhin Pakete über die serielle 
Schnittstelle ein, obwohl der Mikrocontroller nichts mehr zu senden hat.

Liegt das an einem Puffer des virtuellen COM-Ports? Liegt das an der 
.NET-Klasse? Einem Windows Treiber? Einem...?

Ich hoffe jemand von euch kennt das Problem und hat ein paar Tipps :)


vG
Traubensaft

von Jim M. (turboj)


Lesenswert?

Da sind überall Puffer (FIFO) mit drin. Selbst neuere FT232 Chips haben 
FIFOs im KByte Bereich IIRC.


Wir sehen hier z.B. nicht wie schnell Du vom SerialPort liesst.

von Dirk (Gast)


Lesenswert?

Windows ist kein Echtzeitsystem. Die Daten solltest Du mittels TimeStamp 
anzeigen, weil es nix bringt die UI alle paar us upzudaten.

von Traubensaft (Gast)


Lesenswert?

Ich lese immer im SerialPort.DataReceived-Event. Wie oft das geraist 
wird kann nicht beeinflussen, oder?

Der CAN Bus läuft mit 500 kBaud. Wenn alle Messages einen DLC von 0 
haben und die Buslast 100 % beträgt, kommen neue Messages mit ca. 8 kHz. 
Dass das für die UI nicht geht ist klar. Darum kommen empfangene 
Messages auf eine List<T>.

von Donni D. (Gast)


Lesenswert?

Wie sieht es denn hiermit aus? 
https://msdn.microsoft.com/de-de/library/system.io.ports.serialport.receivedbytesthreshold(v=vs.110).aspx

So kannst du ein Puffer vollschreiben lassen und dann einen großen Block 
aufeinmal lesen.

von Traubensaft .. (increasingcurrant)


Lesenswert?

Erhöht das die Performance weil der Event-Aufruf zu viel Zeit kostet? 
Ich dachte ja bislang ich hätte einen Buffer der zu langsam leer läuft.

von Pandur S. (jetztnicht)


Lesenswert?

Das GUI ist kein Mass wie schnell die Daten kommen. Denn das Gui 
verplempert sehr viel Zeit mit sich selbst. Mach mal einen Transfer von 
zB 100MByte zwischen zwei Arrays im RAM und miss die Zeit. Das waere 
dann die Transferzeit. Sobald Bestaetigungen versendet werden muessen, 
kommt die Antwortverzoegerung rein, und ist bei Windows konstant, um die 
vielleicht 10..50ms, und schlaegt bei kleinen Bloecken zu, dh macht 
alles langsam.

Nebenbei ist CAN eh nicht geeignet fuer grosse Transfers. CAN wurde 
designt fuer kleine Packete, ich glaub 8 bytes inkl. Adressing/Routing, 
und schneller Responsezeit. Die Responsezeit bringt dir nichts mit einem 
PC, weil der viel zu langsam ist. Wenn du Filetransfers machen willst, 
nimm zB einen RS232 fuer kleinere Baudraten, und RS422 fuer hohe 
Baudraten an einem FT232. Es gibt RS485/RS422 Treiber bis 25MBit. Der 
FT232 ist glaub bei 3Mbit am Ende. Wegen des USB-1 Interfaces. Aber 
vielleicht gibt es ja auch USB-2 taugliche USB-Serialport Controller

Falls es trotzdem CAN sein muss schalt einen Controller zwischen FT232 
und den CAN controller, der die Packete richtig schnell reinstopfen 
kann.

von Traubensaft .. (increasingcurrant)


Lesenswert?

Sabberalot W. schrieb:
> Mach mal einen Transfer von
> zB 100MByte zwischen zwei Arrays im RAM und miss die Zeit.

Und was weiß ich dann?

Sabberalot W. schrieb:
> Nebenbei ist CAN eh nicht geeignet fuer grosse Transfers.

Na dann mache ich eben keine. Warum willst du wie wild Arrays durch die 
Gegend kopieren?

Sabberalot W. schrieb:
> Wenn du Filetransfers machen willst,

Will ich doch gar nicht, verdammt!

Sabberalot W. schrieb:
> Falls es trotzdem CAN sein muss...

Muss es. Sonst gebe ich das Auto zurück und lasse alle Steuergeräte per 
USB verdrahten...

Sabberalot W. schrieb:
> schalt einen Controller zwischen FT232
> und den CAN controller

Gib es zu, du hast hier nicht einen Beitrag gelesen. Beiträge wie deiner 
zerstören den Lesefluss des Threads und senken für mich die Chance eine 
Lösung zu finden.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Lass den CAN-Bus mal testweise außen vor... Verbinde mal RX und TX vom 
FT232 direkt, sende kontinuierlich Daten vom .NET-Programm aus mit max. 
Datenrate und schau ob du die wieder rein bekommst. Wenn das schon nicht 
klappt musst du dich nicht auch noch mit dem CAN Bus zusätzlich 
rumplagen. i.A. hilft es bei I/O-Aufgaben immer so viele Daten wie 
möglich auf einmal zu übertragen, und nicht jedes Byte einzeln o.ä. CAN 
über Seriell-Port zu übertragen ist auch nicht so optimal, mit 
"richtigen" CAN<->USB Adaptern wie denen von Vector geht sowas besser.

von Pandur S. (jetztnicht)


Lesenswert?

aha. Jetzt hoeren wir, es kommt nicht zu grossen Bloecken, Wenn der PC 
aber etwas kann, dann sind es grosse Bloecke. Bei kleinen ist er nicht 
gut. Also mach einen Controller rein, der zwischen CAN und PC von 
kleinen auf grosse Bloecke aendert. Denn USB bedeutet Bestaetigung der 
Packete. Intern. Davon siehst du nichts. Entlaste den PC vom kleinen 
Zeug.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Sabberalot W. schrieb:
> Bei kleinen ist er nicht
> gut
CAN ist aber so langsam, dass man das locker schaffen kann bei 
geeigneter Programmierung.

Sabberalot W. schrieb:
> Denn USB bedeutet Bestaetigung der
> Packete. Intern. Davon siehst du nichts.
Selbst bei FullSpeed-USB hat man die 24-fache Roh-Datenrate. Bei 
High-Speed die 960-fache. Mit Pufferung und geschickter Programmierung 
ist es absolut kein Problem, CAN über USB zu übertragen, wie man bei 
diversen kommerziellen Adaptern sieht, welche sogar mehrere CAN-Busse 
bei 100% Buslast live zum PC übertragen können.
Außerdem hat er garantiert schon einen Controller dazwischen, welcher 
CAN<->Seriell wandelt. Der FT232RL wird die Seriell-Daten schon so 
paketieren dass keine Verluste auftreten; es tritt höchstens eine Latenz 
bedingt durch Pufferung auf.

von Arc N. (arc)


Lesenswert?

Traubensaft .. schrieb:
> Hi,
>
> ich bastele momentan an einem CAN -> PC Interface. Ich verwende dazu
> einen STM32 (CAN -> UART), einen FT232RL (UART -> USB @1.5MBaud) und die
> SerialPort-Klasse des .NET-Frameworks.
>
> Mein Problem: der Flaschenhals des Systems scheint aktuell die
> SerialPort-Instanz bzw. irgendein Buffer zu sein. Wenn ich das Kabel vom
> CAN-Bus trenne liest mein Programm weiterhin Pakete über die serielle
> Schnittstelle ein, obwohl der Mikrocontroller nichts mehr zu senden hat.

USB wird gepollt und der FTDI schickt nicht kontinuierlich Daten raus...
Dazu gibt's Einstellungen im FTDI-Treiber/DLL:
http://www.ftdichip.com/Support/Documents/AppNotes/AN232B-04_DataLatencyFlow.pdf
http://www.ftdichip.com/Support/Knowledgebase/index.html?settingacustomdefaultlaten.htm
und dann kommt noch, wie schon angemerkt wurde, der Treiber von Windows 
hinzu bzw. .NET (ReceivedBytesThreshold), wo dann nochmal 
zwischenspeichert/verzögert wird.

von c-hater (Gast)


Lesenswert?

Traubensaft schrieb:

> Ich lese immer im SerialPort.DataReceived-Event. Wie oft das geraist
> wird kann nicht beeinflussen, oder?

Direkt nicht, indirekt aber schon. Im Prinzip hängt die "raise rate" von 
folgenden drei Größen ab:

1) die Rate, mit der die Daten eingehen
2) die Größe des Lesepuffers
3) die Lese-Timeouts der Schnittstelle

Dass es so kompliziert ist, hängt damit zusammen, dass COM-Ports zu sehr 
verschiedenen Zwecken verwendet werden können. Eine "LiveChat"-Anwendung 
stellt völlig andere Anforderungen als Datentransfer am Durchsatzlimit 
der Schnittstelle.

Die Standardeinstellungen von SerialPort sind eher ausgerichtet auf 
Anwendungen vom Typ "LiveChat". Also optimiert auf kurze Reaktionszeiten 
bei geringem Datendurchsatz.

Um hohe Durchsätze zu erreichen, muß man den Lesepuffer und die 
Lese-Timeouts vergrößern. Der Erfolg ist eine (relativ zum Durchsatz) 
geringere "raise rate" des Events, wobei dann aber bei jedem Event sehr 
viel mehr Daten bereitgestellt werden.

In einem Echtzeitsystem könnte man das komplett ausoptimieren, nur ist 
leider Windows kein Echtzeitsystem und das .Net-Framework macht die 
Sache natürlich auch nicht besser...

Trotzdem sind auf einem halbwegs modernen PC-System (2+ Kerne) 
problemlos Raten im Bereich >>1Mit/s stabil erreichbar. Wenn die 
Peripherie mitspielt und nicht schon dort drin irgendwelche Puffer 
überlaufen. Deswegen ist eine PCI(e) COM-Schnittstellenkarte immer die 
bessere Lösung gegenüber USB-Hardware.

von Chris R. (hownottobeseen)


Lesenswert?

Hi,

die Implementierung des SerialPort in .net ist grausig und hat mir schon 
einiges an Kopfzerbrechen bereitet.

Mir hat folgende Implementierung geholfen:

https://www.sparxeng.com/blog/software/must-use-net-system-io-ports-serialport

Ansonsten scheint wohl auch ein Backgroundworker der ständig liest zu 
helfen:

https://stackoverflow.com/questions/35605763/c-sharp-serial-datareceived-very-slow?rq=1

HTH

: Bearbeitet durch User
von Dirk (Gast)


Lesenswert?

>die Implementierung des SerialPort in .net ist grausig und hat mir schon
>einiges an Kopfzerbrechen bereitet.

Stimme ich zu. Hier etwas fertiges:

https://github.com/jcurl/SerialPortStream

Eventuell hätte ich mir noch den FT232RL gespart und ein STM32 mit USB 
genommen.

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.