Schalter mit Abfrage für HIGH und LOW sowie Timer

Hallo Zusammen,

wie bei den meisten ersten Posts, kommt auch hier eine Anfängerfrage. Ich habe bereits erste Schalter und LEDs Programmierungen hinter mir und das Meister verstanden.
Nun bin ich an folgender Herausforderung.
Ich möchte eine grüne LED leuchten lassen wenn der Schalter an ist (Pin 7 HIGH) und eine rote LED leuchten lassen wenn der Schalter aus ist (Pin 7 LOW).
Das funktioniert soweit ganz gut, grüne und rote LED leuchten je nach Schalterstatus.
Was nicht funktioniert ist das Ausschalten nach einem delay.

Nun möchte ich noch weiter gehen und die LED (Rot oder Grün - je nach Schalterstatus) soll nach einer gewissen Zeit komplett ausgehen und nicht mehr einschalten. Erst wenn sich der Schalterstatus ändert soll die andere LED für eine gewisse Zeit leuchten.

Hier komme ich nicht weiter. Kann mir jemand einen Tip geben?
Ich denke mit for oder while könnte man es schaffen, aber wie kann ich eine Variable errechnen die dann reagiert wenn sich der Schalterstatus ändert?

Hier der Code und die Schaltung:

int LEDgruen = 10;
int LEDrot = 9;
int Switch = 7;
int SwitchStatus = 0; 
int delaytime = 1000;
void setup ()
{

pinMode(LEDgruen, OUTPUT); 
pinMode(LEDrot, OUTPUT); 
pinMode(Switch, INPUT);  
}

void loop () {
SwitchStatus=digitalRead(Switch); //Schalterstatus abfragen
if (SwitchStatus == HIGH) // Bei Schalter an
{
digitalWrite(LEDgruen, HIGH);
delay (delaytime);  
digitalWrite(LEDgruen, LOW); 
 }
if (SwitchStatus == LOW) // Bei Schalter aus
{
digitalWrite(LEDrot, HIGH);
delay (delaytime);  
digitalWrite(LEDrot, LOW); 
 SwitchStatus = LOW;
}
}

BlinkWithoutDelay

Ok, ich kann gerne das Programm mit Millis umschreiben aber ich habe noch nicht ganz verstanden wohin das führt.
Wenn ich den Schalter umlege brennt die LED für z.B. 10 Sekunden, danach soll sie ausgehen. Wenn ich erst am nächsten Tag den Schalter wieder betätige, würde doch der Speicher permanten mit der Zeitzählung vollgeschrieben werden.

Ginge nicht auch eine Möglichkeit mit einer Variablen?
Also so: Wenn Wert X = 1 dann schalte die grüne LED ein warte 10 Sekunden, schalte grüne LED aus und erhöhe Wert X = 2. Da X dann zwei ist, wird die grüne LED nicht mehr eingeschaltet und der Arduino läuft solange im Loop bis sich X ändert.
Wenn Schalter ausgeschaltet wird, dann schreibe X=3.
Bei X = 3 schalte Rote LED, warte 10 Sekunde, schalte rote LED aus und schreibe X = 2.
Wenn X = 2 dann laufe solange im Loop bis sich was ändert.

Hallo,

Delay sorgt dafür, dass der Prozessor für eine Zeit komplett blockiert. Das ist nicht schön. Deshalb beschäftige dich mit BlinkwithoutDelay und variiere es. Da immer die selben Variablen benutzt werden, wird dabei auch nicht der Speicher vollgeschrieben und wenn du das Programm 2Jahre laufen lässt.

würde doch der Speicher permanten mit der Zeitzählung vollgeschrieben werden.

Erstens würde er nicht "voll" geschrieben werden, weil du ja immer in dieselbe Variable schreiben kannst.
Zweitens macht dem Ram das nichts aus. Es hat keinen Verschleiß.

lies dir diesen Beitrag von agmue mal durch, ich denke, damit kommst du weiter
Anleitung endlicher Automat

Danke für die schnelle und kompetente Hilfe.
Ich habe jetzt alles mal umgeschrieben. Natürlich nach bestem Wissen und Gewissen.

Das Ergebnis: Die LED flackert für ein kurzen Augenblick dann ist Pause und dann flackert sie kurz wieder.
Hmm. Wo ist das Problem?

const int LEDgruen = 10; // grüne LED
const int LEDrot = 9; // rote LED
const int Switch = 7; // Schalter mit on/off
int LEDState= LOW; // Status für LED (LOW or HIGH)
unsigned long previousMillis = 0;        // Speichert letzten Zeitpunkt bei der die LED aktualisiert wurde
unsigned long currentMillis = millis(); // 
long interval = 5000;// Zeit wie lange LED leuchtet
int SwitchStatus=LOW;

