Zeitschaltuhr mit manuellem Ein/Aus Schalter

Guten Abend,

wie so viele bin ich am Anfang meiner Arduino Karriere.

Ich versuche zur Zeit eine Zeitschaltuhr mittels Arduino UNO zu realisieren. Hat bis her recht gut funktioniert, aber stecke gerade in einer Sackgasse:

Möchte zusätzlich zur Zeitschaltfunktion das Relais zu jedem Zeitpunkt per Schalter ein- und ausschalten können.

Wenn ich das so wie im beigefügtem Skach mache kann ich zwar mit dem Schalter das Relais ein und ausschalten, sobald aber der Timer aktiv ist, flackert das LED des Relais, vermutlich das Relais auch da es aber zu träge ist merkt man das nicht.

Vielen Dank schon mal für eure Hilfestellung.

0.ino (11.3 KB)

VBen:
Ich versuche zur Zeit eine Zeitschaltuhr mittels Arduino UNO zu realisieren. Hat bis her recht gut funktioniert,

Wenn ich das so wie im beigefügtem Skach mache kann ich zwar mit dem Schalter das Relais ein und ausschalten, sobald aber der Timer aktiv ist, flackert das LED des Relais,

Ich weiss noch nicht, wo ich eigentlich sinnvoll anfangen kann ohne Dir auf die Füsse zu treten.

Der Code ist - sorry für die Worte, eigentlich Mist.
Du verbrauchst 11KB Codezeilen für nen Zeitschalter und nen Taster/Schalter - also einen Input-PIN.
Da hab ich wirklich gehofft, das da in jeder Zeile ein Kommentar steht.
Ist nicht.
Ok.

Deine ganze if if if if nochein if if if if irgendwas Geschichte macht da ein Konstrukt draus, was erstmal verstanden werden muss. Das geht eindeutig besser.

Ich versuch mich da durchzudröseln, dauert aber 'nen Moment.

Dein Problem ist aber das Du nicht gegeneinander verriegelst.

Erkläre mit ja/nein::

  • Schalter ist ein Schalter und kein Taster
  • Wenn Schalter eingeschaltet soll Timer ohne Funktion sein?
  • Timer soll nur dann in Funktion sein, wenn Schalter off/aus
  • Wenn Schalter aus/off geht, soll ein vorher gesetzter Timer ebenfalls gelöscht werden

Leider kann ich deinen Sketch am Tablett nicht anschauen, wenn er als Anlage anstatt in Code Tags gepostet ist.

Tippe aber darauf, dass du den Ausgang schreibst, einmal mit dem Resultat der Uhr und dann nochmal mit Schalter du musst das mit && ver“and“en

ElEspanol:
Leider kann ich deinen Sketch am Tablett nicht anschauen, wenn er als Anlage anstatt in Code Tags gepostet ist.

Als .txt sollte es gehen.
Ich bin sonst nicht so, aber hier denke ich macht es Sinn.
Der TO hat noch viel mehr Probleme, als seine Verknüpfung

Spätestens hier: (Originalcode!)

  stop = EEPROM.read (50);
  if (stop == 0)
  {
  }
  else
  {
    mode = 1;
    WriteEeprom ();
    delay (20);
    mode = 2;
    WriteEeprom ();
    delay (20);
    mode = 3;
    WriteEeprom ();
    delay (20);
    mode = 4;
    WriteEeprom ();
    delay (20);
    mode = 0;
  }
  EEPROM.write (50, 0);

:wink:

0_sample_.txt (12.8 KB)

VBen:
wie so viele bin ich am Anfang meiner Arduino Karriere.

Vielen Dank schon mal für eure Hilfestellung.

Na dann will ich mal anfangen an einer Stelle, die ich noch auf einem kleine Dsplay beharken konnte, nur um Dir zu zeigen, wie es gehen kann - Dir wirklich Hilfe angeboten wird und Du nicht frustriert hier wieder weg bist.....

