Zwei parallele Programme laufen lassen

Hallo und einen schönen guten Morgen an alle!

Ich setze mich für eine kleine Projekt-Steuerung neuerdings mit dem Arduino auseinander und hänge aktuell fest. Vielleicht könnt ihr mir einen simplen Lösungsvorschlag aufzeigen, den ich dann umsetzen kann :) (Meine Kenntniss-Stand ist gleich +/- 0)

[u]Das System an sich ist relativ einfach:[/u] Es gibt zwei unabhängig voneinander arbeitende Kreise. Jeder Kreis besitzt einen IR-Sensor und eine Pumpe. Sobald der IR-Sensor eine Bewegung erkennt, soll die Pumpe für 2 Sekunden laufen. Beide Kreise sollen jedoch unabhängig voneinander, parallel funktionieren!

[u]Problem:[/u] Hat jetzt allerdings der erste Sensor eine Bewegung festgestellt, ist der zweite Kreis für eine Zeit komplett außer Funktion. Wie kann ich die beiden Kreise unabhängig voneinander gestalten? Liegt meine Vermutung richtig, dass "delay" an dieser Stelle fehlplatziert ist?

int ir1Pin = 2;    // Infrarotsensor 1
int pump1Pin = 5;   // Pumpe 1
int ir2Pin = 3;   // Infrarotsensor 2
int pump2Pin = 6;   // Pumpe 2

void setup() {
  Serial.begin(9600);
  pinMode(ir1Pin, INPUT);
  pinMode(pump1Pin, OUTPUT);
  pinMode(ir2Pin, INPUT);
  pinMode(pump2Pin, OUTPUT);
}

  
void loop() {
 int s1 = digitalRead(ir1Pin);
  if( s1 == LOW){    
      Serial.println("sens1 = 0 Sensor 1: Kein Objekt gefunden...");  
  }else{                       
      Serial.println("sens1 = 1 Sensor 1: Objekt erkannt!");      
      digitalWrite(pump1Pin, HIGH);                                
      delay(2000);                                                 
      digitalWrite(pump1Pin, LOW);                                
  }  
  
 int s2 = digitalRead(ir2Pin);
  if( s2 == LOW){    
      Serial.println("sens2 = 0 Sensor 2: Kein Objekt gefunden...");  
  }else{                       
      Serial.println("sens2 = 1 Sensor 2: Objekt erkannt!");      
      digitalWrite(pump2Pin, HIGH);                                
      delay(2000);                                                 
      digitalWrite(pump2Pin, LOW);                                
  } 
}

Ich danke vorab und wünsche schonmal einen guten Start in's Wochenende!

Mfg, Lars

Damit das sicher und richtig funktioniert, musst du delay aus dem Sketch entfernen und durch die Funktion mit millis ersetzen.

Sieh dir dazu "BlinkWithoutDelay" aus den Beispielen der IDE an.

Und tausche bitte die Quote-Tags durch durch Code-Tags, dann wird der Sketch besser lesbar.

kahmui: Ich setze mich für eine kleine Projekt-Steuerung neuerdings mit dem Arduino auseinander und hänge aktuell fest. Vielleicht könnt ihr mir einen simplen Lösungsvorschlag aufzeigen, den ich dann umsetzen kann :) (Meine Kenntniss-Stand ist gleich +/- 0)

Beste Voraussetzungen - herzlich willkommen!

[u]Das System an sich ist relativ einfach:[/u] Es gibt zwei unabhängig voneinander arbeitende Kreise. Jeder Kreis besitzt einen IR-Sensor und eine Pumpe. Sobald der IR-Sensor eine Bewegung erkennt, soll die Pumpe für 2 Sekunden laufen. Beide Kreise sollen jedoch unabhängig voneinander, parallel funktionieren!

[u]Problem:[/u] Hat jetzt allerdings der erste Sensor eine Bewegung festgestellt, ist der zweite Kreis für eine Zeit komplett außer Funktion. Wie kann ich die beiden Kreise unabhängig voneinander gestalten? Liegt meine Vermutung richtig, dass "delay" an dieser Stelle fehlplatziert ist?

guten Morgen,

Zwei Dinge: Ich empfehle erstmal mit einem Kreis anzufangen. Wenn der läuft, kannst Du das auf den zweiten Kreis adaptieren. So wie Du jetzt anfängst, musst Du immer beide Kreise bearbeiten, bis Du sicher bist, das die sich nicht gegenseitig beeinflussen. (Was sie derzeit tun)

