INFO: Dieses Forum nutzt Cookies...
Cookies sind für den Betrieb des Forums unverzichtbar. Mit der Nutzung des Forums erklärst Du dich damit einverstanden, dass wir Cookies verwenden.

Es wird in jedem Fall ein Cookie gesetzt um diesen Hinweis nicht mehr zu erhalten. Desweiteren setzen wir Google Adsense und Google Analytics ein.

Antwort schreiben 
 
Themabewertung:
  • 1 Bewertungen - 2 im Durchschnitt
  • 1
  • 2
  • 3
  • 4
  • 5
Sich wiederholende Intervalle ohne Delay Verzweiflung
12.12.2019, 22:07
Beitrag #25
RE: Sich wiederholende Intervalle ohne Delay Verzweiflung
(12.12.2019 11:18)RolandF schrieb:  Hallo RobertLeRob,

ergänzent zu den anderen guten Vorschlägen die schon gemacht wurden, würde ich Dir auch einmal empfehlen das Konzept der StateMachine anzuschauen.

Vielen Dank für deine Mühe und die ausführliche Antwort. Idea

Ich versuche aktuell in dem Code meine Pins fest zu legen damit ich sie ansteuern kann aber er lässt mich das nicht machen.

Kannst du mir bitte erklären wofür das enum state_enum steht ? Und was muss an die Stelle, an der du eingetragen hast "Hier werden alle möglichen Zustände aufgelistet", ein Beispiel wäre super !

Code:
enum State_enum
{
  RELAIS1,
  RELAIS2,
  RELAIS3,
  RELAIS4
}; // Hier werden alle möglichen Zustände aufgelistet

Und nochmal besten Dank !
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
12.12.2019, 22:57
Beitrag #26
RE: Sich wiederholende Intervalle ohne Delay Verzweiflung
(12.12.2019 16:24)RolandF schrieb:  
(12.12.2019 11:35)MicroBahner schrieb:  Eine 'komplette' Statemachine lohnt eigentlich nur, wenn in jedem Zustand wirklich unterscheidliche Dinge gemacht werden sollen, und wenn auch auf unterschiedliche Ereignisse reagiert werden soll.
Eine Schrittkette ist eine abgespeckte Variante davon, die hier vollkommen ausreicht.
Da hast Du natürlich Recht solange nicht mehr Aktionen in den einzelnen Zuständen hinzukommen.
Ich mache das aber lieber schon etwas früher so, dann bin ich bei späteren Änderungen schneller.
Solange die Zustände ähnlich abläufe haben steht dann in jedem Zustand nur eine Funktionsaufruf mit Parameter.
Aber hier ist das wie Du schon richtig festgestellt hast nicht unbedingt nötig.

Dann denke ich ist es tatsächlich besser wenn ich gleich mit einer stateMachine anfange, es sollen ja noch mehr Sensoren verbaut werden, ein Display angeschlossen, und ein Menü aufgesetzt, durch das ich mit einem druck und dreh Knopf navigieren kann.

Ich versuche gerade auf diese Art meine Tag und Nacht unterscheide zu realisieren und wollte danach anfangen die Pause in der Nacht ein zu bauen, klappt leider auch nach dem 5ten versuch noch nicht Undecided

Code:
#include <Arduino.h>


#define dayInterval 3000
#define nightInterval 1500
#define breakInterval 8000

const int sensorvcc = 8;
const int threshold = 100;

enum State_enum {RELAIS1, RELAIS2, RELAIS3, RELAIS4};
State_enum state = RELAIS1;

unsigned long previousMillis;
void stateMachine();

void setup()
{
  Serial.begin(9600);
  while (!Serial) delay(10);

  previousMillis = millis();

  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);

}

void loop() {

  digitalWrite(sensorvcc, HIGH);
  int sensorValue = analogRead(A0);
  stateMachine();
}


