Home / Arduino / Arduino: Taster abfragen und entprellen

Arduino: Taster abfragen und entprellen

005

Manchmal möchte man einige Funktionen des Arduinos per Tastendruck steuern können. Zum Glück ist das Anschließen eines Tasters sehr einfach und es gibt sogar einen fertigen Sketch, den man unter Beispiele –> 02.Digital –> Button finden kann.

 

Neben einem Arduino, braucht man natürlich nur noch einen Taster und einen Widerstand. Der Widerstand hält die Spannung am Pin2 auf Masse, bis man den Taster betätigt, dann springt die Spannung sofort auf  Betriebsspannung. Diese Spannungserhöhung wird vom Arduino erfasst und kann über die Funktion digitalRead ausgelesen werden.

Arduino Taster_Steckplatine

Der Sketch versetzt den Pin 2 zuerst in den Inputmodus und Pin 13 in den Outputmodus. An Pin 2 befindet sich natürlich unser Taster und an Pin 13 ist auf dem Arduino sowieso schon eine LED eingebaut. In der Loop Schleife wird kontinuierlich über die Funktion digitalRead die Variable buttonstate entweder auf 0 oder 1 gesetzt, je nachdem ob der Taster betätigt wurde oder nicht. Wurde die Variable auf 1 gesetzt, dann leuchtet die LED auf, ansonsten bleibt sie dunkel. Das ganze funktioniert auch wunderbar, wovon man sich gerne selbst überzeugen kann.

Dieser Code eignet sich aber nicht um auf einzelne Tastendrücke zu reagieren. Wenn man den Taster gedrückt hält, ändert sich zwar rein optisch nichts aber der Code in der if-Bedingung wird dennoch jedesmal ausgeführt. Möchte man jedoch, dass für jedes einzelne Drücken des Tasters etwas passiert, dann klappt das so noch nicht.

Einzelne Tastendrücke verarbeiten

Für einzelne Tastendrücke muss das Programm des Arduinos sich merken ob der Taster bereits gedrückt wurde oder nicht, indem er diese Information in einer Variable speichert. Ich habe dafür den Sketch einmal ein wenig Code umgeschrieben:

/*
  Button

 Turns on and off a light emitting diode(LED) connected to digital
 pin 13, when pressing a pushbutton attached to pin 2.


 The circuit:
 * LED attached from pin 13 to ground
 * pushbutton attached to pin 2 from +5V
 * 10K resistor attached to pin 2 from ground

 * Note: on most Arduinos there is already an LED on the board
 attached to pin 13.

 */

// constants won't change. They're used here to
// set pin numbers:
const int buttonPin = 2;     // the number of the pushbutton pin
const int ledPin =  13;      // the number of the LED pin

// variables will change:
int buttonState = LOW;         // variable for reading the pushbutton status
int buttonread = 0;

void setup() {
  // initialize the LED pin as an output:
  pinMode(ledPin, OUTPUT);
  // initialize the pushbutton pin as an input:
  pinMode(buttonPin, INPUT);
  Serial.begin(9600);
}

void loop() {
  // read the state of the pushbutton value:
  buttonread = digitalRead(buttonPin);

  // check if the pushbutton is pressed.
  // if it is, the buttonState is HIGH:
  if (buttonread == HIGH) { //Check if Button was pressed before and being pressed now

    if (buttonState == LOW)
    {
      // turn LED on:
      digitalWrite(ledPin, HIGH);
      buttonState = HIGH;
      Serial.println("Button pressed");
    }
  }
  else {
    if (buttonState == HIGH) {
      digitalWrite(ledPin, LOW);
      buttonState = LOW;
    }
  }
}

ButtonState wird ganz am Anfang auf LOW initialisiert. Diese Variable speichert, ob der Taster schon gedrückt wurde. Ist diese LOW, wurde der Taster also noch nicht gedrückt, und ist der aktuelle Zustand des Tasters HIGH, dann erkennt dies eine geschachtelte if-Abfrage und gibt uns die Statusmeldung „Button pressed“ aus. Danach wird ButtonState auch auf HIGH gesetzt, da wird den Taster ja auch gedrückt haben. Sollte beim nächsten Durchlauf der Taster immer noch auf High gesetzt sein, passiert gar nichts.

An sich funktioniert das auch, aber…was ist das?

Button_prellen

Was ist Prellen und wie kann man Taster Entprellen?

Wenn man den Sketch ausprobiert, kommen häufig mehrere „Button pressed“ Nachrichten über die serielle Schnittstelle, obwohl man den Taster nur einmal gedrückt hat.  Das obige Bild z.B. ist nach einem einzigen Tastendruck entstanden. Was passiert hier? Wenn man den Taster betätigt schließt man zwar einen Stromkreis, aber das geschieht nicht sofort. Die mechanischen Bauteile im Taster sind nicht perfekt und beim Schließen kann es, zum Beispiel, zu Vibrationen kommen. Dabei öffnet und schließt sich der elektrische Kontakt abwechselnd sehr schnell und für den Arduino sieht es so aus, als würde man den Taster sehr, sehr schnell mehrmals drücken. Dieses Verhalten nennt man auch „Prellen„. Wie man sich vorstellen kann ist das ziemlich schlecht. Eine Tastatur würde z.B. pro Tastendruck mehrere Zeichen hintereinander ausgeben. Die Korrektur dieses Verhalten heißt dementsprechend „Entprellen„. Es gibt dafür mehrere Ansätze, sowohl durch elektronische Schaltungen als auch nur per Software.

Entprellen per Software

Am einfachsten entprellt man einen Taster durch das Einlesen des Tasters einen kurzen Moment zu warten und dann, falls dieser HIGH war, den Zustand des Taster noch einmal einzulesen. Sollte der Taster immer noch auf HIGH sein, dann hat man relative sicher einen Tastendruck registriert:

void loop() {
  buttonread = digitalRead(buttonPin);

  if (buttonread == HIGH) { 
    delay(5);
    if (digitalRead(buttonPin)) { //Check button twice

      if (buttonState == LOW)
      {
        if (digitalRead(buttonPin)) {
          // turn LED on:
          digitalWrite(ledPin, HIGH);
          buttonState = HIGH;
          Serial.println("Button pressed");
        }
      }
    }
  }
  else {
    if (buttonState == HIGH) {
      digitalWrite(ledPin, LOW);
      buttonState = LOW;
    }
  }
}

Wie lange man genau warten muss, hängt von Fall zu Fall ab und ist oft nicht besonders kritisch. Für gewöhnlich reichen 5 bis 50 Millisekunden. Das ganze lässt sich natürlich noch in eine nette Funktion packen, die uns HIGH zurück gibt, wenn der Taster einmal gedrückt wird und ansonsten LOW.

int debounce(int buttonPin) {
  static int buttonState;
  if (digitalRead(buttonPin)) {
    delay(5);
    if ((digitalRead(buttonPin)) ) {// Button was pressed 5ms before and is still pressed now
      
      
      if (buttonState == LOW) {//button changed LOW-->HIGH
        buttonState = HIGH;
        return HIGH;
      }
      if (buttonState == HIGH) {//button was already HIGH
        return LOW;
      }   
    }
  }
  //bounce or button low
  buttonState = LOW;
  return LOW;
}

Leave a Reply

Your email address will not be published. Required fields are marked *

*