dauernder Rundlauf durch Taster jederzeit unterbrechen (neuling)

Hallo zusammen,

ich bin neu hier und programmiere gerade meinen ersten Arduino Uno. (das erste mal seit 10 Jahren das ich irgendwas programmiere :wink: )
es funktioniert ganz gut aber ich habe ein kleine Schwierigkeit!

  • Ich möchte einen Spühlvorgang alle 6 Stunden durchführen ... mit ewiger Widerholung

  • Der Spühlvorgang soll durch einen Taster/Schalter JEDERZEIT unterbrochen werden können um Wasser manuell auszulassen.

Mit meinen Programmierkentnissen schaffe ich es zurzeit nur, dass ich nur alle 6 Stunden, genau zur richtigen Zeit den Taster betätigen müsste :wink:
Ich möchte ihn aber immer betätigen können und die Wartezeit soll dann sofort oder innert 30sec unterbrochen werden und das Wasser soll für eine bestimmte Zeit manuell ausfliessen - Die 6h Schlaufe darf danach gerne wider bei 0 anfangen.

Hier ist mein Programm:

Achtung: ich habe für die Testdurchläufe die Zeiten von Stunden auf Sekunden reduziert! :wink:

{
                // manuelles Wasserbeziehen

        if    (digitalRead(druckSchalter) == HIGH){
               digitalWrite(Magnetventil, HIGH);
               delay(5000);                                     //  1`wasser abzapfen
               digitalWrite(Magnetventil, LOW);
               }
        else {

                  // Spühlroutine - alle 6 Stunden - start mit 1min Spühlen

                  delay(15000);                               // 6h warten
                  digitalWrite(Magnetventil, HIGH);
                  delay(10000);                               // 6` spühlen
                  digitalWrite(Magnetventil, LOW);

                  delay(12000);                               // für testzwecke (für Schalterbetätigung)
             }
}

Ich hoffe jemand von euch weiss, wie ich so einen loop erstellen kann (ich hoffe, das ist technisch möglich!!)

Danke & schönen Abend

Mit delay wird das nichts, da macht dein Controller Pause, also nichts außer warten.

Sieh dir mal in den Beispielen "BlinkWithoutDelay" an, das wird dir weiter helfen.

Hallo,

willkommen im Forum.

Mit delay geht das nicht. Da macht der Programablauf eine Pause und macht nix mehr außer warten bis die Zeit abgelaufen ist. Damit bekommst du also nicht mit wenn der Taster gedrückt wird.

Schau dir das Beipiel blink without delay an , das arbeitet mit millis(). Dazu gibt es hier noch eine hübsche Beschreibung zum Nachtwächter. Wenn Du das verstanden hast ist das ganz einfach mit millis() Zeiten zu realisieren.
Achtung Millis immer in Verbindung mit unsigned long Variablen verwenden.

PS: Dieter war schneller

Heinz

Und zur weiteren Erklärung:
Die Loop kannst du nicht unterbrechen, die läuft immer durch.
Du kannst nur bedingt durch deine gewünschten Zeiten in entsprechende Funktionen springen, die nach Ablauf wieder in der Loop laufen.

Damit das alles problemlos funktioniert musst du es nicht blockierend, also ohne delay aufbauen.

Danke für die Antworten!
Ich habe mich eingelesen und das Programm gleich mal umgeschrieben und werde es Morgen testen!
Danke

unsigned long MagV_timestore;
unsigned long Schalter_timestore;
const int druckSchalter = 6;     
const int Magnetventil  = 13;  
int MagState = LOW;


void setup() {
                       

pinMode(Magnetventil, OUTPUT);
pinMode (druckSchalter, INPUT); 

} 


void loop() 
{



if (MagState == LOW) {
    if (millis() - MagV_timestore> 10000 ) {              // Zeit für lange Schlaufeum?
      digitalWrite(MagState, HIGH);
      MagV_timestore = millis();
      MagState = HIGH;
    }
  } else {
    if (millis() - MagV_timestore> 3000) {                   // Spühlzeit
      digitalWrite(MagState, LOW);
      MagState = LOW;
    }
  }
  
if (MagState == LOW){
               if (digitalRead(druckSchalter) == HIGH){
                   digitalWrite(MagState, HIGH);
                   Schalter_timestore = millis();
                   digitalWrite(MagState, HIGH);
                   }
  
             } else {
               if (millis() -  Schalter_timestore > 20000){        // manueller Wasserausguss 
                   digitalWrite(MagState, LOW);     
                   }
             }
}

Guten Abend zusammen,

erkennt jemand, was ich Falsch mache?

Beim ersten if wird der Pin13 nach 10sec auf HIGH gesetzt, das funktioniert.
Aber das anschliessende else - wechseln auf LOW nach 3sec macht er leider nicht. Ich habe es auch einfach mal mit einem 2. If probiert, darum ist das else " //* " (ausgenommen)
Auch die Funktion für den Schalter will noch nicht so wirklich...

ich hoffe jemand von euch kann mir helfen... :slight_smile:

Grüsse

unsigned long MagV_timestore;
unsigned long Schalter_timestore;
const int druckSchalter = 6;       
const int Magnetventil  = 13;  
int MagState = LOW;


void setup() {
                       
                    
pinMode(Magnetventil, OUTPUT);
pinMode (druckSchalter, INPUT);   

}

