Zum Inhalt springen

Serialle Port in Echtzeit auslesen


kathi008

Empfohlene Beiträge

Hallo Zusammen!

Gleich zu meinem Problem:

Mein Programm hängt an einem virtuellen COM Port(USB) als Slave und horcht den Bus ab. In regelmässigen Abständen kommt eine Anfrage vom Mastergerät an die Software. Wenn nötig antwortet die Software dem Mastergerät.

Funktioniert soweit auch gut.

Das blöde ist, die Daten kommen bei der Software ungefähr mit 1 Sekunde verspätung, was bei 19200 Baud zimlich viel ist. Wenn die Software dann Antwortet, kommt es öfters zu Kolisionen am Bus, da Mastergerät schon andere Slaves anfragt.

Hat jemand ein Rat wie ich das ganze in Echtzeit gestalten kann?

Ich nutze c# .NET2005

die Software hat auch mehrere Fenster, in welchen die Daten dargestellt werden.

Die Kommunikation ist mit SerialPort Klasse realisiert und ist Interrupt gesteuert.

Link zu diesem Kommentar
Auf anderen Seiten teilen

  • 2 Wochen später...

Hallo!

hab eine Lösung gefunden.:bimei

Ich erstelle einfach eine zusätzliche Anwendung, welche nur das Senden und Empfangen am Seriellen Port übernimmt.

Die Hauptanwendung und die Hintergrundanwendung lasse ich mittels IPC-Kanal miteinander kommunizieren.

Wer aber eine elegantere Lösung parat hat nur her damit!:D

Das Thema kann dann geschlossen werden.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Klar war die Kommunikation in einem Backgroundworker ausgelagert.

Das Problem ist: Der Windows reserviert für die gesamte Anwendung bestimmten Speicherbereich und händelt ja die Threads intern nacheinander, abhängig von der Priorität der Threads, ab. Wenn der User ein Mausklick auf eine Form macht, bekommt Diese ganz kurz die höchste Priorität, so dass das Programm sich nicht aufhängt. Dadurch werden alle anderen Thread kurz abgebremst. So habe ich das zumindest verstanden.

Wenn ich nun das in eine extra Anwendung auslagere ohne Forms und Grafik, so arbeiten die zwei Anwendungen unabhängig von einander und die Hintergrundanwendung wird durch den User nicht gestört.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Na, klar war das nicht. Hast es ja auch bisher nirgendwo erwaehnt.

Ich wuesste jetzt auch nicht, warum ein getrenntes Programm Vorteile gegenueber dem Backgroundworker bringen sollte.

Kannst Du vielleicht das Problem noch einmal ausfuehrlich beschreiben. Dass die Probleme durch UI-Interaktionen entstehen hast Du auch erst im letzten Post geschrieben.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Wenn ich nun das in eine extra Anwendung auslagere ohne Forms und Grafik, so arbeiten die zwei Anwendungen unabhängig von einander und die Hintergrundanwendung wird durch den User nicht gestört.

Naja nicht unbedingt. Wenn die beiden Prozesse nicht gerade auf unterschiedlichen CPUs bzw. Kernen abgearbeitet werden hast du ja das selbe Problem.

Du könntestr deinen Prozess zwar als Prirität Echtzeit geben aber wie sich das genau auswirkt kann ich nicht sagen...

Link zu diesem Kommentar
Auf anderen Seiten teilen

Das blöde ist, die Daten kommen bei der Software ungefähr mit 1 Sekunde verspätung,

Hat jemand ein Rat wie ich das ganze in Echtzeit gestalten kann?

Zuerst musst Du festlegen, was "Echtzeit" für Dich in diesem Fall konkret bedeuten soll. Sprich, welche Verzögerung im Durchschnitt akzeptabel ist und ob Du akzeptieren kannst, wenn es auch (gelegentlich) viel länger dauern könnte, auch wenn dies in der Praxis nicht unbedingt oder nur selten auftritt, oder ob festgelegte Reaktionszeiten zugesichert werden müssen.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hallo!

Meine Anwendung dient zur Parametrierung eines Gerätes, welches als Master am Seriellen Bus angeschlossen ist. Das heißt: dieses Gerät schickt regelmäßig eine Anfrage an alle angeschlossenen Geräte, auch an den PC. Die Reaktionszeit auf die Anfrage beträgt 20 -60 ms. Schafft der PC in dieser Zeit nicht zu antworten, soll er auf die nächste Anfrage warten und dann die Anwort wegschicken.

Die Daten werden per SeriellPort- Klasse eingelesen. Die Klasse puffert die Daten, sodass, wenn der PC die Anfrage abholt, eigentlich schon andere Geräte angefragt werden. Wenn nun der PC antwortet, kommt es zur Kollision.

Die Kommunikation lief anfangs in einem Backgroundworker, bei dem ich auch die Priorität 'Echtzeit' eingestellt habe. Leider brachte es keine Verbesserungen.

Erst als ich extra eine Anwendung dafür erstellt habe, ging es.

Wenn die beiden Prozesse nicht gerade auf unterschiedlichen CPUs bzw. Kernen abgearbeitet werden hast du ja das selbe Problem.

Guybrush Threepwood

