Entprellungsfunktion arbeitet nicht zuverlässig

OP #4546835
Lesenswert?

Hallo

Ich habe diese Entprellungsroutine 
https://www.mikrocontroller.net/articles/Entprellung#Flankenerkennung 
für einen "Active HIGH"-Taster umgebaut:
1
#include <avr/io.h>
2

3
#define BUTTONPORT PIND
4
#define BUTTONPIN PD2
5
 
6
char debounce(void)
7
{
8
    static unsigned char state;
9
    char rw = 0;
10
 
11
    if(state == 0 && (BUTTONPORT & (1<<BUTTONPIN)))   //Taster wird gedrueckt (steigende Flanke)
12
    {
13
        state = 1;
14
        rw = 1;
15
    }
16
    else if (state == 1 && (BUTTONPORT & (1<<BUTTONPIN)))   //Taster wird gehalten
17
    {
18
         state = 2;
19
         rw = 0;
20
    }
21
    else if (state == 2 && !(BUTTONPORT & (1<<BUTTONPIN)))   //Taster wird losgelassen (fallende Flanke)
22
    {
23
        state = 3;
24
        rw = 0;
25
    }
26
    else if (state == 3 && !(BUTTONPORT & (1<<BUTTONPIN)))   //Taster losgelassen
27
    {
28
        state = 0;
29
        rw = 0;
30
    }
31
 
32
    return rw;
33
}

Über
1
while(1){
2
    
3
    if(debounce() == 1)  LED_EVENT(LED2,2);
4
}
lasse ich eine LED blinken, wenn "rw" 1 ist.
Leider klappt das aber irgendwie nur bei jedem 2. Mal (selten auch erst 
beim 3. Drücken)
Woran kann das liegen?

Der µC läuft mit 16 MHz und nebenbei (in der While-Schleife) wird noch 
ein NeoPixelRing angesteuert.

Danke
Hannes
#4546967
Lesenswert?

Du könntest statt
1
    else if (state == 1 && (BUTTONPORT & (1<<BUTTONPIN)))   //Taster wird gehalten
2
    {
3
         state = 2;
4
         rw = 0;
5
    }

folgendes machen:
1
    else if (state == 1 && (BUTTONPORT & (1<<BUTTONPIN)))   //Taster wird gehalten
2
    {
3
         state = 2;
4
         rw = 1;
5
    }

Dadurch wird dir zumindest beim Halten des Tasters auch eine 1 
zurückgeliefert.
Was macht denn deine Funktion "LED_EVENT(LED2,2)" genau?
Du müsstest die LED ja auch irgendwo wieder ausschalten...?

Insgesamt ist diese Entprell-Funktion nicht so super.
Sie geht davon aus, dass der Taster beim Prellen bei jedem 
Funktionsaufruf seinen Zustand geändert hat.
Wenn er "langsamer" prellt (also 2 Funktionsaufrufe den gleichen Wert 
liefert) steigt diese Funktion schon aus.

Ich würde es eher über ein Timeout machen.
Also nach der Flankenerkennung (in beiden Richtungen) eine gewisse Zeit 
lang (ein paar ms) den Taster nicht abfragen.
Das kann man z.B. über einen Counter in debounce() realisieren.

Also so:
1
#define DEBOUNCE_DELAY (100)    // <--- entsprechend anpassen
2

3
char debounce(void)
4
{
5
    static unsigned char state = 0;
6
    static unsigned int  delay = 0;
7
    
8
    if (delay > 0)
9
    {
10
      delay--;
11
    }
12
    else
13
    {
14
      if(state == 0 && (BUTTONPORT & (1<<BUTTONPIN)))   //Taster wird gedrueckt (steigende Flanke)
15
      {
16
          state = 1;
17
          delay = DEBOUNCE_DELAY;
18
      }
19
      else if (state == 1 && !(BUTTONPORT & (1<<BUTTONPIN)))   //Taster losgelassen
20
      {
21
          state = 0;
22
          delay = DEBOUNCE_DELAY;
23
      }
24
    }
25

26
    return state;
27
}
OP #4548518
Lesenswert?

@Peter
Ach so! Hm, ja diesen einen Satz hatte ich dann in der Tat nicht richtig 
verstanden.

@Joe
Wie Peter schon sagte, ist das also keine Entprellfunktion. Die stand 
nur in der Liste ganz oben, deswegen hab ich die zuerst ausprobiert.
Die Timeoutvariante ist auch in dem Tutorial enthalten, wenn auch in 
anderer Form.
"LED_EVENT" schaltet die LED kurz ein und dann wieder aus.
OP #4557740
Lesenswert?

Hi Peter,

Ich habe Deinen Code (Komfortroutine) jetzt integriert.
Woran ich aber gerade grüble ist, dass das "get_key_long" bereits nach
sehr kurzem "Lang-Drücken" des Tasters registriert wird.

Ich habe in den Defines diesen Wert von 50 auf 100 geändert "#define
REPEAT_START    100 "
Da sich das Verhalten aber nicht ändert, nehme ich also an, dass ich an
der falschen Stelle gedreht habe.
Ebenso habe ich den Vorteilquotienten von 1024 auf 1600 gesetzt da ich 
mit einem höheren Takt als in Deinem Beispiel arbeite.

Mein Ziel ist es, ein Lang-Drücken von etwa 2 Sekunden zu detektieren.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren