Probleme beim Einlesen eines Keypads

Hallo,

ich möchte ein Keypad einlesen. Es hat 4 Zeilen und 3 Spalten (4x3 Keypad). Bei Tastendruck wird ein Kontakt geschlossen. Wenn ich mir die gedrückten Tasten im Serial Monitor anzeigen lasse wird ein durcheinander von allen möglichen Zeichen des Keypads eingelesen wenn ich noch garnichts drücke. Wenn ich dann alle Tasten des Keypads gleichzeitig drücke wird nichts mehr eingelesen. Ich habe auch schon in der Library die Zustände HIGH mit LOW vertauscht weil ich gedacht habe das es daran liegen könnte, aber ohne Erfolg. Hat einer von euch eine Idee??

Ich benutze folgenden Code zum Testen der Funktion (Arduino Mega):

#include <MyKeyPad.h>

int rowArray[] = {28, 29, 26, 27}; // Array mit Zeilen Pin-Nummern initialisieren
int colArray[] = {24, 25, 22};    // Array mit Spalten Pin-Nummern initialisieren
MyKeyPad myOwnKeyPad(rowArray, colArray); // Instanziierung eines Objektes

void setup(){
  Serial.begin(9600);               // Serielle Ausgabe vorbereiten
  myOwnKeyPad.setDebounceTime(500); // Prellzeit auf 500ms setzen
}

void loop(){
  char myKey = myOwnKeyPad.readKey(); // Abfragen des gedrückten Tasters
  if(myKey != KEY_NOT_PRESSED)        // Abfrage, ob irgendein Taster gedrückt
    Serial.println(myKey);            // Ausgabe des Tastenzeichens
}

Das ist die Header Datei:

#ifndef MYKEYPAD_H
#define MYKEYPAD_H
#if ARDUINO < 100
#include <WProgram.h>
#else
#include <Arduino.h>
#endif

#define KEY_NOT_PRESSED '-' // Wird benötigt, wenn keine Taste gedrückt wird
#define KEY_1 '1'
#define KEY_2 '2'
#define KEY_3 '3'
#define KEY_4 '4'
#define KEY_5 '5'
#define KEY_6 '6'
#define KEY_7 '7'
#define KEY_8 '8'
#define KEY_9 '9'
#define KEY_0 '0'
#define KEY_STAR '*'
#define KEY_HASH '#'

class MyKeyPad{
  public:
    MyKeyPad(int rowArray[], int colArray[]);        // Parametrisierter Konstruktor
    void setDebounceTime(unsigned int debounceTime); // Setzen der Prellzeit
    char readKey(); // Ermittelt die gedrückte Taste auf dem KeyPad
  private:
    unsigned int debounceTime; // Private Variable für die Prellzeit
    long lastValue; // Letzte Zeit der millis-Funktion
    int row[4];     // Array für die Zeilen
    int col[3];     // Array für die Spalten
};
#endif

Das ist die CPP Datei:

#include "MyKeyPad.h"
// Parametrisierter Konstruktor
MyKeyPad::MyKeyPad(int rowArray[], int colArray[]){
  // Kopieren der Pin-Arrays
  for(int r = 0; r < 4; r++)
    row[r] = rowArray[r];
  for(int c = 0; c < 3; c++)
    col[c] = colArray[c];
  // Programmieren der digitalen Pins
  for(int r = 0; r < 4; r++)
    pinMode(row[r], OUTPUT);
  for(int c = 0; c < 3; c++)
    pinMode(col[c], INPUT);
  // Initialwert für debounceTime auf 300ms festlegen
  debounceTime = 300;
}

// Methode zum Setzen der Prellzeit
void MyKeyPad::setDebounceTime(unsigned int time){
debounceTime = time;
}

// Methode zum Ermitteln des gedrückten Tasters auf dem KeyPad
char MyKeyPad::readKey(){
  char key = KEY_NOT_PRESSED;
  for(int r = 0; r < 4; r++){
    digitalWrite(row[r], HIGH);
    for(int c = 0; c < 3; c++){
      if((digitalRead(col[c]) == HIGH)&&(millis() - lastValue) >= debounceTime){
        if((c==2)&&(r==3)) key = KEY_1;
        if((c==1)&&(r==3)) key = KEY_2;
        if((c==0)&&(r==3)) key = KEY_3;
        if((c==2)&&(r==2)) key = KEY_4;
        if((c==1)&&(r==2)) key = KEY_5;
        if((c==0)&&(r==2)) key = KEY_6;
        if((c==2)&&(r==1)) key = KEY_7;
        if((c==1)&&(r==1)) key = KEY_8;
        if((c==0)&&(r==1)) key = KEY_9;
        if((c==2)&&(r==0)) key = KEY_STAR; // *
        if((c==1)&&(r==0)) key = KEY_0;
        if((c==0)&&(r==0)) key = KEY_HASH; // #
        lastValue = millis();
      }
    }
  digitalWrite(row[r], LOW); // Zurücksetzten auf Ursprungspegel
  }
  return key;
}

