Go Down

Topic: Mehrere Inputs debouncen (Read 688 times) previous topic - next topic

sxon

Moin,

ich quäle mich seit mehreren Tagen mit dem Problem mehrere Inputs (via buttonState) zu debouncen. Ein einzelner Input ist kein Problem, da habe ich mit der bounce library gearbeitet. Ich habe es allerdings nicht geschafft diese so umzubauen das es auch mit mehreren Inputs funktioniert.

Code: [Select]

int buttonState = 0;
...
void loop(){
buttonState = digitalRead(buttonPin);
if (buttonState == HIGH) {
   Serial.print("H");
}
else {
   Serial.print("L");
}


Ich habe gelesen das die bounce library gänzlich ungeeignet sein soll, wie kann ich also mehrere Inputs debouncen?

Gruß sxon

sschultewolter

Warum soll die bounce libary ungeeignet sein? Die geht wunderbar. Von deinem Sketch her sehe ich aber nicht, ob du es überhaupt irgend schon versucht hast.
Keinen technischen Support über PN!

sxon

Wie gesagt, ich habe das nur gelesen.

Code: [Select]
#include <Bounce2.h>

#define OUT_PIN 11
#define LEDPin 10
#define buttonPin 13


// Instantiate a Bounce object
Bounce debouncer = Bounce();


int x_buttonState = 0;
int y_buttonState = 0;


void setup()
{
  Serial.begin(9600);
  pinMode(buttonPin, INPUT);
  pinMode(LEDPin, INPUT);
 
  digitalWrite(buttonPin,HIGH);
  digitalWrite(LEDPin,HIGH);
 
  debouncer.attach(buttonPin);
  debouncer.interval(5);

  debouncer.attach(LEDPin);
  debouncer.interval(5);
 
  //Setup the LED
  pinMode(HUPE_PIN,OUTPUT);
 

}

void loop(){
x_buttonState = digitalRead(buttonPin);
if (x_buttonState == HIGH) {
    Serial.print("H");
}
else {
    Serial.print("L");

}
y_buttonState = digitalRead(LEDPin);
if (y_buttonState == HIGH) {
    Serial.print("H");
}
else {
    Serial.print("L");

}
// Update the debouncer
  debouncer.update();

// Get the update value
int value = debouncer.read();

// Turn on or off the LED
if ( value == HIGH) {
   digitalWrite(OUT_PIN, HIGH );
} else {
    digitalWrite(OUT_PIN, LOW );
}

}

Darkwing

Ich persönlich bin dazu übergegangen, bestimmte Dinge auch mal ganz einfach in Hardware zu lösen. Wenn es also dein Projekt erlaubt, und du sowieso hier und da noch andere Komponenten benutzt, dann kommts auf ein paar mehr oder weniger sicher auch nicht mehr drauf an.??;)

Was ich damit sagen will: vllt. ist jetzt die Zeit gekommen, sich einmal das Hardware-Deboucing als Alternative anzusehen. Jeremy Blum hat dazu ein super Video gemacht: Klick! (Wir sind hier zwar im Deutsch-Abteil, aber ich hoffe du bist des Englischen trotzdem mächtig? Ansonsten einfach auf den Schaltplan und das Breadboard schauen.?;)?)

(Ist bisschen off-topic, soll auch nur als Tipp nebenbei angesehen werden; wegen dem Tellerrand und so?…?;)

Fr33man

Code: [Select]

Bounce debounce1 = Bounce();
Bounce debounce2 = Bounce();
...

debounce1.attatch(button1);
debounce2.attatch(button2);
...

Serenifly

Ja, Schmitt-Trigger mit RC-Glied ist eine schöne Schaltung dafür, und wesentlich einfacher als ein RS-Flip-Flop. Damit kann man auch problemlos mehrere Taster entprellen, da es bis zu 6 Gatter pro IC gibt. :)

sxon


Code: [Select]

Bounce debounce1 = Bounce();
Bounce debounce2 = Bounce();
...

debounce1.attatch(button1);
debounce2.attatch(button2);
...


Das erscheint logisch, funktionieren tut es aber nicht. Im SerialMonitor schreibt er dann "HLHLHLHLHL".

Hier nochmal mein angepasster Code, habe ich noch einen Fehler verbaut?
Code: [Select]
#include <Bounce2.h>

#define buttonPin3 11
#define buttonPin1 10
#define buttonPin2 13


// Instantiate a Bounce object
Bounce debounce1 = Bounce();
Bounce debounce2 = Bounce();


//const int buttonPin = 12;     // the number of the pushbutton pin
int buttonState = 0;

