Entprellung (Debounce) von Tastern

Mikrotaster
Abb.: Mikrotaster

Verwendete Bauteile

Eine Funktion oder ein elektrisches Bauteil soll beim Arduino manchmal auch durch einen diskreten Tastendruck (z.B. durch einen Mikrotaster) ausgelöst werden. Da aber beim Drücken eines Tasters niemals ein eindeutiger Übergang von HIGH zu LOW bzw. umgekehrt in Nullzeit entsteht, sondern immer eine nicht vorhersehbare Folge an HIGHs und LOWs bis der gewünschte Zustand erreicht ist ("Prellen"). Dadurch können versehentlich mehrere Umschaltungen erkannt werden. Die Lösung dieses Problems kann sowohl durch den richtigen Aufbau der Hardware als auch per Software gelöst werden ("Entprellung").

Signale bei einem prellenden Mikrotaster
Abb.: Signale bei einem prellenden Mikrotaster

Entprellung per Hardware

Durch sogenannte Pullup- bzw. Pulldown-Widerstände kann immer für ein eindeutiges Signal am entsprechenden Pin gesorgt werden. Dies sollte immer geschehen, alleine schon, um Kurzschlüsse zu vermeiden.
Weiterhin kann ein einfacher RC-Tiefpass eingesetzt werden. Hierbei wird ein Kondensator über einen Widerstand je nach Schalterstellung auf- oder entladen. Das RC-Glied bildet einen Tiefpass, sodass die Spannung über den Kondensator nicht von einem Pegel auf den anderen springen kann.

RC-Tiefpass zur Entprellung
Abb.: RC-Tiefpass zur Entprellung

Entprellung per Software

Einen Taster per Software zu entprellen ist meist billiger und kommt ohne Hardware-Komponenten aus, kann aber auch zusätzlich erfolgen. Hierfür gibt es mehrere Ansätze:

Flankenerkennung

Bei einem Taster gibt es insgesamt 4 theoretische Zustände:

  1. war nicht gedrückt und ist nicht gedrückt
  2. war nicht gedrückt und ist gedrückt (steigende Flanke)
  3. war gedrückt und ist immer noch gedrückt
  4. war gedrückt und ist nicht mehr gedrückt (fallende Flanke)

Diese einzelnen Zustände lassen sich jetzt bequem abfragen/durchlaufen. Die Entprellung geschieht dabei durch die ganze Laufzeit des Programms. Die Taster werden hierbei als Active-Low angeschlossen, um die internen Pull-Ups zu nutzen.
Die folgende Routine gibt für den Zustand "steigende Flanke" den Wert "true" zurück, sonst "false"

byte buttonState = 0;

bool isButtonPressed(byte buttonPin)
{
    byte buttonValue = digitalRead(buttonPin);

    if(buttonState == 0 && buttonValue == HIGH) {
        // Taster wird gedrückt (steigende Flanke)
        buttonState = 1;
        return true;
    } else if (buttonState == 1 && buttonValue == HIGH) {
        // Taster wird gehalten
        buttonState = 2;
        return false;
    } else if (buttonState == 2 && buttonValue == LOW) {
        // Taster wird losgelassen (fallende Flanke)
        buttonState = 3;
        return false;
    } else if (buttonState == 3 && buttonValue == LOW) {
        // Taster losgelassen
        buttonState = 0;
        return false;
    }
}

Warteschleife

Ein weiteres Verfahren ist die Warteschleife, d.h. die Rountine zum Prüfen auf einen Knopfdruck reagiert erst nach einer gewissen Zeit nach dem letzten Signal wieder. Das Intervall muss je nach Anwendungsfall etwas länger oder kürzer eingstellt werden, um ein optimales Ergebnis zu liefern.

#define BUTTON_PIN 2

const unsigned long debounceInterval = 20; // in milliseconds
volatile unsigned long lastButtonPressed=0;

void setup()
{
    pinMode(BUTTON_PIN, INPUT);
    attachInterrupt(digitalPinToInterrupt(BUTTON_PIN), isrButtonPressed, RISING);
}

void loop()
{
}

void isrButtonPressed()
{
    if((millis() - lastButtonPressed) > debounceInterval) {
        lastButtonPressed = millis();
        // now react on button press!
    }
}

Fertige Library

Natürlich kann man auch die Hilfe von Software-Libraries verwenden, z.B. Bounce2

zurück