Forum: Compiler & IDEs Verständnissfrage zu ENTPRELLUNG.


von hansi mausi (Gast)


Lesenswert?

Hallo,

Ich möchte gerne die Entprellroutine von Herrn Dannegger besser 
verstehen.
Ich habe nichts davon wenn ich einfach den Code rauskopiere und nicht 
weiß was da passiert.

Habe ich richtig verstanden dass:

1. Tasten beim Drücken prellen = Die Taste schaltet nicht einfach nur 
ein sondern schaltet ein und ständig aus im ms Bereich bis der Kontakt 
letztendlich hergestellt ist. Je nach Taster mehrmals ... und 
verschieden lang.

2. Um falschen Einschalt-Folgen zu entgehen lesen wir nach dem ersten 
Einschaltvorgang den Zustand der Taste ein und warten bis zum nächsten 
Zustand. Ist dieser entgegengesetzt machen wir das ganze Spiel nochmal 
sodass wir idealerweise die Folge 1 0 1 0 haben. Diesen ganzen Ablauf 
versuchen wir in möglichst unter 20ms hinzubekommen und zwar OHNE 
delays.
Deswegen dann auch die Interrupts die den µC nicht "anhalten".

Das würde dann praktisch bedeuten das wir einen Taster 4 mal innerhalb 
z.b. 20ms abfragen und bei einer Folge von 1 0 1 0 einen Tastvorgang 
registrieren.


- Sind meine Überlegungen so richtig oder habe ich es nicht ganz 
verstanden?

- Herr Dannegger benutzt 10ms für die gesamte Abfrage wenn ich mich 
nicht täuschen sollte. Ist das ein vernünftiger Richtwert den man ohne 
weiteres nutzen kann?


Danke schonmal für hilfreiche Beiträge!

Gruß H. M.

von Karl H. (kbuchegg)


Lesenswert?

hansi mausi schrieb:

> Ich habe nichts davon wenn ich einfach den Code rauskopiere und nicht
> weiß was da passiert.

In diesem Fall ist das ausnahmsweise OK.
Die Funktion ist ziemlich trickreich und es ist keine Schande, wenn man 
die nicht gleich durchschaut.


> 1. Tasten beim Drücken prellen = Die Taste schaltet nicht einfach nur
> ein sondern schaltet ein und ständig aus im ms Bereich bis der Kontakt
> letztendlich hergestellt ist. Je nach Taster mehrmals ... und
> verschieden lang.

Das hast du richtig.

> 2. Um falschen Einschalt-Folgen zu entgehen lesen wir nach dem ersten
> Einschaltvorgang den Zustand der Taste ein und warten bis zum nächsten
> Zustand. Ist dieser entgegengesetzt machen wir das ganze Spiel nochmal
> sodass wir idealerweise die Folge 1 0 1 0 haben. Diesen ganzen Ablauf
> versuchen wir in möglichst unter 20ms hinzubekommen und zwar OHNE
> delays.

Nö.
Im Timer Interrupt wird einfach nur ein Zähler hochgezählt, wenn der 
jetzige Zustand des Input Pins identisch ist mit dem vorhergehenden. Ist 
er das nicht, wird der Zähler auf 0 zurückgesetzt.


Vom Prinzip her passiert da für einen einzelnen Pin folgendes (aber wie 
gesagt: nur vom Prinzip, die tatsächliche Implementierung ist viel 
trickreicher)
1
uint8_t  keyState;
2
uint8_t  keyPressed;
3
uint8_t  oldState;
4
uint8_t  pinCount;
5
6
ISR( ... )
7
{
8
  uint8_t newState;
9
10
  newState = PIN & ( 1 << bewusster_Pin );
11
12
  if( newState != oldState )
13
    pinCount = 0;
14
  else
15
    pinCount++;
16
17
  oldState = newState;
18
19
  if( pinCount == 4 ) {
20
    if( newState == 1 && keyState == 0 )
21
      keyPressed = TRUE;
22
    keyState = newState;
23
  }
24
}

Ich habe das nicht getestet aber für einen einzelnen Pin müsste das 
logikmässig in etwa dem entsprechen, was die veröffentlichte PeDa Lösung 
auch macht. Nur dass die PeDa Lösung das ganze trickreicherweise für 
maximal 8 Tasten gleichzeitig macht und es nicht 8 Variablen gibt, 
sondern das ganze Bitweise in verschiedenen Variablen organisiert ist 
:-)

> - Herr Dannegger benutzt 10ms für die gesamte Abfrage wenn ich mich
> nicht täuschen sollte. Ist das ein vernünftiger Richtwert den man ohne
> weiteres nutzen kann?

Ja, kann man.
Aber die 10ms sind nicht in Stein gemeisselt.
Wenn du sowieso schon eine Timer ISR hast, die alle 8ms aufgerufen wird, 
oder alle 15ms, oder alle 20ms, dann ist das auch in Ordnung und du 
kannst den Entprellcode da mit reinnehmen.

Wie gesagt: Die PeDa Entprellung ist so trickreich, dass es i.O. ist, 
sie nicht zu verstehen. Hauptsache sie funktioniert. Und das tut sie 
ausgezeichnet.

von hansi mausi (Gast)


Lesenswert?

vielen Dank für die nützlichen Hinweise!
Braucht sich also keiner schämen wenn er den Code nicht ganz 
durchschaut... dachte schon ich bin alleine damit :O).

Gruß
H.M.

von hansi mausi (Gast)


Lesenswert?

@Buchegger


Kannst Du mir Bitte sagen was Dein Code hier genau tut?

    if( newState == 1 && keyState == 0 )
      keyPressed = TRUE;
      keyState = newState;

beim 2ten Durchlauf würde diese Bedingung doch nicht mehr wahr werden 
oder?
Dein keystate ist ja praktisch immer dann eine 1. Wo würde dieser Wert 
denn wieder zurückgesetzt werden und welche Rolle spielt er hier?


Gruß H.M.

von Karl H. (kbuchegg)


Lesenswert?

hansi mausi schrieb:
> @Buchegger
>
>
> Kannst Du mir Bitte sagen was Dein Code hier genau tut?
>
>     if( newState == 1 && keyState == 0 )
>       keyPressed = TRUE;
>       keyState = newState;
>
> beim 2ten Durchlauf würde diese Bedingung doch nicht mehr wahr werden
> oder?

Genau das ist der Sinn der Sache.
Einen 0->1 Übergang zu erkennen

> Dein keystate ist ja praktisch immer dann eine 1. Wo würde dieser Wert
> denn wieder zurückgesetzt werden und welche Rolle spielt er hier?


Irgendwann (nämlich wenn du den Taster wieder löslässt) wird newState 
wieder 0.
keyState erhölt diese 0 dann durch Zuweisung von newState

          keyState = newState;

von hansi mausi (Gast)


Lesenswert?

Ich habe den Code jetzt bei mir folgendermaßen eingebaut


ISR(TIMER2_OVF_vect)
{
    uint8_t newState;

  //nur so funktioniert bei mir der Schalter
    newState = !(PIND & (1 << PD2));

    if( newState != oldState )
      pinCount = 0;
    else
      pinCount++;

    oldState = newState;

    if( pinCount == 4 )
    {
      if( newState == 1 && keyState == 0 )
    {
          //keyPressed = 1;
      PORTC ^= (1 << PC5);
    }
                  //nachdem ich keystate aus dem IF genommen hab funzt
                  der Schalter
    keyState = newState;
    }
}

Soweit klappt alles wunderbar. LED blinkt bei jedem Tastendruck. 
Prellabfrage bei 10ms. Werde mal versuchen das nun auf nen LCD zu 
bringen. Da kann man dann noch besser sehen wie oft der tatsächlich 
gezählt hat.

Danke für die Hilfe!!

Gruß

H.M.

von gascht (Gast)


Lesenswert?

Richtiger wäre es aber die Tasten anders auszuwerten.
Nicht ein Tastendruck  , sondern das loslassen der Taste  führt besagte 
Aktionen durch.
Ebenso ob die gedrückte Taste auch die losgelassene war.

von High Performer (Gast)


Lesenswert?

>Nicht ein Tastendruck  , sondern das loslassen der Taste  führt besagte
>Aktionen durch.

1.) was soll das bringen?

2.) Ist das Verhalten für den Anwender sehr unangenehm. Ich empfinde das 
immer als seltsam, wenn man eine gedrückte Taste erst loslassen muss, um 
eine Reaktion zu erreichen. Gefällt mir nicht.

von High Performer (Gast)


Lesenswert?

>Wie gesagt: Die PeDa Entprellung ist so trickreich, dass es i.O. ist,
>sie nicht zu verstehen.

Ähmm, ohne die Funktion jetzt angeschaut zu haben: die Entprellung eines 
Tasters bzw. mehrerer Taster sind doch wirklich absolute Basics. Ich 
brauche halt irgend eine Zeit. Woher ich die nehme, ist völlig wurscht. 
Und dann warte ich halt, bis ein Eingang für mindestens z.B. 10ms lang 
true ist. So mache ich das seit Jahren, und ich verstehe jetzt nicht, 
was daran auch nur im Entferntesten kompliziert sein soll. Werde mir die 
berühmte Dannegger-Funktion doch mal kurz anschauen, wenn ich Zeit habe 
;-)

von Peter D. (peda)


Lesenswert?

High Performer schrieb:
> Ähmm, ohne die Funktion jetzt angeschaut zu haben: die Entprellung eines
> Tasters bzw. mehrerer Taster sind doch wirklich absolute Basics.

Was viele aber nicht einsehen wollen.
Z.B. bei unserem teuren Kaffeautomat prellt der Drehgeber zur 
Mengeneinstellung wie Sau.


