Mehr Taster oder LEDs als Anschlüsse? Wie geht das? - [Teil 1]

Mit dem Port Expander MCP23017, der neu in das Sortiment von AZ-Delivery aufgenommen wurde, stehen 16 zusätzliche GPIOs zur Verfügung. Es gibt aber auch einfache Tricks, wie man mehr Taster/Tasten abfragen kann bzw. mehr LEDs zum Leuchten bringt, als wir dafür GPIO-Pins belegen. Den Anfang machen wir mit den Eingängen für Keypads.

4x4 Keypad am Raspberry Pi

Wer kennt die kleinen Zifferntastaturen nicht – als Zugangskontrolle, für die Zahleneingabe, oder auch ersatzweise für Spiele. Diese Keypads haben aber nur sieben bzw. acht GPIO-Anschlüsse für 12 bzw. 16 Tasten? Wie geht das denn?

 



Das geht selbstverständlich nicht, wenn man jede Taste separat an einem GPIO-Port anschließen wollte; dann würde man 12+1 bzw. 16+1 Leitungen benötigen. Aber wenn man nacheinander abfragen kann, in welcher Zeile und dann in welcher Spalte die jeweilige gedrückte Taste liegt, benötigen wir je Zeile und je Spalte einen GPIO-Anschluss. Wie auf einer Schreibmaschine kann man natürlich nicht zwei Tasten gleichzeitig drücken (Nach einer Ableitung aus Murphy’s Law landet dabei ja immer der Buchstabe auf dem Papier, den man nicht haben wollte).


Ich habe das Keypad an die „unteren“ GPIO-Pins angeschlossen, um keine Pins von Schnittstellen zu blockieren. Die Leitungen für die vier Zeilen liegen bei mir auf GPIO 26, 19, 13 und 6, die Leitungen für die Spalten an GPIO 21, 20, 16 und 12 (für die vierte Spalte A B C D, wenn vorhanden. Es gibt ja auch 3x4 Matrix-Keypads ohne diese Spalte). Mit Änderungen am Programm können selbstverständlich auch andere Pins/Ports belegt werden.

Wir müssen nun nacheinander die „Spalten-Pins“ auf GND legen und die „Zeilen-Pins“ als Eingänge mit internem Pull-up-Widerstand definieren. Wenn auf diese Weise die richtige Zeile gefunden wurde, muss „umgepolt“ werden und wir finden die Spalte heraus. Nun wollen wir das Python-Programm dazu entwickeln.

Heutzutage ist bei Python-Programmen das Modul gpiozero die erste Wahl für die Programmierung der GPIO-Schnittstellen. Für mich ein Parade-Beispiel für Objekt-orientierte Programmierung. Aber das Umpolen der Pins beschert uns mit diesem Modul ein Zeitproblem, weil alle Objekte vor der neuen Instanziierung zunächst mit der Methode close() geschlossen werden müssen. Deshalb importieren und benutzen wir das ursprüngliche Modul RPi.GPIO.


Anmerkungen zum Python-Programm:

  1. Am Anfang importieren wir die benötigten Programmerweiterungen (Module) RPi.GPIO und time. Bei RPi.GPIO bitte das kleine i vor dem Punkt beachten; alle anderen Buchstaben werden groß geschrieben.
  2. Hier werden die Anzahl der Spalten am Keypad eingegeben, also columns = 3 für ein 3x4-Keypad, columns = 4 für die abgebildeten 4x4-Keypads.
  3. Die GPIO-Ports (BCM-Nomenklatur) für die Reihen und Spalten werden jeweils in einer Liste zusammengefasst. Und die Bezeichnungen der Tasten in einer Matrix, einer Liste mit vier Listen.
  4. Mit der selbst-definierten Funktion fx_row() ermitteln wir die Reihe, in der eine Taste gedrückt wurde. Hier warten wir in einer Endlos-Schleife auf den Tastendruck.
  5. Entsprechend definieren wir die Funktion fx_column für die Spalte. Hier benötigen wir keine Endlos-Schleife, denn die Taste ist schon gedrückt.
  6. Die eigentliche Ermittlung der gedrückten Taste habe ich ebenfalls in eine selbst-definierte Funktion gepackt, damit Sie ggf. die Abfrage leichter in eigene Programme integrieren können. Hier werden zunächst die Pins für die Reihen als Eingang definiert und mit dem internen Pull-Up-Widerstand auf GPIO.HIGH sowie die Pins für die Spalten als Ausgänge auf GPIO.LOW gesetzt. Dann wird die Funktion fx_row() aufgerufen. Dann erfolgt das „Umpolen“: die Pins für die Reihen werden als Ausgänge mit GPIO.LOW und die Pins der Spalten als Eingänge definiert. Dann wird die Funktion fx_column() aufgerufen und der entsprechende Wert zurück gegeben.
  7. Beispielhaft wird im Hauptprogramm gezeigt, wie ein Code aus vier Ziffern abgefragt wird. Alternativ kann man z.B. einen Bewegungsmelder im Python-Code einbinden, um eine Abfrage zu starten.

