Forum: Mikrocontroller und Digitale Elektronik Tastaturmatrix Entprellen


von Mia (Gast)


Angehängte Dateien:

Lesenswert?

Einen schönen Abend zusammen,

ich habe an meinem ATmega328 eine 3x4 Tastaturmatrix und verwende hierzu 
die Entprellung vom Peter Dannegger -> 
Beitrag "Re: Tastatur Matrix entprellen"

Meine Dateien sind im Anhang. Timer in der Main wird gestartet.

Wenn ich nur einen Spalte auslese funktioniert alles und dieser 
Tastendruck wird auch erkannt. (Nur einen Spalte in der Funktion 
keyscan() aktiviert - rest auskommentiert).

Wenn ich nun alle drei Spalten abfrage, dann werden auch immer die 
Taste(n) der folgenden benachtbarte Reihe mit angezeigt.

Mit schein so, dass ich hier eine Kleinigkeit zur Trennung der Tasten 
übersehen habe...

Kann mir hier jemand kurz auf die Sprünge helfen ?

Viele Grüße,

Mia

von MaWin (Gast)


Lesenswert?

Mia schrieb:
> Kann mir hier jemand kurz auf die Sprünge helfen ?

Das einzige was mir auffällt: Du schiebst um 1, 5, 9, erwartest aber 
KEY0 bei bit 0.

von Mia (Gast)


Lesenswert?

Ja... Ich werte aber key0 nicht aus und will eigentlich die Zählweise 
wie beim Telefon mit 1 beginnen

von Klaus (Gast)


Lesenswert?

Naja. Vergleiche mal die Definitionen, insbesondere von ROWX und wie sie 
mit den Schiebeooperationen zusammenhängen.

Im Code hier Beitrag "Re: Tastatur Matrix entprellen" sind 
es PB0 und PB2, die dann um 1 verschoben werden, was beim Auslesen der 
zweiten Reihe direkt addiert (verodert) werden kann.

Bei deinen Definitionen liegen die Reihen direkt nebeneinander. Du musst 
also andere Schiebeoperationen nehmen. Du hast dagegen einfach immer 
wieder 4 addiert, was natürlich im Getriebe knirscht.

von Klaus (Gast)


Lesenswert?

Mia schrieb:
> Ja... Ich werte aber key0 nicht aus und will eigentlich die Zählweise
> wie beim Telefon mit 1 beginnen

Das ist doch völlig Wurst. Ignoriere das erstmal.

von mia (Gast)


Lesenswert?

Klaus schrieb:
> Naja. Vergleiche mal die Definitionen, insbesondere von ROWX und
> wie sie
> mit den Schiebeooperationen zusammenhängen.
>
> Im Code hier Beitrag "Re: Tastatur Matrix entprellen" sind
> es PB0 und PB2, die dann um 1 verschoben werden, was beim Auslesen der
> zweiten Reihe direkt addiert (verodert) werden kann.
>
> Bei deinen Definitionen liegen die Reihen direkt nebeneinander. Du musst
> also andere Schiebeoperationen nehmen. Du hast dagegen einfach immer
> wieder 4 addiert, was natürlich im Getriebe knirscht.

Falls ich hier einen denkfehler in der Zuordnung gemacht habe, dann kann 
man das ja noch in der Definition anpassen.
Ich habe halt die Schiebeoperation mir so überlegt...

1. COL0 auf Masse und die ROW einlesen -> 1 schieben, das sind dann  die 
Bits 1 bis Bit 4 von der Variable val

2. CLO1 auf Masse und die ROW einlesen -> 4 schieben -> das sind dann 
die Bits 5 bis Bit 9 von der Variable Val

3. CLO2 auf Masse und die ROW einlesen -> 9 schieben -> das sind dann 
die Bits 10 bis Bit 14 von der Variable Val

