Forum: Mikrocontroller und Digitale Elektronik Denkfehler bei Matrixtastatur?


von Stefan K. (zerb287)


Lesenswert?

Hallo,

ich hatte mich Gestern schoneinmal an Euch gewendet, da ich Probleme mit 
meiner Matrixtastatur 3x4 habe.

Ich habe die Schaltung jetzt wie auf 
http://sprut.de/electronic/pic/programm/tastatur.htm beschrieben 
umgesetzt.


Die Spalten auf die Ausgänge 0..2 die Zeilen auf die Eingänge 3..6

Weiter sind bei den Eingängen die internen Pull UP Wiederstände auf HIGH 
gesetzt.

Von jedem Schalter geht jeweils in Kabel in einen Ausgang und eins in 
einen Eingang. Am Pin vom Schalter, der einen Ausgang anliegen hat, geht 
noch ein Kabel zu GND.

Nun ist es allerdings so, dass auch wenn die Ausgänge auf High liegen am 
Schalterpin 0V anliegen. Sobald ich die Kabel von GND wieder trenne, 
liegen 5V an.

Was mache ich falsch?


Danke und Gruß,

Zerb287

von Severino R. (severino)


Lesenswert?

Stefan K. wrote:

> Von jedem Schalter geht jeweils in Kabel in einen Ausgang und eins in
> einen Eingang. Am Pin vom Schalter, der einen Ausgang anliegen hat, geht
> noch ein Kabel zu GND.

Wozu???

> Nun ist es allerdings so, dass auch wenn die Ausgänge auf High liegen am
> Schalterpin 0V anliegen. Sobald ich die Kabel von GND wieder trenne,
> liegen 5V an.

Oh Wunder!

> Was mache ich falsch?

Wohl das Kabel zu GND?

von Stefan K. (zerb287)


Lesenswert?

Hallo,

danke für die rasche Antwort. Jedoch, wenn das Kabel zu GND nicht gelegt 
ist, dann bekomme ich die 0 nicht in den Port, da der Pull UP 
Wiederstand nicht los lässt!

Soweit war ich schon, deshalb ja das Kabel zu GND!

Wie kann ich das nun lösen?

Mein code:

#include <avr/io.h>

int main (void) {



   //DDRC  = 0x00;
   //PORTC = 0x00;
   //PORTA = 0xff;



  DDRC  &= ~(1<<DDC3) | (1<<DDC4) | (1<<DDC5) | (1<<DDC6);
  PORTC |= (1<<PC3) | (1<<PC4) | (1<<PC5) | (1<<PC6);
  PORTC |= (1<<PC0) | (1<<PC1) | (1<<PC2);


   while(1) {


    PORTC &= ~(1<<PC0);


    if (! (PINC & (1<<PC3)) )
     {
     PORTA = 0xff;
     } else { PORTA = 0x00;}




    //PORTC |= (1<<PC0);

}

   return 0;
}

von Severino R. (severino)


Lesenswert?

Stefan K. wrote:
> Hallo,
>
> danke für die rasche Antwort. Jedoch, wenn das Kabel zu GND nicht gelegt
> ist, dann bekomme ich die 0 nicht in den Port, da der Pull UP
> Wiederstand nicht los lässt!

Die 0 kommt doch (nacheinander) von den Ausgängen 0..2!

> Soweit war ich schon, deshalb ja das Kabel zu GND!

Habe wohl nicht verstanden, wie Du das Kabel zu GND angeschlossen hast.
Mach bitte eine Zeichnung.

> Wie kann ich das nun lösen?

Prüf nach, ob bei den Ausgängen 0..2 jeweils eine 0 anliegt.
Z.B. zwischen 5V und dem Ausgang mit dem Voltmeter messen.
Dabei muss aber der Ausgang ruhen, also das Programm muss angehalten 
sein.

>
> Mein code:
Sorry, ich kann kein AVR-ASM

von Stefan K. (zerb287)


Lesenswert?

Hallo,

ja die Null bei den Ausgängen, die ich nach und nach anlege, die Liegt 
an, das passt soweit.

ABER: Die 0 liegt an den Pins des Atmega zwar an, da aber von selben 
Schalterpin an dem das Kabel vom Ausgang ankommt, auch ein Kabel zu GND 
wegführt, liegt dort auch wenn der Ausgan 0..2 geschaltet ist eine 0 an.

