Skript für Bewegungserkennung funktioniert nicht

  • Hi,

    ich steige gerade erst mehr oder weniger in Python ein und bin aktuell ein wenig am Zweifeln.

    Was ich erreichen möchte:
    Step 1: Touchscreen Display Beleuchtung für 5 Minuten aktivieren wenn Bewegung erkannt wurde
    Step 2: 433MHz Sensor schalten zu bestimmten Zeiten

    Nun habe ich das folgende Skript:

    An sich funktioniert das An- und Ausmachen des Displays problemlos.
    Aber halt nicht im Skript selbst...
    Wenn ich die beiden Zeilen mit os.system('sudo...') an anderer Stelle im Skript verwende klappt es.
    Aber sobald ich das so mache wie oben beschrieben wird keine Differenz mehr berechnet und entsprechend die Variable nicht monitor_an auf 1 gesetzt...

    Kann mir jemand sagen woran es hapert?

    Danke im Voraus!

  • Ich wuerde das mit datetime machen, und auch nicht implizit einschalten durch das manipulieren von irgendwelchen Zeitstempeln. Simple Loesung mit datetime:

    Einfach deinen GPIO-callback verwenden, und den timeout anpassen - die Python-Doku sagt alles dazu.

  • Hi,

    wow, klasse, vielen Dank für deine Mühen!
    Habe es lauffähig bekommen, muss nun mal noch versuchen den ganzen Code in Gänze zu verstehen und entsprechend noch mit den Uhrzeiten etc. ergänzen.

    Aber sieht schon mal super aus, ärgert mich dass mein eigener nicht will aber nun ja, vielleicht schaue ich in ein paar Wochen mal wieder drüber und dann weiß ich was los ist ;)

    Danke dir schon mal!

  • Hi,

    ich habe mehrfach Kabel gelötet und irgendwie habe ich den Verdacht dass evtl. doch die Programmierung einen Hau hat...
    Stand jetzt ist es so:

    - ich starte das Script
    - es erkennt jede Bewegung
    - nach 5 min ohne Bewegung geht der Monitor an
    - sobald der Monitor aus ist wird keine Bewegung mehr erkannt

    Kann sich jemand evtl. noch mal die Programmierung angucken? :(

  • Hi,

    ich komme nicht weiter, evtl. ist das Skrip ja auch einfach zu lang für jemanden der sich das mal anschauen könnte.
    Habe es mal gestrippt und aufs Wesentliche gekürzt:


    Das gelötete Kabel sieht übrigens aus wie ein H, der Querstrich ist sozusagen der Widerstand mit 10k Ohm. Ich denke dass das korrekt sein sollte, es läuft ja auch irgendwie ein paar Male :(

    Wäre wirklich klasse wenn ihr noch eine Idee dazu hättet!

  • Das simple Programm sieht erstmal nicht so aus, als ob da ein Problem vorliegt. Was passiert, wenn du den Timeout auf einige Sekunden stellst? Klappt dann alles? Vielleicht haut irgendwann der eingebaute Bildschirmschoner rein.

    Ausserdem solltest du die monitor_an/aus-Funktionen mal mit print-Ausgaben bestuecken, dich per SSH auf den PI verbinden, und dann das Skript starten. Wenn die Ausgaben noch kommen nachdem der Monitor schon nicht mehr reagiert liegt das Problem woanders.

  • Wieso führst du os.system für echo aus? Öffne die Datei lieber nativ in python und führ das Script selbst über sudo aus.

    So wie ich das sehe hast du in deiner while am Ende ein Einrückungsproblem: time.sleep(5.0) muss exakt bündig mit "if"
    Also nicht so:
    [code=php]
    def main():
    try:
    GPIO.add_event_detect(SENSOR_PIN , GPIO.RISING, callback=callback)

    while True:
    if timestamp is not None and datetime.datetime.now() - timestamp > TIMEOUT:
    monitor_aus()
    time.sleep(5.0)
    except KeyboardInterrupt:
    print "Beende..."
    GPIO.cleanup()
    [/php]

    Sondern so:
    [code=php]
    def main():
    try:
    GPIO.add_event_detect(SENSOR_PIN , GPIO.RISING, callback=callback)

    while True:
    if timestamp is not None and datetime.datetime.now() - timestamp > TIMEOUT:
    monitor_aus()
    time.sleep(5.0)
    except KeyboardInterrupt:
    print "Beende..."
    GPIO.cleanup()
    [/php]wichtig ist das sich die while nicht ungebremst drehen kann da sonst das Script 100% CPU Last erzeugt und somit auch den Interrupt beeinflusst etc..

    Und wie gesagt würde ich /sys/class/backlight/rpi_backlight/bl_power nativ in python bearbeiten, nicht über os.system oder subprocess.

  • Hi,

    danke erstmal für deine Hilfe.
    Ich habe die Einrückungen kontrolliert und korrigiert, aber am Prinzip ändert sich nichts leider.

    Hier mal ein Log-Auszug von heute morgen:

    Code
    23.06.2016 08:10:54: Monitor an
    23.06.2016 08:10:54: Monitor an
    23.06.2016 08:15:50: Monitor aus

    Der Prozess läuft noch, allerdings ohne weitere Bewegungserkennungen zu signalisieren :(
    Und das An- und Ausschalten selbst funktioniert ganz gut - also zumindest eben einmal. Oder denkst du da kann hinter stecken dass das Skript nicht weitere Bewegungen erkennt?

    Einmal editiert, zuletzt von Sirel (23. Juni 2016 um 16:09)

  • Streng nach dem Fehlerausschlussprinzip kann das schon am aus/einschalten liegen. Also als naechstes die Aktion *nicht* durchfuehren, und schauen, was dann passiert. Einen echten Grund, warum das von alleine aufhoert bezueglich des GPIO-Ereignisses kann ich jedenfalls nicht erkennen.

  • Es sieht so aus als hättest Du das Script bereits verändert da ja ein Log geschrieben wird?
    Wir sehen also nicht das aktuell von Dir verwendete oder wie Du das aufrufst und somit ist jegliche Hilfestellung eigentlich für die Katz..... Also entweder du hälst uns mit den Details auf dem laufenden, oder du löst dein Problem selber, so hart das auch klingen mag.


    Also erst mal würde ich den Code ein bisschen abändern und sicherstellen das du das Script selbst via sudo ausführst:

    Es sieht ja so aus als würde "Monitor an" zwei mal kurz nacheinander ausgeführt werden - das könnte daran liegen das der Taster nicht entprellt ist.
    Dann wie gesagt von "os.system" weg hin zum nativen beschreiben der bl_power Datei.
    Dann würd ich auch erst mal diese "lock" Sache rauswerfen - solange das Script nicht zu funktionieren scheint erst mal alle Zweifelhaften Sachen weg lassen.
    Ich finde es zudem sehr verwirrend wieso es "monitor_status" heißt obwohl es doch nur das Backlight behandelt :-/

    Man kann das ganze insofern kürzen das bei Aufruf einer Funktion immer der Gegenteilige Status vom Vorherigen gesetzt wird. Wenn also "monitor_status" vorher False war wird beim aktuellen Aufruf True gesetzt, wird danach die Funktion noch mal aufgerufen wirds auf False gesetzt usw. Da mich monitor_status aber irritiert benenne ich es "backlight_status"

    => http://codepad.org/fs4EVvIQ

  • Das lock ist notwendig, weil es sonst zu einer Race-Condition mit der monitor_status-Variable kommt. Das ist absolute Grundlage der nebenlaeufigen Programmierung. Es gibt einen Unterschied zwischen zweifelhaft und nicht verstanden...

  • Es gibt auch einen Unterschied zwischen Freundlichkeit und Herablassend. Bitte behalte diese Umgangsform im python-forum und verschone uns

    Du erklärst es nirgends, setzt aber voraus das der TE es entweder selber versteht oder es blind copy&pasted - toll.

  • Es ist immer wieder faszinierend, wie gut du austeilen, aber nicht einstecken kannst. Du schmeisst hier gerne mit fies-smilies, Besserwissen und Belehrung ueber Code-Style rum - wehe aber, das geht in deine Richtung. Darum sehe ich ueblicherweise davon ab, mich mit dir auseinander zu setzen, weil dass sinnlos ist - aber wenn du meinen Code kommentierst, erreicht das seine Grenzen.

  • Hi,

    also tatsächlich führe ich das Skript aus Beitrag #5 aus und nicht #6. Da ich auf #5 keinerlei Antworten bekam dachte ich, ich kürze mal aufs Wesentliche um dem geneigten Helfer das Leben zu erleichtern.

    Und ich bin über jedweden Tipp dankbar, mich hat das ganze Thema schon einige Nerven gekostet - erst habe ich das Touchdisplay für den Grund gekauft, dann die Sensoren um festzustellen es muss ein Widerstand eingebaut werden, ergo habe ich mir sämtliches Material besorgt zum Löten etc.
    Die Aufgabe klang erstmal recht einfach und doch ist es scheinbar nicht so trivial wie gedacht. Aber zu spät zum Aufgeben :)

  • Wie, du hast auf #5 keine Antworten bekommen? Was ist denn #6, wenn keine Antwort darauf?

    Und wie gesagt: du solltest das Programm aus #5

    - mit logging versehen.
    - noch weiter reduzieren, indem du die eigentliche backlight-Ansteuerung auskommentierst.

    Damit sollte man dann sehen koennen, ob *nur* die IO und Timeout-Logik passt, oder nicht. Erst danach machen wir weiter. Zum testen den Timeout natuerlich auch gerne auf ein paar Sekunden setzen, wobei du das auch mal unter 'echten' Bedingungen testen solltest.

  • Hi,

    sorry hatte mich verschrieben, klar hatte ich auf #5 Antworten bekommen, meinte eher dass der Grund war dass ich #5 erstellt habe überhaupt der war, dass es vorher ggf. zu lang war.
    Nun ja, also ich habe in die kürzere Variante logging wieder reingebracht und nun habe ich folgendes Problem welches evtl. weiterhilft.

    Hier erstmal der gesamte Code:

    Und nun das interssantere Logging dazu:

    Code
    25.06.2016 12:50:42: Monitor Status an
    25.06.2016 12:50:42: Bewegung erkannt
    25.06.2016 12:51:42: Monitor Status aus
    25.06.2016 12:51:47: thread slept
    25.06.2016 12:51:52: thread slept
    25.06.2016 12:51:57: thread slept
    25.06.2016 12:52:02: thread slept
    [...]

    Zur Erklärung: Sobald der Monitor ausgeschaltet wird, springt das Programm in die Schleife und kommt da scheinbar nicht mehr raus bzw. ist evtl. "timestamp" das Problem?

  • Ja und nein. Tatsaechlich ist es ein bisschen ungluecklich, dass die if-Anweisung immer wieder ausgefuehrt wird, weil timestamp nicht auf None zurueckgesetzt wird. Das kann und sollte man aenderen.

    Es erklaert aber nicht, warum keine Bewegung mehr erkannt wird. Bevor wir uns also dem Timestamp widmen, bitte ich dich das zu tun, was ich jetzt schon zweimal erwaehnt habe: entferne den Code, der den Monitor tatsaechlich schaltet. Also deine os.system-calls. Denn nur so koennen wir rausfinden, ob das einen Einfluss auf den Sensor hat. Der sollte ja immer noch per callback aufgerufen werden.
    Automatisch zusammengefügt:
    Manul: das tut man in Python ueblicherweise nicht, die Operator-Praezedenz ist ohne Klammern schon vollkommen ok. and/or sind niedriger als Vergleiche, und die sind niedriger als Arithmetik.

  • Hi,

    danke euch, es geht voran :)

    Also - habe Klammern eingebaut und den os.system() Part auskommentiert - und es läuft.
    Nun habe ich den os.system() Part wieder reaktiviert und es läuft nicht, also wird es wohl daran liegen.

    Ich glaube am Anfang kam der Tipp die Datei "nativ in Python" zu öffnen... geht tatsächlich nur darum eine 1 oder 0 Datei zu schreiben, richtig?

  • @__deets__: Okay, danke. Ich kann mir sowas immer schlecht merken, deswegen klammere ich gerne explizit - da sehe ich auf Anhieb, was Sache ist.

    Sirel: Sicherheitshalber nachgefragt: Das Programm bleibt tatsächlich länger als die von Dir eingestellten 60 Sekunden in der Schleife?

Jetzt mitmachen!

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