Wer das Keypad mit seinem Arduino betreiben möchte, kann das kostenlose
E-Book zu unseren Produkten herunterladen oder den Blog-Beitrag dazu lesen:

Für das kapazitive Keypad sei auf das eBook, das Sie wie (fast) immer auf der Produktseite finden, und einen früheren Blog verwiesen.

Eine andere, ggf. zusätzliche Möglichkeit der Zugangskontrolle bietet ein RFID-Leser mit RFID-Chips? Hier verweise ich auf unser E-Book und unseren früheren Blog.

Hier noch einmal der Python Code zum Kopieren.

 #! /usr/bin/python3
import RPi.GPIO as GPIO
import time

columns = 3 # set to 4 for a 4x4 Matrix Keypad
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)

rowPorts = [26,19,13,6]
columnPorts = [21,20,16,12]
Keypad = [[1,2,3,"A"],[4,5,6,"B"],[7,8,9,"C"],["*",0,"#","D"]]

def fx_row():
    while True: # Warten auf Eingabe
        for i in range(4):
            if GPIO.input(rowPorts[i]) == GPIO.LOW:
                return i
            else:
                pass

def fx_column():
    for j in range(columns):
        if GPIO.input(columnPorts[j]) == GPIO.LOW:
            return j
        else:
             pass

def fx_key():
    global row_selected, column_selected
    for i in range(4):
        GPIO.setup(rowPorts[i],GPIO.IN, pull_up_down=GPIO.PUD_UP)

    for j in range(columns):
         GPIO.setup(columnPorts[j],GPIO.OUT)
         GPIO.output(columnPorts[j],GPIO.LOW)

    row_selected = fx_row()
#     print ("row_selected = ",row_selected + 1)

    for i in range(4):
        GPIO.setup(rowPorts[i],GPIO.OUT)
        GPIO.output(rowPorts[i],GPIO.LOW)

    for j in range(columns):
        GPIO.setup(columnPorts[j],GPIO.IN, pull_up_down=GPIO.PUD_UP)

    column_selected = fx_column()
#    print ("column_selected = ",column_selected + 1)

    key = Keypad[row_selected][column_selected]
    return key

# main program
for k in range(4):
    key = fx_key()
    time.sleep(0.3)
    print("Key pressed is ",key)

GPIO.cleanup()

 

Ein letztes Wort, warum ich hier die Programmierung mit selbst definierten Funktionen vorstelle, wo man doch im Internet ein Modul zum keypad herunterladen kann.

Erstens ist das Programm-Modul nicht Teil der Raspberry Pi OS Distribution, so dass man dieses immer separat bereitstellen muss. Zweitens sehe ich überhaupt keine Notwendigkeit, hier eine eigene Klasse zu definieren. Bei aller Begeisterung für Objekt-orientiertes Programmieren (OOP) wird der Blick auf das Wesentliche für den weniger geübten Programmierer getrübt und die eigentlichen Vorteile der OOP, die Vererbung von Eigenschaften und Methoden, werden nicht genutzt.

Mir kam es darauf an, Ihnen den Trick mit der Mehrfachbelegung der GPIO-Eingänge zu erläutern. Eine andere Methode, mehrere Schalter abzufragen, zeigt Andreas Wolter in seinem mehrteiligen Blog Multi-IO und EEPROM.

In der Fortsetzung werde ich Ihnen zeigen, welche Art von 7-Segment-Anzeigen es gibt, und wie man diese an möglichst wenigen Pins anschließt.

Auf vielfachen Wunsch geht es hier zum Download.

2 Kommentare

Bernd Albrecht

Bernd Albrecht

Danke für den Hinweis. Im Download passen die Einrückungen und hier im Blog habe ich versucht, mit Leerzeichen den Fehler zu korrigieren. Wenn etwas nicht funktioniert, bitte am Bildschirmfoto orientieren.

Ulrich

Ulrich

Bei den py-Codes sind die Einrückungen kaputt.

Einen Kommentar hinterlassen

Alle Kommentare werden vor der Veröffentlichung moderiert