Steuerung Lüftung einschalten mit Zeitverzögerung

Möchte eine neue Funktion für die Lüftungssteuerung hinzufügen.

Bisher funktionierte:
Signal 1: schaltet Lüftung ein und sie schaltet automatisch wieder ab
Signal 2: schaltet Lüftung ab

Nun möchte ich die Lüftung mit Zeitverzögerung einschalten können und sie soll dann auch selbständig wieder abschalten. Das soll mit Signal 3 geschehen.

#include <Arduino.h>
#include <IRremote.h>

uint32_t startzeitluft;
uint32_t wartezeit1h;

int RECV_PIN = 11;

IRrecv irrecv(RECV_PIN);

decode_results results;

void setup()

{
Serial.begin(9600);

pinMode (12, OUTPUT);    // Lüfter
   
irrecv.enableIRIn();


digitalWrite (12, HIGH);
digitalWrite(5, HIGH);
digitalWrite(4, HIGH);

}

void loop()
{
  
  if (irrecv.decode(&results))
    {
      if (results.value == 1082110031)  // Signal 1 Regelung Lüfter Dampf
      {
      digitalWrite (12, LOW);           // mache Lüfter an
      startzeitluft = millis();         // starte Zeit um Lüfter danach wieder abzustellen
      }                                   
      
      if (results.value == 1082075351)  // Signal 2 mache Lüfter Dampf aus
      {digitalWrite (12, HIGH);}
      
      if (results.value == 1082122271)  // Signal 3 Regelung für nachtlüftung 1 Stunde verspätet für 1 Stunde einschalten
      {wartezeit1h = millis();}
           
    }
 
 if (millis() - startzeitluft > 5000)  //  Wenn Zeit um mache Lüfter wieder aus   
  {digitalWrite(12, HIGH);
  wartezeit1h == (0);}                  // wollte hier denn Wert auf Null setzen!?!

 if (millis() - wartezeit1h > 5000)     // Wenn Wartezeit1h um ist Schalte Lüfter ein und starte StartzeitLuft
     {digitalWrite(12, LOW); 
      startzeitluft = millis();}
    }

so wie ich das hier versuche klappt es aber leider nicht... Lüfter beginnt ohne signal 3 zusenden nach der Wartezeit und lässt sich danach nicht wieder ausschalten....
vielen Dank für eure Hilfe

Zeichne dir doch mal ein Zustandsdiagramm.
Da kannst du leicht einzeichnen, was sonst noch an Übergängen von einem in den andern Zustand möglich ist, die du nicht erwähnt hast.
Was soll z.B. passieren, wenn du im Wartezustand nach (3) bist, und es kommt (1 sofort ein) oder (2 sofort aus) ?

Das Zustandsdiagramm kannst du dann programmieren, testen und erweitern.

Vielen Dank
Das habe ich nun versucht:

Gibt es noch ein Beispiel wie man Zustände programmiert? brauche eine Startthilfe...

das ist sicher nicht fertig, könnte dir aber eine Richtung geben wie man das machen könnte:

ungetested und buggy:

#include <Arduino.h>
#include <IRremote.h>

uint32_t startzeitluft;
uint32_t wartezeit1h;

int RECV_PIN = 11;

IRrecv irrecv(RECV_PIN);

decode_results results;

enum State {OFF, ON, WAIT} state;

const uint8_t fan = 12;

const uint32_t s1 = 1082110031;
const uint32_t s2 = 1082075351;
const uint32_t s3 = 1082122271;

void setup()
{
  Serial.begin(9600);

  pinMode (fan, OUTPUT);    // Lüfter

  irrecv.enableIRIn();

  digitalWrite (fan, HIGH);
  digitalWrite(5, HIGH);
  digitalWrite(4, HIGH);
}

void loop()
{

  irrecv.decode(&results);

  switch (state)
  {
    case ON :

      if (millis() - startzeitluft > 5000)  //  Wenn Zeit um mache Lüfter wieder aus
      {
        Serial.println(F("Wenn Zeit um mache Lüfter wieder aus"));
        digitalWrite(fan, HIGH);
        state = OFF;
      }

      if (results.value == s2)  // Signal 2 mache Lüfter Dampf aus
      {
        digitalWrite (fan, HIGH);
        state = OFF;
      }
      break;

    case OFF :
      if (results.value == s1)  // Signal 1 Regelung Lüfter Dampf
      {
        digitalWrite (fan, LOW);           // mache Lüfter an
        startzeitluft = millis();         // starte Zeit um Lüfter danach wieder abzustellen
        state = ON;
      }
      break;

    case WAIT:
      if (millis() - wartezeit1h > 5000)     // Wenn Wartezeit1h um ist Schalte Lüfter ein und starte StartzeitLuft
      {
        digitalWrite(fan, LOW);
        startzeitluft = millis();
        state = ON;
      }
      break;

      if (results.value == s1)  // Signal 1 Regelung Lüfter Dampf
      {
        digitalWrite (fan, LOW);           // mache Lüfter an
        startzeitluft = millis();         // starte Zeit um Lüfter danach wieder abzustellen
        state = ON;
      }

      if (results.value == s2)  // Signal 2 mache Lüfter Dampf aus
      {
        digitalWrite (fan, HIGH);
        state = OFF;
      }
  }
}

