Taster auslesen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
nccbk
User
Beiträge: 16
Registriert: Sonntag 10. November 2013, 15:23

Hallo zusammen.
Bin gerade etwas verwirrt.
Ein Modul soll ausgelesen werden, wenn der Taster losgelassen wird...
Mit dem RaspberryPi wird gearbeitet.

Code: Alles auswählen

import serial
import sys
import time
from operator import xor
import RPi.GPIO as GPIO

#Tasterbelegung
GPIO.setmode(GPIO.BCM)
GPIO.setup(24, GPIO.IN)
count = 0
# UART
ID = ""
Zeichen = 0

# UART oeffnen
UART = serial.Serial("/dev/ttyAMA0", 9600)
UART.open()

ID = ""
inputValue=GPIO.input(24)

while(inputValue== False):
    # Variablen loeschen
        ID = ""
    # Zeichen einlesen
        Zeichen = UART.read()
        # ID zusammen setzen 
        for Counter in range(13):
        
                Zeichen = UART.read() 
                ID = ID + str(Zeichen)
        
        # Ausgabe der Daten
        print ("ID: ", ID[4:10])
         
 
Es soll währenddessen aber noch weitere Abfragen statfinden...

Danke für die Hilfe.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Ja und wo liegt nun das Problem? Was funktioniert denn nicht? Irgend wie stellst Du gar keine Frage...
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
FooTheBar
User
Beiträge: 5
Registriert: Mittwoch 25. Dezember 2013, 18:03

Auf jeden Fall solltest du inputValue in der while-Schleife neu einlesen. Aktuell liest du Pin nur ein Mal aus, so dass dein While nur ein If ist.
BlackJack

@nccbk: Allgemeine Anmerkungen zum Quelltext:

Über die Hälfte der Importe werden gar nicht verwendet. `count` wird an eine 0 gebunden aber auch überhaupt nicht verwendet. `ID` wird zweimal viel zu früh und unnötig an eine leere Zeichenkette gebunden. `Zeichen` wird zu früh unnötig an den Wert 0 gebunden. Das kann alles ersatzlos weg.

Die Namensschreibweisen entsprechen nicht alle dem Style Guide for Python Code.

„Magische” Zahlen sollte man vermeiden. Wenn es einen Zahlwert mit einer Bedeutung gibt, die man nicht an der Zahl selber erkennen kann, dann sollte man dafür eine Konstante mit einem aussagekräftigen Namen verwenden. Das betrifft zum Beispiel die 24 überall dort wo sie als Nummer des IO-Pins verwendet wird an der der Taster hängt. Zusätzlicher Vorteil: Wenn man den mal an einen anderen Pin anschliesst muss man im Programm nur eine einzige Stelle ändern wo die Konstante definiert wird, und nicht das ganze Programm nach dem alten Wert durchsuchen und überall wo er die Pin-Bedeutung hat, durch den neuen Wert ersetzen.

Kommentare sollten dem Leser Zusatzinformation bieten und nicht das offensichtliche noch einmal wiederholen was man im Code lesen kann. Üblicherweise sollte man nur Kommentieren *warum* Code etwas bestimmtes tut und nicht *was* er tut. Wenn man erklären muss *was* er tut besteht die Chance das die Namen schlecht gewählt sind oder der Code schlecht organisiert ist, wenn man an ihm nicht ablesen kann was er tut.

`Serial`-Objekte bei denen man einen Port angegeben hat sind bereits im Zustand offen. Darauf `open()` direkt nach dem Erstellen aufzurufen macht keinen Sinn. Man sollte aber wie bei Dateien darauf achten, dass die serielle Verbindung auch wieder geschlossen wird. Auch bei so einer Endlosschleife, denn die kann ja durch Fehler oder den Benutzer abgebrochen werden. Da ist es sauberer wenn man selbst dafür sorgt, dass die Verbindung zeitnah geschlossen wird.

``while`` ist keine Funktion, also sollte man es nicht so schreiben wie Funktionsaufrufe. Überhaupt sind die Klammern um die Bedingung unnötig. Bei `print()` dagegen sollte man kein Leerzeichen zwischen den Funktionsnamen und die öffnende Klammer setzen, das ist eine Funktion wie jede andere auch.

Wahrheitswerte explizit mit literalen Wahrheitswerten zu vergleichen ergibt wieder nur einen Wahrheitswert und ist deshalb schlechter Stil, weil unnötig. Wenn man auf das Gegenteil eines Wahrheitswerts prüfen möchte gibt es ``not``.

Die Schleife zum Lesen ist unnötig kompliziert geschrieben. Du liest sowohl vor als auch in der Schleife Bytes. Dadurch wird ein klein wenig verschleiert das 14 und nicht 13 Bytes gelesen werden. Man könnte eine ``while``-Schleife schreiben die aufhört wenn 14 Bytes gelesen wurden, dann muss der Leseaufruf nur in der Schleife stehen und das überflüssige `counter` wird nicht mehr benötigt. Man kann aber auch ganz einfach die Anzahl der zu lesenden Bytes an den `read()`-Aufruf als Argument übergeben.