In der Erklärung fehlt noch etwas wichtiges: Möchtest Du bei der ersten Erkennung die Pumpe starten - 2 sekunden laufen lassen und dann abschalten - und wieder auf Erkennung warten ODER Möchtest Du permanent die Erkennung abfragen und die Pumpe "nachlaufen" lassen, wenn der letzte LOW gemeldet wurde?

In jedem Fall benötigst Du mindestens eine Statusvariable und eine weitere um Dir die Zeit zu merken. Und das für jeden Kreis. Daher nochmal eindringlich der Tip: Mach das erst mit einem...

Ich hatte mal einen User mit Wasser+Pumpenprojekt längere Zeit begleitet: https://forum.arduino.cc/index.php?topic=673884.0 Da waren zwei Feuchtesensoren an zwei Pumpenkreisläufen mit Nachlauf etc.

Der Thread ist recht lang, aber in #96 ist dann die fertige Lösung auf wenige Codezeilen zusammengeschrumpft. https://forum.arduino.cc/index.php?topic=673884.msg4556720#msg4556720

Erstmal vielen Dank für die vielen und schnellen Rückmeldungen!

BlinkWithoutDelay.... klingt interessant, fühlt sich aber an wie 'ne Pfanne die an den Kopf fliegt. Leicht erschlagend :)

Von der Logik her verstehe ich die Funktion. Beim Umsetzen muss ich allerdings gestehen, dass ich überhaupt nichts zustande bringe.

Wie sage ich dem Arduino, dass die Pumpe für 2 Sekunden laufen soll, NACHDEM der Sensor ausgelöst wurde?

Also: if sensor1 = high -> zeitstempel setzen (?), pumpe1 betätigen und von 2 runterzählen (?) -> nach dem Runterzählen den Sensor wieder "scharf" (also auf low) schalten

Dazu muss ich (gehen wir jetzt mal nur, wie von euch geraten, von einem Kreis aus) meine Pins mit Nummer und Input oder Output deklarieren. Zudem muss ich für die Zeitstempel meinen Kreis 1 und die Dauer der Pumpenbetätigung festlegen.

const int sensor1Pin =  2;
const int pumpe1Pin =  3;

unsigned long kreis1 = 0;

const long interval1 = 2000;

void setup() {
  pinMode(sensor1Pin, INPUT);
  pinMode(pumpe1PIN, OUTPUT);
}

Dann geht's los. Wie kann ich nun mitteilen, dass die Pumpe1 erst läuft, nachdem der Sensor1 ausgelöst wurde?

void loop() {
   unsigned long currentMillis = millis();

   if (currentMillis - kreis1 >= interval) {
    previousMillis = currentMillis;

    if (sensor1Pin == HIGH) {
      digitalWrite(pumpe1PIN, HIGH);
    } else {
      digitalWrite(pumpe1PIN, LOW);
    //--------Müsste an dieser Stelle nicht der Code für Zeitablauf rein?
    }
  }
}

Sieht irgendwie murksig aus und wird wahrscheinlich auch nicht funktionieren.

my_xy_projekt: In der Erklärung fehlt noch etwas wichtiges: Möchtest Du bei der ersten Erkennung die Pumpe starten - 2 sekunden laufen lassen und dann abschalten - und wieder auf Erkennung warten ODER Möchtest Du permanent die Erkennung abfragen und die Pumpe "nachlaufen" lassen, wenn der letzte LOW gemeldet wurde?

Erkennung -> Pumpe starten und 2 Sekunden laufen lassen -> abschalten (am besten mit 3 Sekunden Zwangspause) -> warten auf erneute Erkennung

Wie ihr seht, tu ich mich noch ziemlich schwer. Für weitere Gedankenstützen wäre ich dankbar.

Mfg Lars

kahmui: Erstmal vielen Dank für die vielen und schnellen Rückmeldungen!

Also: if sensor1 = high -> zeitstempel setzen (?), pumpe1 betätigen und von 2 runterzählen (?) -> nach dem Runterzählen den Sensor wieder "scharf" (also auf low) schalten

Moment: Du schaltest nicht den Sensor.... Du nutzt erst dann den Wert des Sensor, wenn die Bedingungen dafür stimmen. Das geht mit einer Statusvariablen.

