16er-Tastatur mit I2C-Ansteuerung

Abfrage von Matrix-Tastaturen bis zu 16 Tasten im Format 4 x 4 oder z.B. 12 Tasten (4 x 3) oder 4 Tasten (1 x 4) mit dem I2C-Portexpander PCF8574.




Testaufbau am Beispiel Arduino:

Verwendete Bauteile:

  • 1 Arduino Uno oder Nano
  • 1 Portexpander PCF8574
  • 2 Widerstände 10 kOhm
  • 1 Tastatur z.B. 16 Tasten (4 x 4)


Anschluss der Tastatur:

Für die Funktionalität der Library ist beim Anschluss der Tastatur darauf zu achten, dass bei den Port-Ein-/Ausgängen des Portexpanders PCF8574 die Zeilen der Tastaturmatrix nur auf P0-P3 und die Spalten nur auf P4-P7 (oder umgekehrt) geschaltet sind, aber nicht vermischt!!

(Siehe auch "Anschluss der Tastatur" unter 16er-Tastatur)


I2C-Adresse:

Die I2C-Adresse ist hardwaremäßig über die Adresseingänge A0 - A2 an der Porterweiterung einstellbar. Jedoch ist der Adressbereich nicht bei allen PCF8574x-Typen gleich. Bisher habe ich folgende Adressen bzw. Adressbereiche festgestellt:

  • PCF8574N, PCF8574P und PCF8574T: 0x20 bis 0x27
  • PCF8574AN, PCF8574AT:                    0x38 bis 0x3F


Aufbau auf einem Mini-Steckbrett:


Library MyKeypad_I2C für Arduino und Attiny45/85:

Die Library ist für 16er-Tastaturen (4 x 4 Tasten) zu verwenden, kann aber auch für Tastaturen mit weniger Tasten, also z.B. mit 4, 9 oder 12 Tasten verwendet werden. Folgende Funktionen stehen zur Verfügung:


  • Abfrage, ob die I2C-Schnittstelle ansprechbar ist
  • Abfrage der Tastatur (= Rückgabewert)
  • Löschen aller Tastencodes
  • Eingabe der Tastencodes zur Anpassung an verschiedene Tastaturen


Zusätzliche Funktionen zur Anpassung der Tastatur:  1)

  • Ausgabe des Tastencodes und des Rückgabewertes einer gedrückten Taste am Seriellen Monitor (nur für Arduino)
  • Ausgabe aller Tastencodes am Seriellen Monitor (nur für Arduino)


