Bewegungsmelder mit Nachlaufzeit

  • Hallo und guten Abend,
    ich habe mich an einer "Haussteuerung" versucht.

    Also folgender Sachverhalt:
    Ich habe einen Bewegungsmelder, der mir auf meinen Pi ein Input von einer halben Minute gibt (natürlich über Relais, sodass er seine 3.3V bekommt), sobald eine Bewegung aufkommt.
    Wenn ich einen Input bekomme, dann schalte ich Relais, die in meinem Fall einfach nur Licht anmachen.
    Nach der halben Minute von dem Bewegungsmelder möchte ich noch eine weitere halbe Minute die Relais halten. Was ich bisher auch ganz gut hinbekomme.
    Wo ich jetzt allerdings scheitere, ist wenn der Bewegungsmelder erneut ein Signal gibt, dann geht das Licht kurz an und wieder aus nachdem er seine halbe Minute zusätzlich die Relais angesteuert hat.

    Klar kann man das so lassen, aber ich finde es besser, wenn es komplett durch gängig anbleibt bzw. die halbe Minute von dem Pi nur dann geschalten wird, wenn das Signal vom Melder wieder weg ist.

    Mein jetziger Code kommt aus einem Blog, wo ein PIR Sensor im Einsatz war:
    (Den habe ich nur auf meine Ein- und Ausgänge angepasst.)

    Also wüsste ich gern, wie ich den Code so schreibe, dass die Zeit immer wieder zurück gesetzt wird, sobald der Bewegungsmelder kein Signal mehr gibt auch nach erneuten Signal.

    Vielen Dank!

  • FAQ => Nützliche Links / Linksammlung => Interrupt => #8
    Beziehungsweise https://github.com/meigrafd/Sampl…_interrupt_2.py

    Und die Nachlaufzeit würde sich über datetime anbieten

  • Hallo,
    Danke für die Antworten und die Vorschläge werde ich noch versuchen umzusetzen.

    Das mit der datetime habe ich nur noch nicht ganz heraus gefunden, wie du das meinst. Gibt es da ein passendes Beispiel zum Nachlesen bzw. wie soll ich das kombieren?

  • Naja, das von mir gezeigte Script verwendet ja bereits datetime und schreibt den Zeitpunkt wann der Interrupt durch den PIR ausgelöst wurde ins Queue. Eine Schleife gibt es ebenfalls schon.

    Das einzige was du dann noch brauchst:
    - sobald deine "Action" ausgeführt wird setzt du ein Statusflag
    - eine Prüfung ob genug Zeit seit "Action"-aktiv vergangen ist um "Action" wieder zu deaktiveren.

    Vorlage https://github.com/meigrafd/Sampl…_interrupt_2.py dafür abgeändert:
    [code=php]
    #!/usr/bin/python2
    from __future__ import print_function
    from time import sleep
    from datetime import datetime
    from RPi import GPIO
    from Queue import Queue
    from functools import partial


    def interrupt_event(q, channel):
    q.put( (channel, GPIO.input(channel), datetime.now()) )


    def main(PIR_PIN=23, ACTION_PIN=21, DELTA=15):
    action=False
    action_time=datetime.now()
    queue = Queue()
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(ACTION_PIN, GPIO.OUT)
    GPIO.output(ACTION_PIN, GPIO.HIGH)
    GPIO.setup(PIR_PIN, GPIO.IN)
    try:
    GPIO.add_event_detect(PIR_PIN, GPIO.RISING, callback=partial(interrupt_event, queue), bouncetime=100)
    while True:
    sleep(0.01)
    if not queue.empty():
    pin, state, dt = queue.get()
    action = True
    action_time = dt
    GPIO.output(ACTION_PIN, GPIO.LOW)
    if action and (datetime.now() - action_time).seconds > DELTA:
    action = False
    GPIO.output(ACTION_PIN, GPIO.HIGH)


    except KeyboardInterrupt:
    print("Quit")

    if __name__ == '__main__':
    main()
    GPIO.cleanup()

    #EOF
    [/php]
    ..das ist nur ein Beispiel, ob es tatsächlich sofort bei Dir funktioniert weiß ich selbstverständlich nicht, da auch du deine Code-Zeilen nicht detailliert beschreibst :daumendreh2:

    Bei weiteren Fragen bitte erst zuvor genannte Links folgen und durchlesen.

  • Hallo,
    das hilft mir erstmal ein gutes Stück weiter. Und es funktioniert auch von der theoretischen Seite.
    Mein Pi sitzt in einem Schaltschrank, wo noch andere Relais für andere unabhängige Sache verbaut sind. Wenn ich das Skript laufen lasse und jetzt andere Relais schalten, dann sieht der Pi das als Input vom Bewegungsmelder, jedoch hat er nicht geschalten. Genau so ist es, wenn ich einen Draht an den Eingang halte, schaltet der Pi mein Licht ungewollt an.
    Ich habe schon probiert die Bouncetime zu erhöhen und Widerstände (10k Ohm zur Masse und 1k Ohm zu 3.3V) an den GPIO Input zuhängen. Ohne jeglichen Erfolg.
    Wenn ich einfach nur mit den "if GPIO.input == HIGH" arbeite und da eine kurze sleep Funktion einbaue, dann kommt der Fehler nicht auf. Was ich dann aber nicht realisieren kann, ist die Nachlaufzeit nach einen neuen Impuls vom Melder, da die Zeit erst ablaufen muss, bis ein neuer Input verarbeitet werden kann.
    Getestet habe ich das Skript von meigrafd auf der Basis, das alle anderen Relais und Störungen abgeschaltet waren, dann hat das mit der Nachlaufzeit prima funktioniert. Sobald innerhalb der "AN-Zeit" vom Licht ein neuer Impuls vom Bewegungsmelder kam, lief die Zeit (in dem Fall die 15s) von vorne los.
    Ich würde mich über einen Lösungsansatz freuen!

  • Den Beitrag habe ich dazu auch schon gelesen und versucht umzusetzen mit den Widerständen. Erst nur zur Masse mit 100k, 50k und 10k Ohm und dann nur testweise zu einem 3.3 V Pin und dem Eingang. Leider hat das nichts gebracht und auch softwaremäßig den Pull Down davor zuschalten hat nichts besseres bewirkt.

    Wie ich oben schon geschrieben habe, passiert das ganze nicht mit dem "if input.. " . Mit dem "add event detect" kommt erst der Fehler auf. Was ich aber nicht verstehe ist, dass die Bouncetime das ganze beheben soll, aber keine Reaktion zeigt ob ich jetzt 100 oder 2000 schreibe.

  • Die Bouncetime entprellt nur: http://www.labbookpages.co.uk/electronics/debounce.html
    Ein Pull-UP/DOWN hingegen dient zur Störsicherheit.

    Bei dir schaltet du das Relais indem du den GPIO auf LOW schaltest?

    Lies dir bitte 8. von obigem Link noch mal durch ;)

  • Okay, dann probiere ich das nochmal mit einem Kondensator und einem Pull-Up Widerstand.

    Genau, wenn ich output LOW habe, dann geht das Relais.

    EDIT: Ich habe das genau so, wie in dem verlinken Beitrag gemacht, also mit 10k Pull Up und 100 nano Kondensator. Es bringt immernoch Störungen in das System. Keine Verbesserung erkennbar.

    Einmal editiert, zuletzt von tuersteherj (17. September 2017 um 13:37)

  • Also ich kann absoult keine Erfolge verzeichnen. Sobald ich ein anderes Relais schalte, dann springt der Pi auf den Eingang an, der aber nicht anliegt. Ich habe es, wie in der Verlinkung (von oben), mit den Pull-Up Widerständen probiert und zusätzlich mit einem Kondensator. Dann nochmal mit Widerständen in beide Richtungen (up und down). Es brachte garkeine Verbesserung.

    Deswegen nochmal die Frage, kann man bei dem Code irgendwie noch zusätzlich z.b. sleep 0.1 dazu setzen?

    [code=php]#!/usr/bin/python2
    from __future__ import print_function
    from time import sleep
    from datetime import datetime
    from RPi import GPIO
    from Queue import Queue
    from functools import partial


    def interrupt_event(q, channel):
    q.put( (channel, GPIO.input(channel), datetime.now()) )


    def main(PIR_PIN=23, ACTION_PIN=21, DELTA=15):
    action=False
    action_time=datetime.now()
    queue = Queue()
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(ACTION_PIN, GPIO.OUT)
    GPIO.output(ACTION_PIN, GPIO.HIGH)
    GPIO.setup(PIR_PIN, GPIO.IN[font="Roboto, Arial, Helvetica, sans-serif"], pull_up_down = GPIO.PUD_DOWN[/font])
    try:
    GPIO.add_event_detect(PIR_PIN, GPIO.RISING, callback=partial(interrupt_event, queue), bouncetime=100)
    while True:
    sleep(0.01)
    if not queue.empty():
    pin, state, dt = queue.get()
    action = True
    action_time = dt
    GPIO.output(ACTION_PIN, GPIO.LOW)
    if action and (datetime.now() - action_time).seconds > DELTA:
    action = False
    GPIO.output(ACTION_PIN, GPIO.HIGH)
                   
       
    except KeyboardInterrupt:
    print("Quit")

    if __name__ == '__main__':
    main()
    GPIO.cleanup()

    #EOF[/php]

    Dieses kurze Warten hat bei der normalen "if GPIO.input == HIGH" Abfrage perfekt funktioniert, da ich anfangs die gleichen Probleme hatte.
    Jedoch kann ich mit dem Befehl und meinen Wissensstand nicht das selbe erreichen, wie mit dem "GPIO.add_event_detect", sodass das Licht nach erneuten Input nochmal und die Zeit X verlängert wird.

    Danke im Voraus!

  • Es gibt bestimmt eine Lösung das ganze Hardwareseitig zu lösen - nicht zu ignorieren. Auch wenn du Softwareseitig eine Bremse einbaust ändert das nämlich nichts daran dass die Störungen weiterhin auftreten und auch vom GPIO erfasst werden. Es wäre dann nur eine Frage der Zeit bis die Software dann doch mal "unerwünscht" auslöst, obwohl die ja nur das macht was sie soll: Bei Flankenwechsel am GPIO reagieren.

    Wie gesagt dient ein Kondensator nur zur Entprellung. Du hast aber kein "prell"-Problem.
    Einzig spezielle Keramik-Kondensatoren (Kerko) zwischen VCC und GND bringen bei Deinem Problem Besserung, aber wie gesagt nicht einfach irgendwelche Kondensatoren sondern nur Kerko. Es spielt aber auch eine große Rolle Wo du das Konstrukt verschaltet hast, mit welchem Abstand zum GPIO..

    Hast du dir "8. Welches Prinzip sollte man anwenden? Pullup- oder Pulldown-Widerstand?" durchgelesen?

    Es fängt damit an, was für Relais du überhaupt einsetzt.
    Dann geht es weiter mit: Wie sind die Relais verdrahtet.
    Bis hin zu: Wie lang sind die Kabel zwischen Pi und Relais.
    Und Endet letztlich auch damit, Wo sind die Relais platziert (Abstand zum Pi und den Adern die zum Pi gehen).

    Das sind alles Punkte die für dein Problem verantwortlich sein können.

  • Hallo,

    lang habe ich mich nicht gemeldet, doch jetzt möchte ich meinen aktuellen Stand mitteilen.

    Also mein akutelles Python Programm, womit ich arbeite, damit das Licht angeht wenn es dunkel ist und es an bleibt, wenn ein neuer Input da ist laut:

    Funktioniert genau so wie es soll. Nur leider gibt es ein Problem, dass das Licht abends nicht wieder angeht, obwohl es dunkel (unter 3 lx) ist. Sobald ich das Programm neustarte funktioniert es einwandfrei. Zur Info ich starte den Pi jeden Tag um Mitternacht neu und beim Neustart wird über die rc.local Datei das Python Programm gestartet.

    Um den Verlauf der Schalterei zuverfolgen, hatte ich noch print Befehle mit Zeitstempeln im Code, die mir sagten, dass das Licht eigentlich angegangen ist, jedoch nicht war.( Habe ich jetzt für die Übersicht entfernt )

    Das selbe Programm nur ohne der Helligkeitsabfrage läuft noch einmal auf dem Pi, um ein anderes Licht zusteuern von einem anderen Bewegungsmelder. Jedoch funktioniert es da den ganzen Tag richtig.

    Im Moment weiß ich keine Lösung/Verbesserung für das Problem. Vielleicht könnt ihr mir helfen..


    Und das ich beim ausmachen des Lichtes mehrmals das Relais schalte ist gewollt, da ich eine Switch-Dimm Funktion an meinem Vorschaltgerät nutze.

Jetzt mitmachen!

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