Dann geht's los. Wie kann ich nun mitteilen, dass die Pumpe1 erst läuft, nachdem der Sensor1 ausgelöst wurde?

    if (sensor1Pin == HIGH) {
      digitalWrite(pumpe1PIN, HIGH);
    } else {
      digitalWrite(pumpe1PIN, LOW);
    //--------Müsste an dieser Stelle nicht der Code für Zeitablauf rein?

Ja.

Erkennung -> Pumpe starten und 2 Sekunden laufen lassen -> abschalten (am besten mit 3 Sekunden Zwangspause) -> warten auf erneute Erkennung

Wie ihr seht, tu ich mich noch ziemlich schwer. Für weitere Gedankenstützen wäre ich dankbar.

Ach das wird.

Also mal aufgedröselt: Loop - Anfang WENN ir HIGH DANN - Pumpe AN - Zeit merken (Start der Laufzeit)

WENN Pumpe AN ist UND Laufzeit > 2000 DANN - Pumpe aus - Zeit merken (Begin der Pause) Loop - Ende

Jetzt fällt auf, das die Pumpe wieder angehen würde, ohne das auf die 3 Sek.Pause gewartet wurde. Also muss die erste Bedingung geändert werden in: WENN ir HIGH UND Pausezeit > 3000 DANN

Für Laufzeit und Pausenzeit brauchst Du Variablen.

Schliesslich könnte das so aussehen - ausm Bauch heraus

const int ir1Pin = 2;      // Infrarotsensor 1
const int pump1Pin = 5;    // Pumpe 1
const int laufzeit = 2000;
const int pausezeit = 3000;
long pausemillis = 0;
long laufmillis = 0;

void setup()
  {
  Serial.begin(115200);
  pinMode(ir1Pin, INPUT);
  pinMode(pump1Pin, OUTPUT);
  }


void loop()
  {
  if ((digitalRead(ir1Pin)) && (millis() - pausemillis > pausezeit))
    {
    Serial.println("sens1 = 1 Sensor 1: Objekt erkannt!");
    digitalWrite(pump1Pin, HIGH);
    laufmillis = millis();
    }
  if (millis() - laufmillis > laufzeit) // Hier könnte noch geprüft werden ob die Pumpe tatsächlich an ist
    {
    digitalWrite(pump1Pin, LOW);
    pausemillis = millis();
    }
  }

Und dann noch ein Hinweis Wenn Du fertige Relaisboards benutzt, sind die oftmals LOW-aktiv. Das heisst, das LOW/HIGH für die Pumpe muss dann getauscht werden.

kanns erst jetzt posten,

das wäre meine Variante

/*
  https://forum.arduino.cc/index.php?topic=692478.msg
  by noiasca
*/

struct Messen                // jede Messstelle braucht 3 Variablen
{
  const byte irPin;          // Infrarotsensor
  const byte pumpPin;        // Pumpe
  uint32_t previousMillis;   // Zeitstempel vom letzten Einschalten
};

Messen messen[]
{
  {2, 5, 0},     // irPin, pumpPin, previousMillis
  {3, 6, 0}
};

const uint32_t interval = 2000;         // Laufzeit in Millisekunden
const size_t messstellen = sizeof(messen) / sizeof(messen[0]);

void setup() {
  Serial.begin(115200);
  for (byte i = 0; i < messstellen; i++)
  {
    pinMode(messen[i].irPin, INPUT);
    pinMode(messen[i].pumpPin, OUTPUT);
  }    
}

void check(byte actual)
{
  // checken, ob eingeschaltet werden soll
  if ( digitalRead(messen[actual].irPin == LOW) ) {
    Serial.print("sens = 0 Sensor ");
    Serial.print(actual + 1);
    Serial.println(": Kein Objekt gefunden...");
  } else {
    messen[actual].previousMillis = millis();                         // Zeit merken
    Serial.print("sens = 0 Sensor ");
    Serial.print(actual + 1);
    Serial.println(": Objekt erkannt");
    digitalWrite(messen[actual].pumpPin, HIGH);
  }
  // wenn EIN, checken auf Zeitablauf
  if (digitalRead(messen[actual].pumpPin) == HIGH && millis() - messen[actual].previousMillis >= interval ) 
  {
    digitalWrite(messen[actual].pumpPin, LOW);
    Serial.print("Pumpe ");
    Serial.print(actual + 1);
    Serial.println("abschalten");
  }
}

void loop() {
  for (byte i = 0; i < messstellen; i++)
    check(i);
}

noiasca: kanns erst jetzt posten,

das wäre meine Variante

Huch, vom Netz zwangsgetrennt? ;)