Das Problem, welches daraus resultiert ist, dass jede Taste einer Zeile 
die LED einschalten kann, da ja überall eine Null anliegt, kann jeder 
Andere Taster einer Zeile den Pull UP Wiederstand down zeihen.

Gruß Stefan

von Sven S. (stepp64) Benutzerseite


Lesenswert?

Du musst schon auch lesen und verstehen, was den sprut sein Programm 
macht:

"Die Ausgänge werden nacheinander auf "0" gelegt und dabei die Eingänge 
RB4-RB7 ausgewertet. Liegt dabei ein Eingang auf "0", so muß dieser 
durch eine gedrückte Taste mit dem aktiven Ausgang verbunden sein."

Das heist also,

1. Deine vier Eingänge liegen im Ruhezustand auf high.
2. Dann schaltest du einen der Ausgänge auf low und liest die vier 
Eingänge ein. Ist ein Bit gesetzt, dann weist du aufgrund des 
geschalteten Ausgangs und des gestzten Bits, welcher Taster gedrückt 
wurde.
3. Du deaktivierst den 1. Ausgang und aktivierst den 2. Ausgang. Dann 
liest du wieder die vier Eingänge ein und schaust ob ein Taster gedrückt 
wurde.
4. Zu guter letzt musst du das nun noch einmal mit dem 3. Ausgang 
machen.

Auf diese Weise findest du heraus, welcher Taster gedrückt wurde. Nun 
noch entprellen und du kannst damit arbeiten...

Sven

PS: Dein Kabel zu Ground ist Unsinn.

von Severino R. (severino)


Lesenswert?

Stefan K. wrote:
> Hallo,
>
> ja die Null bei den Ausgängen, die ich nach und nach anlege, die Liegt
> an, das passt soweit.

Super


> ABER: Die 0 liegt an den Pins des Atmega zwar an, da aber von selben
> Schalterpin an dem das Kabel vom Ausgang ankommt, auch ein Kabel zu GND
> wegführt, liegt dort auch wenn der Ausgan 0..2 geschaltet ist eine 0 an.

Kabel zu GND????


> Das Problem, welches daraus resultiert ist, dass jede Taste einer Zeile
> die LED einschalten kann, da ja überall eine Null anliegt, kann jeder
> Andere Taster einer Zeile den Pull UP Wiederstand down zeihen.

Willst Du nun bitte ein Zeichnung posten und uns erklären, warum ein 
Kabel (übrigens eher Verbindung, oder wenn's wirklich sein muss, Draht, 
Litze oder Leitung genannt) nach GND führen muss?

von Stefan K. (zerb287)


Lesenswert?

Hallo,

Zeichnung ist in Arbeit, jedoch wenn ein Ausgang auf 0 gesetzt ist, wir 
am Eingang nie eine 0 Angelegt, warum weiss ich nicht!

Hierbei ist der Ausgang mit einer 0 direkt mit dem Eingang mit 5V durch 
den Pull UP Wiederstand verbunden.


Verbindung zw. Schalter und GND wurde bereits beseitigt.


Gruß Stefan


P.S. Ich bin angehender Wirtschaftsinformatiker und habe mit E-Technik 
etc. leider nicht viel zu tun, beschäftige mich aber Hobbymäßig damit 
daher entschuldigt bitte meine wirren Bezeichnungen ;-))

von Sven S. (stepp64) Benutzerseite


Lesenswert?

Der Ausgang ist doch aber niederohmig mit GND im µC verbunden, wenn er 
auf low liegt. Und dein Pullup ist hochohmig mit +5V verbunden. Damit 
zieht dein Ausgang den Eingang auf low. Wenn er das bei dir nicht tut, 
dann überprüfe noch mal deine Verdrahtung.

von was-willst-du (Gast)


Lesenswert?

Hast Du schon mal einen einzelnen Schalter an einen uC angeschlossen und 
per Software ausgewertet?

Oder ist dies Dein erstes Projekt?

Willst Du was lernen oder nur ein Ergebnis haben?

von Stefan K. (zerb287)


Angehängte Dateien:

Lesenswert?

So meine Zeichnung

von was-willst-du (Gast)


Lesenswert?

Die Pull-Ups vergessen?

von Stefan K. (zerb287)


Lesenswert?

Nachtrag:

