Laden...

[gelöst] Konzeptfrage Master-Slave Komunikation

Erstellt von Daniel83 vor 14 Jahren Letzter Beitrag vor 14 Jahren 2.687 Views
D
Daniel83 Themenstarter:in
171 Beiträge seit 2008
vor 14 Jahren
[gelöst] Konzeptfrage Master-Slave Komunikation

Hallo Zusammen,

Ich habe ein Programm, welches via COm-Port mit einem Microcontroler kommuniziert. Das klappt auch alles wunderbar. Mein Problem ist nur, dass ich auch auf "keine Antwort" reagieren muss. Im Moment löse ich das über eine Zählschleife, das funktioniert auch.

//Warte bis genug Daten am SerialPort anliegen oder ein Timeout auftritt
                while ( port.BytesToRead < bufferSize && count < 100000 )
                {
                    count++;
                }

Aber hat zwei Nachteile, erstens ich denke nicht, dass das besonders schön ist. Zweitens wenn ich das Programm auf einen anderen Rechner mit mehr oder weniger Rechenleistung bringe, dann habe ich möglicherweise zu kurze Wartezeiten, d.h. das was ich in einer bestimmten Zeit erwarte kommt nicht, weil sich die Zeitspanne der bestimmten Zeit verkürzt.

Ich habe als überlegt und bin auf sowas gekommen:

Timeout = false;
                        TimeoutTimer.Enabled = true;
                        while ( !( port.BytesToRead == BytesToRead ) && !Timeout )//1000
                        { counter++; }
                        TimeoutTimer.Enabled = false;

Timeout wird im Event von Timertick auf true gesetzt.

Dummerweise geht das nicht, weil der timer merkwürdigerweise nicht ttickt. Außerdem denke ich auch nicht, dass diese Lösung deutlcih hübscher ist.

Die dritte Lösung, die mir eingefallen ist wäre einfach zu warten.

Threadsleep würde aber immer auftreten, da ich viele Datensätze verschieben muss, wäre eine feste Wartezeit nicht soo toll, da das ganze schon bei sauberer Verbindung relativ lange dauert und ich das nicht zusätzlich verlängern möchte.

Hat von euch vieleicht eine Idee, wie ich das anders angehen kann?

Über das Data resieve Event möchte ich es nichtmmachen, da teilweise antworten von unterschiedlichen Teilnehmern kommen, dsa Event nicht wirklich ganz zuverlässig funktioniert, und ich letzt endlich da dann das selbe Problem habe.

Danke schon mal Daniel

297 Beiträge seit 2008
vor 14 Jahren

Zum Starten und Beeden des Timers benutzt du die Methoden Start() und Stop(), nicht Enabled auf true/false setzen.
Zudem musst du noch definieren, was beim Tick-Event passieren soll, indem du einen EventHandler für das Event registrierst. Aber das hast du ja scheinbar gemacht, wenn ich dich richtig verstanden habe.

There are 10 kind of people, those who understand binary and those who don't.

X
1.177 Beiträge seit 2006
vor 14 Jahren

Master-Slave Kommunikation funktioniert am besten mit Peitsche.

😁

Aber zu deinem Problem: Dein counter++ sollte ziemlich schnell durch sein; schneller als dein Timer vermutlich einmal Tick sagen kann. Ausserdem ziehst Du mit beiden Schleifen-Varianten die Prozessorzeit auf 100%.

Was allerdings nicht klar ist:

Mein Problem ist nur, dass ich auch auf "keine Antwort" reagieren muss

Wieso?

Desweiteren, wie kommen denn antworten auf einem COM-Port von mehreren Teilnehmenrn an?

Erklär mal bitte etwas genauer was Du vor hast.

🙂

Xynratron

Herr, schmeiss Hirn vom Himmel - Autsch!

Die Erfahrung zeigt immer wieder, dass viele Probleme sich in Luft auslösen, wenn man sich den nötigen Abstand bzw. Schlaf gönnt.

X
1.177 Beiträge seit 2006
vor 14 Jahren

huhu

Zum Starten und Beeden des Timers benutzt du die Methoden Start() und Stop(), nicht Enabled auf true/false setzen.

Start() Stop() macht aber das gleiche:

public void Start()
{
    this.Enabled = true;
} 

Herr, schmeiss Hirn vom Himmel - Autsch!

Die Erfahrung zeigt immer wieder, dass viele Probleme sich in Luft auslösen, wenn man sich den nötigen Abstand bzw. Schlaf gönnt.

D
Daniel83 Themenstarter:in
171 Beiträge seit 2008
vor 14 Jahren

Ja, einen Evnthandler habe ich regestriert.
Den Timer mit Enabled true und false zu benutzen habe ich schon immer so gemacht, auch wenn es vieleicht falsch ist, hat es bisher immer geklappt.

Im Event setzte ich lediglich Timeout auf true

D
Daniel83 Themenstarter:in
171 Beiträge seit 2008
vor 14 Jahren

Was ich eigentlcih mache:

Ich habe ein Gerät auf das ich Einstellungen von einem PC übertrage.
Das mache ich mit mehreren Protokollen, da die definierte Protokollgröße es nicht anders zu lässt.
An dem Bus den ich benutze hängt noch ein zweites Gerät, welches mir meine Protokolle sowie die Antworten darauf mit einem Fehler Quitiert. Deshalb 2 Teilnehmer, die antworten. Dieses Problem habe ich aber soweit im Griff.
Warum ich auf "Keine Antwort" reagieren muss ist einfach. Wenn der fall eintritt, dass jemand wärend der Komunikation über das Kabel Stolpert und/oder es Rauszieht, kann es sein, dass die übertragung unter-/abgebrochen wird. Würde ich hier jetzt warten wäre das nicht im Sinne des Erfinders, da sich ja einfach nichts mehr tut.

