Entprellen fkt. nicht.

Hallo Forum,

ich hab mir einen Arduino auf dem Breadboard mit einem Mega328 gebaut. Ich habe ein Display dran und möchte jeden Tastendruck zählen und am Display anzeigen. Soweit funktioniert alles, nur das Entprellen des Tasters will nicht. Soll heißen, wenn ich den Taster einmal drücke, dann zählt er gleich bis auf 100 hoch oder so.

Mein Sketch sieht so aus:

#include <Bounce.h>
#include <LiquidCrystal.h>
#include <LCDMenuLib.h>
#include <LCDMenu.h>
#include <LCDMenuLib_makros.h>


// Display Konfiguration
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
/* Sonderzeichen für das LCD */
  #define _LCD_ARROW_UP                     {0x04,0x0E,0x15,0x04,0x04,0x04,0x00,0x00}
  #define _LCD_ARROW_DOWN                   {0x00,0x04,0x04,0x04,0x15,0x0E,0x04,0x00}
  
  
// Taster Beschaltung
int MenuPin = 8;
Bounce bouncer=Bounce(MenuPin,100);  
  
//diverses
int ret;
int count=0;

void setup() {
    pinMode(MenuPin, INPUT_PULLUP);
    lcd.begin(16,4);
    lcd.clear();
    lcd.print(count);
  }
  
void loop() {
    //Entprellen
    bouncer.update();
    
    ret=bouncer.read();
    if (ret==LOW) {
      count++;
      lcd.setCursor(0,0);
      lcd.print(count);
    }  
  }

Jemand ne Idee?

Markus

Da hat nichts mit prellen zu tun. Das Problem ist Du zählst hoch solange der Taster gedrückt ist. http://www.arduino.cc/en/Tutorial/Switch Grüße Uwe

uwefed:
Da hat nichts mit prellen zu tun.
Das Problem ist Du zählst hoch solange der Taster gedrückt ist.
http://www.arduino.cc/en/Tutorial/Switch
Grüße Uwe

Ok, wenn ich dich richtig vestehe, müsste ich nach einem Zählvorgang warten bis sich der Status des Taster mindestens einmal geändert hat. Also abwarten bis er wieder HIGH ist und bei einem anschließenden LOW erst wurde der Taster erneut gedrückt?

Ich dachte das wäre ein “Nebeneffekt” des debouncens… :drooling_face:

Markus

debouncen glättet dir nur die Signalwelle beim drücken, indem einfach abgewartet wird, bis das schwingen nachlässt, oder ein mittelwert aus HIGH/LOW gebildet wird. Du musst beim drücken einen Status auf z.B. "pressed = 1" setzen und beim loslassen auf "pressed = 0" - und dann in der schleife abfragen, was einmal passieren soll und ggf. einen zweiten status setzen

MarkusH: Ok, wenn ich dich richtig vestehe, müsste ich nach einem Zählvorgang warten bis sich der Status des Taster mindestens einmal geändert hat. Also abwarten bis er wieder HIGH ist und bei einem anschließenden LOW erst wurde der Taster erneut gedrückt?

genau; beim ersten LOW nach einem HIGH den Zähler um 1 erhöhen.

Grüße Uwe

MarkusH: Ok, wenn ich dich richtig vestehe, müsste ich nach einem Zählvorgang warten bis sich der Status des Taster mindestens einmal geändert hat.

Das kann man natürlich auch anders lösen.

Ich habe mal auf die Schnelle eine Button-Klasse gemacht, mit einer "pressed" Funktion, die immer 0 zurückliefert, solange sie aufgerufen wird, aber der Button nicht gefeuert hat.

Der Button liefert (einmalig pro Tastendruck beim Loslassen) eine "1" zurück, wenn er kurz gedrückt war (> Debounce-Zeit).

Der Button liefert (einmalig pro Tastendruck beim Loslassen) eine "2" zurück, wenn er lang gedrückt war (> longpress-Zeit).

Der Pin, die Debounce-Zeit, die Longpress-Zeit und ob es ein INPUT oder INPUT_PULLUP Button ist, wird zusammen mit der Variablendeklaration festgelegt.

Das Beispielprogramm zählt bei kurzen Tastendrücken einen Counter hoch und gibt ihn über den seriellen Monitor aus.

Ein langer Tastendruck setzt den Zähler auf Null zurück.

Im Beispiel wird der Button initialisiert mit buttonClass button(3,INPUT_PULLUP,20,1000); ==> Button an PIN-3 ==> mit internem PullUp-Widerstand aktiviert ==> 20 ms Entprell-Zeit (= Mindestzeit für "kurze" Tastendrücke) ==> 1000 ms Mindestlänge für "lange" Tastendrücke

Teste mal (ich habe das gerade fertig gecodet und noch nicht viel damit getestet):

class buttonClass {
  private:
    int pin;
    int type;
    int debounce;
    int longPress;
    boolean down;
    boolean isDown;
    unsigned long lastpressed;
  public:

  buttonClass(int iPin, int iType, int iDebounce, int iLongPress)
  {
    pin=iPin;
    type=iType;
    debounce=iDebounce;
    longPress=iLongPress;
    if (type!=INPUT_PULLUP) type=INPUT;
    pinMode(pin,type);
    down=false;
    isDown=false;
    lastpressed=0;
  } // buttonClass setup finished
  
  int pressed()
  {
    down=(digitalRead(pin)==HIGH==(type==INPUT) || digitalRead(pin)==LOW==(type==INPUT_PULLUP));
    if (down && !isDown) 
    {
      lastpressed=millis();
      isDown=true;
    }
    else if (!down && isDown)
    {
      isDown=false;
      if (millis()-lastpressed>longPress) return 2;
      if (millis()-lastpressed>debounce) return 1;
    }   
    return 0;
  } // pressed()
};


void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
}

// Button für pin-3,INPUT_PULLUP, debounce=20ms, longpress= 1000ms
buttonClass button(3,INPUT_PULLUP,20,1000);

void loop() {
  // put your main code here, to run repeatedly: 
 int buttonResult=button.pressed(); 
 static int counter=0;
 switch (buttonResult)
 {
   case 1: counter++;break; // kurzer Tastendruck, Zähler hochzählen
   case 2: counter=0;break; // langer Tastendruck, Zähler rücksetzen
 }
 if (buttonResult!=0) Serial.println(counter); 
}

Funktioniert gut, vielen Dank!

Die Bounce-Klasse hat die Funktionen: risingEdge(), fallingEdge(). Damit könnte man genauso die Flanken erkennen und darauf triggern.

Grüße Nighti

Nighti: Die Bounce-Klasse hat die Funktionen: risingEdge(), fallingEdge(). Damit könnte man genauso die Flanken erkennen und darauf triggern.

Grüße Nighti

Du liebes bischen! Wie kann man (ich) nur so blind sein? :)

Danke für den Hinweis, genauso wollte ich es haben, der Tastendruck kommt jetzt auch sofort und nicht erst beim loslassen. Wär zwar nicht so schlimm gewesen, aber so gehts halt noch einfacher.

Markus