Das ist mein erstes Projekt. Ich habe mal vor langer Zeit in der Schule 
einen Roboter mit einem Infineon 515C-L angesteuert.

Ich will hauptsächlich was lernen, so was hat mich schon immer gereizt. 
Ich finds einfach super!


Gruß

von was-willst-du (Gast)


Lesenswert?

Hast Du ein Multimeter oder eine andere Möglichkeit Spannungen zu 
messen?

Leg mal einen Ausgang auf low und schau Dir die Spannungen an. 
Eingänge/Ausgänge. Wenn alles stimmt, dann drück mal ne Taste und schau 
Dir an was passiert. So lernst Du die kleine Schaltung verstehen und 
kannst Dir die Software nochmal ansehen und testen.

Wenn Hardware und Softwrae gleichzeitig nicht stimmen, so ist es schwer 
iorgendwo anzufangen. Viel Glück.

von Severino R. (severino)


Lesenswert?

Stefan K. wrote:

> Zeichnung ist in Arbeit

Super!

> jedoch wenn ein Ausgang auf 0 gesetzt ist, wir
> am Eingang nie eine 0 Angelegt, warum weiss ich nicht!

Ist der Ausgang ganz sicher auf 0 gesetzt? Hast Du zwischen 5V und 
Ausgang die Spannung nachgemessen? Wieviel beträgt sie?

> Hierbei ist der Ausgang mit einer 0 direkt mit dem Eingang mit 5V durch
> den Pull UP Wiederstand verbunden.

Ja, aber der Pullup Widerstand "gibt nach", es müsste sich eine log. 0 
ergeben.

> Verbindung zw. Schalter und GND wurde bereits beseitigt.

OK


> P.S. Ich bin angehender Wirtschaftsinformatiker und habe mit E-Technik
> etc. leider nicht viel zu tun, beschäftige mich aber Hobbymäßig damit
> daher entschuldigt bitte meine wirren Bezeichnungen ;-))
Schon ok.

Sorry, ich schrieb weiter oben, dass ich kein AVR-ASM kann.
Natürlich ist das C und nicht ASM, ich meinte ich kenne die Architektur 
der AVRs und die Register etc. fast gar nicht.

Ich glaube, Du hast möglicherweise die I/O nicht richtig eingestellt:

DDRC  &= ~(1<<DDC3) | (1<<DDC4) | (1<<DDC5) | (1<<DDC6);

Das ~ bezieht sich ev. nur auf den Ausdruck (1<<DDC3).

Versuchs mal mit

DDRC = 7;

oder mit Klammerung
DDRC  &= ~ ( (1<<DDC3) | (1<<DDC4) | (1<<DDC5) | (1<<DDC6) ) ;

von Severino R. (severino)


Lesenswert?

Stefan K. wrote:

> Weiter sind bei den Eingängen die internen Pull UP Wiederstände auf HIGH
> gesetzt.

Sicher? Wo im Code geschieht das?

von Stefan K. (zerb287)


Lesenswert?

Hallo,

ja ein Multimeter habe ich, sogar ein Oszilloskop, das Hilft gerade aber 
nicht. Die Schaltung ist überprüft und stimmt. Mit der Initialisierung 
usw. das passt auch, habe die Schaltung ausgesteckt, denn ich habe einen 
Parallel Port stecker verwendet und an der Quelle gemessen. Das passt 
soweit auch alles. Nur der Pull UP Wiederstand zeiht nicht an, das 
verstehe ich nicht.

von Stefan K. (zerb287)


Lesenswert?

Das passiert hier:

 DDRC  &= ~(1<<DDC3) | (1<<DDC4) | (1<<DDC5) | (1<<DDC6);
  PORTC |= (1<<PC3) | (1<<PC4) | (1<<PC5) | (1<<PC6);

von Stefan K. (zerb287)


Lesenswert?

>Leg mal einen Ausgang auf low und schau Dir die Spannungen an.
Eingänge/Ausgänge.

Das passt, dann liegt nichts an. Wenn der Eingang auf HIgh ist, dann 
habe ich auf der Anderen Seite, also in Richtung Ausgang auch 5V 
anliegen.

von Sebi 3. (sebi3k)


Lesenswert?

