IR Befehl während Programmablaufs stoppen

Hallo Community, ich bräuchte mal eure Hilfe.

Ich habe mit hilfe von Bausteinen ein Programm geschrieben um, mittels Relais, Pumpen anzusteuern. Das ganze wird über IR gestartet und die Pumpen laufen eine gewisse Zeit. Gedacht ist das als Getränkespender.
Nun habe ich das Problem, wenn eine Pumpe gestartet wurde, kann ich keinen Stop-Befehl über die FB Senden..erst wenn die Zeit abgelaufen ist, werden neue IR-Befehle angenommen...
Ich möchte aber, falls ein "falsches Getränk" angewählt wurde, die Pumpe sofort stoppen können.

Ich würde mich freuen wenn ihr mir helfen könntet.

LG atomicmate

Hier das Programm:

#include <IRremote.h>
int RECV_PIN = 11;
IRrecv irrecv (RECV_PIN);
decode_results results;

#define ein LOW
#define aus HIGH

int Cola = 4;
int Fanta = 5;
int Sprite = 6;
int Wasser = 7;

void setup() {
 digitalWrite(Cola, HIGH);
 pinMode(Cola, OUTPUT);
 digitalWrite(Fanta, HIGH);
 pinMode(Fanta, OUTPUT);
 digitalWrite(Sprite, HIGH);
 pinMode(Sprite, OUTPUT);
 digitalWrite(Wasser, HIGH);
 pinMode(Wasser, OUTPUT);
 Serial.begin(9600);
 irrecv.enableIRIn();



}

void loop() {
 if (irrecv.decode(&results)) {
Serial.println(results.value, DEC);


if (results.value == 16753245)
{digitalWrite(Cola, aus);}

if (results.value == 16724175)  // Cola läuft für 6sek, stoppt selbstständig // Zeit für ca 200ml
{digitalWrite(Cola, ein);
delay(6000);
digitalWrite(Cola, aus);}



if (results.value == 16753245)  
{digitalWrite(Fanta, aus);}

if (results.value == 16718055)  // Fanta läuft für 6sek, stoppt selbstständig
{digitalWrite(Fanta, ein);
delay(6000);
digitalWrite(Fanta, aus);}



if (results.value == 16753245)
{digitalWrite(Sprite, aus);}

if (results.value == 16743045)  // Sprite läuft für 6sek, stoppt selbstständig
{digitalWrite(Sprite, ein);
delay(6000);
digitalWrite(Sprite, aus);}

if (results.value == 16753245)
{digitalWrite(Wasser, aus);}

if (results.value == 16716015)  // Wasser läuft für 6sek, stoppt selbstständig
{digitalWrite(Wasser, ein);
delay(6000);
digitalWrite(Wasser, aus);}

if (results.value == 16726215)  // Mezzo-Mix
{digitalWrite(Cola, ein);
digitalWrite(Fanta, ein);
delay(3000);
digitalWrite(Cola, aus);
digitalWrite(Fanta, aus);}

if (results.value == 16769565)   // Spülen für 5sek
{digitalWrite(Cola, ein);
digitalWrite(Fanta, ein);
digitalWrite(Sprite, ein);
digitalWrite(Wasser, ein);
delay(5000);
digitalWrite(Cola, aus);
digitalWrite(Fanta, aus);
digitalWrite(Sprite, aus);
digitalWrite(Wasser, aus);}

if (results.value == 16734885)  // Cola läuft für 8sek, stoppt selbstständig // Zeit für ca 260ml
{digitalWrite(Cola, ein);
delay(8000);
digitalWrite(Cola, aus);}

if (results.value == 16728765)  // Fanta läuft für 8sek, stoppt selbstständig
{digitalWrite(Fanta, ein);
delay(8000);
digitalWrite(Fanta, aus);}

if (results.value == 16730805)  // Sprite läuft für 8sek, stoppt selbstständig
{digitalWrite(Sprite, ein);
delay(8000);
digitalWrite(Sprite, aus);}

if (results.value == 16732845)  // Wasser läuft für 8sek, stoppt selbstständig
{digitalWrite(Wasser, ein);
delay(8000);
digitalWrite(Wasser, aus);}

irrecv.resume();

 }
}