Ich bin dann bei so etwas (ungetestet):

Code: Alles auswählen

from contextlib import closing
from serial import Serial
import RPi.GPIO as GPIO

TASTER_PIN = 24


def main():
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(TASTER_PIN, GPIO.IN)

    with closing(Serial('/dev/ttyAMA0', 9600)) as uart:
        while not GPIO.input(TASTER_PIN):
            id_ = uart.read(14)
            print('ID: ', id_[4:10])


if __name__ == '__main__':
    main()
nccbk
User
Beiträge: 16
Registriert: Sonntag 10. November 2013, 15:23

@BlackJack: Vielen Dank BlackJack für die ausführliche Antwort.

Stimmt, an vielen Stellen ist der Quelltext unübersichtlich und es sind Variablen falsch bzw. überflüssig...
(Zu meiner Verteidigung: "count" war noch aus meinen Tests übrig geblieben) :lol:
Auch bei den Kommentaren werde ich mich bemühen...

Ich habe das Programm mal getestet...
Also bei nicht gedrücktem Taster liest er aus. Wenn nun allerdings der Taster gerückt wird und ich dann noch einmal einlese(was eigentlich ignoriert werden soll) gibt er mir noch einmal die ID aus stoppt dann aber...
BlackJack

@nccbk: Die Beschreibung der Vorgänge kann ich nicht ganz nachvollziehen. Wenn der Taster am Schleifenanfang gedrück ist, wird der Schleifenkörper nicht mehr ausgeführt, also kann da auch nichts mehr ausgelesen werden.
nccbk
User
Beiträge: 16
Registriert: Sonntag 10. November 2013, 15:23

BlackJack hat geschrieben:@nccbk: Die Beschreibung der Vorgänge kann ich nicht ganz nachvollziehen. Wenn der Taster am Schleifenanfang gedrück ist, wird der Schleifenkörper nicht mehr ausgeführt, also kann da auch nichts mehr ausgelesen werden.
Es ist wirklich komisch, aber auch nach mehreren Versuchen das gleiche Ergebnis...
Beim Drücken wird weiterhin eingelesen einmal ausgegeben und danach passiert nichts mehr. D.h. es wird gar nichts mehr eingelesen.
BlackJack

@nccbk: Das drücken des Tasters unterbricht natürlich nicht *sofort* sondern erst wenn der Test am Anfang der ``while``-Schleife erreicht ist. Und dann wird die Schleife abgebrochen, also auch nichts mehr abgefragt. Das sollte man so erwarten, denn so steht es im Programm. Wenn man anderes Verhalten möchte, muss man es anders programmieren. :-)

Wenn der Taster nur zum Unterbrechen solange er gedrückt ist, dienen soll, dann könnte man das beispielsweise so scheiben:

Code: Alles auswählen

        while True:
            if not GPIO.input(TASTER_PIN):
                id_ = uart.read(14)
                print('ID: ', id_[4:10])
nccbk
User
Beiträge: 16
Registriert: Sonntag 10. November 2013, 15:23

@BlackJack: Sorry das hatte ich schon geändert...
Ich habe ein anderes Problem:
Er liest aus und liefert beim Drücken noch einmal den ausgelesenen Wert.
Dann ist Ruhe...
Erst beim Loslassen des Tasters liefert er die Werte die in der Zwischenzeit(also beim Drücken des Tasters eingelesen worden sind, obwohl dies laut Code eigentlich nicht sein dürfte) nach...
D.h. wenn ich 10 mal beim Drücken den Tag einlese (RFID-Modul) bekomme ich auch zehn mal die ID nach dem Loslassen wieder ausgegeben.
BlackJack

@nccbk: Das ist eine serielle Verbindung, da kommen die Daten in der Reihenfolge an in der sie gesendet wurden. Mit dem Taster hältst Du nur das auslesen an. Wenn Du loslässt werden dann natürlich die Daten gelesen die während der Zeit gesendet wurden, denn der Taster stoppt ja nicht den Sender. Und einfach so vergessen werden die Daten auch nicht.

Vielleicht möchtest Du das ``if`` ja weiter nach unten verschieben und nur die Ausgabe der gelesenen Daten verhindern:

Code: Alles auswählen

        while True:
            id_ = uart.read(14)
            if not GPIO.input(TASTER_PIN):
                print('ID: ', id_[4:10])
nccbk
User
Beiträge: 16
Registriert: Sonntag 10. November 2013, 15:23

@BlackJack: Ja, die If-Abfrage etwas weiter unten ist das richtige. Nur geht es hier nicht un das reine Ausgeben von "id_", sondern es soll damit weiter gearbeitet werden...
ICh habe jetzt folgendes gemacht, damit auch nur in dem Fall das der Taster nicht gedrückt wird die zum Verarbeiten genutzte ID2 geändert wird:

Code: Alles auswählen

while True:
            id_ = uart.read(14)
            if not GPIO.input(TASTER_PIN):
                ID2 = id_[4:10]
                print('ID: ', ID2)
Antworten