Relais per USB-Scanner für 10 Sekunden schalten

Heute ist Stammtischzeit:
Jeden Donnerstag 20:30 Uhr hier im Chat.
Wer Lust hat, kann sich gerne beteiligen. ;)
  • 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,

    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.com/2017/06/python…-threading.html

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

    Einmal editiert, zuletzt von simonz (19. November 2021 um 15:26)

  • 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

    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.

    Oh, man kann hier unliebsame Nutzer blockieren. Wie praktisch!

    2 Mal editiert, zuletzt von Gnom (19. November 2021 um 14:22)

  • 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.

    2 Mal editiert, zuletzt von simonz (19. November 2021 um 18:11)

  • 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?

    Oh, man kann hier unliebsame Nutzer blockieren. Wie praktisch!

    Einmal editiert, zuletzt von Gnom (19. November 2021 um 18:20)

  • 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.

    Oh, man kann hier unliebsame Nutzer blockieren. Wie praktisch!

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

    “Dawn, n.: The time when men of reason go to bed.” — Ambrose Bierce, “The Devil's Dictionary”

Jetzt mitmachen!

Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!