mikrocontroller.net

Forum: PC-Programmierung C# SerialPort read timeout


Autor: David1 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Leute,

Ziel: Ich möchte Daten von einem Mikrocontroller zu meiner Software in 
C# geschrieben übertragen.

Problem:
Ich kann eine unterschiedlich lange Anzahl an Zeilen einlesen, aber dann 
ab >200(Variiert manchmal auch erst bei 800) werden keine Daten mehr 
eingelesen, obwohl noch welche gesendet werden. Kürzere Abschnitte (<150 
Zeilen) werden jedoch vollständig empfangen.

Wenn ich per HyperTerminal zugreife habe ich keine Probleme die Daten zu 
empfangen, egal mit welcher Länge.

Hintergrund
Code:
void OnDataReceived(object sender, SerialDataReceivedEventArgs args)
{
    if (this.IsOpen)
    {
        try
        {
            string data = this.realPort.ReadLine(); 
            if (this.DataReceived != null)
            {
                this.DataReceived(data);
            }
        }
        catch (Exception e)
        {}
    }

Hier ist die Funktion die ausgelöst wird:
  // Wird ausgelöst wenn Daten über den Com-Port empfangen werden
private void OnDataReceived(string data)
{
     queueDatensaetze.Enqueue(data);
}

Ich vermute dass der Fehler entweder an den Einstellung oder an dem 
Event-Konzept liegt.

Einstellungen:
            realPort.Parity = Parity.None;
            realPort.StopBits = StopBits.One;
            realPort.DataBits = 8;
            realPort.Handshake = Handshake.RequestToSend;
            realPort.NewLine = "\r";
            realPort.Encoding = Encoding.GetEncoding(28591);
            realPort.ReadBufferSize = 16536;
            realPort.WriteBufferSize = 4096;
            realPort.DataReceived += OnDataReceived;
            realPort.ReadTimeout = 6000;
            this.occuredTimeouts = 0;
Ich habe das ganze mit einem SerialPort Monitor beobachtet dort werden 
die Daten empfangen, OnDataReceived wird zwar aufgerufen jedoch keine 
Daten gelesen was zu einer Timeout Exception führt.

Kann jemand eine Fehlerquelle ausmachen oder hat eine vernünftige 
Quelle/Referenz für mich?

Danke im Vorraus
David

Autor: Arc Net (arc)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dürfte daran liegen, dass im DataReceived-Event mit ReadLine auf die 
nächste vollständige Zeile gewartet wird. ReadLine blockiert entweder 
bis die Zeile vollständig gelesen ist oder, falls so eingestellt, bis 
zum Timeout. Was passiert jetzt wenn während ReadLine wartet, neue Daten 
eintreffen...
Etwas aufwändiger wäre eine Lösung, die im DataReceived-Event mit 
ReadExisting erstmal einen Buffer füllt und diesen Buffer in einem 
separaten Thread auseinanderzunehmen.

Autor: Daniel G. (daniel83)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Klasse SerialPort ist ein bischen labil. Meiner Erfahrungnach sollte 
man soviel wie möglich selbst machen und die Funktione dieser Klasse 
soweit wie möglich bei Seite legen. Das Verhalten ist sehr merkwürdig.
OnDataReceived kann wärendeiner Kommunikation, die von dir als eine 
betrachtet werden durchaus mehrfach ausgelöst werden. Dann hast du 
mehrere Threads, die Paralell auf das Zeilenende warten.

Du hast 2 mal OnDataReceived geschrieben, das ist jedoch bestimmt nur 
ein Fehler beim Kopieren gewesen.

Als referenz hönnte ich dir das hier 
http://www.mycsharp.de/wbb2/thread.php?threadid=43748 anbieten. Das 
Template hat mir sehr geholfen und zeigt wie man ordentlich mit der 
Klasse arbeiten kann.

SerialPort hat mir in einigen Anwendungen den letzten Nerv geraubt

Autor: David1 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Readexisting Methode wäre natürlich eine Alternative, das würde ja 
dann aber mehr Aufwand bedeuten da ich die Daten zusammensetzen und 
wieder splitten muss.

Kann ich nicht einfach in einer while-Schleife die Readline-Methode 
benutzen und von den Event gesteuerten Empfang der Daten abweichen?

@Daniel:
das 2.OnDataRecieved ist ein weiteres Event was von dem ersten 
OnDataRecieved ausglöst, etwas verwirren die Notation, werde ich ändern.

Den Ansatz im Beispiel werde ich mal ausprobieren.

Ich hatte die ganze Zeit eher nach einem Speicherproblem gesucht, weil 
ja geringe Zeilen sauber übertragen werden.

Autor: Daniel G. (daniel83)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das mit den kurzen Übertragungen würde ich als Zufall beschreiben. 
OnDataReceived ist wie gesagt eher unzuverlässig. Weist du vorher 
wieviele Daten (Zeilen) kommen? Dann könntest du im OnDataReceived 
entsprecehnd lange warten und dir den Timeout selbst bauen.
// Warte auf Antwort
            do
            {
                Thread.Sleep(10);
                aktuelleZeit = DateTime.Now;
            } while (timeoutZeit + timeout > aktuelleZeit && Port.BytesToRead < 9);

Ich mache das gerne in etwa so. Ich weis allerdings auch wann ich auf 
daten warten muss.
Eine Variante wäre, dass du wenn zu begin der Übertragung der erste 
OnDataReceived ausgelöst wird ein Flag z.B. im TAG des SerialPort 
Objekts setzt und weitere OnDataReceived damit ausschließt, weil du hier 
darauf Prüfst.

Das geht jedoch nur wenn du aus deinen Daten am anfang herausbekommst 
wieviele du erwartest oder dies bereits zur Entwicklungszeit klar ist.

Autor: David 1 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also die Anzahl der Zeilen variert stark(zwischen 4 und 1340).

Ich hatte mir das so vorgestellt:

Pseudocode
comPort.Open()
comPort.SendeBefehl(Start)
do
{
   queueDatensaetze.Enqueue(comPort.ReadLine()); 


}while(EndindikatorVorhanden(data);

comPort.Close();
DoSomethingWith(queueDatensaetze);

Ich werde mal anhand der Beipiele und Überlegungen einige der Sachen 
austesten.

Autor: Daniel G. (daniel83)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was passiert, wenn gerade nichts zu lesen da ist? Exception? du wirst 
vermutlich eine Sehr hohe CPU auslastung bekommen, deshalb ist bei mir 
das thread.Sleep(10) drin. in der Zeit bin ich eigentlich schon 5mal 
fertig.

Autor: David 1 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
In meiner Anwendung sende ich den Befehl zur Datenübertragung und ab da 
an werden nur noch Daten geschickt.
Wenn keine Datenübersendet werden kann nur ein Fehler dafür 
verantwortlich sein, deswegen ist eine Exception in dem Fall auch 
richtig.

Ein Problem mit der CPU-Last konnte ich noch nicht erkennen, in meinem 
Tests war die Auslastung des Prozesses maximal bei 10% aber meist 
zwischen 3-6%.

Ich warte jetzt noch bis sich ein paar mehr Daten angesammelt haben um 
das ausgiebig zu testen.

In meiner Implementierung verarbeite ich die Daten auch gleich, also 
hänge sie nicht in einem Fifo.

Danke schon mal für die vielen nützlichen Hinweise.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.