delay(6000);

muss raus.

Stattdessen könntest du, wenn ein IR-Befehl empfangen wird, das passende Relais einschalten und die StartZeit merken. ( Und eventuell, dass die Ausgabe gerade läuft )

Wenn ein Relais lange genug an war, oder wenn ein Stop-Befehl kommt, alle ausschalten.

Als Stop-Befehl könnte man auch jeden beliebigen Befehl interpretieren, wenn er während der Laufzeit kommt.

Setze Deinen Sketch bitte in Codetags (</> oben links). Das kannst Du auch noch nachträglich ändern.
Sonst ist der Code schlecht lesbar.

Solange Du diese langlaufenden Delay drin hast, kannst Du keine schnellen Reaktionen durchführen.
Du brauchst eine andere Zeitsteuerung.
Schaue Dir mal BlinkWithoutDelay an und lies zum Verständnis die Nachtwächtererklärung.

Gruß Tommy

Danke erstmal Michael_X

Das mit dem entfernen des delay ist klar...aber ich möchte ja, das ein Glas automatisch über eine Zeit befüllt wird.

Hättest du da eventuell einen Programmcode für mich? Bin noch Anfänger :slight_smile:

atomicmate:
... Ich würde mich freuen wenn ihr mir helfen könntet.

Ich habe Deinen Code nicht gelesen. Fasse ihn in „Code-Tags“, damit er les- und scrollbar wird. Du kannst das auch nachträglich tun: „Posting bearbeiten“ wählen („more -> modify“), Code markieren, Code-Knopf (Symbolleiste ganz links) klicken.

Ich vermute, dass Du die Zeit bis zum Pumpenstop per delay() fesgelegt hast. Während ein delay() läuft, ist der Prozessor blockiert. Programmiere das, was Du tun möchtest, als „endlichen Automaten“. Dann kannst Du es so programmieren, dass Befehle möglich sind, während die Pumpe läuft. Was mir zum Thema eingefallen ist, habe ich hier ins Netz gekippt. Beachte ggf. auch die Folgeseite.

HTH

Gregor

gregorss:
Ich habe Deinen Code nicht gelesen. Fasse ihn in „Code-Tags“, damit er les- und scrollbar wird. Du kannst das auch nachträglich tun: „Posting bearbeiten“ wählen („more -> modify“), Code markieren, Code-Knopf (Symbolleiste ganz links) klicken.

Ich vermute, dass Du die Zeit bis zum Pumpenstop per delay() fesgelegt hast. Während ein delay() läuft, ist der Prozessor blockiert. Programmiere das, was Du tun möchtest, als „endlichen Automaten“. Dann kannst Du es so programmieren, dass Befehle möglich sind, während die Pumpe läuft. Was mir zum Thema eingefallen ist, habe ich hier ins Netz gekippt. Beachte ggf. auch die Folgeseite.

HTH

Gregor

Vielen Dank für deine Antwort. Ja, habe Delays benutzt..von den millis habe ich bisher noch keinen Plan...
Bin es gerade am lesen und muss sagen, nicht gerade einfach :slight_smile:

atomicmate:
Bin es gerade am lesen und muss sagen, nicht gerade einfach :slight_smile:

Seine „Pausen-Denke“ zu ändern ist vielleicht ein bisschen schwierig, aber mit der richtigen Erklärung ist es ein Klacks. Was ich sehr gut finde, ist die erwähnte „Nachtwächter-Erklärung“. Wenn Du das gelesen hast, weißt Du, worauf es ankommt.

Gruß

Gregor

gregorss:
Seine „Pausen-Denke“ zu ändern ist vielleicht ein bisschen schwierig, aber mit der richtigen Erklärung ist es ein Klacks. Was ich sehr gut finde, ist die erwähnte „Nachtwächter-Erklärung“. Wenn Du das gelesen hast, weißt Du ungefähr, worauf es ankommt.

