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
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.
Windows ist kein Echtzeitsystem. Die Daten solltest Du mittels TimeStamp anzeigen, weil es nix bringt die UI alle paar us upzudaten.
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>.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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
>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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.