Wenn ich in meiner Funktion nur eine Spalte auslese - z.B. so
1
static uint16_t keyscan(void)
2
{
3
  uint16_t val;
4
5
          
6
        DDRC  &=  ~(ROW0 | ROW1 | ROW2 | ROW3); // Inputs
7
  DDRD  &=  ~(COL0 | COL1 | COL2 ); // Inputs
8
  PORTC |=  ROW0 | ROW1 | ROW2 | ROW3;  // with pullup
9
  PORTD |=  COL0 | COL1 | COL2;  // with pullup
10
  PORTD &= ~COL0;                       // Low
11
  DDRD  |=  COL0;                       // Output
12
  NOP();                            // load Input latch !
13
  val = (PINC & (ROW0 | ROW1| ROW2 | ROW3)) << 1;    
14
  
15
        */
16
  DDRC  &=  ~(ROW0 | ROW1 | ROW2 | ROW3); // Inputs
17
  DDRD  &=  ~(COL0 | COL1 | COL2 ); // Inputs
18
  PORTC |=  ROW0 | ROW1 | ROW2 | ROW3;  // with pullup
19
  PORTD |=  COL0 | COL1 | COL2;  // with pullup
20
  PORTD &= ~COL1;                       // Low
21
  DDRD  |=  COL1;                       // Output
22
  NOP();                           // load Input latch !
23
  val |= (PINC & (ROW0 | ROW1| ROW2 | ROW3)) << 5;  
24
  */
25
  /*
26
  DDRC  &=  ~(ROW0 | ROW1 | ROW2 | ROW3); // Inputs
27
  DDRD  &=  ~(COL0 | COL1 | COL2 ); // Inputs
28
  PORTC |=  ROW0 | ROW1 | ROW2 | ROW3;  // with pullup
29
  PORTD |=  COL0 | COL1 | COL2;  // with pullup
30
  PORTD &= ~COL2;                       // Low
31
  DDRD  |=  COL2;                       // Output
32
  NOP();                            // load Input latch !
33
  val |= (PINC & (ROW0 | ROW1| ROW2 | ROW3)) << 9;
34
  */
35
36
  return val;
37
}
..dann fuktioniert es.

Ich habe nur das Problem mit der Erkennung der benachtbarten Tasten - 
hängt das auch mit der Schiebeoperation zusammen ?

Mia

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


Lesenswert?


von Klaus (Gast)


Lesenswert?

Tja. Schau' Dir den Code einfach mal im Debugger oder Simulator genau 
an, was er tut. Man muss Dir zugute halten, das Peter Danneggers Codes 
manchmal so ausgefuchst sind, das man so ein oder zwei Facepalms 
braucht, bis es klingelt. Ist mir auch schon so gegangen - bis zum 
Zweifel ob das eigentlich ein Qualitätsmerkmal ist oder eine 
Manieriertheit.

Ich bin offen gesagt gerade zu faul, das selbst zu machen. Ich würde an 
Deiner Stelle mal genau schauen was denn nun:
1
a |= b << c;

insbesondere durch den Vorrang der Operatoren, bedeutet.

Das ist halt so ein Problem wenn man so ein Programm nur nach 
Mustervergleich erweitert, ohne es zu verstehen. :-) Bei Kochrezepten 
geht das eher (bin selber ein Hobbykoch), aber in der Software nicht 
(immer).

von Sigi (Gast)


Lesenswert?

Dein Problem kann auch an der Schaltgeschwindigkeit
beim Umschalten der einzelnen Reihen liegen.
Drück einfach mal zwei nicht in Spalte nebeneinander
liegende Tasten und lass dir das Ergebnis anzeigen.
Schaltest du zu schnell um, dann erscheint die
Taste der ersten Reihe quasi wie ein Schatten in
der nächsten Reihe. (ist durch Debuggen/Simulieren
nicht so einfach erkennbar)

Ich hatte das Problem mal bei einem FPGA-Board, bei
dem ich  dann mit der Abfragefrequenz bis in den
"sicheren" Bereich runtergegangen bin.

von Mia (Gast)


Lesenswert?

Sigi schrieb:
> Dein Problem kann auch an der Schaltgeschwindigkeit
> beim Umschalten der einzelnen Reihen liegen.
> Drück einfach mal zwei nicht in Spalte nebeneinander
> liegende Tasten und lass dir das Ergebnis anzeigen.
> Schaltest du zu schnell um, dann erscheint die
> Taste der ersten Reihe quasi wie ein Schatten in
> der nächsten Reihe. (ist durch Debuggen/Simulieren
> nicht so einfach erkennbar)
>
> Ich hatte das Problem mal bei einem FPGA-Board, bei
> dem ich  dann mit der Abfragefrequenz bis in den
> "sicheren" Bereich runtergegangen bin.