Hab zwar noch nicht den Durchblick durch den Thread, aber ich sehe grad 
auf anhieb das du PORTC verwendest? Weiss nicht welchen Chip du hast, 
aber bei den vielen liegt auf dem PORTC das JTAG-Interface (PC2 bis 
PC5). Wenn das Teil nicht per Fuse-BIT deaktiviert wird, kann man mit 
den Pins wenig anfangen. Bin erst gestern selbst wieder drauf 
reingefallen, wieso eine 7-Segment Anzeige, die am PORTC hing, komische 
Zeichen angezeigt hat... ;-)

Das so von meiner Seite als Schuss ins Blaue...

Grüße,
Sebi

von Stefan K. (zerb287)


Lesenswert?

Ich verwende einen Atmega32 i.V.m. dem Net-IO von pollin.

von Sebi 3. (sebi3k)


Lesenswert?

Keine Ahnung wie der Auslieferungszustand beim ATmega32 ist, aber hast 
du geprüft ob das FUSE-BIT (JTAGEN = 0) richtig gesetzt ist?

von Stefan K. (zerb287)


Lesenswert?

Hallo,

keine Ahnung, was das macht oder wie ich das setzen oder löschen muss.

Was mich wundert ist, dass

wenn der Ausgang auf 0 ist, der Eingang per Pull-UP auf 1 ist tritt 
folgendes beim Spannung messen auf:

->> Bei gedrücktem Schalter (kontakt zu)

Der Pin am Schalter vom Eingang ist auf 5V, der Pin am Schalter worauf 
der Ausgang sitzt, ist ebenso 5V.

Der Pull-UP Wiederstand wird also nicht down gezogen, sondern das Signal 
von 5V wird über die Schaltung weitergegenen!


WARUM?

von Sebi 3. (sebi3k)


Lesenswert?

Die Pins PC2 bis PC5 haben ein eigenes Verhalten wenn JTAG aktiviert 
ist. Da kannst du setzen oder auslesen wie du lustig bist, die PINS 
lassen sich nicht normal nutzen, ausser für das JTAG-Interface.

Im Grunde müsste das mit der Software gehen mit welcher du deinen Chip 
programierst. Im Artikel werden mehere Tools besprochen:

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

Ansonsten hilft die Suche im Forum hier, da dieses Thema recht häufig 
vorkommt. ;-)

Du kannst natürlich auch einen anderen Port probieren...

Grüße,
Sebi

von Stefan K. (zerb287)


Lesenswert?

Vielen Dank so weit.

Das versuche ich doch mal.


Gruß Stefan

von Stefan K. (zerb287)


Lesenswert?

Hallo nochmal,


also, JTAG ist deaktiviert!

also, ich habe jetzt meine Schaltung verkleinert. Nur noch das 
AVR-NET-IO Bord von pollin. daran habe ich an den PortC0 0V angelegt. 
Das passt soweit auch. Als Eingang den ProtC3 verwendet und den internen 
PullUp Wiederstand aktiviert. Auch das passt.


Wenn ich jetzt direkt den PORTC0 mit PORTC3 verbinde, bleibt der Pull UP 
Wiederstand gesetzt!

Es wird an PORTC3 keine 0 angelegt!

MEIN CODE:

int main(void)
{
DDRC &= ~( ( 1 << DDC3 ) | ( 1<<DDC4) | (1<<DDC5) | (1<<DDC6) );
PORTC |= (1<<PC3);
PORTA = 0x00;

while(1)
   {


   if (!(PINC & (1<<PINC3)))
      {
    PORTA = 0xff;
    } else { PORTA = 0x00;}
   }

return 0;
}

FUNKTIONIERT NICHT!!!


Gruß Stefan

von Severino R. (severino)


Lesenswert?

Stefan K. wrote:

> daran habe ich an den PortC0 0V angelegt.
PortC0 ist doch ein Ausgang, oder? Da darfst Du nichts anlegen.
Den musst Du in Software auf 0 oder 1 setzen.

> Das passt soweit auch. Als Eingang den ProtC3 verwendet
Wie setzt Du PortC3 auf Eingang? Soviel ich weiss, ist das bei AVR über 
den DDRC. 0 = Eingang, 1 = Ausgang

> und den internen PullUp Wiederstand aktiviert.
Wo im Code passiert das?

> Wenn ich jetzt direkt den PORTC0 mit PORTC3 verbinde, bleibt der Pull UP
> Wiederstand gesetzt!
>
> Es wird an PORTC3 keine 0 angelegt!