Du hast natürlich Recht, das muss ich noch ausprobieren. Aber hier hat der Windows die Chance die verschiedenen Prozesse auf verschiedene Kernel zu verteilen, was bei einer einzigen Anwendung schwierig wäre.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Du hast natürlich Recht, das muss ich noch ausprobieren. Aber hier hat der Windows die Chance die verschiedenen Prozesse auf verschiedene Kernel zu verteilen, was bei einer einzigen Anwendung schwierig wäre.

Nein, dashat nichts damit zu tun, ob es eine Anwendung ist, oder nicht. Sobald Du Threads verwendest, sollten diese auch parallel verarbeitet werden können.

Hast Du vielleicht eine Synchronisierung verwendet, die zu Verklemmungen führt und Du diese einfach durch das Auslagern in eine andere Anwendung umgangen hast?

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hallo zusammen!

Ich habe nun meine Anwendung noch mal gründlich durchgesehen und neu aufgebaut.

Das Auslagern der Kommunikation in eine extra Anwendung hat mir geholfen diese von dem Hauptprgramm richtig zu trennen.

Ich habe nun die Kommunikation in einen Backgroundworker(BGW1) verpackt, welcher wiederrum aus einem anderen Backgroundworker(BGW2) aufgerufen wird.

BGW1 erledigt reine Kommunikation.

BGW2 entscheidet, wie mit den Daten weiterverfahren wird und löst ein paar Events aus, auf die im Hauptfenster reagiert wird.

Soweit so gut. Es funktioniert nun auch in Echtzeit.

Danke für die Infos.

Ein neues Problem:

BGW1 wird durch Usereingaben gestartet.

Innerhalb der Do_Work() läuft eine 'endlose' while- Schleife, die auch nur durch Usereingaben abgebrochen wird. In der while- Schleife steht kein Code, weil die Kommunikation über SeriellPort- Klasse und deren Events läuft. Ich muss halt den BGW1 irgendwie blockieren, damit er weiterläuft.

Das eigentliche Problem:

die while- Schleife nimmt bei meinem DualCore Processor 50% von den CPU- Ressourcen.

Die Anwendung sollte aber mehrmals auf einem Rechner gestartet werden können. Damit wird aber der PC lamgelegt!

Gibt es ein Ersatz für die While - Schleife?

Hab in MSDN AutoResetEvent gefunden...

Kann man mit Hilfe von AutoResetEvent den Thread solange blockieren, bis der User den Befehl zum Schließen gibt? Wird dabei die SeriellPort Klasse mit deren Events auch blockiert?

Link zu diesem Kommentar
Auf anderen Seiten teilen

An deiner Stelle würd ich die Backroundworker einstampfen und direkt mit der Threak Klasse Arbeiten.

Da machste statt 2 Backroundworker 2 Threads.

Vorteil:

-Du kannst prioritäten der einzelnen Thread festlegen.

-Du kannst jeden Thread nach belieben Pausieren (Suspend nennt sich die Funktion).

Lg

Gateway

Link zu diesem Kommentar
Auf anderen Seiten teilen

Suspend nennt sich die Funktion
Und man sollte sie nur benutzen, wenn man ganz genau weiß, was man tut. Diese Funktion ist nicht zur Synchronisierung geeignet, oder dazu, einen Thread zu "parken". Man kann damit sehr leicht das ganze Programm zum Hängen bringen.

Sie Remarks-Abschnitt in der MSDN-Library-Seite von Thread.Suspend.

Ganz grob gesagt, sollte man von Thread.Suspend die Finger lassen, wenn man nicht gerade einen Debugger schreibt.

Link zu diesem Kommentar
Auf anderen Seiten teilen

  • 2 Wochen später...

Hallo Zusammen!

Hab mit dem AutoResetEvent gelöst. Funktioniert soweit.

Wirklich in Echtzeit die Daten einzulesen habe ich dann doch nicht geschaft, fehlen nur ein paar Millisekunden. Dadurch wächst der Berg an Daten im Empfangspuffer der SerialPort Klassen. Hab mit dem DiscardInPuffer gelöst. Dadurch geht zwar einiges verloren, aber bei der Funktion ist es nicht schlimm.

Ein anderes Problem:

Meine Anwendung beinhalt eine DataLogger Funktion. Hier werden die Daten in einem RichTextBox dargestellt, welcher nach bestimmter zeit geleert wird und die Daten in einer Datei gespeichert werden.

Das Problem: Es wird nur die Anzeige von dem RichTextBox geleert, der allocierter Speicher bleibt aber beibehalten und wird erst mit Beender der Anwendung freigegeben. Wenn die Anwendung Tage läuft, reicht irgendwann der Speicher nicht mehr aus.

Das zerstören des Steuerelemets hat nix gebracht, da der Speicher anscheinend der gesamten Anwendung zugesichert wird.

Hab mit dem Memory Profiler beobachtet: Solange der Text dem RichTextBox hinzugefügt wird, steigen Gen0 - Gen3 permanent. Schließe ich die Form mit dem RichTextBox, bleibt es auf der letzten Höhe und fällt nicht zurück. Beim erneuten Starten steigt das Ganze ab dem letzten Punkt weiter!

Wie kann ich zusammen mit dem leeren (evtl. Zerstören) des RichTextBoxes auch den Speicher freigeben?

Danke im Voraus.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Dein Kommentar

Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...