Dein Code aus void setTimer an der Stelle:

  if (setMode == 0 && setAlarm > 0 && mode == 0)
  {
    lcd.setCursor (0, 0);

ein wenig verändert zu:
if (setMode == 0 && setAlarm > 0 && mode == 0)
{sub_lcd()}

Gut.
Ist nicht alles, da gehört natürlich noch die Funktion zu :wink:
Da wird ein Kurztext draus:

void sub_lcd();
{
 lcd.setCursor (0, 0);
  lcd.print (" T1  T2  T3  T4 ");
  lcd.setCursor (0, 1);
  if (timer1 || timer2 || timer3 || timer 4)
  {
    lcd.print ("  A");
  }
  else
  {
    lcd.print ("  D");
  }
}

Wenn ich das überfliege, wird Dein Code entschieden kürzer.
Willst?

my_xy_projekt:
Ich weiss noch nicht, wo ich eigentlich sinnvoll anfangen kann ohne Dir auf die Füsse zu treten.

Der Code ist - sorry für die Worte, eigentlich Mist.
Du verbrauchst 11KB Codezeilen für nen Zeitschalter und nen Taster/Schalter - also einen Input-PIN.
Da hab ich wirklich gehofft, das da in jeder Zeile ein Kommentar steht.
Ist nicht.
Ok.

Deine ganze if if if if nochein if if if if irgendwas Geschichte macht da ein Konstrukt draus, was erstmal verstanden werden muss. Das geht eindeutig besser.

Ich versuch mich da durchzudröseln, dauert aber 'nen Moment.

Dein Problem ist aber das Du nicht gegeneinander verriegelst.

Erkläre mit ja/nein::

  • Schalter ist ein Schalter und kein Taster : es ist ein Schalter
  • Wenn Schalter eingeschaltet soll Timer ohne Funktion sein? : ja
  • Timer soll nur dann in Funktion sein, wenn Schalter off/aus: ja
  • Wenn Schalter aus/off geht, soll ein vorher gesetzter Timer ebenfalls gelöscht werden: nein
    Unabhängig von der Schalterbetätigung soll der gesetzte Timer erhalten bleiben

Guten Morgen,
vielen Dank für deine Antwort...wie erwähnt es sind meine ersten Gehversuche. Möchte mich auch nicht mit fremden Federn schmücken. Den Basis-Skach habe ich aus dem Netz geholt und nach bestem Wissen und Gewissen auf meine Bedürfnisse angepasst...bis hier her.
Deine Fragen habe ich in deinem Text beantwortet.
Ich möchte mit dieser Zeitschaltuhr meine Gartenpumpe täglich zu einer bestimmten Zeit automatisch ein und ausschalten. Dennoch möchte ich die Möglichkeit mit dem Schalter die Pumpe manuell ein und auszuschalten, ohne dass der Timer beeinflusst bzw. gelöscht wird.
Des weiteren möchte ich an meine Steuerung einen Regensensor anschließen der den Timer unterbricht falls es regnet.
Der Regensensor ist ein eigenständiges Modul, so dass es bei Regen ein Relais schaltet d. h. wie ein Schalter funktioniert, also wenn es regnet Schalter geschlossen, wenn es aufgehört hat Schalter offen.
Der Regensensor ist so programmiert, dass er schaltet wenn eine bestimmte Regenmenge gefallen ist.

my_xy_projekt:
Na dann will ich mal anfangen an einer Stelle, die ich noch auf einem kleine Dsplay beharken konnte, nur um Dir zu zeigen, wie es gehen kann - Dir wirklich Hilfe angeboten wird und Du nicht frustriert hier wieder weg bist.....

Dein Code aus void setTimer an der Stelle:

  if (setMode == 0 && setAlarm > 0 && mode == 0)

{
   lcd.setCursor (0, 0);




ein wenig verändert zu:
if (setMode == 0 && setAlarm > 0 && mode == 0)
{sub_lcd()}

Gut.
Ist nicht alles, da gehört natürlich noch die Funktion zu ;)
Da wird ein Kurztext draus:


void sub_lcd();
{
lcd.setCursor (0, 0);
 lcd.print (" T1  T2  T3  T4 ");
 lcd.setCursor (0, 1);
 if (timer1 || timer2 || timer3 || timer 4)
 {
   lcd.print ("  A");
 }
 else
 {
   lcd.print ("  D");
 }
}




Wenn ich das überfliege, wird Dein Code entschieden kürzer.
Willst?

:slight_smile: :slight_smile: sehr gerne ja

VBen:
:slight_smile: :slight_smile: sehr gerne ja

Dann mal alles ab Anfang:
Als erstes die #defines der PINs weg und const draus gemacht.
Zusäzlich brauche ich noch eine Variable. Sieht dann so aus:

// Tasten
const byte bt_clock = A1;
const byte bt_up = A2;
const byte bt_down = A3;
const byte bt_timer = 1;
const byte bt_pumpe = 3;

// OutputPin
const byte relay = 5;
const byte LED1 = 10;
const byte LED2 = 11;

// Schaltermerker
bool manual_ein = false;

Dann ersetze den Code zwischen blinking(); und delay(100); am Ende durch folgendes:

  if (alarmMode == 1)
  {
    // Wenn bt_pumpe nach LOW gezogen, wird manual_ein true
    if (!digitalRead (bt_pumpe))
    {
      manual_ein = true;
    }
    // ON
    if ((timer1 == 1 && hh == Start1HH && mm == Start1MM)
        || (timer2 == 1 && hh == Start2HH && mm == Start2MM)
        || (timer3 == 1 && hh == Start3HH && mm == Start3MM)
        || (timer4 == 1 && hh == Start4HH && mm == Start4MM)
        || (!digitalRead (bt_pumpe))
       )
    {
      digitalWrite (relay, LOW);
      digitalWrite (LED1, HIGH);
    }
    // OFF
    else
      if ((timer1 == 1 && hh == Finish1HH && mm == Finish1MM)
          || (timer2 == 1 && hh == Finish2HH && mm == Finish2MM)
          || (timer3 == 1 && hh == Finish3HH && mm == Finish3MM)
          || (timer3 == 1 && hh == Finish4HH && mm == Finish4MM)
          // nur wenn bt_pumpe HIGH *UND* manual_ein true
          || (digitalRead (bt_pumpe) && manual_ein)
         )
      {
        digitalWrite (relay, HIGH);
        digitalWrite (LED1, LOW);
        // Wenn bt_pumpe nach HIGH gezogen, wird manual_ein false
        if (digitalRead (bt_pumpe))
        {
          manual_ein = false;
        }
      }
  }

Hintergrund ist, das in jeder Deiner if's der alarmmode==1 sein muss.
Also wird das als Ausgangspunkt genommen und dann auf die Timer geprüft.
Jeweils getrennt auf on / off.

Versuche, ob es das ist, was Du suchst.
Wenn ja: machen wir weiter; Bekommst dann einen Codeschnipsel zugereicht, aus dem Du weiter entwickeln kannst.

Wenn nein: dann sag, was anders sein soll.
Hinweis: Ich formatiere anders. Wenn Dir das nicht gefällt, mache ein STRG-T in der Arduino-SW.

Einfach nur genial.... :smiley: :smiley: :smiley: :smiley: es hat auf anhieb geklappt.

Es macht Spaß mit Profis zu arbeiten.

Jetzt fehlt nur noch der Regensensor. Es ist dieser Sensor: https://rainsensors.com/

Den Sensor kann man so programmieren, dass wenn eine bestimmte Menge Regen gefallen ist, schaltet es ein Relais (Öffner oder Schließer).
Im Prinzip wie der manuelle Schalter. Wenn es betätigt ist, soll der Timer deaktivier sein damit die Pumpe bei Regen nicht anläuft.

VBen:
Einfach nur genial… :smiley: :smiley: :smiley: :smiley: es hat auf anhieb geklappt.

Im Prinzip wie der manuelle Schalter. Wenn es betätigt ist, soll der Timer deaktivier sein damit die Pumpe bei Regen nicht anläuft.

Der Sensor ist nicht so problematisch. Ist eigentlich nur ne zusätzliche Zeile.
Bevor den bekommst, gibt es zwei Codeschnipsel, mit denen Du Dich beschäftigen sollst.

Der erste Teil ist als Ersatz für void blinking() gedacht. Der ist übersichtlich und soll Dir nur mal zeigen, wie dieses if if && && if if && && && if if aufgelöst werden kann.

void blinking ()
{
  //BLINKING SCREEN
  //Set Clock
  // *INDENT-OFF*  // das sorgt dafür, das die Formatierung nicht mehr verändert wird
  if (setAlarm < 2) {
  switch (setMode)  {
  case 1: {lcd.setCursor (0, 0); break;}
  case 2: {lcd.setCursor (3, 0); break;}
  case 3: {lcd.setCursor (6, 0); break;}
  case 4: {lcd.setCursor (1, 1); lcd.print("  ");break;}
  case 5: {lcd.setCursor (5, 1); break;}
  case 6: {lcd.setCursor (8, 1); break;}
  case 7: {lcd.setCursor (11, 1);lcd.print("  ");break;}
  default:{break;}}
  lcd.print ("  ");}
  //Set Timer
  if (setMode == 0) { 
    if (mode == 0)  { 
    switch (setAlarm) { 
      case 1: {lcd.setCursor (2, 1);break;}
      case 2: {lcd.setCursor (6, 1);break;}
      case 3: {lcd.setCursor (10, 1);break;}
      case 4: {lcd.setCursor (13, 1);break;}
      default: {break;}}
      lcd.print("  ");}
    else if (mode > 0) {
      switch (setAlarm) {
      case 1: {lcd.setCursor (11, 0);break;}
      case 2: {lcd.setCursor (14, 0);break;}
      case 3: {lcd.setCursor (11, 1);break;}
      case 4: {lcd.setCursor (14, 1);break;}
      default:{break;}}
      lcd.print ("  ");}}
  // *INDENT-ON*  // die Formatierung via STRG-T wieder eingeschaltet
}

Das sollte eigentlich funktionieren.

Interessant wird es, wenn Du das für Deine Tasten auf/ab umsetzt.

In Deinem Code in void setupClock(void) beginnend mit
if(digitalRead (bt_up) == 0){
ersetze das gesamte Konstrukt mal durch folgendes:

  if (!digitalRead (bt_up)) {
// *INDENT-OFF*
    if (setAlarm < 2) {
      switch (setMode){
      case 1:{hh++;if (hh > 23)hh = 0;break;}
      case 2:{mm++;if (mm > 59)mm = 0;break;}
      case 3:{ss++;if (ss > 59)ss = 0;break;}
      case 4:{set_day++;if (set_day > 7)set_day = 0;break;}
      case 5:{dd++;if (dd > 31)dd = 0;break;}
      case 6:{bb++;if (bb > 12)bb = 0;break;}
      case 7:{yy++;if (yy > 2030)yy = 2000;break;}
      default:break;}}
    //Timer
    if (setMode == 0) {
      if (mode == 0 {
        switch (setAlarm){
        case 1:{timer1 = 1;break;}
        case 2:{timer2 = 1;break;}
        case 3:{timer3 = 1;break;}
        case 4:{timer4 = 1;break;}
        default:break;}}
      else if (mode > 0) {
        switch (setAlarm){
        case 1:{StartHH++;if (StartHH > 23)StartHH = 0;break;}
        case 2:{StartMM++;if (StartMM > 59)StartMM = 0;break;}
        case 3:{FinishHH++;if (FinishHH > 23)FinishHH = 0;break;}
        case 4:{FinishMM++;if (FinishMM > 59)FinishMM = 0;break;}
        default:break;}}}
    rtc.setDOW (set_day);
// *INDENT-ON*    
  }

Es wird also nicht Zeile für Zeile mit Bedingungen und Vergleichen geprüft, sondern von oben nach nur weiter gemacht, solange der vorherige Teil erfüllt ist.

Da fällt dann auch auf, das Du Dich das erste Mal schon auf Abwegen befindest.
dd könnte im Februar oder auch November 31 werden.
Das müsstest abfangen.

Wenn das mit dem Taster so funktioniert, dann bau das für if (digitalRead (bt_down) == 0) nach.
Wenn das hast, zeigs und dann gibts die Zeile für den Sensor :wink:

my_xy_projekt:
Der Sensor ist nicht so problematisch. Ist eigentlich nur ne zusätzliche Zeile.
Bevor den bekommst, gibt es zwei Codeschnipsel, mit denen Du Dich beschäftigen sollst.

Der erste Teil ist als Ersatz für void blinking() gedacht. Der ist übersichtlich und soll Dir nur mal zeigen, wie dieses if if && && if if && && && if if aufgelöst werden kann.

void blinking ()

{
 //BLINKING SCREEN
 //Set Clock
 // INDENT-OFF  // das sorgt dafür, das die Formatierung nicht mehr verändert wird
 if (setAlarm < 2) {
 switch (setMode)  {
 case 1: {lcd.setCursor (0, 0); break;}
 case 2: {lcd.setCursor (3, 0); break;}
 case 3: {lcd.setCursor (6, 0); break;}
 case 4: {lcd.setCursor (1, 1); lcd.print("  “);break;}
 case 5: {lcd.setCursor (5, 1); break;}
 case 6: {lcd.setCursor (8, 1); break;}
 case 7: {lcd.setCursor (11, 1);lcd.print(”  “);break;}
 default:{break;}}
 lcd.print (”  “);}
 //Set Timer
 if (setMode == 0) {
   if (mode == 0)  {
   switch (setAlarm) {
     case 1: {lcd.setCursor (2, 1);break;}
     case 2: {lcd.setCursor (6, 1);break;}
     case 3: {lcd.setCursor (10, 1);break;}
     case 4: {lcd.setCursor (13, 1);break;}
     default: {break;}}
     lcd.print(”  “);}
   else if (mode > 0) {
     switch (setAlarm) {
     case 1: {lcd.setCursor (11, 0);break;}
     case 2: {lcd.setCursor (14, 0);break;}
     case 3: {lcd.setCursor (11, 1);break;}
     case 4: {lcd.setCursor (14, 1);break;}
     default:{break;}}
     lcd.print (”  ");}}
 // INDENT-ON  // die Formatierung via STRG-T wieder eingeschaltet
}



Das sollte eigentlich funktionieren.

Interessant wird es, wenn Du das für Deine Tasten auf/ab umsetzt.

In Deinem Code in `void setupClock(void)` beginnend mit 
if(digitalRead (bt_up) == 0){
ersetze das gesamte Konstrukt mal durch folgendes:



if (!digitalRead (bt_up)) {
// INDENT-OFF
   if (setAlarm < 2) {
     switch (setMode){
     case 1:{hh++;if (hh > 23)hh = 0;break;}
     case 2:{mm++;if (mm > 59)mm = 0;break;}
     case 3:{ss++;if (ss > 59)ss = 0;break;}
     case 4:{set_day++;if (set_day > 7)set_day = 0;break;}
     case 5:{dd++;if (dd > 31)dd = 0;break;}
     case 6:{bb++;if (bb > 12)bb = 0;break;}
     case 7:{yy++;if (yy > 2030)yy = 2000;break;}
     default:break;}}
   //Timer
   if (setMode == 0) {
     if (mode == 0 {
       switch (setAlarm){
       case 1:{timer1 = 1;break;}
       case 2:{timer2 = 1;break;}
       case 3:{timer3 = 1;break;}
       case 4:{timer4 = 1;break;}
       default:break;}}
     else if (mode > 0) {
       switch (setAlarm){
       case 1:{StartHH++;if (StartHH > 23)StartHH = 0;break;}
       case 2:{StartMM++;if (StartMM > 59)StartMM = 0;break;}
       case 3:{FinishHH++;if (FinishHH > 23)FinishHH = 0;break;}
       case 4:{FinishMM++;if (FinishMM > 59)FinishMM = 0;break;}
       default:break;}}}
   rtc.setDOW (set_day);
// INDENT-ON    
 }




Es wird also nicht Zeile für Zeile mit Bedingungen und Vergleichen geprüft, sondern von oben nach nur weiter gemacht, solange der vorherige Teil erfüllt ist.

Da fällt dann auch auf, das Du Dich das erste Mal schon auf Abwegen befindest.
dd könnte im Februar oder auch November 31 werden.
Das müsstest abfangen.

Wenn das mit dem Taster so funktioniert, dann bau das für `if (digitalRead (bt_down) == 0)` nach.
Wenn das hast, zeigs und dann gibts die Zeile für den Sensor ;)

… also das was Du vorbereitet hast funktioniert einwandfrei.
Ich habe versucht den *if (!digitalRead (bt_down) *nachzubauen leider ohne erfolg. Eine Fehlermeldung wird komischerweise nicht ausgegeben aber es funktioniert nicht :sob: :sob: :sob:.

Es sieht so aus:
if (!digitalRead (bt_down)) {
// INDENT-OFF
if (setAlarm < 2) {
switch (setMode){
case 1:{hh–;if (hh < 0)hh = 23;break;}
case 2:{mm–;if (mm < 0)mm = 59;break;}
case 3:{ss–;if (ss < 0)ss = 59;break;}
case 4:{set_day–;if (set_day < 0)set_day = 7;break;}
case 5:{dd–;if (dd < 0)dd = 31;break;}
case 6:{bb–;if (bb < 0)bb = 12;break;}
case 7:{yy–;if (yy < 0)yy = 2030;break;}
default:break;}}
//Timer
if (setMode == 0) {
if (mode == 0) {
switch (setAlarm){
case 1:{timer1 = 0;break;}
case 2:{timer2 = 0;break;}
case 3:{timer3 = 0;break;}
case 4:{timer4 = 0;break;}
default:break;}}
else if (mode < 0) {
switch (setAlarm){
case 1:{StartHH–;if (StartHH < 0)StartHH = 23;break;}
case 2:{StartMM–;if (StartMM < 0)StartMM = 59;break;}
case 3:{FinishHH–;if (FinishHH < 0)FinishHH = 23;break;}
case 4:{FinishMM–;if (FinishMM < 0)FinishMM = 59;break;}
default:break;}}}
rtc.setDOW (set_day);
// INDENT-ON
}

VBen:
… also das was Du vorbereitet hast funktioniert einwandfrei.
Ich habe versucht den *if (!digitalRead (bt_down) * nachzubauen leider ohne erfolg. Eine Fehlermeldung wird komischerweise nicht ausgegeben

Es sieht so aus:

Ok, zwei Dinge:
Bitte unter Datei - Voreinstellungen, Haken bei:

  • Ausführliche Ausgabe bei Kompilierung
    UND
    Warnungen [alle]
    einstellen.
    Sieh, was Dir der Compiler ausgibt.
    Notfalls stells hier rein - in codetags - dann findet sich evtl. was dazu…
    Ich hab das schon gesehen - ohne Kompiler :wink:

Und:
Dann bitte Deinen Code in Codetags: Unter Deinem Post auf modify Message unten rechts und dann den Code markieren und oben im Editorfenster auf das “</>” Symbol klicken, dann stehen die Tags davor und dahinter.

[edit]
vermutlich wird der Kompiler nichts auswerfen.
[edit]
Mal als Hinweis:

  1. Du willst nicht wirklich bis 0 runterzählen
    if (yy < 0)yy = 2030;
  2. Das wirst Du nie erreichen:
    else if (mode < 0)
    Und da hatte ich eigentlich die Warnung erwartet, aber Du hast ja int und nicht unsigned int deklariert - da gehts dann also auch für den Kompiler ohne weiteres.

Vielen Dank für Deine Tips.

Das Runterzählen nur bei der Timereinstellung funktioniert gar nicht.

:slight_smile: :slight_smile: :slight_smile:

so funktioniert es:

if (!digitalRead (bt_down)) {
// *INDENT-OFF*
    if (setAlarm < 2) {
      switch (setMode){
      case 1:{hh--;if (hh < 0)hh = 23;break;}
      case 2:{mm--;if (mm < 0)mm = 59;break;}
      case 3:{ss--;if (ss < 0)ss = 59;break;}
      case 4:{set_day--;if (set_day < 0)set_day = 7;break;}
      case 5:{dd--;if (dd < 0)dd = 31;break;}
      case 6:{bb--;if (bb < 0)bb = 12;break;}
      case 7:{yy--;if (yy < 200)yy = 2030;break;}
      default:break;}}
    //Timer
    if (setMode == 0) {
      if (mode == 0) {
        switch (setAlarm){
        case 1:{timer1 = 0;break;}
        case 2:{timer2 = 0;break;}
        case 3:{timer3 = 0;break;}
        case 4:{timer4 = 0;break;}
        default:break;}}
      else if (mode > 0) {
        switch (setAlarm){
        case 1:{StartHH--;if (StartHH < 0)StartHH = 23;break;}
        case 2:{StartMM--;if (StartMM < 0)StartMM = 59;break;}
        case 3:{FinishHH--;if (FinishHH < 0)FinishHH = 23;break;}
        case 4:{FinishMM--;if (FinishMM < 0)FinishMM = 59;break;}
        default:break;}}}
    rtc.setDOW (set_day);
// *INDENT-ON*   
  }

VBen:
so funktioniert es:

Na also!
Ok, Jetzt für den Regensensor mit Logik den Weg finden.

Gegeben ist bisher:
(WENN Zeit für Timer1
ODER Zeit für Timer 2 […] erreicht
ODER WENN Manuell == EIN)
DANN Pumpe ein.

Das muss unterbunden werden, wenn der Regensensor sich meldet.

Es muss also geprüft werden, ob der Regensensor aus ist:
Aber eben nicht ODER, sondern das gesamte Einschaltkonstrukt darf nur laufen:
WENN Regensensor == AUS
UND (mindestens eine der vorherigen Bedingungen erfüllt ist)

Jetzt gibt es zwei Möglichkeiten um diese Bedingung aufzulösen.
Entweder, man prüft erst, ob Regensensor AUS und prüft dann die Zeiten oder erst die Zeiten und dann den Sensor.
Ich würde mich für letzteres entscheiden um das nachvollziehbar zu lassen:
Gegeben ist der RegensensorPIN mit INPUT_PULLUP,der beim einschalten nach GND zieht.
GND ist der einzige Pegel, der fest definiert ist! HIGH kann alles zwischen 1 und xxx sein.

Daraus wird:

if (((timer1 == 1 && hh == Start1HH && mm == Start1MM)
         || (timer2 == 1 && hh == Start2HH && mm == Start2MM)
         || (timer3 == 1 && hh == Start3HH && mm == Start3MM)
         || (timer4 == 1 && hh == Start4HH && mm == Start4MM)
         || (!digitalRead(bt_pumpe))) // hier ist ODER-Vergleich zu Ende
        // Und wenn Regensensor nicht aktiviert
        && (digitalRead(rain_pin)))

Beim ausschalten ist das Ganze anders rum.
Da ist es entweder einer der vorherigen Auschaltmomente ODER ein aktiver Regensensor.

Das heisst da ist ganz einfach die Bedingung nur noch zu erweitern:

    else if ((timer1 == 1 && hh == Finish1HH && mm == Finish1MM)
             || (timer2 == 1 && hh == Finish2HH && mm == Finish2MM)
             || (timer3 == 1 && hh == Finish3HH && mm == Finish3MM)
             || (timer3 == 1 && hh == Finish4HH && mm == Finish4MM)
             // nur wenn bt_pumpe HIGH und manual_ein true
             || (digitalRead(bt_pumpe) && manual_ein)
             // wenn Regensensor aktiviert
             || (!digitalRead(rain_pin)))

Also gar nicht so schwer.

Spiel es durch.
Dann komm zurück und ich schau mal, was ich Dir noch mitgeben kann um das Ganze noch übersichtlicher und kürzer zu machen…

das hört sich sehr logisch an und es funktioniert sehr gut.

Was aber ein wenig störend ist, dass währen der Regensensor aktiv ist, die Pumpe manuell nicht eingeschaltet werden kann.

Das heißt wenn ich tagsüber aus der Pumpe Wasser entnehmen will und es regnet ich die Pumpe nicht einschalten.

const byte bt_clock = A1;
const byte bt_up = A2;
const byte bt_down = A3;
const byte bt_timer = 1;
const byte bt_pumpe = 3;
const byte rain_pin = 4;


pinMode(bt_clock, INPUT_PULLUP);
pinMode(bt_up,    INPUT_PULLUP);
pinMode(bt_down,  INPUT_PULLUP);
pinMode(bt_timer, INPUT_PULLUP);
pinMode(bt_pumpe, INPUT_PULLUP);
pinMode(rain_pin, INPUT_PULLUP);


if (((timer1 == 1 && hh == Start1HH && mm == Start1MM)
         || (timer2 == 1 && hh == Start2HH && mm == Start2MM)
         || (timer3 == 1 && hh == Start3HH && mm == Start3MM)
         || (timer4 == 1 && hh == Start4HH && mm == Start4MM)
         || (!digitalRead(bt_pumpe))) // hier ist ODER-Vergleich zu Ende
        // Und wenn Regensensor nicht aktiviert
        && (digitalRead(rain_pin)))
    {
      digitalWrite (relay, LOW);
      digitalWrite (LED1, HIGH);
      digitalWrite (LED2, HIGH);
    }
    // OFF
    
    else if ((timer1 == 1 && hh == Finish1HH && mm == Finish1MM)
             || (timer2 == 1 && hh == Finish2HH && mm == Finish2MM)
             || (timer3 == 1 && hh == Finish3HH && mm == Finish3MM)
             || (timer3 == 1 && hh == Finish4HH && mm == Finish4MM)
             // nur wenn bt_pumpe HIGH und manual_ein true
             || (digitalRead(bt_pumpe) && manual_ein)
             // wenn Regensensor aktiviert
             || (!digitalRead(rain_pin)))
      {

VBen:
es funktioniert sehr gut.

Das heißt wenn ich tagsüber aus der Pumpe Wasser entnehmen will und es regnet ich die Pumpe nicht einschalten.

Ja.

Wenn Du das ändern willst dann geh zurück zur Logik.
Du musst also den manuellen Teil ausblenden, bis nach dem Regensensor:
((WENN Timer1==EIN
ODER Timer2==EIN)
UND Regensensor==AUS)
ODER Manuell==EIN
DANN ....

Fürs einschalten:

    if (((timer1 == 1 && hh == Start1HH && mm == Start1MM)
         || (timer2 == 1 && hh == Start2HH && mm == Start2MM)
         || (timer3 == 1 && hh == Start3HH && mm == Start3MM)
         || (timer4 == 1 && hh == Start4HH && mm == Start4MM)
         // Und wenn Regensensor nicht aktiviert
         && (digitalRead(rain_pin)))
        || (!digitalRead(bt_pumpe))) // hier NEUER ODER-Vergleich

Fürs auschalten machs mal selber. :wink:

ich denke so müsste es sein:

else if ((timer1 == 1 && hh == Finish1HH && mm == Finish1MM)
             || (timer2 == 1 && hh == Finish2HH && mm == Finish2MM)
             || (timer3 == 1 && hh == Finish3HH && mm == Finish3MM)
             || (timer4 == 1 && hh == Finish4HH && mm == Finish4MM)
             // nur wenn bt_pumpe HIGH und manual_ein true
             & (!digitalRead(rain_pin)))
            || (digitalRead(bt_pumpe)&& manual_ein))) // hier NEUER ODER-Vergleich
    {
        digitalWrite (relay, HIGH);
        digitalWrite (LED1, LOW);
         digitalWrite (LED2, LOW);

dabei bekomme ich diese Fehlermeldung:

exit status 1
expected primary-expression before '||' token

und bezieht sich auf diese Zeile:

           || (digitalRead(bt_pumpe)&& manual_ein))) // hier NEUER ODER-Vergleich

VBen:
ich denke so müsste es sein:

             // nur wenn bt_pumpe HIGH und manual_ein true

& (!digitalRead(rain_pin)))
            || (digitalRead(bt_pumpe)&& manual_ein))) // hier NEUER ODER-Vergleich
    {

Ja.
Bitte gehe mit dem Cursor in der Ide von vorne (oben) nach hinten (unten) durch die Klammern.
Beginne hier:

else if ((timer1 == 1 && hh == Finish1HH && mm == Finish1MM)

Du wirst merken, mit der öffnenenden Klammer an einer nicht gewollten Stelle bereits eine (ab)schliessende Klammer vorhanden ist.
Die ist da nicht richtig, wenn Du den Teil danach noch mit auswerten willst.

Das ist das mit der Logik :wink:

so bekomme ich keine Fehlermeldung mehr, aber der Regensensor funktioniert nicht mehr

  if (((timer1 == 1 && hh == Start1HH && mm == Start1MM)
         || (timer2 == 1 && hh == Start2HH && mm == Start2MM)
         || (timer3 == 1 && hh == Start3HH && mm == Start3MM)
         || (timer4 == 1 && hh == Start4HH && mm == Start4MM)
         // Und wenn Regensensor nicht aktiviert
         & (digitalRead(rain_pin)))
        || (!digitalRead(bt_pumpe))) // hier NEUER ODER-Vergleich
    {
      digitalWrite (relay, LOW);
      digitalWrite (LED1, HIGH);
      digitalWrite (LED2, HIGH);
    }
    // OFF
    
    else if (((timer1 == 1 && hh == Finish1HH && mm == Finish1MM)
             || (timer2 == 1 && hh == Finish2HH && mm == Finish2MM)
             || (timer3 == 1 && hh == Finish3HH && mm == Finish3MM)
             || (timer4 == 1 && hh == Finish4HH && mm == Finish4MM)
             // nur wenn bt_pumpe HIGH und manual_ein true
             & (!digitalRead(rain_pin)))
            || (digitalRead(bt_pumpe)&& manual_ein)) // hier NEUER ODER-Vergleich
    {
        digitalWrite (relay, HIGH);
        digitalWrite (LED1, LOW);
         digitalWrite (LED2, LOW);
        // Wenn bt_pumpe nach HIGH gezogen, wird manual_ein false
        if (digitalRead (bt_pumpe))
        {
          manual_ein = false;
        }