Forum: Mikrocontroller und Digitale Elektronik Frage zu Entprellung gemäß Timer-Verfahren (nach Peter Dannegger)


von Mike (Gast)


Lesenswert?

Hallo zusammen,

ich habe eine Frage zu einem Code-Beispiel im Artikel "Entprellung":

http://www.mikrocontroller.net/articles/Entprellung
1
uint8_t key_state;
2
uint8_t key_counter;
3
volatile uint8_t key_press;
4
 
5
ISR( ... Overflow ... )
6
{
7
  uint8_t input = KEY_PIN & ( 1 << KEY0 );
8
 
9
  if( input != key_state ) {
10
    key_counter--;
11
    if( key_counter == 0xFF ) {
12
      key_counter = 3;
13
      key_state = input;
14
      if( input )
15
        key_press = TRUE;
16
    }
17
  }
18
  else
19
    key_counter = 3;
20
 
21
}
22
 
23
uint8_t get_key_press()
24
{
25
  uint8_t result;
26
 
27
  cli();
28
  result = key_press;
29
  key_press = FALSE;
30
  sei();
31
 
32
  return result;
33
}

Folgende Erklärung zum Code steht dabei - Zitat: "Da ist keine Hexerei 
dabei: In key_state wird der letzte bekannte entprellte Zustand der 
Taste gehalten. Der Pin-Eingang wird mit diesem Zustand verglichen und 
wenn sich die beiden unterscheiden, dann wird ein Zähler 
heruntergezählt. Produziert dieses herunterzählen einen Unterlauf des 
Zählers, dann gilt die Taste als entprellt und wenn dann auch noch die 
Taste gerade gedrückt ist, dann wird dieses in key_press entsprechend 
vermerkt."

Dazu habe ich folgende Fragen:

- Mit welcher Frequenz sollte die ISR (sinnvollerweise) aufgerufen 
werden?
- Wenn ich es richtig verstehe, gilt die Taste dann als gedrückt, wenn 
bei vier Aufrufen der ISR (in Folge) der Zustand der Taste abweichend 
vom jeweils vorherigen Aufruf ist und die Taste aktuell gedrückt ist? 
Wie "zuverlässig" ist das? Wenn z. B. in der Entprellungsphase bei zwei 
aufeinanderfolgenden Aufrufen der Zustand der Taste ("immer") gleich 
wäre und dann wechselt, würde die Taste nie als gedrückt erkannt, oder? 
Z. B.:

Aufruf 1: gedrückt
Aufruf 2: gedrückt
Aufruf 3: nicht gedrückt
Aufruf 4: nicht gedrückt
...

Was wahrscheinlich auch von der Frequenz der ISR abhängt?

Oder falls die Taste Hardware-seitig schon entprellt wäre, würde dieser 
Wechsel gedrückt/nicht gedrückt auch nicht auftreten und der Tastendruck 
würde nicht erkannt?

Oder versteh ich etwas vollkommen falsch?

Danke & VG
Mike

von Carsten W. (eagle38106)


Lesenswert?

Hi!

20 bis 30 ms Timer-Intervall sind völlig ausreichend.

In der ISR wird die Variable bei fertigem Entprell-Vorgang gesetzt. Im 
Hauptprogramm sollte sie nach dem Abarbeiten wieder gelöscht werden.

Gruß
Carsten

von Mike (Gast)


Lesenswert?

Danke!

Carsten Wille schrieb:
> In der ISR wird die Variable bei fertigem Entprell-Vorgang gesetzt.

Und funktioniert der Entprell-Vorgang wie von mir angenommen? 4x Aufruf 
mit unterschiedlichem Tastezustand und dann Variable gesetzt? Und sind 
die von mir genannten "Bedenken" unbegründet?

von Karl H. (kbuchegg)


Lesenswert?

Mike schrieb:

> - Mit welcher Frequenz sollte die ISR (sinnvollerweise) aufgerufen
> werden?

Ist nicht kritisch.
Wenn dein Timer in deinem Programm schon eine andere Aufgabe hat und die
ISR eine Aufruf-Zeitdifferenz im Bereich 5ms bis ca. 50ms hat, dann
passt das schon. Du kannst die Tastenentprellung da mit dazuhängen.

Hast du noch keinen Timer im Einsatz, dann such dir eine Zeit in diesem
Bereich aus, die dir genehm ist.

> - Wenn ich es richtig verstehe, gilt die Taste dann als gedrückt, wenn
> bei vier Aufrufen der ISR (in Folge) der Zustand der Taste abweichend
> vom jeweils vorherigen Aufruf ist