Das Problem sind nicht zwei Tasten die nacheinander gedrückt werden, 
sonder das Ein Tastendruck als zwei interpretiert werden - die 
eigentliche Taste plus deren nachbar.

Ich werde das mal am debugger nachvollziehen...

mia

von Karl H. (kbuchegg)


Lesenswert?

Das wird im Debugger schwierig werden. Am Code seh ich erst mal nichts 
auffälliges.

Vorschlag:
Du hast ein Programm, bei dem du irgendwo die gedrückte Taste sehen 
kannst. und zwar alle 12. Gut.

Wenn du im Code nur die erste Spalte aktivierst und alle anderen 
auskommentierst, kriegst du dann bei einem Tastendruck auf einer Taste 
die NICHT in dieser Spalte liegt auch eine Ausgabe? Oder kriegst du nur 
die jeweils richtige Taste gemeldet?
Wenn du reihum dann nacheinander jeweils eine andere Spalte aktivierst, 
stimmt dann jeweils die Tastenzuordnung?

Wenn das bei einzeln aktivierten Spalten funktioniert, dann hast du 
tatsächlich ein Problem mit dem schnellen Umschalten zur nächsten 
Spalte. Ev. sind da irgendwelche Kapazitäten im Spiel, die nicht schnell 
genug umgeladen werden können.

Du könntest das zb so zu lösen versuchen, dass du pro KeyTimerEvent 
Aufruf nicht das komplette Tastenfeld abscannst, sondern immer nur 1/3. 
Reihum das jeweils nächste Drittel (die nächste Spalte). Bei halbwegs 
moderatem Aufruf der KeyTimerEvent sollte das von der Haptik noch immer 
kein Problem sein.

: Bearbeitet durch User
von Sigi (Gast)


Lesenswert?

Mia schrieb:
> Das Problem sind nicht zwei Tasten die nacheinander gedrückt werden,
> sonder das Ein Tastendruck als zwei interpretiert werden - die
> eigentliche Taste plus deren nachbar.

Aber das habe ich doch mit meinem Beispiel
gemeint: Du drückst eine Taste einer Reihe
und dein Programm zeigt die Taste in den
zwei benachbarten Zeilen an. Wenn du 2 bzw.
3 "diagonale" Tasten drückst, siehst du
die "Schatten" bzw. die Mehrfachaktivierung
am deutlichsten, und zwar für alle Reihen
parallel.

Das Hauptproblem liegt hier an der Umschalt-
Geschwindigkeit. In einer IRQ-Routine schaltest
du auf alle Reihen um und fragst auch noch ab.
Schalte doch statt dessen folgendermassen um:
1. IRQ: 1. Reihe anschalten
2. IRQ: 1. Reihe abfragen
3. IRQ: 1. Reihe abschalten
4. IRQ: 2. Reihe anschalten
5. IRQ: 2. Reihe abfragen
.. etc ..
und das mit z.B. 1 kHz Timer-IRQ.
Damit gibst du deiner Tastaturmatrix zwschen je
anschalten/abfragen und abschalten genug Zeit zum
einpendeln. Und genau das war bei mir auch das
Problem, hab's mit dem Oszi nachgemessen
und die "Schatten" beobachten können. Nur mit einer
Simulation hätte ich das nie entdeckt.

von Karl H. (kbuchegg)


Lesenswert?

Alternativ könnte man auch einmal probieren, hier
1
  NOP();                            // load Input latch !

einen 'Arsch voll' NOPS einzufügen. Natürlich nur zu Probezwecken:-)

von Sigi (Gast)


Lesenswert?

Karl H. schrieb:
> einen 'Arsch voll' NOPS einzufügen. Natürlich nur zu Probezwecken:-)

gute Idee zum Rumprobieren, hab's beim ersten
Mal auch so gemacht. Soweit ich mit noch erinnere,
lag die max. umschaltfrequenz deutlich unter
100 kHz.

von Mia (Gast)


Lesenswert?

Hallo,

bin heute endlich wieder mal zum testen gekommen.

Die gnazen NOPs und auch ein Delay hat hier niht gebracht.
Habe nun die Lösung von fritzler-avr.de im Einsatz - sieht bis jetzt 
ganz gut aus..

Danke für das Suchen nach dem Problem

Mia

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.