Viele Projekte mit Mikrocontroller, Arduino oder Raspberry Pi verwenden eine kleine Tasten-Matrix mit Zahlen und einigen zusätzlichen Funktionen für Anwender-Eingaben. Üblicherweise sind es 12 oder 16 Tasten, die als Matrix, also mit Anschlüssen für 3 oder 4 Spalten und Reihen geschaltet sind.
Ich verwende für meine Projekte gerne eine 4×4-Matrix mit 16 Tasten. Der hier vorgestellte Ansatz funktioniert aber gleichermaßen mit Folien-Tastaturen, auch dann, wenn sie über weniger Tasten verfügen. Die einzige Voraussetzung ist, dass die Tasten elektrisch als Matrix angeordnet sind, also jede Taste bei Betätigung eine Spalte mit einer Zeile verbindet.
Für diese Tastaturen gibt es Bibliotheken für Arduino oder Raspberry Pi, die den Anschluss relativ einfach ermöglichen. Ein Nachteil ist aber, dass bei einer 4×4-Matrix 8 Port-Anschlüsse gebraucht werden. Wenn der Mikrocontroller noch andere Aufgaben zu erledigen hat, dann kann es eng werden. Außerdem benötigt die Bibliothek einen Timer-gesteuerten Interrupt, um die Tasten auszulesen. Dieser Interrupt kann mit anderen Funktionen eines Anwenderprogramms in einen Konflikt geraten.
Treiber-Schaltung für die Tasten-Matrix
Um diesen Problemen entgegen zu wirken, habe ich einen anderen Ansatz gewählt. Die Tastatur bekommt einen eigenen Mikrocontroller, einen ATmega328, der sich vollständig um die Tasten kümmert und die Daten über eine I2C-Schnittstelle dem Anwendersystem, wir nennen es den „Host“, zur Verfügung stellt. Die Tasten-Matrix ist dabei ein I2C-Slave. So werden auf dem Host (fast) keine Ressourcen für die Matrix benötigt.
Sicherlich hätte man dieses Projekt auch mit einem Arduino, z.B. einem Nano aufbauen können. Aus meiner Sicht wäre das aber ein unangemessener Aufwand für diese einfache Aufgabe. Der Nano ist größer, teurer und benötigt mit seiner Peripherie mehr Strom als ein „nackter“ ATmega. Deshalb habe ich mich für die kleine Lösung entschieden.
Die Schaltung benötigt nur sehr wenig Hardware. Ein ATmega328 kostet zur Zeit weniger als 2 Euro, so dass die Kosten gering bleiben. Er läuft mit seinem internen 8 MHz-Taktgenerator, so dass kein externen Quarz benötigt wird. Wenn man schon einmal dabei ist, kann der ATmega noch ein paar zusätzliche Aufgaben übernehmen. Meine Schaltung bekommt einen kleinen Piezo-Schallwandler, um Tasten-Klicks zu erzeugen. Außerdem habe ich vier LEDs vorgesehen, die über die I2C-Schnittstelle ein- oder ausgeschaltet werden können. Der Piezo-Buzzer und die Leuchtdioden sind natürlich optional und können auch weggelassen werden.
Die Schaltung benötigt eine Spannungsversorgung von 3.3 oder 5V. Es werden also 4 Verbindungsleitungen zum Host benötigt: GND, Vcc und die beiden I2C-Leitungen SDA und SCL. Diese beiden Leitungen benötigen einen PullUp-Widerstand nach Vcc, sofern das Host-System nicht bereits über PullUp-Widerstände verfügt. Ich verwende an dieser Stelle gerne 2,2 kOhm-Widerstände. Das I2C-Interface kann mit den üblichen 100 kHz oder im Fast-Mode mit 400 kHz betrieben werden.
Die Schaltung ist schnell auf einem Stück Lochraster-Platine aufgebaut. Ich habe die Platine auf die Größe der Tastenmatrix zurecht geschnitten und mit Abstandshaltern direkt unter die Tastatur geschraubt.
Software mit Komfort-Funktionen
Die Software für den ATmega328 im Zentrum der Schaltung wurde mit dem Atmel-Studio entwickelt. Da der ATmega hier ohne Peripherie arbeitet, gibt es kein USB-Interface, wie wir es vom Arduino kennen. Deshalb benötigt man einen Programmier-Adapter, um die Software auf den Chip zu laden. Ich verwende seit vielen Jahren den AVR-ISP mkII für diese Aufgabe.
Das Programm fragt die Spalten und Zeilen der Tasten-Matrix 20 mal pro Sekunde ab. Wenn eine Tasten gedrückt ist, wird der Tastenwert entprellt und in einen internen Puffer geschrieben. Ein kurzes akustisches Signal vom Piezo-Buzzer bestätigt den Tastendruck.
Das Host-System kann über das I2C-Interface zu jeder Zeit anfragen, ob eine Taste gedrückt wurde. Im Register 0 findet sich der jeweilige noch nicht gelesene Tastenwert aus dem Puffer. Dazu gibt es – wie bei einer normalen Computer-Tastatur – eine Repeat-Funktion. Wenn eine Taste länger als eine Sekunde gerückt ist, wird der Tastendruck 5 mal pro Sekunde erzeugt.
Alternativ gibt es im Register 1 die Möglichkeit, die Tasten vom Host ohne den Puffer direkt abzufragen, z.B. um irgendetwas auf dem Host-System auszulösen, solange eine bestimmte Taste gedrückt ist.
Schließlich können noch die Leuchtioden über das I2C-Interface geschaltet werden oder die Konfigurations-Parameter für Sound und Auto-Repeat gesetzt werden.
Der Quellcode der Software verteilt sich über 6 Dateien, die in das Projekt im Atmel-Studio eingebunden werden müssen. main.c
ist das Hauptprogramm. keyboard.c
und keyboard.h
sind die Funktionen zur Bearbeitung der Tasten-Matrix. twi_slave.c
und twi_slave.h
kümmern sich um das I2C-Interface. keyboard_layout.h
enthält die ASCII-Zeichen für die Tasten.
Die I2C-Slave Adresse ist 0x5f. Sie kann in der Software auf jeden anderen gültigen Wert umdefiniert werden (File main.c
)
Übersicht der I2C-Funktionen:
- Register 0: Retrieves the most recent key stroke from the buffer. The keyboard sends the ASCII character of the pressed key or 0 in case there is no pending key stroke in the buffer.
- Register 1: Retrieves the current key from the keyboard without buffering. This function implicitly clears the buffer.
- Register 2: Retrieves the number of bytes (= keys pressed) currently in the buffer
- Register 10: Requires one byte as argument. Sets LED 0 to On (argument > 0) or Off (argument = 0)
- Register 11: Requires one byte as argument. Sets LED 1
- Register 12: Requires one byte as argument. Sets LED 2
- Register 13: Requires one byte as argument. Sets LED 3
- Register 20: Requires one byte as argument. Sets sound On (argument > 0) or Off (argument = 0)
- Register 22: Requires one byte as argument. Sets auto repeat to On (argument > 0) or Off (argument = 0)
Die Einstellungen für Sound On/Off und Auto Repeat On/Off werden im EEPROM gespeichert und damit über das Ausschalten hinaus erhalten.
Das Layout der Tasten ist in der Datei keyboard_layout.h
hinterlegt. Hier können Anpassungen vorgenommen werden.
Anwendung mit Arduino
Jedes Arduino-System, das eine I2C-Schnittstelle hat, kann die Tastatur verwenden. Dazu gibt es die Dateien KeyBoard_I2C.h
und KeyBoard_I2C.cpp
. Nachdem diese Dateien in den Arduino-Sketch eingebunden sind, stehen alle Funktionen bereit.
int check(void);
zur Abfrage, ob ein Tastendruck im Puffer enthalten ist.int read(void);
liefert einen Tastendruck aus dem Puffer, oder 0 im Fall, dass der Puffer leer ist.int read_direct(void);
liest die Tasten-Matrix ohne Puffer aus.void set_led(uint8_t led, bool led_status);
setzt oder löscht eine der LEDsvoid set_dound(bool onoff);
schaltet die Funktion des Piezo-Buzzers ein oder ausvoid set_repeat(bool onoff);
schaltet die Auto-Repeat Funktion ein oder aus
Fazit
Die kleine Schaltung vereinfacht den Einsatz von Tasten-Matrizen für Arduino und Raspberry Pi Systeme. Der ATmega arbeitet unauffällig im Hintergrund und entbindet das Host-System von einer lästigen Aufgabe. Die zusätzlichen Funktionen wie Sound und Auto Repeat geben dem Anwender einen Komfort, wie er oder sie es von einer üblichen Computer-Tastatur kennt.
Inzwischen habe ich die Tasten-Matrix in einigen Projekten im Einsatz und möchte sie nicht mehr missen.
Ressourcen auf GitHub
Software, Schaltplan und Fotos vom Aufbau sind auf GitHub zum Download verfügbar: https://github.com/smlaage/i2c-keyboard-matrix