Für den Arduino und Raspberry Pi gibt es einige Keypad Matrizen, welche relativ einfach angeschlossen und ausgelesen werden können. Ähnlich zum Numpad an einer Tastatur besitzen diese Keypads 3×4 oder 4×4 Tasten. Eingesetzt werden können diese Module bspw. als Codeschlösser oder zum Bau eines kleinen Taschenrechners. Mithilfe ein paar kleiner Veränderungen kann sogar eine T9 Tastatur erstellt werden, womit Texte wie auf älteren Handys eingetippt werden können.
In diesem Tutorial zeige ich den Anschluss einer solchen Keypad Matrix und wie man diese mit den GPIOs einfach auslesen kann. Um weniger GPIOs zu benutzen ist auch ein Anschluss über den I2C Port Expander MCP23017 möglich.
Zubehör
Wie bereits erwähnt gibt es einige verschiedene Modelle dieser „Membranschalter“, wobei sich hauptsächlich die Größe und Beschriftung unterscheidet. In diesem Tutorial habe ich eine 3×4 Tastatur verwendet, jedoch ist es kein Problem das ganze für ein 4×4 (oder größeres) Keypad anzupassen.
Folgende Modelle stehen zur Auswahl:
- 3×4 Keypad Matrix
- 4×4 Keypad Matrix
- spezielle Variante des 4×4 Keypad mit aufgedruckten Buchstaben (T9 Style)
Außerdem solltest du noch Male-Female Jumper Kabel zur Hand haben.
Welches Raspberry Pi Model du verwendest spielt keine Rolle, solange du mindestens 7 bzw. 8 freie GPIOs hast.
Anschluss und Funktion des Raspberry Pi Keypad
Im Grunde können alle freien und ansteuerbaren GPIOs dafür gewählt werden. Je nachdem ob du eine 3×4 bzw. 4×4 Matrix Membran hast werden 7 bzw. 8 Pins belegt. Am besten eignen sich Male-Female Jumper Kabel, welche in die Anschlüsse des Keypads passen. Der grundsätzliche Aufbau einer solchen Tastatur Matrix ist wie folgt:
Die ersten 4 Pins von links sind hierbei für die Zeilen, die weiteren 3 bzw. 4 Anschlüsse für je eine Spalte. Sobald eine Taste gedrückt wird werden zwei Leitungen miteinander verbunden. Um herauszufinden ob und falls ja, welche Taste gedrückt wurde, wird jeweils durch die ersten vier Leitungen kurz ein Signal gesendet. Die restlichen Pins werden „abgehört“.
Wurde z.B. nur Taste 6 gedrückt, so würden die Leitungen „Zeile 2“ und „Spalte 3“ verbunden sein. Senden wir also an dem GPIO für Zeile 2 einen Strom wird nur am GPIO für Spalte 3 ein HIGH Signal empfangen. Alle anderen GPIOs empfangen kein Signal. Indem wir also durch alle Zeilen ein Signal schicken und daraufhin alle Spalten überprüfen, so können wir feststellen, ob eine Taste gedrückt wurde und natürlich auch welche.
Nun, wie bereits erwähnt ist es egal welche 7 bzw. 8 GPIOs man verwendet, jedoch muss dies im Code später ggf. angepasst werden. In diesem Beispiel verwende ich ein 3×4 Keypad, also habe nur 7 GPIOs zu belegen. Von links nach rechts ist die Belegung wie folgt:
3×4 Keypad | Raspberry Pi |
---|---|
Pin 1 | GPIO 7 (Pin 26) |
Pin 2 | GPIO 8 (Pin 24) |
Pin 3 | GPIO 11 (Pin 23) |
Pin 4 | GPIO 25 (Pin 22) |
Pin 5 | GPIO 9 (Pin 21) |
Pin 6 | GPIO 10 (Pin 19) |
Pin 7 | GPIO 15 (Pin 10) |
Schematisch sieht es dann wie folgt aus:
Code zum Ansteuern des Keypads
Um die kleine Tastatur nun benutzen zu können, laden wir uns eine kleine Bibliothek von GitHub. Zuerst erstellen wir einen Ordner.
mkdir keypad-rpi && cd keypad-rpi
Anschließend downloaden wir die Datei:
wget -O keypad.py https://raw.githubusercontent.com/rainierez/MatrixKeypad_Python/master/matrix_keypad/RPi_GPIO.py
Falls du eine 4×4 Tastatur bzw. andere GPIOs als ich verwendest, musst du die GPIO Nummern im Code entsprechend anpassen (sudo nano keypad.py
).
Nun können wir jene Klasse verwenden. Um die Funktionsweise zu verdeutlichen habe ich ein kleines Beispiel erstellt. Um dieses nachzumachen, erstelle eine neue Datei
sudo nano example.py
mit folgendem Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
import time import RPi.GPIO as GPIO from keypad import keypad GPIO.setwarnings(False) if __name__ == '__main__': # Initialize kp = keypad(columnCount = 3) # waiting for a keypress digit = None while digit == None: digit = kp.getKey() # Print result print digit time.sleep(0.5) ###### 4 Digit wait ###### seq = [] for i in range(4): digit = None while digit == None: digit = kp.getKey() seq.append(digit) time.sleep(0.4) # Check digit code print(seq) if seq == [1, 2, 3, '#']: print "Code accepted" |
Die Datei kannst du mit STRG+O, STRG+X speichern und beenden.
Führen wir die Datei nun aus, können die Eingaben auslesene werden.
sudo python example.py
Im nachfolgenden Video siehst du wie das Auslesen der Zahlen aussehen kann:
50 Kommentare
Hallo!
Könntest du bitte die Verbindung zu den GPIOs auch mit einem 3×4 aufzeichnen?
Danke!
Hi,
ich habe doch ein 3×4 Keyboard verwendet 🙂
Falls du eine 4×4 Matrix hast, kannst du irgendeinen freien weiteren GPIO nehmen. Dann musst du das nur noch im Code angeben und es mit
kp = keypad(columnCount = 4)
initialisieren.LG, Felix
Hallo Felix,
tut mir leider ich meinte 4×4.
Reicht es nur kp = keypad(columnCount = 4) auf 4 zu ändern?
Klasse!!!!!!
Immer, wenn ich auf deine Seite gehe, bin ich gespannt was du uns als nächstes wieder Neues präsentierst…!
Hallo,
bei der Umstellung auf 4×4 ist noch ein kleiner Fehler zu beseitigen:
In der Keypad.py steht:
Hierbei werden nur Spalten von 0-2 akzeptiert, die 3 als Wert für die 4. Spalte (A, B, C, D auf dem Keypad) wird damit ignoriert.
Einfach in colVal >3:
ändern und schon geht’s 😀
Gruß
Cornel
Danke für deinen Tipp!
Ist es möglich zu erkennen ob zwei (und welche) Tasten gleichzeitig gedrückt sind?
Ja, dafür müsstest du den Code aber ein wenig verändern. Im Moment wird ja abgebrochen, sobald eine Taste gedrückt wurde und danach nicht mehr geprüft wird, ob ggf. noch eine andere Taste gedrückt ist.
Also in einer Endlosschleife hab ich es schon drin. Über try: except: kann beendet werden. Mein Ziel ist es Ausgänge zu schalten, Zum Test erstmal LEDs. Das klappt auch schon wenn ich z.B. sage wenn eine 1 gedrückt wurde, schalte Pin x 5sec ein. Ich möchte aber das der PIN (bzw. eben auch 2 gleichzeitig) für die Dauer des Tastendruckes geschaltet wird. da steh ich grad echt aufm Schlauch. Mit sleep() ist es eh schlecht da dann während dieser Zeit gar nix anderes geht.
Hallo,
mich würde interessieren, ob es auch „Klingelboards“ für Bastler gibt die man mit dem Raspi kombinieren kann. Ich möchte DoorPI nutzen und benötige dazu passende Klingeltableaus; 16er und 32er. Ich finde aber nur diese Keypads.
Hat jemand eine Idee?
VG
Matthias
Hallo Felix,
hast du zufälligerweise den anschluss des Keypad über den MCP23017 schonmal realisiert und könntest uns den Quellcode zur Verfügung stellen?
Gruß Micha
Hallo Michael,
nein leider nicht. Allerdings sollte sich die Anpassung dazu in Grenzen halten – da nur jene Stellen umgeschrieben werden müssten, wo die GPIO Bibliothek benutzt wird.
Hallo,
was mache ich wenn mein Numernpad bloß Löcher in unten in der Platine hat und kein Kabel? z.B: sowas hier: aliexpress.com/item/Free-Shipping-16-4×4-Matrix-Keyboard-Keypad-Use-Key-PIC-AVR-Stamp-Sml/1072484015.html?spm=2114.13010308.0.0.ZLcjBP
Du müsstest Kabel dafür anlöten.
Reicht es die Male-Seite der Femal-Male-Jumperkabel zu nehmen, in die Locher des RFID Moduls stecken und mit Lötzinn festlöten?
Was hat das denn mit RFID zu tun? Prinzipiell kannst du die Male Seite der Jumper kabel anlöten und mit dem Raspberry Pi verbinden.
Sry meinte natürlich das Numpad
Hallo Felix,
kann man auch das Keypad nehmen? Das ist kabellos.
Logilink Kabelloses Keypad Ziffernblock 18 Tasten
Das wäre mir z.B lieber. Allerdings weiß ich nicht ob es funktioniert.
Hallo Philip,
das kannst du zwar nehmen, wird allerdings nicht mit diesem Tutorial funktionieren.
LG, Felix
Gibt ein Keypad das Kabellos ist und dafür aber funktioniert?
Da mein RPi am ganz anderen Ende des Raumes steht.
Nein, leider nicht. Du kannst das Keyboard schon benutzen, aber eben nicht mit diesem Tutorial – es sollte im Normalfall wie eine Tastatur ohne weiteres erkannt werden.
Hi I did the same code, but just I can put a 1 digit, the other doesn’t appear, I mean dont work like your video my results is :
1
[2, 2, 3, 3]
Why if I push 1, 2, 3 ….. dont appear :
1
2
3
I have same code like your example. Any help? regards
Hi Dave,
I got the same problem did you find the solution?
Thanks
Ralf
Hallo.
Ich benötige das Keypad um bei richtiger Codeeingabe ein anderes Script zu schliessen.
Dazu würde ich gerne bei jedem Tastendruck eine LED aufleuchten lassen. Wo müsste ich das einfügen? Ausserdem wäre eine Löschfunktion sehr nützlich. Hättest du eine Idee?
Und was muss man einfügen, damit das Script nicht geschlossen wird, nachdem man den Code eingegeben hat.?
LEDs kannst du super einfach schalten (siehe z.B. dieses Tutorial). Einfach die Taste per Nummer identifizieren (if..) und den entsprechenden GPIO schalten. Ein anderes Skript kannst du z.B. mit dem Linux Befehl pkill beenden. Das aufgerufene Skript beendest du z.B. mit exit()
Hallo,
Wenn ich example.py ausführe kommt ein indentationError.
Jedoch habe ich keine Ahnung warum und wie ich den beheben kann:
Wenn ich example.py ausführe, wird mir folgendes angezeigt
Traceback (most recentcall latest):
File „example.py“, line 3, in
from keypad import keypad
File „/home/pi/keyboard-rpi/keyboard.py“, line 18
self.row = [12,24,23,22]
^
IndentationError: unexpected indent
Hallo Felix reicht es die GPIOs nur in das verzeichnis zuschreiben also so:
GPIO 23
GPIO 11
…….
oder wie muss ich das machen
In welches Verzeichnis? Du musst in der
keypad
Klasse die GPIOs in den Arrays ROW bzw. COLUMN anpassen.import time
import RPi.GPIO as GPIO
from keypad import keypad
GPIO.setwarnings(False)
keypad = [ [„1″,“2″,“3″,“A“]
[„4″,“5″,“6″,“B“]
[„7″,“8″,“9″,“C“]
[„*“,“0″,“#“,“D“] ]
COL_PINS = [3,5,6,13] # BCM numbering
ROW_PINS = [19,26,20,21] # BCM numbering
factory = rpi_gpio.KeypadFactory()
keypad = factory.create_keypad(keypad=KEYPAD, row_pins=ROW_PINS, col_pins=COL_P$
keypad.registerKeyPressHandler(processKey)
def processKey(key):
if (key==“1″):
print(„number“)
elif (key==“A“):
print(„letter“)
Das ist mein aktueller Code aber er bringt mir folgenden Fehler:
Traceback (most recent call last):
File „example.py“, line 9, in
[„4″,“5″,“6″,“B“]
TypeError: list indices must be integers, not tuple.
Ich habe auch schon deinen Code versucht aber da tippt er dann statt ne 9 ne 1 usw. Ich habe die gleichen GPIOs wie du verwendet + einen GPIO für den 8 Slot.
Manchmal kommt das eingetippte gefühlt 10 Std später.
Deshalb meine Fragen wo ändert man die GPIOs genau und kann man meinen aktuellen Code zum laufen bringen.
LG
und als ergänzung bei deinem Code hab ich columnCount = 4 gesetzt.
OK der Code davor hat zu viele Fehler in sich da stimmt die datei zum download zu dem code gar nicht. Also vergessen wir das wieder und gehen zu deinem Code der nämlich richtig ist für 3×4 (wer hätte es gedacht? 😉 ) Aber wenn ich den columnCount = 4 setzte bringt er den Fehler:
Traceback (most recent call last):
File „example.py“, line 14, in
digit = kp.getKey()
File „/home/pi/keypad-rpi/keypad.py“, line 38, in getKey
GPIO.setup(self.COLUMN[j], GPIO.OUT)
ValueError: The channel sent is invalid on a Raspberry Pi.
Hallo,
Ich habe deine Anleitung durchgeführt, kriege jetzt aber eine Fehlermeldung, wenn ich versuche meinen Code laufen zu lassen.
Traceback (most recent call last):
File „/home/pi/pike.py“, line 3, in
from keypad import keypad
ImportError: No module named keypad
Kannst du vielleicht erkennen was da falsch sein könnte?
Danke schonmal!
LG
Die Datei scheint nicht (unter dem Namen) zu existieren.
Ja das dachte ich mir auch aber wenn ich 1:1 dasselbe gemacht habe müsste es ja eigentlich funktionieren. Ich habe es ja auch so genannt
Habe meinen Fehler gefunden. Danke!
Ich stehe grade vor einer Blockade 😉
Ich bin zu blöd zu erkennen wie ich das Skirpt erweitere mit einem Relais.
ich würde gerne einen Code eingeben und das Relais soll kurz angehen und wieder ausgehen.
Das Tastenfeld hab ich zum laufen und auch das Relais kriege ich angesteuert.
Aber diese beiden Skripte miteinander zu verschmelzen, komme ich nicht weiter.
Wie erkläre ich in der example.py, das er doch bitte wenn der Code richtig eingegeben wurde er den PIN 17 schaltet.
Ich verstehe nicht wie ich GPIO.Board oder BCM umschreibe damit er das in einem Quellcode benutzen kann.
Hilfe! 😉
Das erste Problem habe ich selber gelöst bekommen.
Ich würde zu gern dem Programm sagen, das wenn die Sternchen ‚*‘ Taste gedrückt wird, er die Eingabe resetet. Jemand eine Idee wie man das umsetzt.
Da mein Programm immer weiter läuft und man ohne LCD Display nie weiß, an welcher Stelle man ist bei der Eingabe der Zahlen.
Vielen Dank für die Hilfe schonmal
Code :
Hallo Sebastian,
vorweg: ich kann dir bei deinen Fragen nicht helfen, ich bastle mich gerade mit der Folientastatur per Foren so durch, habe aber eigentlich keine Ahnung…
Ich habe es soweit hinbekommen, dass die oben vorgestellte Anleitung funktioniert.
Dein Post lässt mich hoffen, dass du mir evtl. einen Tip geben kannst:
– Das Programm soll dauerhaft nach einer korrekten Pinfolge „horchen“. Nach der Anleitung benötigt es einen Neustart, nachdem 5 Ziffern eingegeben wurden.
– Dein Wunsch nach einer Startziffer ist nachvollziehbar – hast du evtl. schon eine Lösung? Ich stelle mir es in etwa so vor, dass er immer nach dem Stern vier Ziffern registriert, die dann mit Raute quittiert werden. Ein Display habe ich auch nicht, dann wird es vermutlich schwer…
Evtl. kann hier ja jemand weiterhelfen?
Danke und viele Grüße
Frederik
Nutze einfach eine Endlosschleife (while True: …)
Hier habe ich meine Lösung des Problems, teste es mal.
Es ist nicht perfekt geschrieben, aber es funzt 😉
Code:
Hallo,
ich führe alles wie gehabt aus und bekomme dann folgenden Fehler:
File „example.py“, line 17
print digit
^
SyntaxError: Missing parentheses in call to ‚print‘
Hab es dreimal überprüft, eigentlich müsste in der while Schleife ein Wert für digit gesetzt werden. Jemand eine Idee?
Gruß
Du nutzt Python3. Damit musst du um
digit
Klammern setzen.Musste auch noch die keypad.py bearbeiten, funktioniert aber jetzt.
Danke!
Hallo Felix,
besteht die Möglichkeit über Interrupt die Standardtastatur einzulesen? Input und andere Abfrageroutinen kommen nicht infrage da das Programm weiterdurchlaufen werden muss.
Mit freundlichen Grüßen
Heinz
Hallo,
hat das ganze schon jemand per I2C zum laufen gebracht? Nutze eine 4×4 Tastatur die nur I2C besitzt, aber ich habe da kein Plan wie ich das ganze angehen soll.
Hallo Felix, hast du Erfahrung mit der Reichweite der Kabel? Bis 5m sollte der Spannungsabfall vernachlässigbar für die Funktion sein..
Hey, es gibt eine Möglichkeit native als Tastatur eine Matrix Keypad einzubinden.
das ganze pollen hier ist nicht so cool, ich habe auch erst mal diesen Ansatz verfolgt aber dann die native Version entdeckt.
http://blog.gegg.us/2017/08/a-matrix-keypad-on-a-raspberry-pi-done-right/
Ich habe ein 1×4 Keypad verwendet und ewig nach einem einfachen Code-Beispiel gesucht. Nach langem tüfteln funktionierte folgendes sehr gut:
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
MATRIX = [2,1,4,3]
COL = 7
ROW = [12,13,6,5]
GPIO.setup(COL, GPIO.OUT)
GPIO.output(COL, 1)
for i in range(4):
GPIO.setup(ROW[i], GPIO.IN, pull_up_down = GPIO.PUD_UP)
while True:
try:
GPIO.output(COL,0)
for i in range(4):
if GPIO.input(ROW[i]) == 0:
print(MATRIX[i])
time.sleep(0.2)
while(GPIO.input(ROW[i]) == 0):
pass
GPIO.output(COL,1)
except KeyboardInterupt:
GPIO.cleanup()