Hallo liebe alle,

Derzeit lässt sich die Led mittels Button ein und ausschalten. Je nachdem welcher Zustand LOW oder HIGH gewählt wurde. Habt ihr eine Idee, ich glaube ich habe schon irgendwo einmal was hier gelesen, dass man den Wert des Buttons über eine andere Variable zwischen speichert. Wie würdet Ihr das umsetzen?

Anbei simple Status Quo:
int led = 9;
int schalter = 5;

void setup() {
pinMode(led,OUTPUT);
pinMode(schalter, INPUT);
digitalWrite(schalter, HIGH);
}

void loop() {
digitalWrite(led,!digitalRead(schalter));

}

LG


4 Antworten

Raabinator – 10.12.2015

Hallo Stefanie.

Ich nehme an, du möchtest nur auf eine Zustandsänderung des Buttons reagieren. Momentan wird in jedem Durchlauf von loop() nur der aktuelle Zustand an die LED übertragen.
Um auf diese Schaltflanken zu reagieren, musst du dir den letzten Zustand des Button zwischenspeichern und dann diesen immer mit dem aktuellen Zustand des Button vergleichen.
Zunächst erzeugst zu dir über Setup() eine sogenannte globale Variable:
int buttonZuletzt;
Am Ende von setup() initialisierst du diese Variable mit dem Zustand des Button:
buttonZuletzt = digitalRead(schalter);
In loop() vergleichst du nun immer den Zustand mit dem in der Variablen. Hat er sich geändert, dann reagierst du darauf. Aber nicht vergessen, den dann neuen Zustand wieder merken.

loop()
{
  if(buttonZuletzt != digitalRead(schalter))
  {
    // Änderung hat stattgefunden
    if(buttonZuletzt)
    {
      // buttonZuletzt war <>0, also nicht gedrückt (low-aktiv)
      // muss dann jetzt gedrückt sein
      digitalWrite(led, 1);  // LED ein
      Serial.println("gedrückt");
      buttonZuletzt = 0;  // merken, dass jetzt gedrückt
    }
    else
    {
      // buttonZuletzt war =0, also gedrückt (low-aktiv)
      // muss dann jetzt nicht gedrückt sein
      digitalWrite(led, 0);  // LED aus
      Serial.println("losgelassen");
      buttonZuletzt = 1;  // merken, dass nicht mehr gedrückt
    }
    delay(30);  // zum entprelen verzögern (einfache Version)
  }
}

Das delay(30) am Ende benötigst du, um dem Button Zeit zu geben (30ms), seinen Kontakt vollständig zu öffnen oder zu schließen. Dein Controller ist nämlich so schnell, dass er ohne mehrere Zustandswechsel erkennen würde, obwohl der Button nur einmal betätigt wurde.

Ich hoffe, damit ist dir etwas geholfen.

Raabinator – 10.12.2015

Noch eins. In deiner setup() solltest du
pinMode(schalter, INPUT);
gegen
pinMode(schalter, INPUT_PULLUP);
ersetzten, wenn du nicht einen externen Pull-Up Widerstand verwendest.
Ansonsten bekommst du keinen definierten Zustand und der Schalter reagiert evtl. willkürlich.

Stefanie – 11.12.2015

Vielen Dank Raabinator,

habe es aufbauend auf deiner Idee so gelöst:

int led = 9;
int schalter = 5;
int buttonZuletzt = 0;
int led_an = 0;
 
void setup() {
  pinMode(led,OUTPUT);
  pinMode(schalter, INPUT_PULLUP);
  digitalWrite(schalter, HIGH);
}

void loop()
{
  if((buttonZuletzt == 0) && (!digitalRead(schalter) == 1)) // ueberpruefe ob schalter gerade rising edge hat (betätigt wurde). 
  {
   if(led_an == 1) { led_an = 0; } // toggle led_an
   else { led_an = 1; }
  }

  buttonZuletzt = !digitalRead(schalter); // speichere alten schalterzustand
  digitalWrite(led,led_an); // setze led entsprechend
  delay(30);  // zum entprellen verzögern (einfache version)
}

Raabinator – 11.12.2015

Hallo Stefanie,

Du wolltest also die LED mit dem Taster bei Druck Ein-/Ausschalten. Hab ich wohl falsch verstanden.
Eine Variable “toggeln” geht auch einfacher: led_an = !led_an;
Das späte Speichern des Schalterzustandes birgt die Gefahr, dass sich der Zustand gerade zwischen deiner Abfrage und dem Speichern ändert. Dann bekommst du einen Tastendruck nicht mit.
Das delay() am Ende in der Hauptschleife verzögert das gesamte Programm. Solange es nichts anderes machen soll ist das OK.
Besser ist es, sich nach der Tastenänderung die aktuelle Zeit zu merken (millis()) und vor erneuter Taster-Prüfung nachzusehen, ob bereits genug Zeit vergangen ist.

Beispiel:

unsigned long lastTime = 0L;  // merkt sich die Zeit der letzten Änderung
int buttonZuletzt = 0;  // letzter Zustand des Tasters
int led_an = 0;  // Zustand der LED
#define VERZOEGERUNG 30L

loop()
{
  // ... Mein übriges Programm, das gerne nicht verzögert wäre ...
  if((millis() - lastTime) >= VERZOEGERUNG)  // Genügend Zeit seit der letzten Änderung vergangen?
  {
    // ... ja, Taste auf Änderung prüfen und reagieren
    int buttonJetzt = digitalRead(schalter);  // einmal merken, ist sicherer
    if(buttonJetzt != buttonZuletzt)
    {
      // Zustand geändert
      buttonZuletzt = buttonJetzt;  // neuen Zustand merken
      lastTime = millis();  // Zeit der Änderung merken
      // ... Reaktion auf die Änderung
      if(!buttonJetzt)
      {
        // Gedrückt!
        led_an = !led_an;  // toggeln
        digitalWrite(led,led_an); // setze led entsprechend
      }
    }
  }
  // ... noch mehr Programm, das gerne nicht verzögert wäre ...
}