void stateMachine()
{
  
  switch (state)
  {
      
    case RELAIS1:
      digitalWrite(2, HIGH);
      Serial.println("Relais1 an");
      sensorValue = analogRead(A0);
      Serial.println(sensorValue);
      if (threshold > sensorValue) {


        if (millis() - previousMillis >= dayInterval) {
          digitalWrite(2, LOW);
          state = RELAIS2;
          previousMillis = millis();
        }

        else {
          if (millis() - previousMillis >= nightInterval) {
            digitalWrite(2, LOW);
            state = RELAIS2;
            previousMillis = millis();
          }
        }
      }

      break;

    case RELAIS2:

      digitalWrite(3, HIGH);
      Serial.println("Relai 2 an");
      sensorValue = analogRead(A0);
      Serial.println(sensorValue);
      if (threshold > sensorValue) {


        if (millis() - previousMillis >= dayInterval) {
          digitalWrite(3, LOW);
          state = RELAIS3;
          previousMillis = millis();
        }
        else {
          if (millis() - previousMillis >= nightInterval) {
            digitalWrite(3, LOW);
            state = RELAIS3;
            previousMillis = millis();
          }
          break;
        }
      }
  }
}
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
12.12.2019, 23:08 (Dieser Beitrag wurde zuletzt bearbeitet: 12.12.2019 23:15 von MicroBahner.)
Beitrag #27
RE: Sich wiederholende Intervalle ohne Delay Verzweiflung
(12.12.2019 22:57)RobertLeRopp schrieb:  es sollen ja noch mehr Sensoren verbaut werden, ein Display angeschlossen, und ein Menü aufgesetzt, durch das ich mit einem druck und dreh Knopf navigieren kann.
Das hat aber doch jetzt mit der Schrittkette für deine Relais nichts zu tun - oder soll die dann auch ganz anders ablaufen? Wenn ja, wäre die Frage, warum Du überhaupt so anfängst.
Das Display-Menü ware dann gegebenenfalls eine eigene Statemachine, die sicher nichts mit der Relais-Schrittkette zu tun hat. In komplexen Sketchen hat man oftmals mehrere unabhängige Statemachines/Schrittketten. Immer jeweils aufgabenbezogen. Du kannst i.A. nicht alles mit einer erschlagen.
Die Schrittkette für die Relais ist ja auch eine Statemachine - nur eben aufgabenbezogen für die Abfolge der Relaisansteuerung realisiert. Willst Du deine Relais später gar nicht nacheinander, sondern beliebig unabhängig voneinander ansteuern, brauchst Du allerdings in der Tat einen anderen Ansatz.

Gruß, Franz-Peter
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
12.12.2019, 23:25
Beitrag #28
RE: Sich wiederholende Intervalle ohne Delay Verzweiflung
Danke für deine Antwort.

Nein, ich möchte die Relais immer nur nacheinander ansteuern, niemals durcheinander.

Ich habe mich versucht in Arrays ein zu lesen, damit ich die Tag/Nacht Schaltung auf deren Basis einbauen kann.

Dazu bin ich auf dieses tolle Beispiel gestoßen: https://starthardware.org/lektion-15-array/

Verstanden wie ich das ganze jetzt aber bei mir anwende, habe ich nicht und mir raucht echt langsam gewaltig der Schädel :-S

Ich bin euch sehr sehr dankbar für eure Hilfe, falls jemand hier aus dem Rhein/Main Gebiet kommt, ich lade als Dankeschön gerne mal zum Essen ein Smile
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
13.12.2019, 08:02
Beitrag #29
RE: Sich wiederholende Intervalle ohne Delay Verzweiflung
(12.12.2019 22:07)RobertLeRopp schrieb:  
(12.12.2019 11:18)RolandF schrieb:  Hallo RobertLeRob,

ergänzent zu den anderen guten Vorschlägen die schon gemacht wurden, würde ich Dir auch einmal empfehlen das Konzept der StateMachine anzuschauen.

Vielen Dank für deine Mühe und die ausführliche Antwort. Idea

Ich versuche aktuell in dem Code meine Pins fest zu legen damit ich sie ansteuern kann aber er lässt mich das nicht machen.

Kannst du mir bitte erklären wofür das enum state_enum steht ? Und was muss an die Stelle, an der du eingetragen hast "Hier werden alle möglichen Zustände aufgelistet", ein Beispiel wäre super !

Code:
enum State_enum
{
  RELAIS1,
  RELAIS2,
  RELAIS3,
  RELAIS4
}; // Hier werden alle möglichen Zustände aufgelistet

Und nochmal besten Dank !

Das state_enum ist eine Aufzählung, sozusagen ein Typ mit eigenen Werten. Eine Variable dieses Types kann dann genau die Werte der Aufzählung annehmen.
Dieser Vorteil kommt besonders zur Geltung, wenn Du eine IDE mit Codecompleting nutzt wie z.B. Sloeber, oder VSCode in Verbindung mit Platformio.
Weiterhin habe ich mal meinen Beispielcode um ein paar zusätzliche States erweitert.
Den Code solltest Du 1:1 in Deine IDE kopieren können und das Ergebnis in der Seriellen Console sehen.
Wichtiger Punkt ist dass in dem switch immer nur ein Case-Zweig angesprungen wird welcher das ist legst du selber fest in dem du die Variable state im aktiven state entsprechend umsetzt.
Die Dauer wie lange ein State aktiv bleibt ist in dem Beispiel mit INTERVALL festgelegt, das können aber auch andere Bedingungen sein, oder wie im Fall von "TAGNACHTPRUEFUNG" nur ein einmaliger durchlauf.