Und wenn Du PortC3 mit einem Draht auf GND ziehst (zuerst von PortC0 
trennen), kannst Du das 0 lesen?


Tipp: Schreib mal die direkten Werte in den Sourcecode statt den 
Bit-Operationen. Und mit direkten Zuweisungen statt |= etc.
Sicher ist sicher.

von Stefan K. (zerb287)


Lesenswert?

Hallo,

mir scheint als hätte ich eine wichtige Entdeckung gemacht.

CODE:

if ((PINC & (1<<PC3)))
      {
    PORTC |= (1<<PC7);
    } else { PORTC &= ~(1<<PC7) ;}

Wenn ich nun den PORT7 mit dem Oszilloskop messe, mir also die Ausgabe 
anschaue, dann sehe ich, dass der laufend ein und ausgeschaltet wird.

|-|-|-| Also die Ausgabe des Oszi schaut so aus.

WARUM, das heißt meine if Anweisung stimmt nicht, da diese jedes zweite 
Mal erfüllt zu sein scheint.

von Stefan K. (zerb287)


Lesenswert?

Habe soeben die Zuweisung abgeändert.

Allerdings, ist während der Abfrage der Portpin 7 immer nur teilweise 
aktiviert. Wenn ich messe, dann liegt er auf .3,7V.

Stimmen die Abfragen? Oder wo liegt der Fehler?

Mein CODE:

DDRC = 0x87;

PORTC = 0x00;

//DDRC = 0x07;
while(1)


   {

   PORTC = 0x01;

   if (PORTC == 0x01)
      {
    if (PINC & (1<<PC3))
      {
    PORTC = 0x80;
    }
      if ( PINC & (1<<PINC4))
      {
    PORTC = 0x80;
    }
      if ( PINC & (1<<PINC5))
      {
    PORTC = 0x80;
    }
      if ( PINC & (1<<PINC6))
      {
    PORTC = 0x80;
    }
    } else { PORTC = 0x01 ;}
    PORTC = 0x01;

   }

von Peter D. (peda)


Lesenswert?

Es darf natürlich jeder sein eigenes Fahrrad neu erfinden, bloß brauchts 
dann ordentlich Geduld, ehe man seine eckigen Räder rund kriegt.

Es gibt verständlicher Weise auch wenig Begeisterung der Experten, sich 
den tausendsten Versuch einer Tasteneingabe anzugucken.


Max hat doch gerade erst wieder nen schönen Code gepostet:

Beitrag "Re: Matrix-Tastatur Abfrage in C"

Einfach mal laufen lassen.


Peter

von Severino R. (severino)


Lesenswert?

Stefan K. wrote:

> Stimmen die Abfragen? Oder wo liegt der Fehler?

Ich geb's auf.

von Stefan K. (zerb287)


Lesenswert?

Naja,

Die Abfragen passen nun. Nach reichlich messen mit dem Oszi habe ich das 
Problem entdeckt, weiss aber nicht woran es lag, nun funktioniert der 
Code.

Ein neues Problem ist jedoch entstanden:

Wenn ich 0V vom Ausgang anlege, den Pull UP am Eingang auf 1 habe und 
den Schalter nun drücke, dann passiert folgendes:

Die Schaltung pendelt sich auf 2,5V auf jeder Seite des Schalters ein.

Also im Klartext:

Am Pin worauf der Ausgang liegt nun 2,5V und am Pin worauf der Eingang 
liegt ebenso 2,5V.

Ich finde das ziemlich seltsam?


Was meint Ihr woran es liegt.

--> Sorry, den Code habe ich nicht gesehen.

von Peter D. (peda)


Lesenswert?

Stefan K. wrote:
> Am Pin worauf der Ausgang liegt nun 2,5V und am Pin worauf der Eingang
> liegt ebenso 2,5V.

Miß mal die Stromaufnahme des AVR. Wenn die stark ansteigt, kämpfen 2 
Ausgänge gegeneinander, das ist nicht gesund für den AVR.

Deshalb nimmt man für ne Tastenmatrix immer open-drain Ausgänge, d.h. 
ein Pin kann nur Low-Ausgang oder Eingang sein.

High-Ausgang ist verboten, wenn ein anderer Pin Low-Ausgang ist!


Peter

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.