Tausend Dank für all die prima Antworten!!!
Werde mich heute Abend da rein denken.

Leider klappt es noch nicht wie es soll. Nun habe ich das ganze vollständig vereinfacht und alles "unnötige" weggelassen und versuche es mit 2 Zuständen und einem Signal.
In Zustand 1 soll mit s1 die Led eingschaltet werden und danach den Zustand wechseln.
Wenn das Signal erneut empfangen wird soll die LED wieder ausschalten und wieder den Zustand wechseln. Wo klemmts bei mir?


decode_results results;

enum State {OFF, ON} state;

const uint8_t led = 12;

const uint32_t s1 = 1082110031;

void setup()
{
  Serial.begin(9600);

  pinMode (led, OUTPUT);    // Lüfter

  irrecv.enableIRIn();

  digitalWrite (fan, HIGH);
  digitalWrite(5, HIGH);
  digitalWrite(4, HIGH);
}

void loop()
{

  irrecv.decode(&results);

  switch (state)
  {
    case ON :

      if (results.value == s1)  
      {
        Serial.print(state);
        digitalWrite (led, HIGH);
        state = OFF;
      }
      break;

    case OFF :
      if (results.value == s1)  
      {
        Serial.print(state);
        digitalWrite (led, LOW);           
        state = ON;
      }
      break;

  }
}

:face_with_spiral_eyes:

Also, so wie du die IRRemote Library benutzt ist veraltet:

Wenn man das in der "neuen" Version nutzen will, sieht der Code eher so aus:

Falls Du die Simulation ausprobierst, die Taste 5 drücken.

Als erstes klemmt es bei einer ausreichend detaillierten und verständlichen Beschreibung was du für eine Funktionialität haben willst.

Also die LED gleich wieder ausschalten???

Einmal decode aufrufen

ist bestimmt nicht ausreichend um die variable state auf einen bestimmten Wert zu setzen

da macht es bei mir auch nur
:face_with_spiral_eyes:
zusätzlich vollständigen Sketch posten

Vielen Dank für deine Fragen.

Ja ich möchte die Led einfach nur einschalten und wieder abschalten und dies mit Hilfe von 2 Zuständen und einem Signal.

Am Anfang soll der Zustand OFF sein. Sobald das Signal empfangen wird soll die Led angehen und der Zustand soll zu ON wechseln. Wenn das Signal wieder empfangen wird ausgehen und den Zustand wieder auf OFF setzen.

Wenn ich das so erstmals hinkriegen würde klappt es dann auch für meine Lüftung.

#include <Arduino.h>
#include <IRremote.h>
int RECV_PIN = 11;

IRrecv irrecv(RECV_PIN);
decode_results results;

enum State {OFF, ON} state;

const uint8_t led = 12;

const uint32_t s1 = 1082110031;
const uint32_t s2 = 1082075351;
const uint32_t s3 = 1082122271;

void setup()
{
  Serial.begin(9600);

  pinMode (led, OUTPUT);    // Lüfter

  irrecv.enableIRIn();


}

void loop()
{

  irrecv.decode(&results);
 {
  switch (state)
  {
    case ON :

      if (results.value == s1)  // Signal 2 mache Lüfter Dampf aus
      {
        Serial.print(state);
        digitalWrite (led, OFF);
        state = OFF;
      }
      break;

    case OFF :
      if (results.value == s1)  // Signal 1 Regelung Lüfter Dampf
      {
        Serial.print(state);
        digitalWrite (led, HIGH);           // mache Lüfter an
        state = ON;
      }
      break;
  }
}
 irrecv.resume();                // Warte auf nächsten Wert

}

Leider schaltet die Led nur ein und danach nicht wieder aus.....

Ich weise noch einmal darauf hin, dass die IRremote Bibliothek inzwischen bei der Version 4 ist und Du immer noch Mechanismen der Version 2 verwendest, die „deprecated“ sind.

Es wäre sinnvoll, die IRremote Geschichte mit einer aktuellen Version umzusetzen.

Vielen Dank Kai-R für den Hinweis!
Ich werde mich da schlau machen! Da es zur Zeit so funktioniert lasse ich es mal so bis ich das mit den Zuständen begriffen habe.