> Ich
> brauche halt irgend eine Zeit. Woher ich die nehme, ist völlig wurscht.

Ist es eben nicht.
Am nebenwirkungsfreiesten ist ein Timerinterrupt zur Tastenabfrage. Dann 
geht nirgends CPU-Zeit verloren und Tastendrücke können sogar gemerkt 
werden.

Ohne Timerinterrupt muß beim Drücken oder Loslassen (an den Flanken) die 
Entprellzeit verwartet werden. Ist nicht schön, aber bei einfachen 
Programmen oftmals tolerabel.


> Und dann warte ich halt, bis ein Eingang für mindestens z.B. 10ms lang
> true ist.

Heißt das, solange jemand auf eine Taste drückt, werden der Mainloop 
ständig 10ms geklaut?


> So mache ich das seit Jahren, und ich verstehe jetzt nicht,
> was daran auch nur im Entferntesten kompliziert sein soll.

Ich behaupte mal, jeder kennt mindestens ein kommerzielles Gerät mit 
schlecht funktionierender Entprellung.


Peter

von Karl H. (kbuchegg)


Lesenswert?

High Performer schrieb:
>>Wie gesagt: Die PeDa Entprellung ist so trickreich, dass es i.O. ist,
>>sie nicht zu verstehen.
>
> Ähmm, ohne die Funktion jetzt angeschaut zu haben

Tu das.
Die Funktionalität ist nicht schwer, aber die Art und Weise wie sie 
implementiert ist, ist trickreich. Für einen C-Anfänger ist das mit 
Sicherheit nicht leicht zu durchschauen. Ich halte mich nicht für einen 
Anfänger, aber ich habe auch eine gute Stunde die 5 Zeilen Code studiert 
und mit Beispielen durchgespielt, bis ich verstanden habe wie das 
funktioniert. Der Knackpunkt ist der 'vertikale Zähler'. Hat man den 
erst mal erkannt, fällt alles andere von selbst in die "richtige 
Schublade".

von Chris (Gast)


Lesenswert?

hansi mausi schrieb:
> Ich möchte gerne die Entprellroutine von Herrn Dannegger besser
> verstehen.

Hallo, um welche routine handelt sich? wo finde ich die Entprellroutine 
von Herrn Dannegger?

Gruß

von Karl H. (kbuchegg)


Lesenswert?

Chris schrieb:
> hansi mausi schrieb:
>> Ich möchte gerne die Entprellroutine von Herrn Dannegger besser
>> verstehen.
>
> Hallo, um welche routine handelt sich? wo finde ich die Entprellroutine
> von Herrn Dannegger?

http://www.mikrocontroller.net/articles/Entprellung#Komfortroutine_.28C_f.C3.BCr_AVR.29

von hansi mausi (Gast)


Lesenswert?

@ high performer

die Art und Weise WIE eine Entprellung funktionieren soll kann man recht 
gut dem Forum sowie den Tutorials entnehmen... diese allerdings dann 
erfolgreich und effektiv umzusetzen ist eine Andere.

Herr Dannegger hat mit seiner Lösung mit Sicherheit hohe Maßtäbe 
gesetzt. Es macht jedoch wie eingangs erwähnt nicht wirklich Sinn nur 
rauszukopieren. Mir hat als Anfänger die Lösung von Herrn Buchegger sehr 
gut gefallen da "leicher" nachvollziehbar.
Wenn wir Anfänger mal weiter sind mit Registern und dem Arbeiten auf 
BIT-Ebene werden mit Sicherheit auch die PEDA Lösung besser verstehen. 
Bis dahin heißt es erstmal alles zum Laufen bringen und zwar mit einem 
Code den man selbst auch versteht.

btw.
die von mir mit einer geschweiften Klammer abgeänderte Buchegger Lösung 
funktioniert übrigens perfekt!!! Danke nochmal für diese zunächst
"1-Tasten-Lösung"

Gruß
H.M.

von Karl H. (kbuchegg)


Lesenswert?

hansi mausi schrieb:

> rauszukopieren. Mir hat als Anfänger die Lösung von Herrn Buchegger sehr
> gut gefallen da "leicher" nachvollziehbar.

Ich denke du hast das misverstanden oder ich habe es schlecht 
formuliert.
Diese 'Lösung' hab ich nur schnell zusammengestrickt (noch nicht mal 
gtestet) um das grundsätzliche Prinzip der PeDa Entprellung zu zeigen. 
Beide funktionieren nach dem gleichen Schema, nur ist die PeDa Lösung 
der präsentierten, was Eleganz angeht, haushoch überlegen.

Du kannst und sollst auch die PeDa Lösung nehmen. Es ist ausnahmsweise 
völlig in Ordnung, wenn du die den Inhalt in der ISR nicht verstehst. 
Das ist nichts worüber man sich Kopfzerbrechen machen muss.

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.