Ich hätte es wieder mit Array gelöst. Aber erstmal muss er das mit einem Zweig hinbekommen...

Ich habe mir mal den Code von my_xy zur Brust genommen, da dieser für mich verständlicher ist als der von noiasca (nichts für ungut, aber das ist mir “noch” zu hoch). Trotzdem vielen Dank an dieser Stelle!!! :slight_smile:

Der Sensor erkennt die Bewegung und lässt den Motor auch drehen. Ebenso klappt das parallel mit dem zweiten Kreis. Die Überprüfung, ob die Pumpe überhaupt läuft habe ich auch mit reingenommen.

if ((millis() - laufmillis2 > laufzeit) && (digitalRead(pump2Pin) == HIGH))

Was allerdings nicht funktioniert ist die erste if-Abfrage mit dem millis Abgleich:

if ((digitalRead(ir1Pin)) && (millis() - pausemillis > pausezeit))

Wenn ich den Code beginnend ab “&&” ausblende,

if (digitalRead(ir1Pin)) //&& (millis() - pausemillis > pausezeit))

funktioniert es zumindest wie oben beschrieben (Sensor reagiert, Pumpe dreht). Nur drehen die Motoren permanent weiter und stoppen nicht mehr. Wo kann hier der Fehler liegen?

Gesamter Code:

const int ir1Pin = 2;      // Infrarotsensor 1
const int pump1Pin = 5;    // Pumpe 1
const int ir2Pin = 3;      // Infrarotsensor 2
const int pump2Pin = 6;    // Pumpe 2
const int laufzeit = 2000;
const int pausezeit = 3000;
long pausemillis1 = 0;
long laufmillis1 = 0;
long pausemillis2 = 0;
long laufmillis2 = 0;

void setup()
  {
  Serial.begin(115200);
  pinMode(ir1Pin, INPUT);
  pinMode(pump1Pin, OUTPUT);
  pinMode(ir2Pin, INPUT);
  pinMode(pump2Pin, OUTPUT);
  }


void loop()
  {
  if (digitalRead(ir1Pin)) //&& (millis() - pausemillis1 > pausezeit))
    {
    Serial.println("Sensor 1: Objekt erkannt!");
    digitalWrite(pump1Pin, HIGH);
    laufmillis1 = millis();
    }
  if ((millis() - laufmillis1 > laufzeit) && (digitalRead(pump1Pin) == HIGH))
    {
    digitalWrite(pump1Pin, LOW);
    pausemillis1 = millis();
    }
  
  if (digitalRead(ir2Pin)) //&& (millis() - pausemillis2 > pausezeit))
    {
    Serial.println("Sensor 2: Objekt erkannt!");
    digitalWrite(pump2Pin, HIGH);
    laufmillis2 = millis();
    }
  if ((millis() - laufmillis2 > laufzeit) && (digitalRead(pump2Pin) == HIGH))
    {
    digitalWrite(pump2Pin, LOW);
    pausemillis2 = millis();
    }
  
  }

Übrigens vielen Dank für die Bemerkung mit den Relais. Tatsächlich wird am Ende ein Doppelrelais mit Optokoppler verwendet, um die beiden Pumpen (230V) zu schalten.

Übrigens hab ich mal ein Bild mit Schaltbeispiel angehangen.

Hallo Lars,

jetzt habe ich eine bestimmte Vermutung wie du dir das "Funktionieren" eines Programms vorstellst. Wenn meine Vermutung zuträfe wäre es eine noch nicht korrekte Vorstellung. Wenn meine Vermutung falsch ist bitte ich schon mal um Verzeihung.

Du hattest geschrieben:

Wie kann ich nun mitteilen, dass die Pumpe1 erst läuft, nachdem der Sensor1 ausgelöst wurde?

Das hört sich (in meinem Ohren) so an als ob man dem Microcontroller etwas sagen könnte wie einem Butler "Warte aber mit dem Autowaschen bis das Baby seinen Mittagsschlaf beendet hat" Und der Microcontroller bekommt dann Rest von alleine hin.

Es ist nicht so sehr ein Mitteilen von etwas sondern ein ständiges Überprüfen von verschiedenen Bedingungen.

