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
14.12.2019, 13:14
Beitrag #33
RE: Sich wiederholende Intervalle ohne Delay Verzweiflung
(14.12.2019 11:50)RobertLeRopp schrieb:  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,
};
Das hast Du ja weiter unten schon selbst bemerkt, dass das nicht so ist Wink
(14.12.2019 11:50)RobertLeRopp schrieb:  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.

Richtig erkannt Exclamation

(14.12.2019 11:50)RobertLeRopp schrieb:  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.

in diesem Fall würde ich fasst empfehlen die PAUSE und TAGNACHTPRUEFUNG nicht als eigenen State einzubauen, sondern ich würde nur Zweige für RELAIS1 bis 4 einbauen und beim zweiten Durchlauf eines Zweiges die Pause bzw Tagnachtprüfung durchlaufen. Das müsstes Du dann mit einem Flag und einer if Abfrage umsetzen.

Deshalb auch der berechtigte Hinweis von MicroBahner ob in diesem Fall ein StateMachine überhaubt nötig ist.

Aber wie das beim Programmieren so ist gibt es immer unendlich viele Wege ans Ziel.

Ich persönlich würde jetzt wie gesagt mit vier States arbeiten und in jedem State im ersten Durchlauf das Relais schalten und im zweiten Durchlauf die Pause und die Prüfung vornhemen.

Eine Alternative wäre auch noch die Stateanzahl sogar weiter zu erhöhen also
ein eigener Pausenstate für jedes Relais, was wahrscheinlich programmiertechnisch am einfachsten, aber eben nicht so elegant wäre.

(14.12.2019 11:50)RobertLeRopp schrieb:  Ich hoffe ich habe mich nicht all zu unbeholfen erklärt Angel
Nö hab alles verstanden Smile
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
14.12.2019, 13:52 (Dieser Beitrag wurde zuletzt bearbeitet: 14.12.2019 17:22 von MicroBahner.)
Beitrag #34
RE: Sich wiederholende Intervalle ohne Delay Verzweiflung
(14.12.2019 11:50)RobertLeRopp schrieb:  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.
Beim enum führst Du nur alle States auf, die deine Statemachine kennt. Die Reihenfolge, in der die States ausgeführt werden, hat damit nichts zu tun. Bei einer allgemeinen Statemachine werden die ja sowieso nicht unbedingt in einer festen Reihenfolge ausgeführt. Wenn Du schonmal an die Statemachine für dein Displaymenü denkst: da hängt die Reihenfolge der durchlaufenen States ja davon ab, was der Bediener macht. Das kann u.U. kreuz und quer gehen.

(14.12.2019 11:50)RobertLeRopp schrieb:  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.
Das ist der Grund, weshalb ich für deinen linearen Ablauf immer eine array-gesteuerte Schrittkette gegenüber einer allgemeinen Statemachine bevorzugen würde. Für diesen linearen Fall bist Du da sogar flexibler: Mehr Relais, Einfügen oder Weglassen von Pausen, andere Pins.. Das kannst Du alles nur durch Ändern der Arrayinhalte anpassen, ohne dass eine einzige Zeile (Edit: Anweisungs-)Code geändert werden muss. Und mit welchem Relais es nach einer Pause weitergeht bestimmst Du da auch einfach durch den Array-Inhalt.
Eine allgemeine Statemachine ist dafür m.M.n viel zu umständlich. Aber zum Üben kannst Du das natürlich so machen. Für dein Displaymenü wirst Du definitiv so eine brauchen.

P.S. wenn Du beim Programmieren viele Codesegmente kopieren musst/kannst mit nur marginalen Anpassungen (z.B. nur Pin-Nummern ändern), solltest Du ins Grübeln kommen Wink

Gruß, Franz-Peter
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
14.12.2019, 14:41 (Dieser Beitrag wurde zuletzt bearbeitet: 14.12.2019 14:43 von MicroBahner.)
Beitrag #35
RE: Sich wiederholende Intervalle ohne Delay Verzweiflung
(14.12.2019 13:14)RolandF schrieb:  Deshalb auch der berechtigte Hinweis von MicroBahner ob in diesem Fall ein StateMachine überhaubt nötig ist.
Nun ja, eine Schrittkette ist letztendlich auch eine Statemachine, nur eben eine sehr spezielle, die bereits an die Aufgabenstellung angepasst ist. Und die man deshalb auch entsprechend angepasst programmieren kann Wink
Switch - case ist nicht die einzige Art eine Statemachine zu realisieren ( wenn auch sicher die allgemeinste). Wie Du sagst, es führen immer viele Wege nach Rom ... manche hält kürzer, und manche ein wenig im Kreis herum Big Grin

Gruß, Franz-Peter
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
14.12.2019, 19:44
Beitrag #36
RE: Sich wiederholende Intervalle ohne Delay Verzweiflung
(14.12.2019 14:41)MicroBahner schrieb:  
(14.12.2019 13:14)RolandF schrieb:  Deshalb auch der berechtigte Hinweis von MicroBahner ob in diesem Fall ein StateMachine überhaubt nötig ist.
Nun ja, eine Schrittkette ist letztendlich auch eine Statemachine, nur eben eine sehr spezielle, die bereits an die Aufgabenstellung angepasst ist. Und die man deshalb auch entsprechend angepasst programmieren kann Wink
Switch - case ist nicht die einzige Art eine Statemachine zu realisieren ( wenn auch sicher die allgemeinste). Wie Du sagst, es führen immer viele Wege nach Rom ... manche hält kürzer, und manche ein wenig im Kreis herum Big Grin

So ich sitze nun schon wieder eine weile daran, habe mich nochmal intensiv mit der Lösung über Arrays auseinandergesetzt und bekomme es damit aktuell zumindest leichter zum laufen.

Ich habe natürlich mal wieder einige fragen und habe ein paar Dinge im Code geändert und dir diese markiert, kann es sein das du ganz am ende vergessen hattest den else fall zu benennen, also was else passieren soll. Ich habe dort etwas eingetragen.