Die kompakteste Code-Version für die Funktionaliät
wenn eine bestimme Taste gedrückt wird schalte LED ein
wenn die gleiche Taste noch einmal gedrückt wird schalte LED aus
und dann immer so weiter
Taste ---> EIN
Taste ---> AUS
Taste ---> EIN
Taste ---> AUS
Taste ---> EIN
Taste ---> AUS
...
ist das hier

#include <Arduino.h>
#include <IRremote.h>
const byte RECV_PIN = 11;
const byte led = 12;

IRrecv irrecv(RECV_PIN);
decode_results results;

const uint32_t s1 = 1082110031;

void setup() {
  Serial.begin(9600);
  pinMode (led, OUTPUT);    // Lüfter
  irrecv.enableIRIn();
}

void loop() {

  irrecv.decode(&results);
  if (results.value == s1) {
    digitalWrite(led, !digitalRead(led) );
  }

  irrecv.resume();                // Warte auf nächsten Wert
}

Die entscheidende Zeile ist

    digitalWrite(led, !digitalRead(led) );

Huch ?? Äh ??
So was macht diese Zeile
der vordere Teil
digitalWrite(led , ZUSTAND);

setze den IO-pin "led" auf ZUSTAND
üblicherweise
digitalWrite(led ,LOW);
oder
digitalWrite(led ,HIGH);

der hintere Teil nach dem komma besteht jetzt wieder aus zwei Teilen
Da gibt es ein Ausrufe-Zeichen "!" und dann digitalRead()

digitalRead() funktioniert auch mit IO-pins die als Ausgang konfiguriert sind.

Das Ausrufezeichen ist der not-operator.
Der not-operator invertiert einen booleschen (= einen true/false) - Ausdruck

not true = false
not false = true
nur das man nicht das Wort "not" schreibt sondern ein Ausrufezeichen
! true = false
! false = true

digitalRead() liefert eine "0" oder eine "1"
nehmen wir an die LED ist eingeschaltet und das bedeutet am IO-pin IO-pin ist auf HIGH geschaltet
dann bekommt man nach einem digitalWrite(led,HIGH);
wenn man danach digitalRead(led) macht als Ergebnis eine "1"
.
Ergebnis von digitalRead(led) alleine ist dann "1"
wenn man den not-operator davor setzt wird das Ergebnis invertiert

!digitalRead(led) liefert dann eine 0
.
.
digitalWrite(led, ZUSTAND);

Der Wert von "ZUSTAND" wird in zwei Stufen ermittelt
digitalRead(led) liefert den momentanen Schaltzustand des IO-pins
digitalRead(led) liefert "1"
und der not-operator in Form des Ausrufezeichens invertiert diesen Schaltzustand

!digitalRead(led) liefert "0"