Eine der Bedingungen lautet: meldet IR-Bewegungs-Sensor eine Bewegung? Eine weitere Bedingung ist läuft Pumpe schon 2 Sekunden? noch eine Bedingung ist: Ist es länger als drei Sekunden her, dass Pumpe abgeschaltet wurde

Ob diese Bedingungen zutreffen oder nicht wird innerhalb des Programms ständig überprüft. Nur wenn bestimmte Bedingungen erfüllt sind werden bestimmte Befehle ausgeführt.

So als ob der Butler oben aus dem Beispiel: alle 10 Sekunden ins Kinderbettchen schaut ob das Baby noch schläft. Wenn das Baby die Augen aufmacht und plärrt steht er auf "Hurra endlich Autowaschen!"

Du hattest geschrieben +-0-Ahnung. Nun über Null muss es hinausgehen weil du ja die Arduino-IDE installiert bekommen hast und auch halbwegs sinnvollen Code geschrieben hast. Trotzdem ist dein Wissensstand vergrößerungsfähig. Es macht auf jeden Fall Sinn ein Programmiertutorial durchzuarbeiten. Davon gibt es natürlich sehr viele und 95% davon sind Schrott. Wenn du ein bestimmtes Tutorial nicht verstehst - abbrechen und ein anderes ausprobieren. Ganz im Ernst. Ein leicht verständliches Tutorial ist leicht verständlich.

Auf Englisch habe ich ein entsprechendes gefunden:

Arduino Programming CourseArduino Programming Course

Auf deutsch habe ich noch keines gefunden was diesem englischen in Sachen leichte Verständlichkeit das Wasser reichen könnte. Wenn jemand eines kennt bitte Links posten. Ich möchte es finden.

viele Grüße Stefan

kahmui: Übrigens hab ich mal ein Bild mit Schaltbeispiel angehangen.

Das ist gut, sagst Du mir auch noch, was das für IR-Sensoren sind? Ich vermute mal, das die +5V an den Output schalten und keinen zusätzlichen Widerstand nach GND haben. Damit wäre Dein PIN elektronisch bedingt immer HIGH.

Versuch mal einen Widerstand (unspektakulär zwischen 3,3K und 5K geht alles) sowohl von PIN2 als auch PIN3 nach GND zu stecken, damit Du definierte Zustände hast.

my_xy_projekt:
Das ist gut, sagst Du mir auch noch, was das für IR-Sensoren sind?
Ich vermute mal, das die +5V an den Output schalten und keinen zusätzlichen Widerstand nach GND haben.
Damit wäre Dein PIN elektronisch bedingt immer HIGH.

Versuch mal einen Widerstand (unspektakulär zwischen 3,3K und 5K geht alles) sowohl von PIN2 als auch PIN3 nach GND zu stecken, damit Du definierte Zustände hast.

Das sind ganz normale PIR-Sensoren die auch im Starterset vorhanden sind. Anschlüsse sind Leistung / Masse / Signal. Bei meiner Testschaltung ohne millis() hat das ganze auch ganz gut ohne Widerstand funktioniert, abgesehen vom delay-Dilemma (haha). Die Sensoren dienen hier nur als Platzhalter für ähnliche Sensoren die dann abschließend in der Praxis angewandt werden.

Siehe auch hier: klick klick!

StefanL38:
Es ist nicht so sehr ein Mitteilen von etwas sondern ein ständiges Überprüfen von verschiedenen Bedingungen.

Danke für die Erklärung. Natürlich ist mir bewusst das Signale etc. laufend abgefragt werden. Trotzdem Danke!

StefanL38:
So als ob der Butler oben aus dem Beispiel: alle 10 Sekunden ins Kinderbettchen schaut ob das Baby noch schläft.
Wenn das Baby die Augen aufmacht und plärrt steht er auf “Hurra endlich Autowaschen!”

Ich musste herzhaft lachen. Danke an dieser Stelle :slight_smile:

StefanL38:
Auf Englisch habe ich ein entsprechendes gefunden:

Arduino Programming CourseArduino Programming Course

Schaue ich mir an!

Dennoch bleibt mein das Problem weiterhin bestehen.

Mfg Lars

kahmui: Was allerdings nicht funktioniert ist die erste if-Abfrage mit dem millis Abgleich:

if ((digitalRead(ir1Pin)) && (millis() - pausemillis > pausezeit))

Und ich sag noch, mach erst einen Kreis fehlerfrei fertig - das macht sonst Mehraufwand ;)