Hier der Code:
Code:
#include <Arduino.h>
#define INTERVALL 4000    // Dauer eines Anschaltzeitraumes in Millisekunden
enum State_enum
{
  RELAIS1,
  RELAIS2,
  RELAIS3,
  RELAIS4,
  TAGNACHTPRUFUNG,
  NACHT1,
  NACHT2,
  PAUSE
};
State_enum state = RELAIS1;

unsigned long previousMillis;

void stateMachine();

void setup()
{
  Serial.begin(9600);
  delay(2000);
  previousMillis = millis();
}

void loop()
{
  stateMachine();
}


void stateMachine()
{
  switch (state)
  {
  case RELAIS1:
    Serial.println("Relais1 an");
    if (millis() - previousMillis >= INTERVALL){
      // Zetraum für diesen State beendet
      state = RELAIS2;  // nächsten State setzen
      previousMillis = millis();
    }
    break;

  case RELAIS2:
    Serial.println("Relais2 an");
    if (millis() - previousMillis >= INTERVALL)
    {
      state = RELAIS3;
      previousMillis = millis();
    }
    break;

  case RELAIS3:
    Serial.println("Relais3 an");
    if (millis() - previousMillis >= INTERVALL)
    {
      state = RELAIS4;
      previousMillis = millis();
    }
    break;
  case RELAIS4:
    Serial.println("Relais4 an");
    if (millis() - previousMillis >= INTERVALL)
    {
      state = TAGNACHTPRUFUNG;
      previousMillis = millis();
    }
    break;
  case PAUSE:
    Serial.println("Pausenaktion");
    if (millis() - previousMillis >= INTERVALL)
    {
      state = TAGNACHTPRUFUNG;
      previousMillis = millis();
    }
    break;
  case TAGNACHTPRUFUNG:
    Serial.println("Hier wird geprüft ob Tag oder Nachmodus aktiv sein soll");
      // Hier könnte jetzt Die Bedingung für für die TAG/NAcht-Prüfung stehen
      // Abhängig vom Ergebnis könnte dann eine Zuweisung in der Form:
      //state = RELAIS1;
      // state = PAUSE; oder
      state = NACHT1;
      // stehen
      previousMillis = millis();
    break;
  case NACHT1:
    Serial.println("Hier ist eine Verarbeitung für State NACHT1");
    if (millis() - previousMillis >= INTERVALL)
    {
      
      state = NACHT2;
      previousMillis = millis();
    }
    break;
  case NACHT2:
    Serial.println("Hier ist eine Verarbeitung für State NACHT2");
    if (millis() - previousMillis >= INTERVALL)
    {
      state = RELAIS1;
      previousMillis = millis();
    }
    break;
  }
  delay(1000);
}
Noch weiterhin viel Erfolg, mit Deiner Umsetzung
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
13.12.2019, 09:48 (Dieser Beitrag wurde zuletzt bearbeitet: 13.12.2019 10:02 von MicroBahner.)
Beitrag #30
RE: Sich wiederholende Intervalle ohne Delay Verzweiflung
(12.12.2019 23:25)RobertLeRopp schrieb:  Nein, ich möchte die Relais immer nur nacheinander ansteuern, niemals durcheinander.
Dann ist eigentlich eine einfache arraygesteuerte Schrittkette wie in meinem Beispiel das einfachste und kompakteste für die Relais. Letztendlich passiert in jedem Schritt das Gleiche, und mMn ist es nicht sinnvoll, dass dann n-mal zu programmieren.
Anders sieht das sicher aus, wenn Du später ein Display mit Menüsteuerung hinzufügen willst. Da wirst Du eine 'vollständige' Statemachine, wie sie RolandF zeigt, benötigen. Aber wie gesagt, sind das 2 getrennte Programmteile, die Du unabhängig voneinander realisieren kannst/musst.
Letztendlich ist es aber deine Entscheidung wie Du das machst. Es führen immer viele Wege nach Rom. Auch und gerade bei der Programmierung.

(12.12.2019 23:25)RobertLeRopp schrieb:  Ich habe mich versucht in Arrays ein zu lesen, damit ich die Tag/Nacht Schaltung auf deren Basis einbauen kann.

Dazu bin ich auf dieses tolle Beispiel gestoßen: https://starthardware.org/lektion-15-array/

Verstanden wie ich das ganze jetzt aber bei mir anwende, habe ich nicht und mir raucht echt langsam gewaltig der Schädel :-S
Naja, ist eigentlich genau das, was auch die Schrittkette aus #23 macht. Nur eben nicht als for-Schleife mit delay, sondern mit millis() und in den loop eingebunden um blockierungsfrei zu arbeiten. Die Tonhöhe entspricht dem Relaispin, und die Tondauer der Einschaltzeit des Relais.
Die Blockierungsfreiheit ist wichtig, damit Du deinen Sketch später erweitern kannst, und z.B. die Statemachine für dein Menü hinzufügen kannst.

Edit: Damit Du siehst, dass das letzendlich tatsächlich das selbe ist wie das Beispiel im Link köntest Du spasseshalber das Beispiel aus dem Link auf deine Relais umschreiben. Wären nur wenig Anpassungen - allerdings keine zukunftsfähige Lösung, weil eben blockierend.

P.S. gewöhne dir von Anfang an an, deine Programme ordentlich zu kommentieren und beschreibe, wozu der jeweilige Programmblock da ist, und was er tun soll.
Das hilft Dir später, wenn Du deinen Code noch verstehen willst, und oftmals auch direkt beim Schreiben des Programms.
Ausserdem hilft es uns beim Helfen. Wenn wir lesen, was du mit dem Codeblock bezwecken willst, können wir auch leichter kontrollieren, ob er auch das tut, was Du vorhast.

Gruß, Franz-Peter
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
13.12.2019, 13:45
Beitrag #31
RE: Sich wiederholende Intervalle ohne Delay Verzweiflung
Jungs Ihr seid der absolute Hammer, ich versuche das alles jetzt richtig zu verstehen, werde einiges probieren und mich dann nochmal melden.

Kein Spaß, ich sitze seit 2 Wochen jede Nacht 5 Stunden am Stück vor diesem Monitor und habe langsam 4 eckige Augen, nein wohl eher 16:9.

Ist nicht so easy zwischen Arbeit und zwei kleinen Kindern, deswegen nochmals herzlichsten Dank für euer Engagement und die Hilfe ! Heart
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
14.12.2019, 11:50
Beitrag #32
RE: Sich wiederholende Intervalle ohne Delay Verzweiflung
(13.12.2019 08:02)RolandF schrieb:  Das state_enum ist eine Aufzählung, sozusagen ein Typ mit eigenen Werten. Eine Variable dieses Types kann dann genau die Werte der Aufzählung annehmen.
Dieser Vorteil kommt besonders zur Geltung, wenn Du eine IDE mit Codecompleting nutzt wie z.B. Sloeber, oder VSCode in Verbindung mit Platformio.
Weiterhin habe ich mal meinen Beispielcode um ein paar zusätzliche States erweitert.
Den Code solltest Du 1:1 in Deine IDE kopieren können und das Ergebnis in der Seriellen Console sehen.
Wichtiger Punkt ist dass in dem switch immer nur ein Case-Zweig angesprungen wird welcher das ist legst du selber fest in dem du die Variable state im aktiven state entsprechend umsetzt.
Die Dauer wie lange ein State aktiv bleibt ist in dem Beispiel mit INTERVALL festgelegt, das können aber auch andere Bedingungen sein, oder wie im Fall von "TAGNACHTPRUEFUNG" nur ein einmaliger durchlauf.


Der Tipp mit VSCode war Gold wert danke ! Ich Schreibe das Programm nun nochmal komplett von vorne auf Platformio.

Deshalb nochmal für mein Verständnis bevor ich wieder falsch heran gehe.

Habe ich es richtig verstanden dass: Jeder Case immer hintereinander abläuft ?

Die Aufzählung
Code:
enum State_enum
{
  RELAIS1,
  RELAIS2,
  RELAIS3,
  RELAIS4,
  TAGNACHTPRUFUNG,
  NACHT1,
  NACHT2,
  PAUSE
};

jedoch nicht zwingend in der Reihe geschrieben werden muss ?
Beispiel wie ich es vorerst verstanden hatte:

Code:
enum State_enum
{
  RELAIS1,
  TAGNACHTPRUFUNG,
  PAUSE,
  RELAIS2,
  TAGNACHTPRUFUNG,
  PAUSE,
  RELAIS3,
  TAGNACHTPRUFUNG,
  PAUSE,
  RELAIS4,
  TAGNACHTPRUFUNG,
  PAUSE,
  TAGNACHTPRUFUNG,
};

Und wie ich es jetzt gerne umsetzen würde und denke das es richtig ist:

Code:
enum State_enum
{
  RELAIS1,
  RELAIS2,
  RELAIS3,
  RELAIS4,
  TAGNACHTPRUFUNG,
  PAUSE
};

Ich habe es so verstanden dass ich es auf diesen Weg machen kann/muss:

Code:
case RELAIS1:
    Serial.println("Relais1 an");
    digitalWrite(2, HIGH); // Relai 1 an
    if (millis() - previousMillis >= INTERVALL){
      digitalWrite(2, LOW); // Nach ablauf von INTERVALL Relai 1 aus
      state = TAGNACHTPRUFUNG;  // Ich möchte zwischen jedem Relai überprüfen ob es Tag oder Nacht ist
      previousMillis = millis();
    }
    break;

  case TAGNACHTPRUFUNG: // hier möchte ich den Sensor checken und ggf. den Pausenintervall auslösen, anderenfalls diesen überspringen und einfach mit Relai 2 weiter machen
    Serial.println("Tag/Nacht Prüfung");
    if (lichtsensorwert < schwellwert)
{    
      state = PAUSE;     // Entweder hier state PAUSE auslösen
    }
else
{
state = RELAIS2;  // oder zu state RELAIS2 springen
}
    break;

  case PAUSE:
    Serial.println("Pause");
    if (millis() - previousMillis >= PAUSE){ // Hier möchte ich kein Relai einschalten  
      state = RELAIS2;  // Aber nach der Pause mit dem nächsten Relai in der Reihe weiter machen (RELAIS2)
      previousMillis = millis();
    }
    break;

Beim Tippen ist mir nun aufgefallen das ich mir meine Frage von oben wahrscheinlich schon selbst beantwortet habe.

Also ich grundsätzlich erst mal die States definieren muss im oberen Teil und beim Ablauf unten mich dann immer wieder durch den Namen des States darauf beziehen kann was er nun machen soll.

Heist, ich brauche den State TAGNACHTPRÜFUNG und den State PAUSE nur einmal aufführen, da diese ja immer gleich sind, die 4 Relais jedoch einzeln aufführen da ich ja bei jedem Relai einen anderen Pin schalten möchte.

Was ich bei diesem weg aber nicht verstehe, woher der State PAUSE/TAGNACHTPRÜFUNG weis mit welchem Relai er als nächstes weiter machen soll, sollte ich den State Pause nur einmal festgelegt haben.

Ich hoffe ich habe mich nicht all zu unbeholfen erklärt Angel
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
Antwort schreiben 


Möglicherweise verwandte Themen...
Thema: Verfasser Antworten: Ansichten: Letzter Beitrag
  Fehler bei delay über 32767 Kleingärtner 5 490 07.05.2020 18:51
Letzter Beitrag: Kleingärtner
Question Sketch compilieren und testen ohne hochladen? Triax16 18 1.422 02.05.2020 12:48
Letzter Beitrag: Bitklopfer
  SoftwareSerial.h und SD.h vertragen sich nicht sowerum 25 1.775 25.04.2020 10:46
Letzter Beitrag: hotsystems
  Wie bekomme ich DIESES Delay weg. DO3GE 9 804 18.04.2020 12:44
Letzter Beitrag: Fips
  delay-millis()-while-Sensorenabfrage RCudino 22 1.802 01.04.2020 06:46
Letzter Beitrag: RCudino
  Denkanstoß gesucht - in Schrittkette delay() ersetzen SpaghettiCode 19 1.328 31.03.2020 21:31
Letzter Beitrag: MicroBahner
  for-schleife, delay, millis, interrupt Harry 8 851 31.03.2020 21:02
Letzter Beitrag: Harry
  Menu funktioniert ohne Serial.println nicht GSA1150 7 643 30.03.2020 18:26
Letzter Beitrag: Tommy56
  Stepper Motor mit zwei Taster bedienen / Fehler ohne Fehlermeldung Milano 6 720 21.03.2020 16:06
Letzter Beitrag: MicroBahner
  Arduino IDE 1.8.11 , lassen sich keine Sketch.zip hinzufügen Christian_Moba-Arduino 4 782 23.02.2020 13:18
Letzter Beitrag: Christian_Moba-Arduino

Gehe zu:


Benutzer, die gerade dieses Thema anschauen: 1 Gast/Gäste