Gruß

Gregor

Da hast du sicherlich recht....Aber für nen absoluten Anfänger echt nicht einfach :smiley:

atomicmate:
Da hast du sicherlich recht....Aber für nen absoluten Anfänger echt nicht einfach :smiley:

Lies die Nachtwächter-Erklärung. Die ist genial.

Gruß

Gregor

Aber für nen absoluten Anfänger echt nicht einfach :smiley:

Das normale Problem ist, zu denken loop() wäre "das Programm" :

{ Befehl erkennen - Relais ein - Warten - Relais aus }

loop() beschreibt aber statt dessen, was in jedem Moment zu tun ist:

( - Meistens gar nix, oder der Einfachheit halber wie unten "Zeit immer noch abgelaufen" )

  • Wenn ein IR-Befehl empfangen wurde: Relais an, Zeit merken
  • Wenn Zeit abgelaufen: Relais aus

Das kann man jetzt noch verfeinern, für den Stop-Befehl

  • Wenn ein IR-Befehl empfangen wurde und Ausgabe nicht aktiv: Relais an, Zeit merken, Ausgabe aktiv
  • Wenn ein IR-Befehl empfangen wurde und Ausgabe aktiv: Relais aus, Ausgabe stop
  • Wenn Ausgabe aktiv und (aktuelle Zeit - Startzeit > Intervall): Relais aus, Ausgabe stop merken

Hi atomicmate, versuch's mal damit:

#include <IRremote.h>
int RECV_PIN = 11;
IRrecv irrecv (RECV_PIN);
decode_results results;

#define ein LOW
#define aus HIGH

int Cola = 4;
int Fanta = 5;
int Sprite = 6;
int Wasser = 7;

// steuervariablen
int Pumpe = 0 ;                     // Nummer der Pumpe (0 = keine Pumpe läuft)
bool Status = false;                // true = eine Pumpe wurde eingeschaltet,  false = es läuft grad keine Pumpe
bool Stop = 0;                      // 1 = Stop gesendet, laufende Pumpe stoppen
unsigned long pumpDauer;            // gibt an wie lange gepumpt wird
unsigned long pumpStart;            //merkt sich, wan pumpe gestartet (um die Dauer des Pumpens messen zu können


void setup() {
  digitalWrite(Cola, HIGH);
  pinMode(Cola, OUTPUT);
  digitalWrite(Fanta, HIGH);
  pinMode(Fanta, OUTPUT);
  digitalWrite(Sprite, HIGH);
  pinMode(Sprite, OUTPUT);
  digitalWrite(Wasser, HIGH);
  pinMode(Wasser, OUTPUT);
  Serial.begin(9600);
  irrecv.enableIRIn();
}

void loop() {
  if (irrecv.decode(&results)) {
Serial.println(results.value, DEC);


    if (results.value == 16753245)  Stop = 1;
    
    if (Status == false) {              // folgende Zeilen nur ausführen, wenn keine Pumpe läuft)
    if (results.value == 16724175) Pumpe = 1;    // Cola läuft für 6sek, stoppt selbstständig // Zeit für ca 200ml
    if (results.value == 16718055) Pumpe = 2;    // Fanta läuft für 6sek, stoppt selbstständig
    if (results.value == 16743045) Pumpe = 3;    // Sprite läuft für 6sek, stoppt selbstständig
    if (results.value == 16716015) Pumpe = 4;    // Wasser läuft für 6sek, stoppt selbstständig
    if (results.value == 16726215) Pumpe = 5;    // Mezzo-Mix äuft für 6sek, stoppt selbstständig
    if (results.value == 16769565) Pumpe = 10;   // Spülen für 5sek
    if (results.value == 16734885) Pumpe = 11;   // Cola läuft für 8sek, stoppt selbstständig // Zeit für ca 260ml
    if (results.value == 16728765) Pumpe = 12;   // Fanta läuft für 8sek, stoppt selbstständig
    if (results.value == 16730805) Pumpe = 13;   // Sprite läuft für 8sek, stoppt selbstständig
    if (results.value == 16732845) Pumpe = 14;   // Wasser läuft für 8sek, stoppt selbstständig
    
    irrecv.resume();
    callPumpe(Pumpe);
    Status = true;
    pumpStart = millis();
    }
  }
  
  if (Status == true) {                                         // prüfen ob eine Pumpe läuft
     if (Stop == 1 || (millis() - pumpStart >= pumpDauer))      // hier wird geprüft, wie lange eine pumpe schon läuft
     {                                                          // oder ob das Stop gesendet wurde 
        callPumpe(Pumpe);                                       // Laufende Pumpe ausschalten
        Stop = 0;                                              // stop wieder auf null
        Status = false;                                        // Status wieder auf false alles bereit für nächstes Getränk
     }
  }
}  // loop end