Nachbearbeitet. Ich sagte, Du brauchst eine Statusvariable. Die hast Du mit dem PumpenPIN - Beim einschalten muss die natürlich auch rein.

Wenn Du nicht ständig die Bedingungen LOW und HIGH schreiben willst, geht das auch so wie ich das gemacht habe.

const int ir1Pin = 2;      // Infrarotsensor 1
const int pump1Pin = 5;    // Pumpe 1
const int ir2Pin = 3;      // Infrarotsensor 2
const int pump2Pin = 6;    // Pumpe 2
const int laufzeit = 2000;
const int pausezeit = 3000;
long pausemillis1 = 0;
long laufmillis1 = 0;
long pausemillis2 = 0;
long laufmillis2 = 0;

void setup()
{
  Serial.begin(115200);
  pinMode(ir1Pin, INPUT);
  pinMode(pump1Pin, OUTPUT);
  pinMode(ir2Pin, INPUT);
  pinMode(pump2Pin, OUTPUT);
}


void loop()
{
  if ((digitalRead(ir1Pin)) && (millis() - pausemillis1 > pausezeit) && (!digitalRead(pump1Pin)))
  {
    Serial.println("Sensor 1: Objekt erkannt!");
    digitalWrite(pump1Pin, HIGH);
    laufmillis1 = millis();
    
  }
  if ((millis() - laufmillis1 > laufzeit) && (digitalRead(pump1Pin)))
  {
    Serial.println("Pumpe aus!");
    digitalWrite(pump1Pin, LOW);
    pausemillis1 = millis();
  }
}

Ausgabe auf dem seriellen Monitor:

15:11:42.542 -> Pumpe aus!
15:11:45.572 -> Sensor 1: Objekt erkannt!
15:11:47.571 -> Pumpe aus!
15:11:50.569 -> Sensor 1: Objekt erkannt!
15:11:52.568 -> Pumpe aus!
#include <CooperativeTask.h>



class Pumpe: public Task
{
  protected:
    const byte inPin;
    const byte outPin;
    const unsigned long laufZeit;
    const unsigned long pauseZeit;
  
  public:
    Pumpe(const byte inPin,const byte outPin,const unsigned long laufZeit,const unsigned long pauseZeit):
       inPin(inPin),
       outPin(outPin),
       laufZeit(laufZeit),
       pauseZeit(pauseZeit)
    {
    }
    
    virtual void init() override
    {
      pinMode(inPin,INPUT);
      pinMode(outPin,OUTPUT);
    }
    
    virtual void run() override
    {
      TaskBlock
      {
        taskWaitFor(digitalRead(inPin));
        digitalWrite(outPin,HIGH);
        taskPause(laufZeit);
        digitalWrite(outPin,LOW);
        taskPause(pauseZeit);
      }
    }
};

Pumpe pumpen[] { // {inPin,outPin,laufZeit,pauseZeit}
                    {2,    8,     2000,    3000},
                    {3,    9,     2000,    3000}
               };




void setup() 
{
 Scheduler::instance().init();
}

void loop() 
{
  Scheduler::instance().run();
}

Alles drin, was das Herz begehrt:

  • Endlosschleifen
  • Goto
  • BlinkWithoutDelay
  • Multitasking
  • Automat/Schrittkette

Nur die if() habe ich großzügig weggelassen, bzw. vergraben.

CooperativeTask.zip (10.1 KB)

noiasca: wenn du mal die beiden Codes vergleichst wirst du feststellen dass sich diese gar nichtso sehr unterscheiden. Außer dass meiner Codeduplikate vermeidet. Auch das hinzufügen eines weiteren Sensors/Relais wäre nur die Sache von einer einzigen Zeile. Gehe es einfach mal durch und sollte etwas unklar sein dann frage.

Werde ich auf jeden Fall machen! Danke :)

BlinkWithoutDelay… klingt interessant, fühlt sich aber an wie 'ne Pfanne die an den Kopf fliegt.

Das Prinzip eines endlichen Automaten ist für einen Anfänger nicht leicht zu verstehen. Meistens liegt’s aber nur daran, wie es erklärt wird.

Mein Gesabbel dazu findest Du hier. Eine Erklärung, die IMO erheblich leichter zu verstehen ist, findest Du hier.

Gruß

Gregor

EDIT: Da ein vorhergehender Beitrag gelöscht wurde, habe ich meinen Text angepaßt.