Wenn der IO-Pin gerade auf HIGH (gleichbedeutend mit "1" steht
dann liefert ! digitalRead(led) eine "0"

Wenn der IO-Pin gerade auf LOW (gleichbedeutend mit "0" steht
dann liefert !digitalRead(led) eine "1"

Der Wert von "ZUSTAND" wird dann benutzt um den neuen Schaltzustand im digitalWrite() zu setzen

wenn IO-pin "led" gerade "HIGH" ist dann ist der IO-pin nach

    digitalWrite(led, !digitalRead(led) );

auf LOW
.
.
wenn IO-pin "led" gerade "LOW" ist dann ist der IO-pin nach

    digitalWrite(led, !digitalRead(led) );

auf HIGH

eben invertiert.

Der Zustand des IO-pins selbst wird anstatt der Variable "state" benutzt.

Was soll jetzt an Funktionalität noch hinzukommen?
vgs

Das was du da schreibst, hätte der TO sich in Beitrag #8, zweiter Link alles schon anschauen können.

Meinst du mit "Beitrag #8 zweiter Link " das hier?

Dort wird der Not-operator verwendet aber nicht erklärt.
Aus dem wie der TO schreibt nehme ich an, dass er eher wenig Programmierkenntnisse hat.
Daher die ausführliche Erklärung.

vgs

Ja, kann natürlich sein, dass zu viel vorausgesetzt wurde.

Vielen Dank
euch beiden! Ich habe das Beispiel gesehen und mit den Erklärungen auch verstanden.
Leider habe ich euch etwas in die Irre geführt. Das Ziel ist es nicht nur mit einem Signal auszukommen. Am Ende will ich einen Lüfter wie im Zustandsdiagramm (siehe Bild) oben steuern können.
Ja dazu fehlen mir an Kenntnissen an allen Ecken und Enden und ich versuche ich durchzumogeln.

Was bisher funktioniert ist:

#include <Arduino.h>
#include <IRremote.h>
int RECV_PIN = 11;

uint32_t startled;

IRrecv irrecv(RECV_PIN);
decode_results results;

enum State {OFF, ON, WAIT} state;

const uint8_t led = 12;

const uint32_t s1 = 1082110031;
const uint32_t s2 = 1082075351;
const uint32_t s3 = 1082122271;

void setup()
{
  Serial.begin(9600);

  pinMode (led, OUTPUT);    // Lüfter

  irrecv.enableIRIn();


}

void loop()
{

  irrecv.decode(&results);
 {
  switch (state)
  {
    case ON :
    
      if (results.value == s2)  // Signal 2 mache Lüfter Dampf aus
      {
        Serial.print(state);
        digitalWrite (led, OFF);
        state = OFF;
      }

//      if (millis() - startled > 5000)  //  Wenn Zeit um schalte Relais "heisser" wieder aus   
//       {digitalWrite (led, OFF);
//       }
      
      break;

    case OFF :
      if (results.value == s1)  // Signal 1 Regelung Lüfter Dampf
      {
        Serial.print(state);
        digitalWrite (led, HIGH);           // mache Lüfter an
//        startled == millis();
        state = ON;
      }
      break;
  }




 irrecv.resume();                // Warte auf nächsten Wert
}
}

Nun möchte ich das ganze erweitern.
Es soll beim Einschalten die Zeit gemessen werden um automatisch wieder auszuschalten und danach den Zustand wieder auf OFF zu stellen.
Wenn ich das so versuche:

#include <Arduino.h>
#include <IRremote.h>
int RECV_PIN = 11;

uint32_t startled;

IRrecv irrecv(RECV_PIN);
decode_results results;

enum State {OFF, ON, WAIT} state;

const uint8_t led = 12;

const uint32_t s1 = 1082110031;
const uint32_t s2 = 1082075351;
const uint32_t s3 = 1082122271;

void setup()
{
  Serial.begin(9600);

  pinMode (led, OUTPUT);    // Lüfter

  irrecv.enableIRIn();


}

void loop()
{

  irrecv.decode(&results);
 {
  switch (state)
  {
    case ON :
    
      if (results.value == s2)  // Signal 2 mache Lüfter Dampf aus
      {
        Serial.print(state);
        digitalWrite (led, OFF);
        state = OFF;
      }

      if (millis() - startled > 5000)  //  Wenn Zeit um schalte Relais "heisser" wieder aus   
       {digitalWrite (led, OFF);
       }
      
      break;

    case OFF :
      if (results.value == s1)  // Signal 1 Regelung Lüfter Dampf
      {
        Serial.print(state);
        digitalWrite (led, HIGH);           // mache Lüfter an
        startled == millis();
        state = ON;
      }
      break;
  }




 irrecv.resume();                // Warte auf nächsten Wert
}
}

Dann klappt das leider nur 1 mal und danach kann ich die Led nicht mehr anmachen.
Vielen Dank für eure Mühe!!!

Hallo,

also ich schlage vor als erstes postest du mal die Namen wie man die Bauteile nennt wenn man deine wirkliche Hardware in die Hand nimmt.

An deinem IO-Ausgang den du mit

digitalWrite (led, HIGH);           // mache Lüfter an

schaltest
steht im Kommentar "Lüfter"

Es mag sein, das du dich wegen der bisher eher geringen Kenntnissen nicht traust am Code etwas zu ändern. Wenn du selbsterklärende Namen verwendest machst du dir das Programmieren einfacher.

Wenn du die Namen selber anpassen willst um so besser.

Ich biete an du benennst die ganzen Bauteile und auch die Tasten auf deiner IR-Fernbedienung so wie sie wirklich heißen und ich benenne das im Code entsprechend um.
Dadurch dass die Namen selbsterklärend sind liest du den Variablennamen und weißt sofort um was es sich handelt. Und es wird kein Kommentar mehr benötigt.

vgs

Zur Funktionalität:

Wenn S1 betätigt wird

  • schalte Lüfter sofort ein
  • und starte eine Zeitüberwachung begrenze Laufzeit
  • Wenn X Minuten Zeit vergangen sind = Laufzeit vorbei schalte Lüfter aus
  • de-aktiviere verzögertes Einschalten

Wenn S2 betätigt wird:

  • schalte Lüfter sofort aus,
  • verzögertes Einschalten de-aktivieren

Wenn S3 betätigt wird:

  • aktiviere verzögertes Einschalten
  • wenn Zeit Y vorbei ist
  • wechsle auf Modus "S1" ( der dann verzögertes Ausschalten nach Zeit X macht)

Das heißt es gibt drei Zustände

  1. Lüfter sofort ein nach Zeit X Lüfter aus
  2. Lüfter aus
  3. verzögertes Lüfter einschalten

Poste Variablennamen die diese drei Zustände für dich selbsterklärend auf den Punkt bringen.

vgs

OFF / On / WAIT