Button liefert unterschiedliche Werte zurück

#define BUT  4 //Button LOW when pressed

void setup() {Serial.begin(9600); digitalWrite(BUT,1);}

void loop()  {getButton();}

byte getButton() //Read button LOW state with debounce
 {unsigned long curTime=0, downTime=0; 
  if(!digitalRead(BUT))
   {delay(20); //Debouncetime ?
    if(!digitalRead(BUT))
     {curTime=millis();
      while(!digitalRead(BUT)); //Wait for button up
     }
    downTime=(millis()-curTime);
    if(downTime>9000)      {Serial.println("5 Very long press");}
    else if(downTime>2000) {Serial.println("4 Long press");}
    else if(downTime>500)  {Serial.println("3 Medium press");}
    else if(downTime>200)  {Serial.println("2 Short press");}
    else                   {Serial.println("1 Click");}
   }
 }

Diese Buttonabfrage funktioniert nicht immer richtig.
Wenn man einfach drauftippt, kommt gelegentlich "4 Long press" oder auch "5 Very long press",
obwohl die Tastzeit nur 1 Click ist.
Liegt hier ein debounce vor oder warum läuft das so unzuverläßig?

Wenn Du den Button nach GND geschaltet hast, sollteest Du den inneren PullUp-Widerstand einschalten.

void setup() {Serial.begin(9600); pinMode(BUT,INPUT_PULLUP);}

Gruß Tommy

Tommy56:
Wenn Du den Button nach GND geschaltet hast, sollteest Du den inneren PullUp-Widerstand einschalten.

Das wird im Codes des Ausgangsposts ja gemacht mit:

void setup() {Serial.begin(9600); digitalWrite(BUT,1);}

Auch wenn es eventuell eine ungewöhnliche Schreibweise ist.

Vorausgesetzt der Taster ist an Pin4 und GND richtig angeschlossen...

...dann wird das Problem wohl durch Prellen entstehen.
Denn es gibt zwar die einfache Entprellmaßnahme durch ein kurzes delay, aber in den Zeilen darunter wird in der while-Schleife der Tasterpin wiederholt eingelesen und zwar ganz ohne Entprellmaßnahmen.

Du solltest also versuchen das Prellen in den Griff zubekommen.
Auch gibt es bessere Möglichkeiten die Dauer eines Tastendrucks zu erfassen, als mit Hilfe einer dieser while-Schleife.

Wie schon geschrieben, ist das nicht unbedingt eine empfehlenswerte Methode unterschiedlich lange Tastendrücke zu erkennen, da der Prozessor während des gesamten Tastendrucks blockiert ist. Das ist wie ein langes delay().

Das es aber nicht funktioniert liegt woanders: Dein Taster prellt ja auch beim Loslassen. Deine 2. Abfrage zum entprellen umfasst aber nur das while, und nicht die Zeitabfragen. Du musst also die geschweifte Klammer hinter dem while hinter die Abfragen verschieden:

#define BUT  4 //Button LOW when pressed

void setup() {Serial.begin(9600); digitalWrite(BUT,1);}

void loop()  {getButton();}

byte getButton() //Read button LOW state with debounce
 {unsigned long curTime=0, downTime=0;
  if(!digitalRead(BUT))
   {delay(20); //Debouncetime ?
    if(!digitalRead(BUT))
     {curTime=millis();
      while(!digitalRead(BUT)); //Wait for button up
     //} << Dies Klammer muss ...
     downTime=(millis()-curTime);
     if(downTime>9000)      {Serial.println("5 Very long press");}
     else if(downTime>2000) {Serial.println("4 Long press");}
     else if(downTime>500)  {Serial.println("3 Medium press");}
     else if(downTime>200)  {Serial.println("2 Short press");}
     else                   {Serial.println("1 Click");}
    } // << ... hierhin
   }
 }

uxomm:
Das wird im Codes des Ausgangsposts ja gemacht mit:

void setup() {Serial.begin(9600); digitalWrite(BUT,1);}

Auch wenn es eventuell eine ungewöhnliche Schreibweise ist.

Du hast Recht, da war ich etwas voreilig.

Gruß Tommy

MicroBahner:
Wie schon geschrieben, ist das nicht unbedingt eine empfehlenswerte Methode unterschiedlich lange Tastendrücke zu erkennen, da der Prozessor während des gesamten Tastendrucks blockiert ist. Das ist wie ein langes delay().

Das es aber nicht funktioniert liegt woanders: Dein Taster prellt ja auch beim Loslassen. Deine 2. Abfrage zum entprellen umfasst aber nur das while, und nicht die Zeitabfragen. Du musst also die geschweifte Klammer hinter dem while hinter die Abfragen verschieden:

Vielen Dank, das war's problem, jetzt scheint es bestens zu funktioniern!

Kann man das noch anders umschreiben?
Es ist etwas pingelig wenn man zB "3 Medium press" erreichen will, vor allem wenn "4 Long press" bei 750ms oder 1sec entfernt liegt...man trifft das dann nicht immer in dem zeitfenster von 250ms.

Kann man das so schreiben, daß die anzeigen jeweils nacheinender erscheinen um dann genau zu wissen,
wann man den finger vom button nehmen muß?

Hi

Ja.

Denke, Das wolltest Du aber irgendwie nicht SO wissen, oder?
Wie sieht Deine Erkennung den jetzt aus?
Da ich Deine Zeiten nicht kenne, z.B. so:
Wenn man noch keine 500ms gedrückt hat, ist's kurz.
Ab 500ms (bis 750ms) ist's 'medium'.
Ab 750ms (bis 1000ms) ist's 'long'
Alles über 1000ms ist 'extra long'.

Den Zeitpunkt, wo der Taster betätigt wird, hast Du.
Die aktuelle Zeit hast Du auch.
Somit sollte Es durchaus erreichbar sein, je nach Abstand zum Start des Drücken eine Anzeige anzupassen.
Beim Lösen des Taster (oder ab der Erkennung der längsten Zeit) ist auch klar, wie lang der Tastendruck war.

MfG