Dann noch eine OOP-Variante, die auf combies Überlegungen basieren, der TO möge wählen:

class Pumpe {
    const byte irPin, pumpPin;
    const uint32_t punpzeit;
    uint32_t vorhin;
  public:
    Pumpe(const byte irPin, const byte pumpPin, const uint32_t punpzeit)
      : irPin(irPin), pumpPin(pumpPin), punpzeit(punpzeit), vorhin(0) {}

    void initPumpe() {
      pinMode(irPin, INPUT);
      pinMode(pumpPin, OUTPUT);
    }

    void runPumpe() {
      if (digitalRead(pumpPin)) {
        if (millis() - vorhin >= punpzeit)
        {
          digitalWrite(pumpPin, LOW);
        }
      } else {
        if (digitalRead(irPin)) {
          digitalWrite(pumpPin, HIGH);
          vorhin = millis();
        }
      }
    }
};

Pumpe pumpe[] {
  {2, 5, 2000},
  {3, 6, 2000}
};

void setup() {
  for (Pumpe &p : pumpe) p.initPumpe();
}

void loop() {
  for (Pumpe &p : pumpe) p.runPumpe();
}

Erstmal vielen Dank an alle, die mir bei meinem Problem so tatkräftig zur Seite stehen. Ich weiß eure Rückmeldungen und Hilfestellungen wirklich sher zu schätzen!

Natürlich wäre es einfach den fertigen Code von euch zu nehmen. Allerdings nehme ich mir lieber die Zeit die ganzen Lösungsansätze mal genauer unter die Lupe zu nehmen, um auch das Konstrukt dahinter zu verstehen und auf lange Sicht selbst in der Lage sein zu können, solche Probleme zu lösen :)

Jetzt habe ich erstmal eine Menge Code-Schnipsel von euch die ich mir in Ruhe anschauen kann!

Allerdings nehme ich mir lieber die Zeit die ganzen Lösungsansätze mal genauer unter die Lupe zu nehmen, um auch das Konstrukt dahinter zu verstehen und auf lange Sicht selbst in der Lage sein zu können, solche Probleme zu lösen :)

So ist recht!

Hast du denn schon so ein schönes dickes modernes C++ Buch? Nein? Dann anschaffen!

Dann hier auch noch mein fertiges Konstrukt - mit ein wenig Kommentar und serieller Ausgabe ;)

// HIER DIE ANZAHL DER KREISE ANGEBEN
const int Kreise = 2;
// Für jeden Kreis ab hier einen Wert angeben!
// Hier die Angabe der PIN
const int irPin[] = {2, 3};
const int pumpPin[] = {5, 6};
// Hier die Angabe für die Zeiten
const int laufzeit[] = {2000, 2000};
const int pausezeit[] = {3000, 3000} ;
// Zeitvariablen init immer 0
unsigned long laufmillis[] = {0, 0};
unsigned long pausemillis[] = {0, 0};
// Ende Eintrag Werte
void setup()
{
  Serial.begin(115200);
  for (int i = 0; i < Kreise; i++)
  {
    pinMode(irPin[i], INPUT);
    pinMode(pumpPin[i], OUTPUT);
  }
}
void loop()
{
  for (int i = 0; i < Kreise; i++)
  {
    if ((digitalRead(irPin[i])) && (millis() - pausemillis[i] > pausezeit[i]) && (!digitalRead(pumpPin[i])))
    {
      Serial.print("Sensor ");
      Serial.print(i+1);
      Serial.println(": Objekt erkannt!");
      digitalWrite(pumpPin[i], HIGH);
      laufmillis[i] = millis();
    }
    if ((millis() - laufmillis[i] > laufzeit[i]) && (digitalRead(pumpPin[i])))
    {
      Serial.println("Pumpe aus!");
      digitalWrite(pumpPin[i], LOW);
      pausemillis[i] = millis();
    }
  }
}

kahmui: Allerdings nehme ich mir lieber die Zeit die ganzen Lösungsansätze mal genauer unter die Lupe zu nehmen, um auch das Konstrukt dahinter zu verstehen und auf lange Sicht selbst in der Lage sein zu können, solche Probleme zu lösen :)

Meine OOP-Variante faßt die Informationen, die zusammengehören, zusammen. Sagt combie und damit hat er mich eingefangen, weshalb ich es mal zeigen wollte.

Bei Interesse bitte nachfragen :)