void setup()
{
  Serial.begin(9600);
  pinMode(buttonPin1, INPUT);
  pinMode(buttonPin2, INPUT);
 
  digitalWrite(buttonPin1,HIGH);
  digitalWrite(buttonPin2,HIGH);
 
  debounce1.attach(buttonPin1);
  debounce1.interval(5);

  debounce2.attach(buttonPin2);
  debounce2.interval(5);
 
  //Setup the LED
  pinMode(buttonPin3,OUTPUT);
 

}

void loop(){
buttonState = digitalRead(buttonPin1);
if (buttonState == HIGH) {
    Serial.print("H");
}
else {
    Serial.print("L");

}
buttonState = digitalRead(buttonPin2);
if (buttonState == HIGH) {
    Serial.print("H");
}
else {
    Serial.print("L");

}
// Update the debouncer
  debounce1.update();
  debounce2.update();

// Get the update value
int value = debounce1.read();

// Turn on or off the LED
if ( value == HIGH) {
   digitalWrite(buttonPin3, HIGH );
} else {
    digitalWrite(buttonPin3, LOW );
}
int value2 = debounce2.read();
  if ( value2 == HIGH) {
   digitalWrite(buttonPin3, HIGH );
} else {
    digitalWrite(buttonPin3, LOW );
}

}

nix_mehr_frei

Versuch doch mal beim debouncen die Zeit hochzusetzen.
Ansonsten bin ich auch für Hardwarelösungen. Ein Triggergatter benötigst du nicht. Die Digitaleingänge kommen mit einer RC Kombination auch so ganz gut klar. Grob kalkuliert ergibt 1µF x 1K = 1ms. R im Bereich 10K bis 100K und C so im Bereich 100n KerKo bis vielleicht 2,2µ Elko. Der Taster überbrückt das C und R nach Plus oder Masse, je nachdem, ob man H oder L aktiv schalten will.

Gruß Gerald
rot ist blau und Plus ist Minus

jurs


ich quäle mich seit mehreren Tagen mit dem Problem mehrere Inputs (via buttonState) zu debouncen.


Ich glaube, sowas ähnliches wird hier im Forum häufiger mal gefragt.

Ich habe daher mal eben was vorbereitet, das man dafür verwenden kann und dabei relativ allgemein gehalten ist.

Eine Datenstruktur, in die man seine Buttons verpacken kann und zwei Funktionen:
- initButtons() ==> wird in der setup-Funktion aufgerufen
- setButtons() ==> wird in der loop-Funktion aufgerufen

Die Funktion kann für beliebig viele Buttons verwendet werden, begrenzt nur die Anzahl der freien Arduino-Pins.

