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: