Forum: Mikrocontroller und Digitale Elektronik Entprellung Ziffern-Tastenfeld


von Mike (Gast)


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

von Axel (Gast)


Lesenswert?

Mike schrieb:
> (nach Danninger)

Und wer soll das sein?

von Mike (Gast)


Lesenswert?

Dannegger natürlich

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

Die Standard 12 Tastenfelder sind doch auch noch gemultiplext.
->http://www.fritzler-avr.de/HP/Librarys/tastenplex_his.php

von Mike (Gast)


Lesenswert?


von MaWin (Gast)


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.

von Mike (Gast)


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?

von MaWin (Gast)


Lesenswert?

> wo finde ich diese Notes?

Auf der WebSite des Herstellers deines uC.

von Mike (Gast)


Angehängte Dateien:

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).

von Mike (Gast)


Lesenswert?

PS: Hatte das nicht explizit erwähnt: ich habe im Prinzip einfach den 
"Standard"-Code dupliziert und jeweils ein Suffix _A (für PORTA) und _E 
(für PORTE) an die Variablen dran gehängt.

von Mike (Gast)


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)

von Mike (Gast)


Lesenswert?

Kann es vielleicht ein Problem sein, dass beim ATMega162 von PORTE nur 3 
Bits genutzt werden (und die Routine 8 Bits "einbezieht")? Tappe 
ziemlich im Dunkeln...

von Mike (Gast)


Lesenswert?

Hat sich erledigt - war ein Copy&Paste Fehler :-(

i_E = key_state_A ^ ~PINE

--> muss natürlich i_E = key_state_E ^ ~PINE sein.

Erstaunlich, dass es trotzdem zu 90% ging ;-)

von MaWin (Gast)


Lesenswert?

> Hat jemand eine Idee?
>  i_A = key_state_A ^ ~PINA;                  // key changed ?

>  i_E = key_state_A ^ ~PINE;                  // key changed ?
                   ^
Das soll doch wohl ein E sein.

von Mike (Gast)


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.

von Mike (Gast)


Angehängte Dateien:

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??

von Peter D. (peda)


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.

von J.-u. G. (juwe)


Lesenswert?

Mike schrieb:
> Die beiden Tasten an PC5 und PC6
> bewirken nichts

JTAG noch aktiviert?
http://www.mikrocontroller.net/articles/AVR_Checkliste#Fuses_richtig_gesetzt.3F

von Mike (Gast)


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!

von Mike (Gast)


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...

von Karl H. (kbuchegg)


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.

von Karl H. (kbuchegg)


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.

von Mike (Gast)


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 (?)

von Ingo (Gast)


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.

von Mike (Gast)


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

von Mike (Gast)


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.

von Mike (Gast)


Lesenswert?

J.-u. G. schrieb:
> JTAG noch aktiviert?

Das war das Problem - funktioniert jetzt einwandfrei - danke!!

von c-hater (Gast)


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...

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.