void callPumpe(int Pump) {
    pumpDauer = 6000;                 // Zeit für ca 200ml
    if(Pump == 10) pumpDauer = 5000;  // Zeit für Spülen
    if(Pump > 10) {
      pumpDauer = 8000;       // Zeit für ca 260ml
      Pump -= 10;             // wenn Pump > 10 (Grosses Glas), 10 abziehen und dann entsprechende Pumpe starten 
    }
    
    switch(Pump) {    // Pumpennummer / Funktion
      case 1:   // Cola
      digitalWrite(Cola, aus);
      if(Status == false) digitalWrite(Cola, ein);
      break;

      case 2:   // Fanta
      digitalWrite(Fanta, aus);
      if(Status == false) digitalWrite(Fanta, ein);
      break;

      case 3:   // Sprite
      digitalWrite(Sprite, aus);
      if(Status == false) digitalWrite(Sprite, ein);
      break;

      case 4:   // Wasser
      digitalWrite(Wasser, aus);
      if(Status == false) digitalWrite(Wasser, ein);
      break;

      case 5:   // MezzoMix
      digitalWrite(Cola, aus);
      digitalWrite(Fanta, aus);
      pumpDauer = 3000; 
      if(Status == false) {
        digitalWrite(Cola, ein);
        digitalWrite(Fanta, ein);
      }
      break;

      case 10:   // Spuehlen
      digitalWrite(Cola, aus);
      digitalWrite(Fanta, aus);
      digitalWrite(Sprite, aus);
      digitalWrite(Wasser, aus);   
      if(Status == false) {
        digitalWrite(Cola, ein);
        digitalWrite(Fanta, ein);
        digitalWrite(Sprite, ein);
        digitalWrite(Wasser, ein);
      }
      break;      
   }
}

LG Stefan

Deltaflyer:
Hi atomicmate, versuch's mal damit:

LG Stefan

Hallo Stefan, vielen Dank für deine Mühe :slight_smile:
Echt wahnsinn.
Werde es direkt mal versuchen und berichten :slight_smile:

So, habe den Sketch hochgeladen...Leider klappt die Aus-Taste auch hier nicht...Teilweise werden unkontrolliert Pumpen gestartet...

Auch ist mir aufgefallen, bei deinem als auch bei meinem Programm, dass sobald die Pumpe läuft, der IR Empfänger scheinbar komplett "tot" ist....er reagiert dann auf nicht...Klemme ich die Pumpen ab und lasse nur die Relais alleine laufen, klappt es zumindest mit meinem Programm....

Hier mal wie ich alles verdrahtet habe:

Arduino Uno - USB-Kabel am PC
Relais Board sowie IR Empfänger - externes 5V Netzteil (Masse mit Arduino verbunden)
Pumpen - externes 12V Netzteil (Keine Verbindung zu anderen Komponenten)