1)  Die Anpassung einer Tastatur ist nach den Programmbeispielen im Kapitel "Die Verwendung der Library mit verschiedenen Tastaturen" beschrieben.


  • Rückgabewert und Übergabeparameter bei der Tastaturabfrage:

  • Für eine gedrückte Taste z.B. 0.....9 gibt die Library die Zahlen (Format byte) 0.....9 zurück, für Sondertasten wie z.B. A.......F oder Sonderzeichen wie Raute oder Stern die Zahlen 10....15. Wurde keine Taste gedrückt, ist der Rückgabewert 255.

  • Die Abfrage des Tastenwertes muss im Hauptprogramm erfolgen und sollte für eine sichere Tastendruckerkennung alle 100 bis 200 ms durchgeführt werden. Als guter Wert hat sich 150 ms erwiesen. Ich verwende für die zyklische Abfrage der Tastatur gerne die Metro-Library (siehe nachfolgendes Programmbeispiel).


    Bei der Abfrage des Tastenwertes ist ein Übergabeparameter mit anzugeben, der bei anhaltendem Tastendruck die Funktion der Taste bestimmt (siehe nachfolgendes Programmbeispiel):

    Übergabeparameter = 0:

    Wird eine Taste längere Zeit gehalten, gibt die Funktion als Rückgabewert bei jedem Abfragefragezyklus den Tastenwert der gedrückten Taste zurück.

    Übergabeparameter  >= 1:

    Wird eine Taste längere Zeit gehalten, gibt die Funktion als Rückgabewert nach einer definierbaren Zeit nicht mehr 0....15, sondern 100 bis 115 zurück. Dadurch hat man im aufrufenden Programm die Möglichkeit, entsprechend auf einen längeren Tastendruck zu reagieren. Wie lange die Taste gedrückt werden muss, wird durch den Übergabeparameter definiert. Gibt man als Übergabeparameter z.B. 5 an, so wird die Rückgabe nach 5 Abfragezyklen (z.B. 5 x 150ms = 750 ms) geändert.

    Übergabeparameter = (-1):

    Wird eine Taste längere Zeit gehalten, gibt die Funktion als Rückgabewert nur einmalig den Tastenwert der gedrückten Taste zurück.


    Ähnlich wie bei einer PC-Tastatur wird (bei Übergabeparameter 0 oder >1) die Rückgabe des Tastenwertes nach der ersten Rückgabe kurz verzögert um eine unbeabsichtigte Doppel- oder Mehrfachrückgabe zu verhindern. Die Verzögerung ist in den Libraries mit 2 Abfragezyklen festgelegt. Ist der Abfragezyklus also z.B. 150 ms, so beträgt die Verzögerung 2 x 150 = 300 ms.


    Die Library für Arduino und Attiny45/85 kann hier heruntergeladen werden:

    Sollte die Library jemand verwenden oder testen, würde ich mich über eine Rückmeldung sehr freuen!


    Version 2.1

    MyKeypad_I2C.cpp.txt

    MyKeypad_I2C.h.txt

    keywords.txt

    .... und eine Version mit gleichen Funktionsumfang, die aber meine Library "MyPCF8574" zur Ansteuerung des PCF8574 nutzt:

    Version 2.1

    MyKeypad_I2C_2.cpp.txt

    MyKeypad_I2C_2.h.txt

    keywords.txt


    Die Library "MyPCF8574" kann hier heruntergeladen werden: Portexpander PCF8574


    Leider kann ich hier keine "cpp"- oder "h"-Files hochladen, daher zum Verwenden der Library ".txt" aus den Dateinamen entfernen und in einem neuen Verzeichnis mit dem Namen "MyKeypad_I2C" bzw. "MyKeypad_I2C_2" dort speichern, wo eure anderen Libraries gespeichert sind.


    Zur Auflistung der Funktionen der Libraries geht es hier: Funktionen


    Programmbeispiel MyKeypad_I2C bzw. MyKeypad_I2C_2 für Arduino

    Das Beispielprogramm gibt die Rückgabewerte der betätigten Tasten am Seriellen Monitor aus. Aufgrund des Übergabeparameters 5 in der Funktion "receiveKey(5)" wird der Rückgabewert bei jedem Zyklus und nach 5 Zyklen ein um +100 erhöhter Wert ausgeben (siehe oben "Übergabeparameter").

    Neben der Standardlibrary Wire wird auch die Library Metro, wo in einem vordefinierten Zyklus (hier im Beispiel 150 ms) die Tastatur abfragt wird, benötigt. Einen Link zu Metro findet ihr hier: Fremd-Libraries

    Wird die Library MyKeypad_I2C_2 benutzt, ist zusätzlich noch meine Library MyPCF8574 zu installieren (siehe Portexpander PCF8574 ).

    Das Funktionieren des Programms setzt voraus, dass die Anpassung der jeweiligen Tastatur entweder in der Library selbst oder im Setup des Beispielprogrammes - wie im nachfolgenden Kapitel "Die Verwendung der Library mit verschiedenen Tastaturen" beschrieben - bereits erfolgt ist!


    //Programmbeispiel zu MyKeypad_I2C
    //Code fuer Arduino
    //Author Retian
    //Version 1.1


    #include <Metro.h>
    #include <MyKeypad_I2C.h>


    MyKeypad_I2C MyKey(0x38); //I2C Adresse des Portexpanders PCF8574
    Metro tastaturZyklus(150); //Festlegung des Tastaturabfragezyklus (150 ms)


    byte key;


    void setup() {
      Serial.begin(115200);
      if (MyKey.isReady()) //Abfrage, ob Tastatur ueber I2C-Schnittstelle ansprechbar ist ...
      {
        Serial.println("Tastatur ok");
        //Eventuell Anpassung der Tastencodes
        //MyKey.clearAllKeyCodes(); //Loeschen der in der Library definierten Tastencodes
        //MyKey.setKeyCode(..., ...);
        //MyKey.setKeyCode(..., ...);
        //...........................
      }
      else
      {
        Serial.println("Tastatur Fehler!!");
        while(1); //...sonst geht's hier nicht weiter
      }
    }


    void loop() {
      if (tastaturZyklus.check()) //Zykluszeit für Tastaturabfrage abgelaufen?
      {
        //Abfrage der Tastatur mit Uebergabeparameter 5
        //(Wird eine Taste laenger gedrueckt, wird nach 5 Zyklen
        //ein um +100 hoehere Rueckgabewert ausgeben)
        key = MyKey.receiveKey(5);
        if (key < 255)  Serial.println(key);
      }
    }


    Programmbeispiel MyKeypad_I2C bzw. MyKeypad_I2C_2 für Attiny45/85

    Da ich mit Attiny den Seriellen Monitor nicht zur Verfügung habe, gebe ich im Programmbeispiel die Rückgabewerte auf einer 7-Segmentanzeige aus. Dazu verwende ich eine Anzeige und meine Library wie hier beschrieben: 7-Segm.anz. HT16K33. Aufgrund des Übergabeparameters -1 in der Funktion "receiveKey(-1)" wird der Rückgabewert bei Betätigung einer Taste nur ein einziges Mal ausgegeben (siehe oben "Übergabeparameter").

    Neben der Library Metro, wo in einem vordefinierten Zyklus (hier im Beispiel 150 ms) die Tastatur abfragt wird, wird für die I2C-Schnittstelle auch noch die Library TinyWireM benötigt. Einen Link zu Metro und zu TinyWireM findet ihr hier: Fremd-Libraries

    Wird die Library MyKeypad_I2C_2 benutzt, ist zusätzlich noch meine Library MyPCF8574 zu installieren (siehe Portexpander PCF8574 ).

    Das Funktionieren des Programms setzt voraus, dass die Anpassung der jeweiligen Tastatur entweder in der Library selbst oder im Setup des Beispielprogrammes - wie im nachfolgenden Kapitel "Die Verwendung der Library mit verschiedenen Tastaturen" beschrieben - bereits erfolgt ist!


    //Programmbeispiel zu MyKeypad_I2C
    //Code fuer Attiny
    //Author Retian
    //Version 1.1


    #include <MyHT16K33_7Seg.h>
    MyHT16K33_7Seg My7S(0x70);


    #include <MyKeypad_I2C.h>
    MyKeypad_I2C MyKey(0x38);


    #include <Metro.h>
    Metro tastaturZyklus(150); //Festlegung des Tastaturabfragezyklus (150 ms)


    byte key;


    void setup() {
      //Wenn 7-Segmentanzeige und Tastatur bereit sind ...
      if (My7S.isReady() && MyKey.isReady())
      {
        My7S.init();
        My7S.sendBlank(); //Dunkelsetzen der Anzeige
        delay(1000);
        My7S.test7Seg(); //Alle Segmente leuchten fuer 1s

        //Tastencodes anpassen, falls erforderlich
        //MyKey.setKeyCode( .., ..);
        //MyKey.setKeyCode(.., ..);
        //.................................
      }
      else while (1); //... sonst geht's hier nicht weiter
    }


    void loop() {
      if (tastaturZyklus.check()) //Zykluszeit für Tastaturabfrage abgelaufen?
      {
        //Abfrage der Tastatur mit Parameter -1
        //(Wird eine Taste laenger gedrueckt, wird der Rueckgabewert nur einmal ausgeben)
        key = MyKey.receiveKey(-1);
        if (key != 255) My7S.sendFixedVal((int)key, 0, true);
      }
    }

    Die Verwendung der Library mit den verschiedenen Tastaturen

    Matrix-(Folien-)Tastaturen erhält man in verschiedenen Ausführungen, mit unterschiedlichen Tastenanzahlen, Tastenbeschriftungen und Tastenverschaltungen. Und auch der Anschluss an den Portexpander kann durch Vertauschen der Tastaturmatrix (Zeilen- und Spaltenanschlüsse) und durch unterschiedliche Anzahl von Zeilen und Spalten variieren. Dadurch ist eine Anpassung der Library an jede Tastaturtype erforderlich.


    Zur Anpassung der jeweiligen Tastatur an die Library gibt es 2 Möglichkeiten:

    1. Anpassung im Setup des Programms oder
    2. Anpassung direkt in einer - in der Library hinterlegten - Tabelle

    Je nach Verschaltung der Spalten-Zeilen-Matrix wird beim Drücken einer Taste durch die Library ein sogenannter Tastencode (Variable "keyCode") ermittelt. Mit Hilfe einer Tabelle wird nun aufgrund dieses Tastencodes ein Rückgabewert (=gedrückter Tastenwert) ermittelt. Stimmt nun dieser Rückgabewert mit dem gewünschten Rückgabewert (also z.B. Rückgabewert 7 für die gedrückte Taste "7") nicht überein, so muss die Tabelle entsprechend geändert werden:


    Die aktuellen Tastencodes erhält man durch Drücken aller Tasten mit nachfolgendem Hilfsprogramm:

    //Hilfsprogramm zur Abfrage der Tastcodes
    //Code fuer Arduino
    //Author Retian
    //Version 1.0


    #include <MyKeypad_I2C.h>
    MyKeypad_I2C MyKey(0x38);


    void setup() {
      Serial.begin(115200);
      Serial.println("TastenCode-Abfrage");
      if (MyKey.isReady()) Serial.println("Tastatur ok");
      else Serial.println("Tastatur Fehler!!");
    }


    void loop() {
      MyKey.checkKey();
      delay(500);
    }

    Ausgabe am Seriellen Monitor, nachdem alle 16 Tasten (von links oben nach rechts unten) gedrückt wurden:

    So sollte z.B. bei gedrückter Taste "7" der Rückgabewert eben 7 sein, bei Taste "A" z.B. 10 oder bei Taste "#" z.B. 15.

    Erhält man z.B. bei Drücken der Taste "7" nicht den gewünschten Rückgabewert 7, so gibt es zwei Möglichkeiten zur Anpassung:


    1. Eingabe der Tastencodes im Setup des Programms (wenn man verschiedene Tastaturen verwendet)

    Die mit Hilfe des obigen Programms - für die jeweilige Tastatur - ermittelten Tastencodes können mit der Funktion

    MyKey.setKeyCode(byte Tastencode, byte Rueckgabewert);

    im Setup des Programms eingegeben werden.

    Werden die Tastencodes z.B. für eine Tastatur mit weniger als 16 Tasten, also z.B. mit nur 9 oder 12 Tasten eingegeben, dann sollte die Vorbelegung der Tastencodes in der Library, vorher mit der Funktion

    MyKey.clearAllKeyCodes();

    gelöscht werden!

    Beispiel:

    //Beispiel fuer Festlegen der Tastencodes, die abweichend von den in der
    //Library festgelegten Codes sind, fuer eine Tastatur mit 12 Tasten:
    //
    // Tastenbelegung       Rueckgabewerte
    //  1  2  3                    1  2  3
    //  4  5  6                    4  5  6
    //  7  8  9                    7  8  9
    //  *  0  #                  11  0 13
    //

    MyKey.clearAllKeyCodes(); //Loeschen der in der Library definierten Tastencodes


    MyKey.setKeyCode(0xDE, 0); //Tastencode 0xDE, Rueckgabewert 0
    MyKey.setKeyCode(0xE7, 1); //Tastencode 0xE7, Rueckgabewert 1
    MyKey.setKeyCode(0xD7, 2); //Tastencode 0xD7, Rueckgabewert 2
    MyKey.setKeyCode(0xB7, 3); //etc.
    MyKey.setKeyCode(0xEB, 4);
    MyKey.setKeyCode(0xDB, 5);
    MyKey.setKeyCode(0xBB, 6);
    MyKey.setKeyCode(0xED, 7);
    MyKey.setKeyCode(0xDD, 8);
    MyKey.setKeyCode(0xBD, 9);
    MyKey.setKeyCode(0xEE, 11);
    MyKey.setKeyCode(0xBE, 13);

    Auf diese Art kann für jede Taste der Rückgabewert für den entsprechenden Tastencode angepasst werden.


    2. Anpassung der Tastencodes in der Library selbst (wenn man hauptsächlich oder immer nur eine Tastatur bzw. einen Tastaturtyp verwendet)

    Die mit obigem Hilfsprogramm ermittelten Rückgabewerte können direkt in der Library angepasst werden.

    Nachfolgend ein Programmauszug aus "MyKeypad_I2C.cpp" mit den vorbelegten Tastencodes:

    (Die hier dargestellten Tastencodes sind beispielhaft und gelten für eine von mir verwendete Tastatur).

    //Vorbelegte Tastencodes
    // Tastenbelegung      Rueckgabewerte
    //  7  8  9  A               7  8  9 10
    //  4  5  6  B               4  5  6 11
    //  1  2  3  C               1  2  3 12
    //  0  F  E  D               0 15 14 13
    // 
    keyCode[0]  = 0x77; //Tastencode fuer Rueckgabewert 0
    keyCode[1]  = 0xB7; //Tastencode fuer Rueckgabewert 1
    keyCode[2]  = 0xBB; //Tastencode fuer Rueckgabewert 2
    keyCode[3]  = 0xBD; //Tastencode fuer Rueckgabewert 3
    keyCode[4]  = 0xE7; //Tastencode fuer Rueckgabewert 4
    keyCode[5]  = 0xEB; //Tastencode fuer Rueckgabewert 5
    keyCode[6]  = 0xED; //Tastencode fuer Rueckgabewert 6
    keyCode[7]  = 0xD7; //Tastencode fuer Rueckgabewert 7
    keyCode[8]  = 0xDB; //Tastencode fuer Rueckgabewert 8
    keyCode[9]  = 0xDD; //Tastencode fuer Rueckgabewert 9
    keyCode[10] = 0xDE; //Tastencode fuer Rueckgabewert 10
    keyCode[11] = 0xEE; //Tastencode fuer Rueckgabewert 11
    keyCode[12] = 0xBE; //Tastencode fuer Rueckgabewert 12
    keyCode[13] = 0x7E; //Tastencode fuer Rueckgabewert 13
    keyCode[14] = 0x7D; //Tastencode fuer Rueckgabewert 14
    keyCode[15] = 0x7B; //Tastencode fuer Rueckgabewert 15

    Nach der Anpassung der Tastencodes im File "MyKeypad_I2C.cpp" oder "MyKeypad_I2C_2.cpp" die Datei speichern, den "TastenCode-Abfrage-Sketch" neu übersetzen und die Rückgabewerte kontrollieren. Wenn alle Werte passen, kann die Library für genau diese Tastatur und für diese Verschaltung verwendet werden.