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.
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_tkeyState;
2
uint8_tkeyPressed;
3
uint8_toldState;
4
uint8_tpinCount;
5
6
ISR(...)
7
{
8
uint8_tnewState;
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.
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.
@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.
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;
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.
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.
>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.
>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
;-)
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
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".
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ß
@ 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.
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.