ich habe mal wieder ein paar kleine Hürden zu meistern. Für einen Testaufbau (Master-Slave) arbeite ich mit einer Switch Case Anweisung, darin verschachtelt eine While Schleife. Der Master sendet an den Slave alle 500ms einen Wert, jedoch ändert der Slave seinen Case immer erst wenn die While Schleife durchlaufen ist, obwohl ich im While Schleifenkopf eine Bedingung definiert habe, die nicht mehr stimmt. Selbst wenn ich in der While Schleife eine IF Anweisung einfüge mit dem Break Befehl passiert nichts.
Nur zum Verständnis, bitte korrigiert mich, wenn ich falsch liege. Sobald der Master sendet, bleibt der Slave im Programm stehen, empfängt die Daten und macht dann an der Stelle im Sketch weiter?!
void setup() {
Wire.begin(3); // Tritt dem Datenbus mit der Adresse 3 bei
Wire.onReceive(konfig); // Registriert Konfiguration vom Master
...
}
void loop() {
switch(modus){
case 0: // PAUSE
...
break;
case 1: // WRG Modus
...
break;
case 2: // DL Modus
digitalWrite(led_wrg, LOW); // Im DL Modus WRG LED aus
digitalWrite(led_dl, HIGH); // Im DL Modus DL LED an
while(zeit < 70 && modus == 2){
zeit++;
analogWrite(fan_1_eta, eta); // Ventilator 1 ETA Betrieb mit definierter Abluftstufe
analogWrite(fan_1_sup, 0); // Ventilator 1 SUP Aus
analogWrite(fan_2_eta, 0); // Ventilator 2 ETA aus
analogWrite(fan_2_sup, sup); // Ventilator 2 SUP Betrieb mit definierter Zuluftstufe
delay(1000); // 1 Sekunde
}
zeit = 0; // Timer Zurücksetzen
temp = 0;
break;
}
}
void konfig(int data){ // Konfiguration vom Master
modus = Wire.read(); // Sendet Betriebsmodus vom Master
stufe = Wire.read(); // Sendet Reglerstufe vom Master
eta = Wire.read(); // ETA Stufe
sup = Wire.read(); // SUP Stufe
}
Kurz zum Ablauf: Der Master sendet den Betriebsmodus (Modus), welcher ausgeführt werden soll. Dann springt der Slave in die entsprechende Case anweisung. Das funktioniert. Hier im Sketch für DL Modus dargestellt. Die anderen Modi sind ähnlich. Sobald ich aber vom Master den Modus ändere ist ja Modus nicht mehr ==2 und die Bedingung ist nicht mehr erfüllt. Jedoch bringt der die While Schleife zu ende (70s) und danach geht er erst in den neu definierten Modus.
mit break kommst raus, aber wenn man so was braucht, sollte man überlegen, ob while das richtige ist ...
deine 3 Denkfehler(MZ) sind:
-die Verwendung des blockierende delay(1000);
-modus wird in der while nicht verändert, also kann es auch nicht als Abbruchbedingung während des While loop verwendet werden
-das wir hier mit Codeschnipseln sehen, was sich sonst im Code tut. poste IMMER einen minimal lauffähigen code den wir evtl. selber auf ein Target hochladen können. Er soll nur so kurz sein, wie unbedingt notwendig. 90% der Fälle wirst du dann lösen können, während du den Sketch für uns reduzierst - garantiere ich dir!
Okay das versteh ich, ich habe den Code nur kurz gehalten, damit es übersichtlich bleibt. Weil im prinzig die anderen Modi genauso aufgebaut sind.
Im Kopf der While wird doch der Modus mit seiner Bedingung festgelegt:
while(zeit < 70 && modus == 2)
Wenn ich durch erneutes senden vom Master den Modus auf Beispielsweise modus == 0 schalte, ist doch die Bedingung nicht mehr erfüllt, jedoch wird die Schleife weiter ausgeführt. Da steh ich auf dem Schlauch.
Ich nutze die Variable Modus einmal im Case und einmal in der Bedingung der While Schleife. Sollte man das lieber nicht tun und zwei verschiedene Variablen nehmen?
Wenn ich durch erneutes senden vom Master den Modus auf Beispielsweise modus == 0 schalte, ist doch die Bedingung nicht mehr erfüllt, jedoch wird die Schleife weiter ausgeführt.
nein falsche Beobachtung.
Du springst bei zeit <70 und modus == 2 in die While UND BLEIBST DORT bis 70 erreicht ist.
Ich sehe im loop keinen Code wie sich modus IN DER SCHLEIFE ändern würde.
Bau dir ein serial.println(modus) ein, dann wirst du es sehen. Das wäre sowieso praktisch das Serial.print Ausgaben eine gute debug-Möglichkeit ist.
Kommando zurück, die Freude war leider doch etwas verfrüht. Ich habe wie du mir empfohlen hast in jeden Case eine Serial.Print(modus) eingefügt, um zu sehen, ob sich der Modus in der Schleife ändert. Das hat auch Prima geklappt. JEDOCH als ich den Sketch "bereinigt" habe, sprich den Serial.print wieder entfernt habe und nochmap probierte, ging es nicht mehr...nachdem ich ihn wieder eingefühgt habe ging es wieder.
Du hast in loop() schon eine Schleife. Du solltest das Programm eher so betrachten dass loop() ständig durchläuft und jeder Durchlauf einen aktuellen Zustand darstellt. Und statt delay() Zeiten mit millis()/BlinkWithoutDelay machen. Dann kann man mehrere Dinge nebeneinander erledigen
Also ich habe jetzt nochmal ein wenig im Sketch experimentiert und es liegt einfach an der "blöden" Delay Funktion. Wenn ich diese deaktivere, dann nimmt der Slave alle Befehle vom Master sofort und ohne Verzögerung entgegen und setzt sie um. Soweit Prima.
ABER, da meine Programmierkenntnisse recht überschaubar sind, tue ich mich gerade schwer mit der millis Funktion einen Timer zu realiesieren, welcher sich alle 70s zurücksetzt.
Ich möchte Realiseren, dass der Ventilator alle 70s seine Drehrichtung ändert. Daher war es für sehr einfach dies mit der delay Funktion zu bewerkstelligen...
ABER, da meine Programmierkenntnisse recht überschaubar sind, tue ich mich gerade schwer mit der millis Funktion einen Timer zu realiesieren, welcher sich alle 70s zurücksetzt.
Das ist der/ein Hügel der Erkenntnis.
Da mussten/müssen wir alle drüber, und jetzt bist du dran.
Wenn er so vor einem liegt, sieht er viel größer aus, als wenn man oben steht und einen das "Aha" Erlebnis gefunden hat.
Ablaufsteuerung
Meine Standardantwort zu Ablaufsteuerungen:
Eine Stichworte Sammlung für Google Suchen:
Endlicher Automat,
State Machine,
Multitasking,
Coroutinen,
Ablaufsteuerung,
Schrittkette,
BlinkWithoutDelay,
Das konnte ich mir schon denken, dass ich diese Hürde meistern muss
Macht ja auch Sinn, da ich in Zukunft sicher noch viel öfter mit dieser Thematik konfrontiert werde. Bin schon seint heute früh am rechachieren! Aber nochmal danke für den Denkanstoß!
Man kann sich das Leben auch etwas einfacher machen, wenn man den MoToTimer der MobaTools benutzt. Insbesondere wenn es nicht um regelmäßig wiederkehrende Intervalle, sondern um asynchron gestartete Zeitabläufe geht, erleichtert die 'expired' Methode das Leben. Die wird beim Ablauf der vorher gestarteten Zeit genau 1x wahr. Damit kann man dann ganz leicht etwas auslösen, dass nach Ablauf der Zeit gestartet werden muss.
Wer die MobaTools nicht komplett installieren will, kann sich auch die MoToTimer.h kopieren - da ist alles notwendige drin.
Das Grundprinzip des Nachtwächters ändert sich dadurch zwar nicht, aber nach meinen Erfahrungen und Rückmeldungen ist es einfacher und übersichtlicher als das direkte Hantieren mit den millis().
Also um die ganze Thematik mal abzuschließen. ich habe in meinem Sketch alle Delays verbannt und durch die Millis Funktion ersetzt. Funktioniert super und erlaubt mir dadruch auch ganz neue Möglichkeiten. Das ist echt Prima. Somit funktioniert jetzt auch die Master-Slave-Kommunikation fehlerfrei und alle machen das was sie sollen.
Mein nächste Herausforderung wird eine Kommunikation zwischen Arduino und einem Sensor über RS232...aber das hebe ich mir für einen anderen Tag auf