Forum: Mikrocontroller und Digitale Elektronik Entprellen nach Dannegger: Debounce Time


von Steve-o B. (steve_o)


Angehängte Dateien:

Lesenswert?

Hallo liebe Leute,

ich hätte mal eine Frage zum Entprellen…

Was will ich machen:

Ich möchte menschliche Reaktionszeiten mit Hilfe einer LED und eines 
Tasters auf die Millisekunde genau messen können. Des Weiteren möchte 
ich den Zeitpunkt eines Tastendrucks sowie den Zeitpunkt des 
Tastenloslassens erfassen.

Wie will ich es machen:

Ich nutze ein Arduino Board mit einem ATmega328P-PU (16Mhz Quarz) und 
bestücke es mit einer LED und drei Tastern. Programmieren tue ich in C++ 
mit dem Atmel Studio 6.

Sobald die LED leuchtet, soll man so schnell wie möglich mit einem 
Tastendruck reagieren. Die Zeit zwischen dem Einschalten der LED und dem 
Drücken des Tasters möchte ich als Reaktionszeit Speichern und an meinen 
PC schicken. Die Zeit messe ich hierbei mit einem Timer der 
folgendermaßen konfiguriert ist: (Takt 16MHz)

Timer:  TIMER0 (8-Bit)
Prescaler: 64         //16000000/64=250000
Modus: CTC
Compare Value: 249    //250000/250=1000

Wenn ich nichts falsch gemacht habe, sollte die ISR mit dieser 
Konfiguration jede Millisekunde angesprungen werden. Die ISR ist im 
Anhang untergebracht.

Zum Entprellen des Tasters nutze ich eine abgeänderte Entprellroutine 
von Peter Dannegger (hoffe ich habe sie nicht verunstaltet), da ich 
gerne drei Taster gleichzeitig verwenden möchte. Wenn ich jetzt den 
Taster drücke, wird der 3-Bit Counter jede Millisekunde heruntergezählt. 
Bei mir wären das dann 8 Millisekunden DEBOUNCE_TIME (wenn ich nicht 
irre).

Ein kleines Beispiel:
1.  LED zum Zeitpunkt t1 = 1000ms aktivieren
2.  Tastendruck wird zum Zeitpunkt t2 = 1308ms erkannt
3.  t2 – DEBOUNCE_TIME – t1 = Reaktionszeit = 300ms


Mein Problem:

Ich habe heute festgestellt, dass die Debounce_Time nicht immer genau 8 
Millisekunden beträgt?! Das hab ich leicht übersehen....
Denn wenn der Taster prellt und sich kurzzeitig wieder im letzten 
bekannten entprellten Zustand befindet während die ISR angesprungen 
wird, dann wird der Counter wieder zurückgesetzt und beginnt wieder bei 
7 mit dem Runterzählen.

Wenn das tatsächlich häufiger sein sollte und ich nicht irgendeinen 
Schmarrn denke, wie kann ich dieses Problem umgehen??

Ich möchte maximal eine Millisekunde bei der Erfassung der Reaktionszeit 
danebenliegen.

Bin wie immer für jede Hilfe dankbar. Solltet ihr sonst irgendwelche 
Fehler im Programm finden dann zögert nicht es mir mitzuteilen, ich bin 
schon gespannt was diesmal alles falsch ist :/

Viele Grüße,
Steve-o

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Wen du die Reaktionszeit messen willst, solltest du tunlichst nicht 
entprellen. Denn sonst misst du die Reaktionszeit + Tasterprellen + 
Entprellzeit. Und zumindest die dir letzten beiden kann der Proband 
nichts...  :-o

von Steve-o B. (steve_o)


Lesenswert?

@Lothar:

Ich verstehe was du meinst aber wenn ich nicht entprelle, dann kommt 
auch nicht nur eine Reaktionszeit an sondern 2 oder 3 und das Programm 
wird unberechenbar.

Hat jemand ne konkrete Idee wie ich das mit Entprellen hinbekommen 
könnte?

Thx

von Jonas K. (jonas_k)


Lesenswert?

nachdem die led sich geändert hat misst du einfach die Zeit bis sich 
irgendwas tut am Taster
dann wird der aktuelle wert der Zeit gespeichert /übermittelt

entprellen brauchst du nicht.

nächsten Wert kann es erst geben wenn die led geändert wurde und NICHT 
wenn sich der Taster ändert

von Steve-o B. (steve_o)


Lesenswert?

@Jonas:

Ja das ist eine gute Idee, nur leider habe ich in der Beschreibung etwas 
vergessen. Ich möchte alle Tastendrücke aufzeichnen, egal welchen 
Zustand die LED hat. Nur wenn die LED an ist und ein Tastendruck erfolgt 
wird zusätzlich noch die Reaktionszeit übertragen. Ansonsten nur die 
Zeitpunkte der Tastendrücke bzw. des Loslassens.

Sry für die ungenaue Angabe,

Grüße,

Steve-o

von Steve-o B. (steve_o)


Lesenswert?

Hat keiner noch ne andere Idee?

von spontan (Gast)


Lesenswert?

Was für Ideen brauchst Du noch????


Vorschlag:  Überleg Dir einfach wie Du einen tastendruck erkennen 
würdest, wenn Du das Programm wärst.

Hilfestelung:

1.  Beobachte den Input-Pin

2.  Er ist high oder low was immer gedrückt heißt, aktuelle Zeit 
speichern

3.  In den nächsten x  milliSekunden ignorierst Du den Input-Pin, da die 
Taste ja prellen kann

4.  Jetzt beobachstest Du wieder den Input-Pin

5.  Wenn die Taste losgelassen wird, so speichere die aktuelle Zeit

6. Wiederhole Punkt 3, die Taste kann ja prellen.

7. Fang bei Punkt 1 wieder an


Was Du mit dieser Prozedur machst ist

a) Erkennen des Wechsels am Input-Pin (press - release)

b) Du erfaßt alle Dir wichtigen Zeiten ohne Verzögerung.


Was Du beachten solltest:

Störimpulse aus der Umgebung sollten keinen Tastendruck vortäuschen -> 
niederohmig aufbauen = laß ruhig ein paar Milliampere durch die Taste 
fließen

Verwende eine robuste Taste, die Testpersonen werden kräftig draufhauen


Für die Zukunft:

Selber denken ;-)

von Fabian O. (xfr)


Lesenswert?

Nachdem eine Taste gedrückt wurde darfst Du halt eine gewisse Zeit lang 
alle weiteren Pin-Wackler nicht berücksichtigen.

Sagen wir mal, Du hast einen Timer-Interrupt, der jede Millisekunde 
kommt. Dann könnte es in etwa so aussehen:
1
#define TASTER_ANZAHL 3
2
#define ENTPRELL_ZEIT 8
3
4
uint8_t entprell_zaehler[TASTER_ANZAHL] = {0};
5
6
TIMER_ISR()
7
{
8
  for (uint8_t i = 0; i < TASTER_ANZAHL; i++) {
9
    if (entprell_zaehler[i] > 0) {
10
       // Entprellzeit läuft noch => Änderungen ignorieren
11
       entprell_zaehler[i]--;
12
    } else {
13
      // Entprellzeit abgelaufen => Änderungen auswerten
14
      if (taste_geaendert(i)) {
15
        aktion_aufzeichnen(i);
16
        entprell_zahler[i] = ENTPRELL_ZEIT;
17
      }
18
    }
19
  }
20
}

von Karl H. (kbuchegg)


Lesenswert?

Im Grunde läuft es darauf hinaus, dass du jede Änderung des 
Tastenzustands erst mal als vom Benutzer verursacht ansiehst. Mit einer 
Ausnahme: Wenn die Zeit zwischen den Wechseln zu kurz war, dann KANN das 
nicht benutzerverursacht sein. Kein Mensch, egal wie schnell er ist, 
schafft es eine Taste innerhalb von 5 Millisekunden zu drücken und 
wieder loszulassen.

Als die ersten Digitaluhren mit Stoppfunktion aufkamen, war es unter uns 
Schülern ein beliebtes Spiel die Start/Stop Taste so schnell es geht 2 
mal hintereinander zu drücken. Schneller als ein paar 
Hunderstel-Sekunden ging nicht. Meist war man im Bereich von so um die 
14 Hunderstel. D.h. da bist du mit deinen Millisekunden noch relativ 
weit weg.
Eine Reaktionszeit von signifikant weniger als einer Zehntel Sekunde 
nach dem Aufleuchten einer LED würde ich ehrlich gesagt in das Reich der 
Fabel verweisen. Das ist entweder pures Glück, sprich er hat mit dem 
Drücken schon begonnen als die LED noch gar nicht geleuchtet hat oder 
ein Messfehler. Und schon rein aus mechanischen Gründen kann ein 
Tastendruck auch nicht beliebig kurz sein.

von Steve-o B. (steve_o)


Lesenswert?

Hey Jungs!

Vielen Dank an alle für die Hilfe.

@spontan:
diese Lösung hatte ich früher bereits aber ich habe gehofft, dass es 
vielleicht noch schöner geht.
Gedacht habe ich selber ;)