Aktuell lässt sich der Sensor nicht auslesen, serieller Monitor sagt 0.
Ich konnte den Fehler noch nicht lokalisieren, hole jetzt aber mal mein Multimeter aus dem Auto.
Was daran auch noch komisch ist, wir sagen ja
Code:
if (sensorValue < 500) {
    istTag = true;
Der Wert beträgt 0, die Pause macht er trotzdem nicht.


Hier der aktuelle Code:
Code:
#include <Arduino.h>

// Schritte der Schrittkette mit der Pinnummern des angezogenen Relais, oder
// 255 wenn kein Relais aktiv ist ( Pausenschritt )
const byte relPin[] = {2, 255, 3, 255, 4, 255, 5, 255}; //<<<<<<<<< Das hier habe ich noch nachträgliche geändert da ich ja zwischen jedem Relai Tag/Nacht überprüfen möchte, richtig ?
const byte schrittZahl = sizeof(relPin); // so einfach möglich, da relPin als byte definiert ist
// Zeitdauer des jeweiligen Schrittes
const int interval[ schrittZahl] = {5, 1, 5, 1, 5, 1, 5, 1}; //<<<<<<<<<<<<<< Hier habe ich den Intervall so gestezt damit immer nacheinader Laufzeit und Pausenzeit kommt, richtig ?
byte schrittNr = schrittZahl - 1;   // Nummer des aktiven Schrittes ans Ende setzen
// beim ersten Start von loop wird dann auf den ersten Schritt (Index 0 )
// umgeschaltet
boolean istTag = true;   //  Merker ob es gerade hell oder dunkel ist

// Variable für die Zeitsteuerung
unsigned long previousMillis = 0;
unsigned long aktIntervall = 0;

const int sensorValue = analogRead(A0); //<<<<<<<<< Das hier habe ich noch nachträgliche eingefügt da ich sonst den Sensorwert nicht hätte ausgeben können, richtig ?

void setup() {
  digitalWrite(8, HIGH);
  Serial.begin(9600 );
  delay (500);
  while (!Serial);
  for (int i = 0; i < schrittZahl; i++) {
    pinMode(relPin[i], OUTPUT);
  }
}

void loop() {
  // vvvvvvvvvvvvvv  zeitgesteuerte Schrittkette  vvvvvvvvvvvvvvv
  if (millis() - previousMillis >= aktIntervall) {
    // Zeitdauer des aktuellen Schrittes ist abgelaufen
    previousMillis = millis();
    // Index des nächsten Schrittes berechnen, bei Überlauf wieder von vorn
    byte neuerSchritt = schrittNr + 1;
    if ( neuerSchritt >= schrittZahl ) neuerSchritt = 0;
    aktIntervall = 1000L * interval[neuerSchritt]; // Zeit für nächsten Schritt setzen

    if ( relPin[schrittNr] < 255  ) {
      //im aktuellen Schritt ist eine Relais an: -> ausschalten
      digitalWrite( relPin[schrittNr], LOW );
      //Serial.print( "Relais "); Serial.print( relPin[schrittNr] ); Serial.println(" AUS");
    }
    if ( relPin[neuerSchritt] < 255 ) {
      // im Folgeschritt soll ein Relais eingeschaltet werden
      digitalWrite( relPin[neuerSchritt], HIGH );
      Serial.print( "Relais "); Serial.print( relPin[neuerSchritt] ); Serial.println(" EIN ");
    } else {
      // im Folgeschritt ist KEIN Relais eingetragen ( Pause )
      // hier kann gegebenenfalls geprüft werden, ob der Schritt übersprungen werden soll
      // ( Tag/Nacht Umschaltung )
      if ( istTag ) {
        // keine Pause
        aktIntervall = 0;
        Serial.print( "Keine Pause "); Serial.print("Sensorwert " ); Serial.println( sensorValue ); //Seriella Ausgabe des Sensorwertes
      } else {
        aktIntervall = 1000L * interval[neuerSchritt]; //<<<<<<<<< Das hier habe ich noch nachträgliche eingefügt, richtig ?!
        Serial.print( "Pause "); Serial.print("Sensorwert " ); Serial.println( sensorValue );  
      }
    }
    schrittNr = neuerSchritt;           // Schrittnummer aktualisieren

  } // ^^^^^^^^^^^^^^^ Ende Schrittkette ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

  // Prüfen ob es hell oder dunkel ist, und das Flag 'istTag' entsprechend setzen
  
  // Für einen sauberen Schaltpunkt in der Dämmerung, den
  // Sensor mit Hystere auswerten:
  if (sensorValue < 500) {
    istTag = true;
  }
  else if (sensorValue > 550) {
    istTag = false;
  }

}
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
14.12.2019, 20:12
Beitrag #37
RE: Sich wiederholende Intervalle ohne Delay Verzweiflung
(14.12.2019 19:44)RobertLeRopp schrieb:  Was daran auch noch komisch ist, wir sagen ja
Code:
if (sensorValue < 500) {
    istTag = true;
Der Wert beträgt 0, die Pause macht er trotzdem nicht.
[/code]
Die soll er am Tag ja auch nicht machen.

Gruß Tommy

"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
14.12.2019, 20:20 (Dieser Beitrag wurde zuletzt bearbeitet: 14.12.2019 20:25 von RobertLeRopp.)
Beitrag #38
RE: Sich wiederholende Intervalle ohne Delay Verzweiflung
(14.12.2019 20:12)Tommy56 schrieb:  
(14.12.2019 19:44)RobertLeRopp schrieb:  Was daran auch noch komisch ist, wir sagen ja
Code:
if (sensorValue < 500) {
    istTag = true;
Der Wert beträgt 0, die Pause macht er trotzdem nicht.
[/code]
Die soll er am Tag ja auch nicht machen.

Gruß Tommy

Danke für den hinweis, das < und > waren tatsächlich vertauscht.

Ich habe gerade herausgefunden das pin8 mir jetzt 1,6V ausgibt, was ist denn da los ?

Gibt es die Möglichkeit, in diesen Code jetzt auch noch ein zu bauen dass er nachts nicht nur eine Pause, sondern generell auch noch einen abweichenden Intervall an Laufzeit hat ?

Und noch etwas, er fängt in meiner Zählung ja immer mit Relai 2 in der Seriellen Ausgabe an da Relai 1 eben Pin 2 ist, kann man das ändern ?
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
14.12.2019, 20:32 (Dieser Beitrag wurde zuletzt bearbeitet: 14.12.2019 20:33 von Tommy56.)
Beitrag #39
RE: Sich wiederholende Intervalle ohne Delay Verzweiflung
So hast Du es aber definiert: <500 = Tag

Es geht (fast) alles. Du musst es nur programmieren. Wenn Du aber aller Momente mit neuen Ideen kommst, kann es auch sein, dass alles neu gemacht werden muss.

Also erst noch mal in Ruhe nachdenken, was sonst noch sein könnte, damit es nicht ein Faß ohne Boden wird.

Gruß Tommy

"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
14.12.2019, 21:42
Beitrag #40
RE: Sich wiederholende Intervalle ohne Delay Verzweiflung
(14.12.2019 19:44)RobertLeRopp schrieb:  Ich habe natürlich mal wieder einige fragen und habe ein paar Dinge im Code geändert und dir diese markiert, kann es sein das du ganz am ende vergessen hattest den else fall zu benennen, also was else passieren soll. Ich habe dort etwas eingetragen.
Hallo Robert,
nein ich hatte da am Ende nichts vergessen, das aktIntervall wird weiter oben gesetzt, da muss man es bei der Pause nicht nochmal setzen, ausser man will es eben mit 0 überschreiben.

Deine Änderungen in den Arrays sind ok, aber das
Code:
const int sensorValue = analogRead(A0); //<<<<<<<<< Das hier habe ich noch nachträgliche eingefügt da ich sonst den Sensorwert nicht hätte ausgeben können, richtig ?
funktioniert nicht. Damit dein Ausdrucken des sensorValue funktioniert, muss Du die Variable global definieren:
Code:
int sensorValue; //<<<<<<<<< Das hier habe ich noch nachträgliche eingefügt da ich sonst den Sensorwert nicht hätte ausgeben können, richtig ?
aber Einlesen mit analogRead musst Du sie weiterhin im loop:
Code:
sensorValue = analogRead(A0);

Ich weis ja nicht, wie dein Sensor angeschlossen ist, aber um Tag/Nacht zu vertauschen, musst Du nur das Setzen des Flags entsprechen ändern.
Wenn also in der Nacht die Spannung am Eingang niedrig ist:
Code:
if (sensorValue < 500) {
    istTag = false;
  }
  else if (sensorValue > 550) {
    istTag =true;
  }

(14.12.2019 20:20)RobertLeRopp schrieb:  Ich habe gerade herausgefunden das pin8 mir jetzt 1,6V ausgibt, was ist denn da los
Was ist dein Pin 8? Du machst da ein digitalWrite, ohne ihn vorher als OUTPUT zu setzen. Da schaltest Du nur den PullUp Widerstand ein.

(14.12.2019 20:20)RobertLeRopp schrieb:  Gibt es die Möglichkeit, in diesen Code jetzt auch noch ein zu bauen dass er nachts nicht nur eine Pause, sondern generell auch noch einen abweichenden Intervall an Laufzeit hat ?
Du kannst ein 2. Array mit den Zeiten für die Nacht anlegen, und liest dann - je nachdem wie dein Flag 'istTag' steht - die Zeiten aus dem einen oder dem anderen Array. Dann kannst Du dort auch am Tag für die Pausenzeiten gleich '0' eintragen, und brauchst das garnicht mehr extra abzufragen.

(14.12.2019 20:20)RobertLeRopp schrieb:  Und noch etwas, er fängt in meiner Zählung ja immer mit Relai 2 in der Seriellen Ausgabe an da Relai 1 eben Pin 2 ist, kann man das ändern ?
Die serielle Ausgabe gibt ja auch die Pinnummer aus. Sonst muss Du direkt den Arrayindex ausgeben. Da zählt er aber die Pausen mit, gegebenenfalls musst Du also noch durch 2 teilen.

Gruß, Franz-Peter
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
Antwort schreiben 


Möglicherweise verwandte Themen...
Thema: Verfasser Antworten: Ansichten: Letzter Beitrag
  for-schleife, delay, millis, interrupt Harry 3 65 Heute 16:57
Letzter Beitrag: Tommy56
  Denkanstoß gesucht - in Schrittkette delay() ersetzen SpaghettiCode 18 317 Heute 15:58
Letzter Beitrag: Tommy56
  delay-millis()-while-Sensorenabfrage RCudino 21 707 Gestern 20:23
Letzter Beitrag: Fips
  Menu funktioniert ohne Serial.println nicht GSA1150 7 121 Gestern 18:26
Letzter Beitrag: Tommy56
  Stepper Motor mit zwei Taster bedienen / Fehler ohne Fehlermeldung Milano 6 237 21.03.2020 16:06
Letzter Beitrag: MicroBahner
  Arduino IDE 1.8.11 , lassen sich keine Sketch.zip hinzufügen Christian_Moba-Arduino 4 479 23.02.2020 13:18
Letzter Beitrag: Christian_Moba-Arduino
  Scrollpausen im Oled Display ohne Delay Alter Fritz 7 430 25.01.2020 13:22
Letzter Beitrag: Alter Fritz
  Millis anstatt delay ThorstenP 25 1.995 29.11.2019 16:34
Letzter Beitrag: Tommy56
  Programm hängt sich auf Jonas Meier 3 473 13.11.2019 11:12
Letzter Beitrag: MicroBahner
  Schleife nur 1x durchlaufen ohne for... Hanibal_Smith 3 674 01.10.2019 19:44
Letzter Beitrag: Tommy56

Gehe zu:


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