Monitor mit PIR HC SR-05 ein-/ausschalten

Python auf Einplatinencomputer wie Raspberry Pi, Banana Pi / Python für Micro-Controller
Antworten
mrSnatz
User
Beiträge: 1
Registriert: Mittwoch 17. April 2019, 09:37

Hallo,
ich bin neu im Thema Python und hoffe auf eure Hilfe. Ich habe ein Skript welches den Monitor bei Bewegung einschalten soll und nach 5 Minuten wieder ausschalten soll (Am liebsten mit ner Schleife das die 5 min. immer von neuem beginnen wenn eine Bewegung erkannt wird, aber soweit bin ich noch lange nicht). das Skript ist in der rc.local als Autostart daher die 120 sek. Wartezeit für den Bootvorgang.
Mein Problem liegt darin, dass dass Skript den Monitor nach 5 min. ausschaltet und nach 1 min. selbstständig wieder einschaltet. Es soll aber aus bleiben bis eine Bewegung erkannt wird und erst dann wieder einschalten

Code: Alles auswählen

#!/usr/bin/python

# Import der Python libraries
import RPi.GPIO as GPIO
import time
import datetime
import subprocess
import os

# Angabe der PIN Nummern 
GPIO.setmode(GPIO.BOARD)

# GPIO Pin an dem die Dataleitung liegt steckt
GPIO_PIR = 7

#  GPIO als "Input" festlegen
GPIO.setup(GPIO_PIR,GPIO.IN)

Current_State  = 0
Previous_State = 0

try:

 # erst mal schlafen bis der bootvorgang abgeschlossen ist
 time.sleep(120)

 # Warten bis Sensor sich meldet
 while GPIO.input(GPIO_PIR)==1:
   Current_State  = 0

 subprocess.Popen('echo PIR bereit | wall', shell=True)

 # Schleife bis CTRL+C
 while True :

   #Status von Sensor auslesen
   Current_State = GPIO.input(GPIO_PIR)

   if Current_State==1 and Previous_State==0:

     # Kommando zum anschalten, Frambuffer erneuern
     os.system("vcgencmd display_power 1")
     time.sleep(300)
     Previous_State=1

   elif Current_State==0 and Previous_State==1:

     # Ausschalten des Monitors
     os.system("vcgencmd display_power 0")
     Previous_State=0

   # Warten
   time.sleep(0.1)

except KeyboardInterrupt:
 print " Exit"
 GPIO.cleanup()
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ich wuerde da komplett anders vorgehen, und damit auch gleich dein Problem mit "immer von neuem beginnen wenn eine Bewegung erkannt wird" loesen.

Das vorgehen ist ganz einfach: du hast einen Zeitstempel. Wenn jetzt spaeter ist als der Zeitstempel ist, schaltest du das Licht AUS. Sonst an. Wenn der PIR etwas meldet, addierst du "jetzt + 5min" auf den Zeitstempel. Und zwar voellig unabhaengig davon, ob gerade Licht an ist oder aus. Damit ist dein Programm besser, und robuster.

Code: Alles auswählen

timestamp = time.time()
while True:
       if sensor_sieht_was:
               timestamp = time.time() + 5minuten
       if time.time() > timestamp:
               .... # licht an
       else:
               .... # licht aus
       time.sleep(.1) # wichtig
Das wars. Luecken bitte selbst ausfuellen.
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

Erstmal zum Code: Eingerückt wird immer mit 4 Leerzeichen pro Ebene, nicht 2. Variablen werden klein_mit_unterstrich geschrieben.
cleanup sollte immer aufgerufen werden, nicht nur bei Ctrl+C, daher gehört das in einen `finally`-Block. Das `as` bei `import RPi.GPIO as GPIO` ist quatsch.

Ob die Signale, die von deinem Bewegungsmelder kommen, stabil sind, hängt auch davon ab, wie er angeschlossen ist.

Statt eines Busy-Wait ist ein GPIO.wait_for_edge besser.
Viele Kommentare erklären nur, was ohnehin in der nächsten Zeile steht, bieten also keinen Mehrwert und können weg. Kommentare sollten beschreiben, warum etwas gemacht wird, nicht wie.

Dein ganzer Code muß in einer oder besser mehreren Funktionen stehen, auf oberster Ebene sollten nur Definitionen sein.

Ungetestet:

Code: Alles auswählen

#!/usr/bin/python
from RPi import GPIO
import time
import subprocess

# GPIO Pin an dem die Dataleitung liegt steckt
GPIO_PIR = 7

def setup():
    GPIO.setmode(GPIO.BOARD)
    GPIO.setup(GPIO_PIR, GPIO.IN)

def work_loop():
    turn_off_time = 0
    while True:
        edge_detect = GPIO.wait_for_edge(GPIO_PIR, GPIO.RISING, timeout=max(turn_off_time-time.time(), 0.01))
        subprocess.call(['vcgencmd', 'display_power', '0' if edge_detect is None else '1'])
        if edge_detect is not None:
            # movement -> keep on for 5 minutes
            turn_off_time = time.time() + 300

def main():
    # erst mal schlafen bis der bootvorgang abgeschlossen ist
    time.sleep(120)

    try:
        setup()
        GPIO.wait_for_edge(GPIO_PIR, GPIO.FALLING)

        subprocess.Popen(['wall'], stdin=subprocess.PIPE).communicate('PIR bereit\n')

        work_loop()
    except KeyboardInterrupt:
        print " Exit"
    finally:
        GPIO.cleanup()
        
if __name__ == '__main__':
    main()
Antworten