atomicmate:
Auch ist mir aufgefallen, bei deinem als auch bei meinem Programm, dass sobald die Pumpe läuft, der IR Empfänger scheinbar komplett "tot" ist....er reagiert dann auf nicht...Klemme ich die Pumpen ab und lasse nur die Relais alleine laufen, klappt es zumindest mit meinem Programm....

Hier sieht es danach aus, dass deine Pumpen Störungen verursachen, die deinen IR-Empfänger stören.
Das kann über die Betriebsspannung oder die Luft kommen.

gregorss:
Ich habe Deinen Code nicht gelesen.

Braucht man ja auch gar nicht. Beschreibung gelesen, me: "Da ist ein delay im Code". michaela_x: "delay(6000)" :slight_smile:

So, habe den IR Empfänger nun an den Arduino direkt angeschlossen so wie im Bild

atomicmate:
So, habe den IR Empfänger nun an den Arduino direkt angeschlossen so wie im Bild

Welches Bild ?

Ok, jetzt ist was da....aber wie soll man da was erkennen, wenn du für alle Kabel (fast) die gleiche Farbe verwendest und dann auch noch die Kabel übereinander zeichnest.
Für Spannungen sollte man rot für Plus (+) und blau oder schwarz für Minus (-) (GND) verwenden.

Aber in deiner Schaltung fehlen Freilaufdioden an den Motoren (Pumpen).
Daher kommen sicher die Störungen.

Hi, ja da war das Irrec.resume() noch am falschen Ort, sodass das resume nur nach druck auf eine Pumpen-Taste aktiv wurde. hab das jetzt korrigiert plus noch ein, zwei kleinigkeiten optimiert.
Wenn nun der IR Reciver störungsfrei läuft, sollte es funktionieren. Auch Der Stop-Befehl muss nun funktionieren sofern der IR-Code den Du angegeben hast, stimmt.

versuche es doch bitte nochmal (Hab leider kein IR-Reciver hier.)

#include <IRremote.h>
int RECV_PIN = 11;
IRrecv irrecv (RECV_PIN);
decode_results results;

#define ein LOW
#define aus HIGH

int Cola = 4;
int Fanta = 5;
int Sprite = 6;
int Wasser = 7;

// steuervariablen
int Pumpe = 0 ;                     // Nummer der Pumpe (0 = keine Pumpe läuft)
bool Status = false;                // true = eine Pumpe wurde eingeschaltet,  false = es läuft grad keine Pumpe
bool Stop = false;                      // 1 = Stop gesendet, laufende Pumpe stoppen
unsigned long pumpDauer;            // gibt an wie lange gepumpt wird
unsigned long pumpStart;            //merkt sich, wan pumpe gestartet (um die Dauer des Pumpens messen zu können


void setup() {
  digitalWrite(Cola, HIGH);
  pinMode(Cola, OUTPUT);
  digitalWrite(Fanta, HIGH);
  pinMode(Fanta, OUTPUT);
  digitalWrite(Sprite, HIGH);
  pinMode(Sprite, OUTPUT);
  digitalWrite(Wasser, HIGH);
  pinMode(Wasser, OUTPUT);
  Serial.begin(9600);
  irrecv.enableIRIn();
}

