Hallo, ich habe einen Raspberry Pi 3B+ und möchte das Programmieren mit Python lernen. Dafür habe ich ein Starterbuch von "Jugend programmiert". Ein paar einfache Projekte sind mir mit Scratch und Python schon gelungen, aber bei einem neuen Projekt habe ich ein Problem: Ich habe ein Keypad (wie eine Telefontastatur) und ein LED-Auswahlsystem schon programmiert. Bei dem LED-Programm kann man wählen, welches der drei LED's man aufleuchten lassen möchte. Beim Keypad habe ich nur eingestellt, dass die gedrückten Zahlen auch ausgegeben werden.
Ich bin mittlerweile an dem Punkt, dass mein Programm fragt, welches LED eingeschaltet werden soll, aber ich kann die Zahl nicht mit dem Keypad eingeben. Es funktioniert erst wieder, wenn die Zahl auf der Tastatur eingegeben und bestätigt wurde. Jedoch soll man das Keypad zur Eingabe nutzen können. Ich schätze, dass die Position/Mischung der beiden Programme das Problem ist. Ich hoffe jemand von euch weiß da weiter.
Der Code für die LED's ist:
import RPi.GPIO as gpio
import time
gpio.setmode(gpio.BCM)
gpio.setup(18, gpio.OUT)
gpio.setup(20, gpio.OUT)
gpio.setup(4, gpio.OUT)
farbe = input("1, 2 oder 3?")
if farbe == "1":
gpio.output(20, gpio.HIGH)
time.sleep(2)
gpio.output(20, gpio.LOW)
if farbe == "3":
gpio.output(18, gpio.HIGH)
time.sleep(2)
gpio.output(18, gpio.LOW)
if farbe == "2":
gpio.output(4, gpio.HIGH)
time.sleep(2)
gpio.output(4, gpio.LOW)
gpio.cleanup()
Der Code für das Keypad ist:
import RPi.GPIO as gpio
import time
gpio.setmode(gpio.BCM)
matrix = [ ["1", "2", "3", "A"],
["4", "5", "6", "B"],
["7", "8", "9", "C"],
["*", "0", "#", "D"] ]
spalte = [19, 17, 27, 22]
zeile = [26, 13, 6, 5]
for j in range(4):
gpio.setup(spalte[j], gpio.OUT)
gpio.output(spalte[j], 1)
gpio.setup(zeile[j], gpio.IN,
pull_up_down=gpio.PUD_UP)
def keypad():
while True:
for j in range(4):
gpio.output(spalte[j], 0)
for i in range(4):
if gpio.input(zeile) == 0:
benutzerEingabe = matrix[j]
while gpio.input(zeile) == 0:
pass
return benutzerEingabe
gpio.output(spalte[j], 1)
return False
try:
while True:
print(keypad())
time.sleep(0.2)
except KeyboardInterrupt:
gpio.cleanup()
Keypad mit LED verbinden
- __blackjack__
- User
- Beiträge: 14047
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@Max2Plays: Anmerkungen zum ersten Programm:
Auf Modulebene sollte nur Code stehen der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst.
Den `cleanup()`-Aufruf sollte man durch ein ``try``/``finally`` sicherstellen.
Die Pin-Nummern sollten nicht als magische Zahlen im Code stehen sondern als Konstanten definiert werden. Hier bietet sich eine Liste an.
Es wäre übersichtlicher wenn man die Eingabe nicht in der Reihenfolge 1, 3, 2, sondern 1, 2, 3 überprüfen würde. Und da sich alle drei Fälle gegenseitig ausschliessen auch nicht jeder Test mit einem ``if`` sondern alle bis auf den ersten mit ``elif``.
Da aber eine Zahl eingegeben wurde, sich der Code in den drei Fällen nur durch die Pin-Nummer unterscheidet, und die Pin-Nummern als Konstante Liste defniert werden kann, braucht man gar keinen Test für jeden Fall, sondern kann aus der eingegebenen Zahl den Index in die Pin-Nummernliste ermitteln.
Ungetestet:
Auch beim zweiten Quelltext sollte das Hauptprogramm in eine Funktion und das `cleanup()` in einen ``finally``-Zweig.
Schleifen nach dem Muster ``for i in range(len(sequence)):`` nur um dann `i` als Index in die Sequenz zu verwenden ist ein „anti pattern“ in Python. Man kann direkt über die Elemente iterieren, ohne den Umweg über einen Laufindex. Falls man zusätzlich eine laufende Zahl benötigt, gibt es die `enumerate()`-Funktion. Falls man über mehr als eine Sequenz ”parallel” iterieren möchte, gibt es die `zip()`-Funktion.
Selbst wenn man das mit Indexzugriff löst, sollte man die Länge der Sequenz(en) nicht als magische Zahl in den Quelltext schreiben, sondern aus der Datenstruktur ermitteln.
`keypad` wäre ein guter Name für ein Objekt das ein Tastenfeld repräsentiert. Als Funktionsname wählt man aktivere Namen, die die Tätigkeit der Funktion beschreiben. Also beispielsweise `read_keypad()`. Das letzte ``return`` in der Funktion kann nie erreicht werden. `False` wäre auch ein unerwarteter Wert an der Stelle, wo die Funktion doch sonst Zeichenketten liefert.
Wo liegt denn das konkrete Problem? Was hast Du gemacht? Warum hast Du das so gemacht? Was hast Du erwartet? Was passiert stattdessen?
Auf Modulebene sollte nur Code stehen der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst.
Den `cleanup()`-Aufruf sollte man durch ein ``try``/``finally`` sicherstellen.
Die Pin-Nummern sollten nicht als magische Zahlen im Code stehen sondern als Konstanten definiert werden. Hier bietet sich eine Liste an.
Es wäre übersichtlicher wenn man die Eingabe nicht in der Reihenfolge 1, 3, 2, sondern 1, 2, 3 überprüfen würde. Und da sich alle drei Fälle gegenseitig ausschliessen auch nicht jeder Test mit einem ``if`` sondern alle bis auf den ersten mit ``elif``.
Da aber eine Zahl eingegeben wurde, sich der Code in den drei Fällen nur durch die Pin-Nummer unterscheidet, und die Pin-Nummern als Konstante Liste defniert werden kann, braucht man gar keinen Test für jeden Fall, sondern kann aus der eingegebenen Zahl den Index in die Pin-Nummernliste ermitteln.
Ungetestet:
Code: Alles auswählen
#!/usr/bin/env python3
import time
from RPi import GPIO as gpio
LED_PINS = [20, 4, 18]
def main():
try:
gpio.setmode(gpio.BCM)
gpio.setup(LED_PINS, gpio.OUT)
try:
index = int(input("1, 2 oder 3?")) - 1
except ValueError:
pass
else:
if 0 <= index < len(LED_PINS):
led_pin = LED_PINS[index]
gpio.output(led_pin, gpio.HIGH)
time.sleep(2)
gpio.output(led_pin, gpio.LOW)
finally:
gpio.cleanup()
if __name__ == "__main__":
main()
Schleifen nach dem Muster ``for i in range(len(sequence)):`` nur um dann `i` als Index in die Sequenz zu verwenden ist ein „anti pattern“ in Python. Man kann direkt über die Elemente iterieren, ohne den Umweg über einen Laufindex. Falls man zusätzlich eine laufende Zahl benötigt, gibt es die `enumerate()`-Funktion. Falls man über mehr als eine Sequenz ”parallel” iterieren möchte, gibt es die `zip()`-Funktion.
Selbst wenn man das mit Indexzugriff löst, sollte man die Länge der Sequenz(en) nicht als magische Zahl in den Quelltext schreiben, sondern aus der Datenstruktur ermitteln.
`keypad` wäre ein guter Name für ein Objekt das ein Tastenfeld repräsentiert. Als Funktionsname wählt man aktivere Namen, die die Tätigkeit der Funktion beschreiben. Also beispielsweise `read_keypad()`. Das letzte ``return`` in der Funktion kann nie erreicht werden. `False` wäre auch ein unerwarteter Wert an der Stelle, wo die Funktion doch sonst Zeichenketten liefert.
Code: Alles auswählen
#!/usr/bin/env python3
import time
from RPi import GPIO as gpio
TASTEN_MATRIX = ["123A", "456B", "789C", "*0#D"]
SPALTEN_PINS = [19, 17, 27, 22]
ZEILEN_PINS = [26, 13, 6, 5]
def read_keypad():
while True:
for spalten_index, spalten_pin in enumerate(SPALTEN_PINS):
gpio.output(spalten_pin, gpio.LOW)
for zeilen_pin, tasten_zeile in zip(ZEILEN_PINS, TASTEN_MATRIX):
if not gpio.input(zeilen_pin):
while not gpio.input(zeilen_pin):
pass
return tasten_zeile[spalten_index]
gpio.output(spalten_pin, gpio.HIGH)
def main():
try:
gpio.setmode(gpio.BCM)
gpio.setup(SPALTEN_PINS, gpio.OUT, initial=gpio.HIGH)
gpio.setup(ZEILEN_PINS, gpio.IN, pull_up_down=gpio.PUD_UP)
while True:
print(read_keypad())
time.sleep(0.2)
except KeyboardInterrupt:
pass
finally:
gpio.cleanup()
if __name__ == "__main__":
main()
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
@__blackjack__ : Danke für deine Antwort und Verbesserung meiner Programme. Mein Problem liegt hauptsächlich darin, dass ich nicht weiß, wie ich die Programme verbinden kann. Am Ende soll man mit dem Keypad die Zahlen eingeben können, nach denen bei den LED's gefragt wird (1, 2 oder 3). Einen Schritt hatte ich schon geschafft, nämlich dass mein Programm fragt, welches LED leuchten soll. Die Zahlen kann man dann aber nur mit der normalen Tastatur und nicht mit dem Keypad eingeben.
@Max2Plays: Du hast zwei Funktionen, eine read_keypad, das eine Ziffer einliest, und eine (noch nicht existierende) die eine LED einschaltet. Du mußt nur das ›input‹ des einen durch ein read_keypad des anderen ersetzen.