nicht vom 'jeweils vorhergehenden Aufruf'.
Die Taste gilt als erkannt, wenn sie 4 mal hintereinander in einem
abweichenden Zustand zum zuletzt als gültig erkannten Zustand
angetroffen wird.

> und die Taste aktuell gedrückt ist?

gedrückt ist wurscht. Die Entprellung arbeitet ja auch beim Loslassen
einer Taste.

> Wie "zuverlässig" ist das?

Extrem zuverlässig

> Wenn z. B. in der Entprellungsphase bei zwei
> aufeinanderfolgenden Aufrufen der Zustand der Taste ("immer") gleich
> wäre und dann wechselt, würde die Taste nie als gedrückt erkannt, oder?
> Z. B.:
>
> Aufruf 1: gedrückt
> Aufruf 2: gedrückt
> Aufruf 3: nicht gedrückt
> Aufruf 4: nicht gedrückt
> ...

Im Prinzip richtig.
Nur wird das nie passieren. Und zwar deshalb nicht, weil kein Mensch es
schafft eine Taste innerhalb von 20ms (4 * 5ms) zu drücken und wieder
loszulassen. 20ms sind 2 Hunderstelsekunden. In der Zeit kannst du noch
nicht mal zwinkern, geschweige denn eine Taste drücken.

> Oder falls die Taste Hardware-seitig schon entprellt wäre, würde dieser
> Wechsel gedrückt/nicht gedrückt auch nicht auftreten und der Tastendruck
> würde nicht erkannt?
>
> Oder versteh ich etwas vollkommen falsch?

Du überschätzt Menschen. Für uns sind 20 oder 50ms eine unglaublich
kurze Zeit. Ein Skirennläufer legt in dieser Zeit bei Vollgas gerade mal
ein paar Zehn Zentimeter zurück. Für uns Menschen ist alles kürzer als
1/10 Sekunde unglaublich kurz. 1/10 Sekunde sind 100ms. Und für einen µC
ist das 'alle heilige Zeiten'.

von Karl H. (kbuchegg)


Lesenswert?

> ich habe eine Frage zu einem Code-Beispiel im Artikel "Entprellung":

Na ja.
Eigentlich ist das ja kein 'Code-Beispiel' im Sinne von 
produktionstauglichem Code. Der von dir zitierte Code soll den 
eigentlichen Entprellcode vom Prinzip her nur verdeutlichen, da hier 
immer wieder im Forum die Aussage auftaucht "Der ist sooo kompliziert, 
den versteh ich nicht". Der von dir zitierte Code ist nur ein 
umgeschriebener Code, für den Fall einer einzelnen Taste und so 
aufgedröselt, dass er leichter verstehbar ist. Der eigentliche Code 
macht genau dasselbe. Nur macht er es für maximal 8 Tasten gleichzeitig, 
ist kürzer und auch schneller, so dass es keinen wirklichen Grund gibt 
die 'Langform' zu benutzen, ausser zu Studienzwecken um sich die 
Systematik zu Gemüte zu führen und einen algorithmischen Ansatzpunkt bei 
der Analyse des Originalcodes zu haben.

von Mike (Gast)


Lesenswert?

Vielen Dank!

Karl Heinz Buchegger schrieb:
> Und zwar deshalb nicht, weil kein Mensch es
>
> schafft eine Taste innerhalb von 20ms (4 * 5ms) zu drücken und wieder
>
> loszulassen.

Dann hatte ich doch was missverstanden... mein Verständnis war, dass der 
schnelle Wechsel "an <> aus" beim Drücken (bzw. Loslassen) nicht durch 
den Menschen verursacht wird, sondern durch so eine Art "Wackelkontakt" 
im Schalter (im Artikel heißt es "mechanische Vibrationen des 
Schaltkontaktes") verursacht würde - und die könnten ja extrem kurz 
sein...

Karl Heinz Buchegger schrieb:
> Die Taste gilt als erkannt, wenn sie 4 mal hintereinander in einem
>
> abweichenden Zustand zum zuletzt als gültig erkannten Zustand
>
> angetroffen wird.

"hintereinander" bedeutet doch bei aufeinander folgenden ISR-Aufrufen. 
D. h. dass der "Wackelkontakt" die gleiche Frequenz wie die ISR haben 
müsste?

Karl Heinz Buchegger schrieb:
> Der von dir zitierte Code ist nur ein
>
> umgeschriebener Code, für den Fall einer einzelnen Taste und so
>
> aufgedröselt, dass er leichter verstehbar ist

Ja, hab ich gelesen - aber wenn ich die "leichter verstehbare" Version 
schon nicht verstehe... ;-)