Werd jetzt wieder auf die alte Version zurückgreifen.

Thx again,

Stefan

von spontan (Gast)


Lesenswert?

Was hat Dir an Deiner Lösung nicht gefallen?
Sie ist simple und funktioniert.

Das mit dem Denken: Hier im Forum weiß man nie wer wirklich denkt und 
wer zu faul ist. Gut für Dich, daß Du mitdenkst.

Denken ist allen Menschen erlaubt, vielen bleibts erspart.

von Steve-o B. (steve_o)


Lesenswert?

@spontan:

Ich hatte damals das Problem, dass ich, wie Karl Heinz schon erwähnt 
hat, an guten Tagen für einen Tastendruck unter 20ms gebraucht habe.

Wenn ich bei dieser Lösung eine fixe Zeit festlege, die ich den Taster 
nach einem Statuswechsel ignoriere, z.B. 20ms, dann geht das 
Tastenloslassen evtl. verloren. Weil der Taster bis dahin noch ignoriert 
wird... wenn ich die Zeit allerdings zu kruz wähle z.B. 5ms, dann könnte 
es passieren, dass der Taster noch prellt und das wieder Probleme macht.

Ist aber letztlich nicht sooo häufig passiert. Aber wenn die Leute 
darauf rumhauen kann es schon mal vorkommen...

Das war auf jeden Fall der Grund, warum ich nach einer "schöneren" 
Lösung gesucht habe.

Ein weiterer Punkt: ich weiß auf Grund von Informationsmangel noch nicht 
welche Taster am Schluss verwendet werden sollen.. vielleicht sind sie 
alt und prellen viel, vielleicht sind sie auch hochwertig und schön 
robust... :/

von Paul B. (paul_baumann)


Lesenswert?

Steve schrabte:
>...an guten Tagen für einen Tastendruck unter 20ms gebraucht habe.

Ach Du bist das, der den Takt für die Netzspannung erzeugt!
;-)
MfG Paul

von Steve-o B. (steve_o)


Lesenswert?

Das lag nicht an mir weil ich schneller bin als die Polizei erlaubt 
sonder irgendwie am Taster... keinen Plan was da passiert ist aber wenn 
ich mit dem Finger so schnell es ging drüber gewischt habe ist das ab 
und zu so passiert. Vielleicht lags auch an meinem Programm und ich habe 
die Zeit falsch erfasst, was leider durchaus auch möglich ist :)

Dann möchte ich kurz fragen: Wie lange dauert ein Tastendruck mit 
Loslassen denn in der Regel.. also bei sehr schnellen Menschen?

von spontan (Gast)


Lesenswert?

>wenn ich die Zeit allerdings zu kruz wähle z.B. 5ms, dann könnte
>es passieren, dass der Taster noch prellt und das wieder Probleme macht.

Hatte noch nie einen Taster, der länger als 8 msec prellt. Wenn Du 
welche hast, dann schmeiß sie weg.

Mit übernommenen Entprellroutinen wirst Du immer Probleme haben, die 
geben den Status "Taste betätigt" erst zurück, wenn die "Prellzeit" 
vorbei ist.
Das aber willst Du nicht, Du willst erkennen, wenn der Schalter sich 
bewegt, von low nach high oder anders rum. Somit mußt Du zwangsweise die 
obige Methode anwenden. Nimm zehn msec als Totzeit und erkenne erst dann 
ein neuerliches Bewegen des Schalters an.

Mach eine Versuchsreihe mit den gemessenen Betätigungszeiten, sollten da 
welche mit obigen 10msec drin sein, so ist das verdächtig, d.h. der User 
kann eine Taste in 10 msec betätigen und auch wieder loslassen.

Ich mag mit Dir wetten, daß der Fall nicht auftritt. Im Klartext, eine 
Betätigung für nur 10 msec wird nicht vorkommen.

von Klaus (Gast)


Lesenswert?

Steve-o Bane schrieb:
> Ich möchte menschliche Reaktionszeiten mit Hilfe einer LED und eines
> Tasters auf die Millisekunde genau messen können.

Steve-o Bane schrieb:
> Wenn ich nichts falsch gemacht habe, sollte die ISR mit dieser
> Konfiguration jede Millisekunde angesprungen werden.

Mit einer Abtastrate von einer Millisekunde kannst du keine Messung mit 
einer Auflösung von einer Millisekunde machen. Bei DSOs wird hier immer 
eine 10fach höhere Abtastrate als die Signalfrequenz empfohlen. Und mit 
einem Sensor, der selbst undefiniertes Verhalten (prellen) im Bereich 
mehrerer Millisekunden liefert, wird das nicht besser.

MfG Klaus

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.