D
Daniel83 Themenstarter:in
171 Beiträge seit 2008
vor 14 Jahren

Das einzige was ich brauche ist ein zweites Abbruchkriterium als ich habe bekommen was ich brauche.
Die Zählschleife und der Timer laufen nicht in der Gleichen Funktion, ich habe die natürlich getauscht un es zu Probieren.
Mit der Zähler Variante läuft mein System hier auf ca 30% mit zwei Offnen Entwicklungsumgebungen und reagiert genau so "schnell" wie wenn ich das Programm nicht ausführe.

V
19 Beiträge seit 2008
vor 14 Jahren

Was ich bei so etwas ganz gerne mache ist folgendes Konstrukt


Tick=System.Environment.TickCount;
while ( !( port.BytesToRead == BytesToRead ) && (Tick+Timeout>System.Environment.TickCount))
    { 
      counter++; 
    }

Ist sicherlich nicht optimal, da ja im Prinzip gepollt wird, aber es ist schnell zu implementieren

D
Daniel83 Themenstarter:in
171 Beiträge seit 2008
vor 14 Jahren

Danke für die Idee, ist ja im Prinzip nichts anderes als meine Zählschleife, ich würde aber gerne weg von der geschwindigkeit der CPU.
Wenn ich z.B. festlege, dass ich maximal 250ms auf eine Antwort warten möchte und das mit meinem 3,4Ghz Rechner herausfinde, das dies 5Mio Ticks sind, dann geht das doch auf einem 1 Ghz Rechner nicht mehr auf, der wartet dann länger, aber schlimmer wenn einer mit einem 7Ghz Rechner kommt, dann wartet der nur 125ms. Die anderen Komponenten werden aber nicht schneller, somit gehen ihm Informationen verloren. Oder habe ich gerade das Konzept deiner Lösung nicht verstanden?

edit: Datetime.now + Timespan könnte eine Lösung sein

A
254 Beiträge seit 2007
vor 14 Jahren

Hallo,

ist ja witzig. Mach gerade etws sehr ähnliches. Hab auch mehrere µC Controller Lösungen, die meistens über ein PC parametrierbar sind.

Bin gerade dabei ein Programm zu erstellen, in dem ich die jeweiligen Gerätetypen und jeweiligen Parameter in einem XML File verwalte.

Damit ist es möglich, dass Gerät an die serielle Schnittstelle an zu stecken, das PC-Programm erfragt Typ und Version des Gerätes und man kann dann über das Programm die Parameter setzen.

Falls sich ein Gerät nicht meldet braucht man wohl immer ein Timeout, wobei die Klasse SerialPort den auch schon liefert, Eigenschaft ReadTimeout. Wenn Du dann noch den Empfang in einen separaten Thread verpackst sollten eigentlich alle Probleme gelöst sein.

Prüfst Du die Dateninhalte ab, ob sie fehlerfrei übertragen wurden (CRC o.ä.) ?

Mach bislang nicht, hatte aber auch noche keine Probleme. Wäre aber sicher sinnvoll.

D
Daniel83 Themenstarter:in
171 Beiträge seit 2008
vor 14 Jahren

Also ich lasse mir von mienem Gerät eine Antwort schicken. Beide Systeme prüfen eine Checksumme und die PC Software prüft ob die Antwort die ist, die zu erwarten ist. Das Senden läuft in einem extra Thread und über die Timespan geschichte jetzt auch so wie sie soll.

Meine jetztige Lösung:


            System.DateTime Aktuell = new DateTime();
            System.TimeSpan TimeOut = new TimeSpan( 5000000 );


            Aktuell = DateTime.Now;
            while ( !( port.BytesToRead == BytesToRead ) && ((Aktuell+TimeOut)>DateTime.Now) )
             { counter++; }

V
19 Beiträge seit 2008
vor 14 Jahren

Nur noch mal zu Erklärung mit meinem Tickcount.
Die liefert die Anzahl der Millisekunden ab, die seit dem Systemstart verstrichen sind. Es ist also unabhängig von der Prozessorgeschwindigkeit.
Dein Timespan funktioniert aber genauso gut

D
Daniel83 Themenstarter:in
171 Beiträge seit 2008
vor 14 Jahren

Habe ich mir schon fast gedacht, als bei Timespan von Ticks die rede war.
Danke dir für das Posting, hat mir zumindest das Brett vorm Kopf weg gerissen.
Auch wenn deins genau so funktioniert wie meine Lösung, bleibe ich bei meiner.
Das sieht mehr nach Zeitmessung aus 😉

A
254 Beiträge seit 2007
vor 14 Jahren

Mir ist die Lösung nicht ganz klar, warum verwendet Ihr nicht einfach den ReadTimeout der Klasse SerialPort. Darüber kann ich doch einen Timeout setzen.

D
Daniel83 Themenstarter:in
171 Beiträge seit 2008
vor 14 Jahren

Würde ich es über Timeout der Serialportklasse machen dann müsste ich ja mit der TimeoutException arbeiten. Da dies aber ein, naja, halbwegs erwarteter Zustand ist möchte ich das Programm nicht gegen die Wand fahren um es nachher wieder glat zu ziehen sondern umgehe die Ausnahme leiber, so sollte man das doch meines Wissens nach tun.

A
254 Beiträge seit 2007
vor 14 Jahren

Glaube nicht, was ist an einer Exception schlimm.

A
254 Beiträge seit 2007
vor 14 Jahren

So rein interesse halber, was für einen µC Controller programmierst Du denn ?

D
Daniel83 Themenstarter:in
171 Beiträge seit 2008
vor 14 Jahren

MSP430 haben wir im Einsatz