Entprellung Ziffern-Tastenfeld

Gast #3086773
Lesenswert?

Hallo zusammen,

ich baue gerade eine IR-Fernsteuerung/Empfänger mit einem 
Zifferntastenfeld (12 Tasten) und zwei zusätzlichen Tasten, über die ich 
den Modus (z. B. Senden/Empfangen) einstellen möchte. Das heißt, ich 
würde gerne 14 Tasten entprellen.

Kann ich dazu das Timer-Verfahren (nach Danninger) verwenden?

http://www.mikrocontroller.net/articles/Entprellung

Der Code ist eigentlich für 8 Tasten ausgelegt. Kann ich da einfach die 
8-Bit-Variablen durch 16-Bit-Variablen austauschen und es läuft? Ich 
habe mir den Code angeschaut, aber nur halbwegs verstanden. Aber würde 
schätzen, dass es gehen sollte? Oder bin ich da auf dem Holzweg?

VG Mike
Gast #3086836
Lesenswert?

> Kann ich dazu das Timer-Verfahren (nach Danninger) verwenden?

Das ist normalerweise vollkommen überflüssig denn 14 Tasten würde man 
normalerweise als 4 x 4 Matrix an 8 I/O Pins im Multiplexverfahren 
abfragen und das entprellt automatisch.

Liest eigentlich niemand von euch Beispiele aus den Application Notes 
der Hersteller der uC?

Natürlich kannst du, wenn es unbedingt sein muss, auch 14 Pins und 
Abfrage nach Dannegger verwenden, einfach 2 bytes verwenden.
Gast #3086845
Lesenswert?

MaWin schrieb:
>
> Das ist normalerweise vollkommen überflüssig denn 14 Tasten würde man
> normalerweise als 4 x 4 Matrix an 8 I/O Pins im Multiplexverfahren
> abfragen und das entprellt automatisch.
>
> Liest eigentlich niemand von euch Beispiele aus den Application Notes
> der Hersteller der uC?
>
> Natürlich kannst du, wenn es unbedingt sein muss, auch 14 Pins und
> Abfrage nach Dannegger verwenden, einfach 2 bytes verwenden.

Ok, nächstes Mal mach ich's so

MaWin schrieb:
> Liest eigentlich niemand von euch Beispiele aus den Application Notes
> der Hersteller der uC?

Kenn ich ehrlich gesagt gar nicht... wo finde ich diese Notes?

> Natürlich kannst du, wenn es unbedingt sein muss, auch 14 Pins und
> Abfrage nach Dannegger verwenden, einfach 2 bytes verwenden

Danke! Sollte ich besser eine uint_16 verwenden oder zwei unit_8? Oder 
egal?
Gast #3095393
Lesenswert?

MaWin schrieb:
> Natürlich kannst du, wenn es unbedingt sein muss, auch 14 Pins und
>
> Abfrage nach Dannegger verwenden, einfach 2 bytes verwenden.

Ich hab das jetzt implementiert und getestet. Code anbei.

Es hängen 8 Tasten an PORTB und 3 Tasten an PORTE (um die übrigen Tasten 
an PORTB kümmere ich mich später).

Folgendes Problem: Für die Tasten an PORTB funktioniert das Ganze 100% 
zuverlässig. Für die Tasten an PORTE nur ca. 90-95% - d. h. die Tasten 
an PORTE muss man ab und zu zwei-/dreimal drücken, bis sie "erkannt" 
bzw. entprellt zurück geliefert werden.

Ich hab zum Test mal den Vorteiler von 1024 auf 256 geändert - das 
scheint die "Zuverlässigkeit" etwas zu erhöhen, aber auch nicht auf 100% 
zu bringen.

Hat jemand eine Idee? Ist der Ansatz im Prinzip ok? Und müsste die 
Frequenz (standardmäßig 10ms) bei Nutzung von 2 Bytes/Ports eher nach 
oben oder nach unten justiert werden (ISR dauert jetzt ja ca. doppelt so 
lange).
Angehängte Dateien:
Gast #3095404
Lesenswert?

Sorry, noch ne Korrektur: ich behandele die Tasten an PORTA und PORTE, 
nicht an PORTB (Schreibfehler oben)

Tasten an PORTA --> 100% zuverlässig
Tasten an PORTE --> ca. 95% zuverlässig (teilweise mehrfaches Drücken 
notwendig)
Gast #3097250
Lesenswert?

Nachdem das jetzt geht, gibt es leider ein neues Problemchen:

Ich habe noch 2 Tasten an PC5 und PC6 hängen. An PC0 bis PC3 hängen 
Ausgänge (Multiplexing eines LED-Displays). Ich möchte nun die 
Entprell-Routine erweitern, wobei nur PC5 und PC6 "berücksichtigt" 
werden sollen. Meine erste Idee war so etwas in der Art:

i_C = key_state_C ^ ~(PINC & 0b01100000);

Aber geht leider nicht - bei Tastendruck passiert nichts, d. h. Änderung 
Zustand wird wohl nicht erkannt.

Was wäre der richtige Ansatz, um die Prüfung der Zustandsänderung auf 
die Tasten an PC5 und PC6 einzuschränken (wenn ich trotzdem die gleiche 
Routine verwenden möchte)?

Besten Dank.
Gast #3097275
Lesenswert?

Anbei mal noch der vollständige Code.

Bei Programmstart bzw. nach Reset liefert die Funktion 
Key_Panel_getKey() eine 255 zurück - danach dann nur noch die 
Tastendrücke an PORTA und PORTE. Die beiden Tasten an PC5 und PC6 
bewirken nichts. Also meine Vermutung ist, dass ich die Wechselwirkungen 
mit den anderen Pins an PORTC nicht richtig "ausgeblendet" bekomme??
Angehängte Dateien:
#3097417
Lesenswert?

Mike schrieb:
> Also meine Vermutung ist, dass ich die Wechselwirkungen
> mit den anderen Pins an PORTC nicht richtig "ausgeblendet" bekomme??

Richtig!

Du benutzt ja nicht die Funktion get_key_press(), diese wertet nur das 
gewünschte Bit aus.
Dein Switch() ist untauglich, denn es wertet immer 8 Bits zusammen aus.

Das Verdreifachen des Codes ist unübersichtlich. Ändere einfach alles 
auf uint16_t und fasse die Tasten einmalig zu 16Bit zusammen.
1
  uint16_t i;
2

3
  i = PINA | (((PINE & 0b00000111) | (PINC & 0b01100000)) << 8);
4
  i = key_state ^ ~i;
5
  // usw.
Gast #3097453
Lesenswert?

Peter Dannegger schrieb:
> Du benutzt ja nicht die Funktion get_key_press(), diese wertet nur das
>
> gewünschte Bit aus.
>
> Dein Switch() ist untauglich, denn es wertet immer 8 Bits zusammen aus.

ja, hatte irgendwie versucht, durch das (PINC & 0b01100000) Änderungen 
an Pins <> PC5 und PC6 zu "neutralisieren" - so dass key_press_C null 
bleibt, wenn sich ein anderer Pin ändert.

Wenn ich get_key_press() verwende (hatte ich anfangs), müsste ich die 
Funktion mit entsprechender Maske pro Taste einzeln aufrufen, oder? Ich 
fand das bei 14 Tasten etwas "umständlicher", aber wenn das das Problem 
löst, gehe ich natürlich diesen Weg.

Das Grundproblem ist wohl, dass ich (= Anfänger) den Code noch nicht 
100% verstehe - ist ja doch sehr "sophisticated"

Peter Dannegger schrieb:
> Das Verdreifachen des Codes ist unübersichtlich. Ändere einfach alles
>
> auf uint16_t und fasse die Tasten einmalig zu 16Bit zusammen.

Ok, werde ich machen. Zumal ich die Tasten insgesamt über 4 Ports 
verteilt sind (ok, erst denken, dann löten). Nur für's Verständnis: 
Diese Änderung ist eher zwecks Übersichtlichkeit - die Lösung des 
Problems würde aber in der bitweisen Auswertung in get_key_press() 
liegen, oder?

J.-u. G. schrieb:
> JTAG noch aktiviert?
>
> http://www.mikrocontroller.net/articles/AVR_Checkl...

Danke für den Hinweis. Das muss ich auch mal kontrollieren. Werde auch 
zunächst nochmal eine grundsätzlichen Test machen, ob die Tasten 
überhaupt "funktionieren"

Erstmal danke an Euch!
Gast #3097614
Lesenswert?

Peter Dannegger schrieb:
> Dein Switch() ist untauglich, denn es wertet immer 8 Bits zusammen aus.

Hmmm, warum eigentlich?

    switch (key_press_E)
    {
      case 1: result = 9;
          break;
      case 2: result = 6;
          break;
      case 4: result = 3;
          break;
    }

Ich werte doch über {1,2,4,8,16,32,64,128} auch immer genau ein Bit aus, 
oder? Zumindest funktioniert es für die Ports A und E... Wenn eine Taste 
gedrückt wurde, ist doch immer das entsprechende Bit gesetzt, d. h. die 
Variable hat einen Wert 2 hoch Bitposition - grübel

Ich werde es heute Abend nochmal testen, aber der Vorschlag
i = PINA | (((PINE & 0b00000111) | (PINC & 0b01100000)) << 8);
nutzt ja eigentlich die gleiche Methode zum "Neutralisieren" der nicht 
relevanten Pins...
#3097754
Lesenswert?

Mike schrieb:

> Ich werte doch über {1,2,4,8,16,32,64,128} auch immer genau ein Bit aus,
> oder?

Und du hast dann im case auch alle Kombinationen, die sich durch 
gleichzeitiges Drücken mehrerer Tasten ergeben?

Gratuliere, das dürfte dann der switch-case des Jahrhunderts sein.

Mach es einfach nur richtig. Dann kommt der Rest von alleine.
#3097759
Lesenswert?

> Danke für den Hinweis. Das muss ich auch mal kontrollieren. Werde
> auch zunächst nochmal eine grundsätzlichen Test machen, ob die
> Tasten überhaupt "funktionieren"

Das wäre allerdings eine extrem gute Idee.
EIgentlich gehen die meisten davon aus, dass du diesen Test schon längst 
gemacht hast!

Immer diese 'Oooch das wird schon so passen' Anfälle.
Wenn du wüsstest, wie oft sich hinten nach, manchmal nach Stunden, 
rausstellt, dass die primtivsten Vortests nicht gemacht wurden und genau 
die fehlschlagen, das Problem aber klar und deutlich aufgezeigt hätten.
Gast #3097767
Lesenswert?

Karl Heinz Buchegger schrieb:
> gleichzeitiges Drücken mehrerer Tasten

so weit bin ich noch nicht - ich drücke nur eine Taste gleichzeitig

Karl Heinz Buchegger schrieb:
> Mach es einfach nur richtig. Dann kommt der Rest von alleine.

Ein kleiner Hinweis, was "richtig" ist, wäre hilfreich ;-)

Prüfung bzgl. JTAG ist sicherlich notwendig. Aber die Nutzung der 
Orginalfunktion get_key_press() löst imho nicht das Problem. Diese 
Funktion würde ich ja auch mit einer Bitmaske aufrufen, um eine EINZELNE 
Taste zu prüfen (?)
Gast #3097771
Lesenswert?

Solche Tastenfelder ließt man am besten mit nem ADC aus, indem quasi 
einen Spannungsteiler baut. Braucht dann erffektiv einen Pin. 
Entprellung ist etwas aufwändig, da man das Drücken, Einpendeln und 
Loslassen per Messung über n paar Werte erfassen muss, wenn man das hat 
ist es die pinsparendste Variante die es gibt. Vor alles ist sie 
beliebig erweiterbar, da quasi nur die LUT erweitert werden muss.
Gast #3097779
Lesenswert?

Karl Heinz Buchegger schrieb:
> primtivsten Vortests nicht gemacht

Ich hab zumindest die Leitungen etc. getestet, passt alles. Die Option 
über JTAG kannte ich nicht - muss ich mich jetzt entschuldigen? ;-)

Dass das Problem an der nicht verwendeten get_key_press() (bzw. andere 
Version) oder der Aufteilung auf mehrere uint8 statt eine uint16 liegt, 
bezweifele ich ehrlich gesagt
Gast #3097786
Lesenswert?

Ingo schrieb:
> Solche Tastenfelder ließt man am besten mit nem ADC aus, indem quasi
>
> einen Spannungsteiler baut. Braucht dann erffektiv einen Pin.
>
> Entprellung ist etwas aufwändig, da man das Drücken, Einpendeln und
>
> Loslassen per Messung über n paar Werte erfassen muss, wenn man das hat
>
> ist es die pinsparendste Variante die es gibt. Vor alles ist sie
>
> beliebig erweiterbar, da quasi nur die LUT erweitert werden muss.

Danke für den Tip - werde ich beim nächsten Mal entsprechend anders 
umsetzen - dieses Mal hab ich schon so viel Aufwand in die Hardware 
gesteckt, dass ich jetzt irgendwie auf diesem Weg zum Ziel kommen 
möchte. Trotzdem danke.
Gast #3098403
Lesenswert?

MaWin schrieb:

> Das ist normalerweise vollkommen überflüssig denn 14 Tasten würde man
> normalerweise als 4 x 4 Matrix an 8 I/O Pins im Multiplexverfahren
> abfragen und das entprellt automatisch.

Natürlich nur, wenn das Pollingintervall groß genug ist. Das ist nicht 
zwingend gegeben, z.B. nicht bei der häufig anzutreffenden 
Pinsparlösung, das Muxen zwischen Displays und Tasten zu "sharen".

Für das Display strebt man ja Muxraten von wenigstens ca. 60 Hz an. 16ms 
können bei stark prellenden Tastern aber schon deutlich zu knapp sein 
als Zeitkonstante zur Entprellung.

Das ist natürlich kein Problem, man fragt dann einfach nur in jedem 
zweiten Muxintervall die Tasten ab. Aber man muß halt dran denken, dies 
auch tatsächlich zu tun. Und dabei sind gerade falsche Axiome wie 
"Tasterabfrage im Mux-Verfahren debounced automatisch" nicht gerade 
hilfreich...

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