Relais per USB-Scanner für 10 Sekunden schalten

  • Hallo ich bin noch ein ziemlicher Anfänger



    zu meiner Hardware


    Raspberry3 Ubuntu Mate


    8 Port Relaisplatine


    Python3



    ich habe einen Usb Scanner am Raspberry angeschlossen dieser soll sobald ein Code gelesen worden ist mein Relais für 10 Sekunden schalten


    Scanner arbeitet als Tastatur ( Enter)


    sobald er erneut Scannt soll die Zeit neu starten


    sollte er nichts scannen bleibt das Relais im ruhe zustand


    das habe ich bis jetzt gemacht


    Scannen und schalten funktioniert nur beim erneute Scannen wird die Zeit nicht neugestartet





    #sudo apt-get update

    #sudo apt-get dist-upgrade

    #Vorab modul installieren "pip3 install keyboard"

    #ggf pip3 install gpiozero

    # Bibliotheken laden

    from gpiozero import DigitalOutputDevice

    from time import sleep

    import keyboard


    # Initialisierung von GPIO4 als digitaler Ausgang für eine Relais-Steuerung

    relais = DigitalOutputDevice(4)

    loop = 1

    # 1 Sekunde warten

    sleep(1)

    while loop == 1:

    while True:

    if keyboard.read_key() == "enter":

    # Relais einschalten

    relais.on()

    sleep(12)

    # Relais ausschalten

    relais.off()

    break



    Vielleicht kann mir ja einer helfen

  • Hallo,


    was meinst du genau mit "Zeit neu starten"? In deinem Code ist nichts mit Zeit oder einem Zähler..


    Den Code bitte in einem Codeblock posten, den erreichst du über die </> Schaltfläche im Editor. Sonst ist der Code schwer lesebar und die bei Python wichtigen Einrückungen gehen verloren.


    Die doppelte while-Schleife in deinem Code ist in der Form auf jeden Fall quatsch, weil doppelt.

    Du schaltest das Relais z.Zt. auch ca. 12 Sekunden, nicht 10.

    `sleep()` blockiert den Code komplett, d.h. wenn innerhalb der sleep-Dauer macht dein Programm nichts, auch keine Eingaben von der Tastatur bzw. dem Scanner entgegen nehmen. Ist das so gewollt?


    Gruß, noisefloor

  • Hallo,


    ja das ist ja mein problem das bei sleep keine eingabe möglich ist bei 10 sekunden habe ich mich vertippt sollen 12 sein


  • Hallo,


    Code bitte im Codeblock posten, nicht als Bild. Als Bild ist das fast noch schlimmer als ohne Codeblock.


    Wie gesagt: `sleep` blockiert die weitere Ausführung des Codes. Wenn der Scanner weiterhin abgefragt werden soll brauchst du nebenläufige Programmierung, im gegebenen Fall wohl per asyncio oder Threading. Beides ist nicht unbedingt ein Einsteigerthema, Threading ist hier IMHO die einfachere Variante.


    Nochmal zum Verständnis: wenn der Scanner was scannt soll das Relais für 12 Sekunden geschaltet werden. Wenn innerhalb der 12 Sekunden ein neuer Scan kommt, dann sollen die 12 Sekunden neu los laufen?


    Gruß, noisefloor

  • Eine Websuche zu "Python timer callback" liefert z.B. dies hier:


    Quelle: https://codesgarage.blogspot.c…back-using-threading.html


    Das liest sich doch ausbaufähig für Deine Anwendung, oder?

    Edited once, last by simonz ().

  • Hallo,


    simonz : wohl eher nicht, weil da die komplette Kommunikation zwischen Scanner und Countdown fehlt. Außerdem kann man das ganze mit einem Workerthread für den Countdown implementieren IMHO einfacher implementieren.

    Dein Code hält sich nicht an die gängigen Konventionen für Funktion - und Variablennamen.


    Gruß, noisefloor

  • Ja da hast du recht sieht wirklich nicht einfach aus

  • Es gibt viele Möglichkeiten, sowas zu machen, manche sind sehr elegant, manche sind sehr raffiniert, manche sehr perfektionistisch.

    Eine sehr einfache Lösung ist eine Zählvariable - hier "loop", die in kurzen Zeitabständen (0,1 Sekunden - die Dauer wird durch ein sleep bestimmt) in der Schleife runtergezählt wird. Erreicht der Zähler 0, wird das Relais ausgeschaltet.

    Wenn er Scanner erkannt wird, wird das Relais eingeschaltet und der Zähler auf 120 gesetzt.

    Da die Schleife immer weiter läuft (mit nur 0.1 Sekunden sleep), kann auch während das Relais eingeschaltet ist, ein weiterer Code erkannt werden. Dann wird der Zähler wieder auf 120 gesetzt.

    Ich hoffe, es funktioniert so - ich hab den Code nicht getestet.

    Edited 2 times, last by Gnom ().

  • Es gibt viele Möglichkeiten, sowas zu machen, manche sind sehr elegant, manche sind sehr raffiniert, manche sehr perfektionistisch.

    Eine sehr einfache Lösung ist eine Zählvariable - hier "loop", die in kurzen Zeitabständen (0,1 Sekunden - die Dauer wird durch ein sleep bestimmt) in der Schleife runtergezählt wird. Erreicht der Zähler 0, wird das Relais ausgeschaltet.

    Wenn er Scanner erkannt wird, wird das Relais eingeschaltet und der Zähler auf 120 gesetzt.

    Da die Schleife immer weiter läuft (mit nur 0.1 Sekunden sleep), kann auch während das Relais eingeschaltet ist, ein weiterer Code erkannt werden. Dann wird der Zähler wieder auf 120 gesetzt.

    Ich hoffe, es funktioniert so - ich hab den Code nicht getestet.

    super vielen dank werde ich testen

  • Hallo,


    der Ansatz ist in der Tat pragmatisch.


    Nachteil: wenn der Scanner während des `sleep` das Signal sendet, verliert sich das im Nirwana. Ob das im gegebenen Fall ein wirkliches Problem ist oder ein praktisch irrelevantes muss du selber entscheiden, weil nur du deine Anforderungen genau kennst.


    Gruß, noisefloor

  • Das hier ist mein erstes Programm mit threading.


    Es macht zumindest das, was ich glaube, das brandschutz meint ;)


    noisefloor: Falls Du Verbesserungsvorschläge hast, bitte gerne.


    Ist ein Prototyp.

    Die print()s müssen natürlich noch durch die GPIO-Befehle ergänzt/ausgetauscht werden.

    Bzw. die ganzen GPIO-Dinge fehlen noch.


    Es wird kein sleep() verwendet, also sollte kein Scanvorgang verloren gehen.


    Edited 2 times, last by simonz ().

  • Nachteil: wenn der Scanner während des `sleep` das Signal sendet, verliert sich das im Nirwana.

    Tatsächlich funktioniert es nicht, weil read_key() blockiert, bis etwas eingegeben wurde. Ich hätte erwartet, dass es einfach den Tastaturpuffer ausliest und wenn der leer ist ein False zurückgibt.
    Gibt es eine Funktion, die ein Zeichen aus dem Puffer liest und falls keins da ist NICHT blockiert?

    Edited once, last by Gnom ().

  • Und hier meine komplette Version inklusive gpiozero:

  • Aber so gehts:

    Nicht mehr so wahnsinnig elegant mit globaler Variable, aber immerhin geht es. Erstaunlich, was man für ein Spagat machen muss, um ein Zeichen aus dem Tastaturpuffer zu lesen... Was ich etwas schräg finde: keyboard fängt den Tastendruck sogar dann ab, wenn ein anderes Programm den Fokus hat. Wenn ich in Word Enter drücke, läuft der Relaistimer wieder von vorne... kann ja in bestimmten Fällen sinnvoll sein - meist aber eher nicht.

  • simonz Einen `AttributeError` behandeln ist eigentlich immer einen Programmierfehler behandeln den man hätte vermeiden sollen.

    “If debugging is the process of removing software bugs, then programming must be the process of putting them in.” — Edsger Dijkstra