LED mit Schalter ein- und ausschalten

10

Ich versuche, Code zu schreiben, um eine LED einzuschalten, wenn sie ausgeschaltet ist, und um sie auszuschalten, wenn sie eingeschaltet ist, indem ich einen taktilen Druckknopfschalter verwende. Ich habe geschrieben, was ich für den richtigen Code mit der wiringPi-Bibliothek halte, aber ich kann ihn nur einschalten, wenn er ausgeschaltet ist, und kann ihn danach nicht mehr ausschalten. In sehr seltenen Fällen und nach vielen wiederholten Drücken wird die LED ausgeschaltet, wenn sie eingeschaltet ist, und ich drücke die Taste, aber ich bin sicher, dass dies nicht der Fall sein soll.

#include <wiringPi.h>
int main (void)
{
    wiringPiSetup ();
    pinMode (0, OUTPUT);
    pinMode (1, INPUT);
    digitalWrite (0, LOW);
    for(;;)
    {
        if(digitalRead (1) == LOW)
        {
            if(digitalRead (0) == HIGH)
                digitalWrite (0, LOW);
            else if(digitalRead (0) == LOW)
                digitalWrite (0, HIGH);
         }
     }
     return 0;
}

Ich habe ein Bild beigefügt, wie die Schaltung verdrahtet ist.LED-Schaltung


quelle
2
Enthält Ihre Bibliothek eine Entprellung für den Switch? Wenn nicht, schalten Sie die LED wahrscheinlich erfolgreich aus und dann sofort wieder ein. Sobald Sie eine Statusänderung festgestellt haben, ignorieren Sie für kurze Zeit alle weiteren Erkennungen.
1
@ MikeW Das glaube ich nicht. Ich werde versuchen, eine Verzögerung einzufügen, nachdem eine if-Anweisung verarbeitet wurde.
6
@duskwuff Bei dieser Frage geht es definitiv um Programmierung.
1
Behalten Sie eine lokale Variable bei, die den aktuellen Status der LED enthält (EIN / AUS) (wahrscheinlich über eine Aufzählung). Versuchen Sie nicht, den Status eines Ausgangspins zu lesen. Erkennen Sie stattdessen die Flanke der Eingangszustandsänderung von hoch nach niedrig des Eingangspins. Aktualisieren Sie dann den aktuellen Status der lokalen Variablen: outputimagevar = (outputimagevar == HIGH)? NIEDRIG: HOCH; dann digitalWrite (0, outputimagevar); Wenn sich der Eingang von LOW auf HIGH ändert, setzen Sie die Erkennungslogik HIGH auf LOW zurück. Stellen Sie außerdem sicher, dass Sie den Eingabestatus "entprellen", indem Sie beispielsweise sicherstellen, dass 3 aufeinanderfolgende Lesevorgänge alle denselben Status anzeigen.
Was ich gerade getan habe, ist eine halbe Sekunde Verzögerung in das Nest jeder if-Anweisung einzufügen, und diesmal scheint es richtig zu funktionieren. Etwas sagt mir, dass dies eine Art Bruteforce-Methode ist, die nicht immer so funktioniert, wie ich es erwarten würde, wenn die Taste schneller als eine halbe Sekunde gedrückt wird, und dass sie in meinem Hauptprojekt wahrscheinlich nicht so funktioniert, also werde ich mich darum kümmern der Rest der Antworten. Ich schätze jeden Beitrag.

Antworten:

4

Die Verkabelung sieht für den Code korrekt aus.

Das Problem ist, dass sich der Code in einer sehr engen Schleife befindet. Theoretisch schaltet der Schleifenkörper beim Drücken der Taste die LED wiederholt ein und aus. Theoretisch besteht eine 50/50-Wahrscheinlichkeit, dass die LED beim Loslassen der Taste an (oder aus) bleibt. Bemerken Sie eine Helligkeitsänderung, wenn Sie die Taste drücken? Möglicherweise ist nicht genug vorhanden, um bemerkt zu werden.

In der Praxis ist der Grund für die Tendenz, die LED eingeschaltet zu lassen, die Art und Weise, wie Sie testen, ob sie bereits leuchtet. Beim Schreiben von Pin 0 HIGH werden 3,3 V an den Ausgang angelegt. Dieser Draht ist jedoch mit der LED verbunden und der Pin ist als Ausgang konfiguriert. Die LED senkt möglicherweise die Spannung so niedrig, dass sie beim Lesen nicht als HIGH registriert wird, aber manchmal, weil sie sich in der Nähe der Abschaltung befindet.

In der Praxis würde ein Code zum Ein- und Ausschalten der LED bei jedem Tastendruck einen durch eine fallende Flanke ausgelösten Interrupt verwenden. Wie in den Kommentaren erwähnt, möchten Sie den Interrupt in diesem Fall entprellen. Sie können dasselbe auch ohne Unterbrechungen tun, indem Sie den vorherigen Status der Taste aufzeichnen und die LED nur ändern, wenn sich der Status der Taste geändert hat. Das Entprellen, während der Code geschrieben wird, macht jetzt keinen Sinn.

#include <wiringPi.h>
int main (void)
{
    wiringPiSetup ();
    pinMode (0, OUTPUT);
    pinMode (1, INPUT);
    digitalWrite (0, LOW);

    int prevButton = HIGH, LED = 0;

    for(;;)
    {
        if(prevButton == HIGH && digitalRead(1) == LOW)  // a falling edge
        {
            prevButton = LOW;

            if(LED)
            {
                LED = 0;
                digitalWrite(0, LOW);
            }
            else
            {
                LED = 1;
                digitalWrite(0, HIGH);
            }
        }
        else if(prevButton == LOW && digitalRead(1) == HIGH)  // a rising edge, do nothing
        {
            prevButton = HIGH;
        )

        // Add a delay here to debounce the button 

    }
    return 0;
}

quelle
0

Es ist wahrscheinlich einfacher, den "Status" in normalen Variablen beizubehalten, als zu versuchen, ihn aus dem aktuellen GPIO-Status abzuleiten.

Außerdem verbraucht die "Busy-Loop" jeden CPU-Zyklus, den das Betriebssystem zulässt. Bei einem so einfachen Vorgang werden Sie feststellen, dass Ihre CPU-Auslastung auf 100% steigt! Sie sollten dem Prozess erlauben, die CPU usleep()beispielsweise mit einem Aufruf an andere Aufgaben abzugeben. Die Verzögerung dient auch dazu, den Schalter zu entprellen.

#include <wiringPi.h>
#include <unistd.h>

int main (void)
{
  wiringPiSetup ();
  pinMode (0, OUTPUT);
  pinMode (1, INPUT);
  digitalWrite (0, LOW);

  // Initial state
  int led = LOW ;
  bool button_down = (digitalRead(1) == LOW) ;

  for(;;)
  {
    // If button-down event (Hi-lo transition)...
    if( !button_down && digitalRead(1) == LOW )
    { 
      // Keep button state
      button_down = true ;

      // Toggle LED state
      led = (led == LOW) ? HIGH : LOW ;
      digitalWrite( 0, led ) ;
    }
    // Button up event...
    else if( button_down && digitalRead(1) == HIGH ) 
    {
      // Keep button state
      button_down = false ;
    }

    usleep( 10000 ) ;
  }

  return 0;
}
Clifford
quelle