void setup ()
{

pinMode(LEDgruen, OUTPUT); 
pinMode(LEDrot, OUTPUT); 
pinMode(Switch, INPUT); 



 
}
void loop () {
unsigned long currentMillis = millis(); // Zeit startet ab 0 Millisekunden

SwitchStatus=digitalRead(Switch); //Schalterstatus abfragen

if ((currentMillis - previousMillis >= interval) && (SwitchStatus == HIGH)) // Vergleich aktuelle Zeit mit gespeicherter Zeit
{
   previousMillis = currentMillis;

   digitalWrite (LEDgruen,HIGH); 
   
   } 
   
 else {

 digitalWrite (LEDgruen, LOW); 
 }
   
 }

schreibe deinen Sketch bitte in Code tags (oben links)

ich vermute mal du hast keinen Pulldown Widerstand verbaut, dann schwingt der offene Eingang wild hin und her.
nimm lieber pinMode(Switch, INPUT_PULLUP); und dafür

SwitchStatus=!digitalRead(Switch); //Schalterstatus abfragen

und den Schalter läßt du gegen GND schalten

außerdem habe ich gerade noch gesehen, das du unsigned long currentMillis = millis(); //
zweimal deklariert hast, einmal Global und einmal Lokal. War das Absicht?

Da currentMillis - previousMillis >= interval nur für einen Schleifendurchgang true wird, blitzt die LED nur kurz auf. Im nächsten Schleifendurchgang wird sie sofort wieder gelöscht.

Leider verstehe ich die Aufgabenstellung nicht, kann daher nicht helfen.

Die Aufgabenstellung ist wie folgt:
Wenn ich den Schalter einschalte, soll die grüne LED für 5 Sekunden leuchten und dann ausgehen.
Wenn ich den Schalter ausschalte soll die grüne LED für 5 Sekunden leuchten und dann ausgehen.
Also je nachdem wie der Schalter steht leuchtet die rote oder grüne LED und das für 5 Sekunden. Erst wenn man den Schalterstatus ändert, geht eine LED an und leuchtet wieder.

Habe den Code jetzt noch mal angepasst. Jetzt ist nur der umgekehrte Fall eingetreten. Die grüne LED ist aus und geht nach 5 Sekunden an, egal ob der Schalter ein ist oder nicht...

Es ist verhext, ich komme einfach nicht dahinter, ich dachte das wäre eine ganz simple Aufgabe...
(Oder ist Fehler 69 - Change User :slight_smile: )

const int LEDgruen = 10; // grüne LED
const int LEDrot = 9; // rote LED
const int Switch = 7; // Schalter mit on/off
int LEDState= LOW; // Status für LED (LOW or HIGH)
unsigned long previousMillis = 0;        // Speichert letzten Zeitpunkt bei der die LED aktualisiert wurde
//unsigned long currentMillis = millis(); 
long interval = 5000;// Zeit wie lange LED leuchtet
int SwitchStatus=LOW;

void setup ()
{

pinMode(LEDgruen, OUTPUT); 
pinMode(LEDrot, OUTPUT); 
pinMode(Switch, INPUT_PULLUP); 



  
}
void loop () {
unsigned long currentMillis = millis(); // Zeit startet ab 0 Millisekunden

SwitchStatus=!digitalRead(Switch); //Schalterstatus abfragen

if ((currentMillis - previousMillis >= interval) && (SwitchStatus == HIGH) ) // Vergleich aktuelle Zeit mit gespeicherter Zeit
{
    previousMillis = currentMillis;


    digitalWrite (LEDgruen, SwitchStatus); 

    } 
     
    
  }

versuch es mal so

[/

const int LEDgruen = 10; // grüne LED
const int LEDrot = 9; // rote LED
const int Switch = 7; // Schalter mit on/off
int LEDState= LOW; // Status für LED (LOW or HIGH)
unsigned long previousMillis = 0;        // Speichert letzten Zeitpunkt bei der die LED aktualisiert wurde
//unsigned long currentMillis = millis(); 
long interval = 5000;// Zeit wie lange LED leuchtet
int SwitchStatus=LOW;

void setup ()
{

pinMode(LEDgruen, OUTPUT); 
pinMode(LEDrot, OUTPUT); 
pinMode(Switch, INPUT_PULLUP); 



  
}
void loop () {
unsigned long currentMillis = millis(); // Zeit startet ab 0 Millisekunden
static bool Switch_alt;


SwitchStatus=!digitalRead(Switch); //Schalterstatus abfragen
if(Switch_alt !=SwitchStatus) previousMillis = millis(); // bei Änderung des Schaltzustandes Zeit merken
Switch_alt=SwitchStatus;

if ((currentMillis - previousMillis <= interval) && (SwitchStatus == HIGH) ) // Vergleich aktuelle Zeit mit gespeicherter Zeit
{
   // previousMillis = currentMillis;


    digitalWrite (LEDgruen, SwitchStatus); 

    } 
else  digitalWrite (LEDgruen, 0); 

     
    
  }


code]

Heelix:
Die Aufgabenstellung ist wie folgt:
Wenn ich den Schalter einschalte, soll die grüne LED für 5 Sekunden leuchten und dann ausgehen.
Wenn ich den Schalter ausschalte soll die grüne LED für 5 Sekunden leuchten und dann ausgehen.
Also je nachdem wie der Schalter steht leuchtet die rote oder grüne LED und das für 5 Sekunden. Erst wenn man den Schalterstatus ändert, geht eine LED an und leuchtet wieder.

Nö, das ergibt keinen Sinn, denn es gibt keine Bedingung für die rote LED. Ich könnte mir dies vorstellen:

Wenn ich den Schalter einschalte, soll die grüne LED für 5 Sekunden leuchten und dann ausgehen.
Wenn ich den Schalter ausschalte soll die rote LED für 5 Sekunden leuchten und dann ausgehen.

Was soll passieren, wenn während der 5 Sekunden umgeschaltet wird?
Ein Sketch zum drüber diskutieren:

const int LEDgruen = 10;        // grüne LED
const int LEDrot = 9;           // rote LED
const int Switch = 7;           // Schalter mit on/off
unsigned long previousMillis;   // Speichert letzten Zeitpunkt bei der die LED aktualisiert wurde
unsigned long currentMillis;    // Zeit startet ab 0 Millisekunden
long zeit = 3000;               // Zeit wie lange LED leuchtet
bool Switch_alt;
bool SwitchStatus;

void setup ()
{
  pinMode(LEDgruen, OUTPUT);
  pinMode(LEDrot, OUTPUT);
  pinMode(Switch, INPUT_PULLUP);
  SwitchStatus = !digitalRead(Switch);  //Schalterstatus abfragen
  Switch_alt = SwitchStatus;
}

void loop () {
  SwitchStatus = !digitalRead(Switch);  //Schalterstatus abfragen
  currentMillis = millis();
  if (Switch_alt != SwitchStatus) {
    previousMillis = millis();
    Switch_alt = SwitchStatus;
    if (SwitchStatus) {
      digitalWrite (LEDgruen, HIGH);
    } else {
      digitalWrite (LEDrot, HIGH);
    }
    delay(50);  // Entprellen
  }
  if ((currentMillis - previousMillis >= zeit) && (digitalRead(LEDgruen) || digitalRead(LEDrot))) {
    digitalWrite (LEDgruen, LOW);
    digitalWrite (LEDrot, LOW);
  }
}

OK, beide Sketches funktionieren, bei ardubu´s Sketch war die rote LED noch gar nicht programmiert, soweit war ich nicht nicht. Jetzt ist aber alles komplett, vielen Dank.
Während den 3 Sekunden leuchten dann beide LEDs wenn sich der Schalterstatus ändert, das ist aber ok.
Jetzt muss ich es nur noch verstehen, was ich bei dem ganzen "Blink without delay" noch nicht ganz durchstiegen habe.
Was passiert denn z.B. durch diese Aussage:
SwitchStatus = !digitalRead(Switch)
Bedeutet es: SwitchStatus ist das Gegenteil von digitalRead, also das Gegenteil von der Schalterstellung?
Oder bedeutet es: Schreibe in den Speicher von SwitchStatus das Gegenteil von der Schalterstellung?
Oder vergleiche ob beide ungleich sind?

Heelix:
Oder vergleiche ob beide ungleich sind?

Genau dieses nicht
Du weist der Variablen das Gegenteil von DigitalRead zu. Wird oft benutzt, wenn man den Taster vom Pin auf Masse anschliesst und die internen Pullup verwendet.

=! ist ungleich !=

! ist eine boolsche Negation. Nicht zu verwechseln mit der bit-weisen Negation ~

https://de.wikibooks.org/wiki/C%2B%2B-Programmierung:_Operatoren#Aussagenlogik