void loop() 

{

if (MagState == LOW) {
     if (millis() - MagV_timestore> 10000 ) { 
        digitalWrite(MagState, HIGH);
        MagV_timestore = millis();
        digitalWrite(Magnetventil, HIGH);
    }
  } 


//* Variant 1

else {
       if (millis() - MagV_timestore> 3000) {     // spühlzeit 1^min um ?
           digitalWrite(Magnetventil, LOW);
        //   digitalWrite(MagState, LOW);
    }
  }
*//

// Variante 2

if (MagState == HIGH) {
     if (millis() - MagV_timestore> 3000) {    
         digitalWrite(Magnetventil, LOW);
         digitalWrite(MagState, LOW);
    }
  }



// Zusatz für Schalter

if (MagState == LOW){
               if (digitalRead(druckSchalter) == HIGH){
                   digitalWrite(MagState, HIGH);
                   Schalter_timestore = millis();
                   digitalWrite(Magnetventil, HIGH);
                   }
  
             } else {
               if (millis() -  Schalter_timestore > 20000){   // manueller Wasserausguss 
                   digitalWrite(Magnetventil, LOW); 
                   digitalWrite(MagState, LOW);    
                   }
             }
}

und was mache ich, wenn der im Arduino integrierte Zähler seinen Maximalwert erreicht hat und wider von Null beginnt. Hängt sich dann das ganze Programm auf?

Weiss jemand wann das ist. Wenn ich das weiss kann ich eine funktion einbauen, dass die "timestores" in dem Moment auch Reseted/auf null gesetzt werden...

Danke

oiresar:
und was mache ich, wenn der im Arduino integrierte Zähler seinen Maximalwert erreicht hat und wider von Null beginnt. Hängt sich dann das ganze Programm auf?

Nein, das kann man berücksichtigen durch jetzt - vorhin >= pausenzeit

oiresar:
Weiss jemand wann das ist.

Ja, nach 2^32 = 4294967296 Millisekunden.

Gib diesem Programm mal eine Chance:

const byte druckSchalter = 6;
const byte Magnetventil  = 13;
const unsigned long spuehlzeit = 3000, pausenzeit = 10000;
unsigned long jetzt, vorhin;
bool MagState = false;

void setup() {
  pinMode(Magnetventil, OUTPUT);         // aktiv HIGH
  pinMode (druckSchalter, INPUT_PULLUP); // gedrückt=LOW
}

void loop() {
  jetzt = millis();
  if (!MagState) {
    if (jetzt - vorhin >= pausenzeit) {
      vorhin = jetzt;
      MagState = true;
      digitalWrite(Magnetventil, HIGH);
    }
  } else {
    if ((jetzt - vorhin >= spuehlzeit) || !digitalRead(druckSchalter)) {
      vorhin = jetzt;
      MagState = false;
      digitalWrite(Magnetventil, LOW);
    }
  }
}

Hi

Damit verstellst Du aber den 6-Stunden-Rhythmus (hier wartezeit aka 10 Sekunden).
Hatte den Eingangs-Post so verstanden, daß zu festen Zeiten gespült werden soll.
Mit Deinem Sketch würde bei Tastendruck oder pausenzeit nach der letzten Spülung die Nächste ausgelöst.
Bei festen Zeiten (wobei der Arduino Dir 'weglaufen' wird - dann ist eine RTC aka DS3231 einen Blick wert) kann Es Dir passieren, daß kurz nach der Taster-Spülung die Zeit-Spülung aktiviert wird.
Die 'spätestens nach der wartezeit'-Variante hätte den Vorteil, daß man den Kram anstöpselt und 'bei Zeit' den Taster zum 1.ten Mal betätigt - und die nächsten Tage wird recht zuverlässig alle 6 Stunden (wartezeit+spülzeit) gespült.

MfG

postmaster-ino:
Damit verstellst Du aber den 6-Stunden-Rhythmus (hier wartezeit aka 10 Sekunden).

Richtig.

postmaster-ino:
Hatte den Eingangs-Post so verstanden, daß zu festen Zeiten gespült werden soll.

Dann ist aber ein Resonator zu ungenau, weshalb sich eine RTC wie DS3231 aufdrängt. Ein anderer Ansatz, von Dir schon skizziert.

Mein Bestreben ist, dem TO Luft für eigene Kreativität zu lassen, weshalb mein Programm nur eine Anregung darstellt, keine perfekte Lösung. Diesem TO würde ich was zutrauen :slight_smile:

Hallo zusammen,

Vielen Dank für alle Tipps und Infos von euch.
Ich habe bis Heute eine grössere Pause eingelegt und mir ein Breadboard zum tüfteln zugelegt - so dass ich nich immer die ganzen Schaltungen umlöten muss :wink:

@agume: Danke für das gute Programm, ich musste nur noch den or-Befehl in vom else-Abschnitt in den if-Abschnitt hochnehmen und seit da funktioniert es einwandfrei! :-))

@postmaster-ino: Danke für die Idee mit dem "RTC aka DS3231". Die Spielzeiten sind sind mir zurzeit noch egal, nur der Rhythmus von 6h sollte stimmen. Somit kann das RTC... noch warten.

Danke & MfG

Danke für die Rückmeldung :slight_smile: