Zu Aufgabe von Tag 6: UDP Button Erweiterung

Foren Adventskalender Zu Aufgabe von Tag 6: UDP Button Erweiterung

Schlagwörter: 

Ansicht von 5 Beiträgen - 1 bis 5 (von insgesamt 5)
  • Autor
    Beiträge
  • #760
    Stefanie
    Mitglied

    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

    #761
    Raabinator
    Mitglied

    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.

    #762
    Raabinator
    Mitglied

    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.

    #790
    Stefanie
    Mitglied

    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)
    }
    #791
    Raabinator
    Mitglied

    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 ...
    }
    • Diese Antwort wurde geändert vor 8 Jahren, 3 Monaten von Raabinator.
Ansicht von 5 Beiträgen - 1 bis 5 (von insgesamt 5)
  • Du musst angemeldet sein, um auf dieses Thema antworten zu können.