void loop() {
  if (irrecv.decode(&results)) {
Serial.println(results.value, DEC);


    if (results.value == 16753245)  Stop = true;
    
    if (Status == false) 
    {                       // folgende Zeilen nur ausführen, wenn keine Pumpe läuft)
    if (results.value == 16724175) Pumpe = 1;    // Cola läuft für 6sek, stoppt selbstständig // Zeit für ca 200ml
    if (results.value == 16718055) Pumpe = 2;    // Fanta läuft für 6sek, stoppt selbstständig
    if (results.value == 16743045) Pumpe = 3;    // Sprite läuft für 6sek, stoppt selbstständig
    if (results.value == 16716015) Pumpe = 4;    // Wasser läuft für 6sek, stoppt selbstständig
    if (results.value == 16726215) Pumpe = 5;    // Mezzo-Mix äuft für 6sek, stoppt selbstständig
    if (results.value == 16769565) Pumpe = 10;   // Spülen für 5sek
    if (results.value == 16734885) Pumpe = 11;   // Cola läuft für 8sek, stoppt selbstständig // Zeit für ca 260ml
    if (results.value == 16728765) Pumpe = 12;   // Fanta läuft für 8sek, stoppt selbstständig
    if (results.value == 16730805) Pumpe = 13;   // Sprite läuft für 8sek, stoppt selbstständig
    if (results.value == 16732845) Pumpe = 14;   // Wasser läuft für 8sek, stoppt selbstständig

    callPumpe(Pumpe);
    Stop = false;
    Status = true;
    pumpStart = millis();
    }
  }
  else if (Status == true) {                                         // prüfen ob eine Pumpe läuft
     if ((millis() - pumpStart) >= pumpDauer) Stop = true;         // hier wird geprüft, wie lange eine pumpe schon läuft
     if (Stop == 1)
     {                                                          // oder ob das Stop gesendet wurde 
        callPumpe(Pumpe);                                       // Laufende Pumpe ausschalten
        Stop = false;                                               // stop wieder auf null
        Status = false;                                         // Status wieder auf false alles bereit für nächstes Getränk
     }
  }
  irrecv.resume();
}  // loop end


void callPumpe(int Pump) {
    pumpDauer = 6000;                 // Zeit für ca 200ml
    if(Pump == 10) pumpDauer = 5000;  // Zeit für Spülen
    if(Pump > 10) {
      pumpDauer = 8000;       // Zeit für ca 260ml
      Pump -= 10;             // wenn Pump > 10 (Grosses Glas), 10 abziehen und dann entsprechende Pumpe starten 
    }
    
    switch(Pump) {    // Pumpennummer / Funktion
      case 1:   // Cola
      digitalWrite(Cola, aus);
      if(Status == false) digitalWrite(Cola, ein);
      break;

      case 2:   // Fanta
      digitalWrite(Fanta, aus);
      if(Status == false) digitalWrite(Fanta, ein);
      break;

      case 3:   // Sprite
      digitalWrite(Sprite, aus);
      if(Status == false) digitalWrite(Sprite, ein);
      break;

      case 4:   // Wasser
      digitalWrite(Wasser, aus);
      if(Status == false) digitalWrite(Wasser, ein);
      break;

      case 5:   // MezzoMix
      digitalWrite(Cola, aus);
      digitalWrite(Fanta, aus);
      pumpDauer = 3000; 
      if(Status == false) {
        digitalWrite(Cola, ein);
        digitalWrite(Fanta, ein);
      }
      break;

      case 10:   // Spuehlen
      digitalWrite(Cola, aus);
      digitalWrite(Fanta, aus);
      digitalWrite(Sprite, aus);
      digitalWrite(Wasser, aus);   
      if(Status == false) {
        digitalWrite(Cola, ein);
        digitalWrite(Fanta, ein);
        digitalWrite(Sprite, ein);
        digitalWrite(Wasser, ein);
      }
      break;      
   }
}

HotSystems:
Aber in deiner Schaltung fehlen Freilaufdioden an den Motoren (Pumpen).
Daher kommen sicher die Störungen.

ok, meinst das ändert was?

Hi, ich würde die E-Motoren mit Kondensatoren entstören. so wie HIER

LG Stefan

Deltaflyer:
Hi, ja da war das Irrec.resume() noch am falschen Ort, sodass das resume nur nach druck auf eine Pumpen-Taste aktiv wurde. hab das jetzt korrigiert plus noch ein, zwei kleinigkeiten optimiert.
Wenn nun der IR Reciver störungsfrei läuft, sollte es funktionieren. Auch Der Stop-Befehl muss nun funktionieren sofern der IR-Code den Du angegeben hast, stimmt.

versuche es doch bitte nochmal (Hab leider kein IR-Reciver hier.)

Hab dein Programm mal geladen....Nun passiert gar nichts mehr

hab meinen anschlussplan mal überarbeitet