Gruß,
Tobi

kleiner Anhang:

Wenn ich in der Library sowohl OUTPUTs als auch INPUTs auf LOW setze wird trotzdem im Serial Monitor das Wirrwarr angezeigt. Wenn ich meinen Finger auf alle Kontakte lege und dann die Tasten auf dem Keypad betätige werden sie richtig eingelesen.

Dir fehlen Pullup- bzw Pulldown-Widerstände die die Eingänge auf einen definierten Pegel halten solangekeine Taste gedrückt ist.
Kannst Du uns einen Schaltplan geben?
Grüße Uwe

hey,

ich habe nun an jeden der 7 Pins die vom Keypad kommen einen 10k Ohm PullDown Widerstand angeschlossen. Es funktioniert aber immer noch nicht.

So habe ich das angeschloßen:

Gruß,
Tobi

Es funktioniert aber immer noch nicht.

ist sehr wage. Bitte eine genauere Fehlerbeschreibung.
Grüße Uwe

Und wenn du dich an diese Anleitung hältst ?

Edit:Bezüglich der Pin-Nummern schein es in diesem Instructable Verwirrung zu geben: Die Pullup-Widerstände sollten jedenfalls an den 4 Column-Pins sein, denke ich.
Evtl. hilft auch ein zweiter Blick in die Library. Tip: Columns und Rows werden unterschiedlich behandelt.

Hey,

Zuerst hatte ich an jeden der sieben Pins des Keypads einen 10k Ohm Widerstand angeschlossen und mit Masse verbunden. Das Problem war das gleiche: Auch wenn keine Tasten gedrückt werden werden im Serial Monitor alle Zeichen in zufälliger Form eingelesen. Drücke ich alle Tasten gleichzeitig wird nichts mehr eingelesen. Jetzt habe ich folgendes gemacht. Die Widerstände sind weiterhin mit den Pins verbunden, nur ich habe deren Enden nicht mit Masse verbunden. Jetzt wird einmalig bei Programmstart das "Raute" Zeichen eingelesen. Ich habe eingestellt das das Array nachdem 4 Zeichen in ihm gespeichert wurden gelöscht wird und der Einlesevorgang von Vorne beginnt. Daher weiß ich das die Raute nur einmalig eingelesen wird. Danach funktioniert das Einlesen Perfekt. Woran kann das jetzt liegen? Ich habe jetzt folgenden Gedanken: Direkt nach Programmstart soll der Arrayinhalt einmal gelöscht werden. So könnte man den Fehler ausmerzen, zwar ohne die Ursache genau zu finden aber es würde funktionieren. Was meint ihr? Ich habe schon etwas rumprobiert aber ich Hänge momentan da das ich den Arrayinhalt nicht löschen kann sondern nur mit Nullen Fülle. Kann mir jemand von euch sagen wie man ein Array des Datentyps Char "löscht"?

Gruß,

Tobi

Kann mir jemand von euch sagen wie man ein Array des Datentyps Char "löscht"?

indem man in jedes Element einen "Null-wert" schreibt.
Grüße Uwe

Es reicht sogar, in das erste eine 0 zu schreiben :wink:

char myArray[100] = "Hallo"; // 5 byte definiert, eine 0, Rest undefinert

*myArray = 0;
// myArray[0] == 0 , Rest undefiniert

hey,

danke für die Info. Bin im Thema Array noch nicht sehr vertraut. Eine Frage würde das dann ungefähr so gehen:

So legt man ein Array an ?

char DASISTEINARRAY[5] = 90000; // Array kann 5 Bits speichern ( [5] ) und bekommt die Zahl 90000 eingespeichert

So kann ich es "löschen" indem ich es mit Nullen beschreibe?

DASISTEINARRAY[5] = 00000;

oder

DASISTEINARRAY[0] = 0;

Ist das so richtig? Weil den Gedanken den ich halt mit dem Null schreiben habe ist, bekomm ich dann nicht auf meinem Display die Nullen angezeigt ? Weil er mir ja auf meinem Display den Array Inhalt darstellt.

Gruß,
Tobi

hey,

habs hinbekommen. Das Problem mit der Raute ließ sich lösen indem ich die Widerstände einfach anstatt auf Masse auf +5V gelegt hab :sweat_smile:
Das mit dem Array klappt soweit auch.

Danke für die Tipps.

Gruß,
Tobi