Karl Heinz Buchegger schrieb:
> Extrem zuverlässig

...glaube ich (auch wenn ich's wohl noch nicht 100% gerafft habe...)

von Karl H. (kbuchegg)


Lesenswert?

Mike schrieb:
> Vielen Dank!
>
> Karl Heinz Buchegger schrieb:
>> Und zwar deshalb nicht, weil kein Mensch es
>>
>> schafft eine Taste innerhalb von 20ms (4 * 5ms) zu drücken und wieder
>>
>> loszulassen.
>
> Dann hatte ich doch was missverstanden... mein Verständnis war, dass der
> schnelle Wechsel "an <> aus" beim Drücken (bzw. Loslassen) nicht durch
> den Menschen verursacht wird, sondern durch so eine Art "Wackelkontakt"
> im Schalter (im Artikel heißt es "mechanische Vibrationen des
> Schaltkontaktes") verursacht würde - und die könnten ja extrem kurz
> sein...

können sie.
Aber irgendwann pendelt sich jeder Taster dann mal in einen stabilen 
Zustand ein. Und das geht um Größenordnungen schneller, als du die Taste 
wieder loslassen kannst.
So ein Taster wechselst ja nicht ewig zwischen gedrückt und nicht 
gedrückt.


> "hintereinander" bedeutet doch bei aufeinander folgenden ISR-Aufrufen.
> D. h. dass der "Wackelkontakt" die gleiche Frequenz wie die ISR haben
> müsste?

Nö.
Das bedeutet lediglich, dass die 4 mal hintereinander abfragen so 
bemessen sind, dass auch der schleissigste Taster nach dieser Zeitspanne 
nicht mehr prellen wird. Hat er sich noch nicht eingependelt, dann 
beginnt eben die Zählung bis 4 jedesmal wieder von vorne. Aber 
irgendwann hat er sich eingependelt und dann wird 4 mal hintereinander 
der gleiche Zustand festgestellt und der Tastenzustand gilt als stabil.

von Mike (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> dann wird 4 mal hintereinander
>
> der gleiche Zustand festgestellt und der Tastenzustand gilt als stabil.

vermutlich steh ich komplett auf dem Schlauch, aber muss nicht 4 mal 
hintereinander ein unterschiedlicher Zustand festgestellt werden?

if( input != key_state )

Sonst müsste es doch heißen:

if( input == key_state )

von Karl H. (kbuchegg)


Lesenswert?

Mike schrieb:
> Karl Heinz Buchegger schrieb:
>> dann wird 4 mal hintereinander
>>
>> der gleiche Zustand festgestellt und der Tastenzustand gilt als stabil.
>
> vermutlich steh ich komplett auf dem Schlauch, aber muss nicht 4 mal
> hintereinander ein unterschiedlicher Zustand festgestellt werden?

unterschiedlich zu wem?

Antwort: zum letzten definitiv richtig erkanntem Tastenzustand.

if( input != key_state )

    .....

    key_state = input


(vermutlich reden wir eh vom selben).


Die Taste ist momentan nicht gedrückt und der Rest vom Programm weiß das 
auch.

Jetzt wird niedergedrückt.
Die Stati sind damit unterschiedlich und der Zähler zählt auf 2

Hoppla. Der Taster prellt: Der Tastenzustand ist wieder gleich dem 
letzten gemeldeten Zustand. Der Zähler wird wieder auf 3 gesetzt.

Die Kontaktzunge federt nach und stellt den Kontakt wieder her.
Damit ist (momentan nicht gedrückt) von (jetzt gedrückt unterschiedlich) 
und der Zähler geht auf 2.

Beim nächsten mal nachsehen ist der Kontakt immer noch gedrückt und der 
Zähler geht auf 1, da ja der zuletzt korrekt erkannte Zustand 'nicht 
gedrückt' (also unterschiedlich) war.

Blöder Taster, der prellt immer noch und der Kontakt geht noch mal auf.
Portzustand und letzter gemeldeter Zustand sind damit wieder gleich und 
der Zähler geht, marsch marsch, wieder zurück auf 3

Aber irgendwann hat auch dieser Preller ein Ende, der Pinzustand wird 
als gedrückt gemeldet (und damit unterschiedlich zum letzten stabilen 
Tastenzustand). Der Zähler geht auf 2

Erneutes Nachsehen, ein paar Millisekunden später. Der Kontakt ist immer 
noch geschlossen (und damit unterschiedlich zum letzten bekannten 
stabilen Zustand, welcher ja nicht gedrückt war - sieh ganz oben die 
Ausgangssituation) und der Zähler geht auf 1

Nochmal nachsehen. Der Pinzustand ist immer noch unterschiedlich. Zähler 
auf 0

Und kurze Zeit später nochmal nachsehen. Der Pinzustand ist immer noch 
unterschiedlich zum letzten stabilen Zustand. Der Zähler geht auf -1 
(0xFF) und damit ist der UNterlauf da: Die Taste ist entprellt, sie 
wurde 4 mal hintereinander in einem anderen Zustand als dem zuletzt 
stabilen Zustand (welcher nicht gedrückt war) angetroffen und gilt damit 
dann tatsächlich als gedrückt. Neuer stabiler Tastenzustand ist daher: 
Die Taste ist gedrückt - und der Zähler geht wieder auf 3.

von J.-u. G. (juwe)


Lesenswert?

Mike schrieb:
> vermutlich steh ich komplett auf dem Schlauch, aber muss nicht 4 mal
> hintereinander ein unterschiedlicher Zustand festgestellt werden?

Du hast doch in Deinem Eingangspost das Zitat aus dem Artikel 
aufgeführt:

> In key_state wird der letzte bekannte entprellte Zustand der
> Taste gehalten. Der Pin-Eingang wird mit diesem Zustand verglichen und
> wenn sich die beiden unterscheiden, dann wird ein Zähler
> heruntergezählt.

Also, wenn sich Zustand am Eingangspin und der in "key_state" 
gespeicherte letzte entprellte Zustand unterscheiden, dann wird der 
Zähler dekrementiert. Sind sie gleich, wird der Zähler zurückgesetzt.

Damit eine Zustandsänderung als gewollt interpretiert wird, müssen also 
zwei Bedingungen erfüllt sein:
1. Es muss 4x hintereinander der gleiche Zustand am Eingangspin 
festgestellt werden.
2. Dieser 4x festgestellte "neue" Zustand muss sich vom "alten" Zustand 
unterscheiden.
Erst dann wird der "neue Zustand" in "key_state" gespeichert und ist ab 
sofort der "alte" Zustand.

von Mike (Gast)


Lesenswert?

ah, ich verstehe (glaube ich zumindest) - danke für die super 
Erläuterung!

Mein Denkfehler war wohl, dass key_state nur aktualisiert wird, wenn das 
Prellen abgeschlossen ist - genau wie Du sagst, vom "definitiv richtig 
erkanntem Tastenzustand" abweicht. Da ist ja noch ein "if( key_counter 
== 0xFF )" dazwischen, bevor key_state aktualisiert wird... dachte 
irgendwie, key_state wäre der Zustand beim letzten Aufruf der ISR

Jetzt kann ich die Routine auch "bedenkenlos" einsetzen :-) oder sogar 
die schnellere und kürzere "Produktivversion" - aber da werd ich gar 
nicht versuchen sie zu verstehen, manchmal muss man auch vertrauen.

von Karl H. (kbuchegg)


Lesenswert?

Mike schrieb:
> ah, ich verstehe (glaube ich zumindest) - danke für die super
> Erläuterung!

Na siehste.
Ist eigentlich gaaaaaanz einfach.

Du hast ein Kabel in der Hand und wenn ich den Taster schliesse kriegst 
du Strom ab.
Spürst du den Strom, dann zählst du langsam von 3 bis auf 0.
Setzt der Strom zwischendurch mal kurz aus, dann war es falscher Alarm 
und du beginnst beim nächsten Stromfluss wieder bei 3, denn dann hat 
mein Taster geprellt oder es war ein ganz kurzer Fehlalarm.

Gelingt es dir bis 0 zu zählen, dann schreist du 'aua' und dein Arzt 
weiß, dass der Strom jetzt definitiv eingeschaltet ist.


:-)


(und beim Ausschalten natürlich auch in der umgekehrten Richtung. Spürst 
du nichts mehr, beginnst du wieder von 3 bis 0 zu zählen und erst wenn 
du bis 0 gekommen bist, kann man davon ausgehen, dass der Strom auch 
wirklich abgeschaltet ist. Selbst dann, wenn es dich kurzfristig noch 
mal gebeutelt hat und du erneut bei 3 hast anfangen müssen)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.