Die Buttons können wahlweise mit externen PullDown-Widerständen angeschlossen sein (#define BUTTONTYPE INPUT) oder es können Buttons mit den internen PullUp-Widerständen verwendet werden (#define BUTTONTYPE INPUT_PULLUP).

Man ruft in der loop die Funktion "setButtons()" auf und dabei werden für jeden einzelnen Button folgende Informationen gesetzt:
myButtons[].down ==> down ist "true", wenn der Button momentan gedrückt ist
myButtons[].pressed ==> pressed ist nur einmalig "true", wenn der Button während des letzten Aufrufs von setButtons() den Status von down==false nach down==true geändert hat.

Wer möchte, kann es ja mal ausprobieren, was man damit machen kann.
Code: [Select]

// Multiple buttons debouncing demo by 'jurs' for German Arduino Forum
#define BUTTONTYPE INPUT_PULLUP  // INPUT or INPUT_PULLUP
struct debouncedButton {byte pin; unsigned long lastChanged; boolean down; boolean pressed;};

debouncedButton myButtons[]={
  {2,0,false,false}, // pin-2
  {3,0,false,false}, // pin-3
  {4,0,false,false}, // pin-4
  {5,0,false,false}, // pin-5
  {6,0,false,false}, // pin-6
};

#define NUMBUTTONS sizeof(myButtons)/sizeof(myButtons[0])
#define DEBOUNCETIME 5

void initButtons()
{
  for (int i=0; i<NUMBUTTONS; i++)
    pinMode(myButtons[i].pin,BUTTONTYPE); // set button pinMode
}

void setButtons()
{
  for (int i=0; i<NUMBUTTONS; i++)
  {
    myButtons[i].pressed=false;
    boolean state=digitalRead(myButtons[i].pin);
    if (BUTTONTYPE==INPUT_PULLUP) state=!state;
    if (state==HIGH && myButtons[i].down==false && labs(millis()-myButtons[i].lastChanged)>DEBOUNCETIME)
    {
      myButtons[i].lastChanged=millis();
      myButtons[i].down=true;
      myButtons[i].pressed=true;
    }
    else if (state==LOW && myButtons[i].down==true && labs(millis()-myButtons[i].lastChanged)>DEBOUNCETIME)
    {
      myButtons[i].down=false;
      myButtons[i].lastChanged=millis();
    }
  } 
}


void setup() {
  Serial.begin(9600);
  Serial.println("Press any button");
  initButtons();
}


void loop() {
  setButtons();
  for (int i=0; i<NUMBUTTONS; i++)
  {
    if (myButtons[i].pressed)
    {
      Serial.print("Button pressed, Index ");Serial.print(i);
      Serial.print("\tPin ");Serial.println(myButtons[i].pin);
    }
  }
}

SkobyMobil

Hallo,
dieses "SoftWareDebouncing" habe ich aufgegeben. Es mag Leute geben die damit
klar kommen. Wenn ich das anwende suche ich nach kürzerster Zeit nach einen
Hammer um den Arduino auszuschalten.
Ich werde das in Zukunft nur noch über Hardware machen. Du brauchst dann keine
Code mehr und es funktioniert immer.
Bis dahin "behelfe" ich mich damit:

Code: [Select]
-------------------------------------------
int valZS1;                               
int buttonStateS1;                       
int buttonPressesS1 = 0;

-----------------------------------------

valZS1 = digitalRead(S1);             
if (valZS1 != buttonStateS1)
{                                     
if (valZS1 == LOW)
{                                     
buttonPressesS1++;                         
}
}
buttonStateS1 = valZS1;

if (buttonPressesS1 > 9)
{
buttonPressesS1 = 1;
}

----------------------------------------------


Damit kann ich, mit zwei Tastern, meine Uhrzeit (Tag, Monat, Jahr, Wtag, Std, Min, Sek) manuell in der RTC setzen.
Ich finde das einfach und recht "mächtig"
Gruß und Spaß
Andreas
die zweite Maus bekommt den Speck...

Fr33man

Bounce2.h ?
Welche Lib benutzt du? bei mir heißt die einfach nur Bounce.h..

im ersten Abschnitt fragst du ja wieder direkt den ButtonPin ab.. der is ja am Bouncen.. darum evtl dein "HLHLHL"..

Code: [Select]
#include <Bounce2.h>

#define buttonPin3 11
#define buttonPin1 10
#define buttonPin2 13


// Instantiate a Bounce object
Bounce debounce1 = Bounce();
Bounce debounce2 = Bounce();


//const int buttonPin = 12;     // the number of the pushbutton pin


void setup()
{
  Serial.begin(9600);
  pinMode(buttonPin1, INPUT);
  pinMode(buttonPin2, INPUT);
 
  digitalWrite(buttonPin1,HIGH);
  digitalWrite(buttonPin2,HIGH);
 
  debounce1.attach(buttonPin1);
  debounce1.interval(5);

  debounce2.attach(buttonPin2);
  debounce2.interval(5);
 
  //Setup the LED
  pinMode(buttonPin3,OUTPUT);
 

}

void loop(){

if ( debounce1.read() == HIGH) {
    Serial.print("B1 = H");
}
else {
    Serial.print("B1 = L");

}

if (debounce2.read() == HIGH) {
    Serial.print("B2 = H");
}
else {
    Serial.print("B2 =  L");

}
// Update the debouncer
  debounce1.update();
  debounce2.update();

// Get the update value
int value = debounce1.read();

// Turn on or off the LED
if ( value == HIGH) {
   digitalWrite(buttonPin3, HIGH );
} else {
    digitalWrite(buttonPin3, LOW );
}
int value2 = debounce2.read();
  if ( value2 == HIGH) {
   digitalWrite(buttonPin3, HIGH );
} else {
    digitalWrite(buttonPin3, LOW );
}

}


(Ungetestet)



Machs wie in dem unteren Abschnitt. Die Bounce-Funktion abfragen. Oder, wie bei dir, den Rückkgabewert der Bouncefunktion in eine Var packen und die dann Abfragen (Weiß nicht, ob das direkte Abfragen von debounce1.read() in einem == verwendet werden kann)

Gehen tuts auf jedenfall.. verwende es selbst genau so. Nur ich habe eine Lib, die nur "Bounce.h" heißt. Hab ich glaub ich aus dem Playground..

Gruß

sxon

#11
Feb 12, 2014, 11:17 pm Last Edit: Feb 12, 2014, 11:23 pm by sxon Reason: 1
Danke Fr33man, der Code funktioniert einwandfrei! Die Bounce2.h ist die aktuellste Library  aus dem Playground.
Die Hardwarevariante werde ich aber auch noch testen.

Vielen dank auch an alle anderen!

Gruß Daniel

Go Up