Alarmanlage GPIO: UND-Verknüfen?

Heute ist Stammtischzeit:
Jeden Donnerstag 20:30 Uhr hier im Chat.
Wer Lust hat, kann sich gerne beteiligen. ;)
  • Hallo,
    neben der Auswertung anderer Signal an GPIO (Wasser- und Stromzähler) habe ich an drei GPIO's auch Kontakte von meiner "Alarmanlage" montiert.
    Ein Schalter dient dazu, die Anlage "scharf" zu stellen (GPIO 27)
    Die zwei anderen sind Türkontake (offen wenn Tür offen), an GPIO 4 und 17

    Die prinzipielle Erfassung der Türimpulse funktioniert (über fallende oder steigende Impulse wird auch erkannt, ob die Tür auf oder zu geht ("... GPIO.BOTH ...")

    Prinzip soll sein:
    1. Tür auf (LivRoom) => Türimpuls (an GPIO 4) wird registriert, in Logfile geschrieben
    2. Jetzt soll überprüft werden, ob Alarmanlage "scharf" ist, also Schalter an GPIO27 geschlossen ist
    3. Wenn "scharf", 1s warten und prüfen, ob die Tür immer noch offen ist (GPIO 4)
    Wenn ja, starte die Alarmaktion (Pushnachricht aufs Handy)
    Wenn nein: Protokolliere einen Fehlalarm

    Bei Schritt zwei habe ich ein Problem, wie kann ich innerhalb eines Interrupt-Aufrufs prüfen, welcher Zustand ein anderer GPIO hat?


    Hier die Teile meines Python-Codes:

    Danke für Tipps, evtl. stehe ich auch nur auf dem Schlauch ;)

    Einmal editiert, zuletzt von topsurfer (17. März 2017 um 19:52)

  • Du bist seit Oktober 2014 hier im Forum registriert und hast schon 127 Beiträge gepostet. Dann müsstest du inzwischen wissen, es gibt einen Code-Tag in dieser Forensoftware. Dein geposteter Code ist Null Wert, weil Phyton mit Einrückungen arbeitet. Wo sind deine?

    • Offizieller Beitrag

    Hallo topsurfer,

    ich kann zwar raten, aber warum fragst Du nicht direkt den GPIO ab also:

    Code
    if GPIO.input(27) == GPIO.HIGH:
        time.sleep(1)
        if GPIO.input(4) == GPIO.LOW:
            Wenn ja, starte die Alarmaktion (Pushnachricht aufs Handy)
        Wenn nein: Protokolliere einen Fehlalarm

    Evtl. hast Du das auch schon versucht... :s

  • :denker: Déjà-vu :s

    In der interrupt-Callback sollte man so wenig wie möglich abhandeln, denn dann wird diese derweil blockiert und verpasst möglicherweise ein Flankenwechsel. Du blockiert die Funktion mit dem sleep sogar absichtlich, was für eine Alarmanlage echt böse is ;)

    Also erst mal solltest du das entsprechend umbauen - auch wenn ich den Rest des Scripts nicht kenne - und die Abhandlung der Events im Script selbst behandeln aber von der Callback nur das Event in ein Queue packen.
    Beispiel dazu findest du über FAQ => Nützliche Links / Linksammlung => Interrupt => #8 oder #9

    Sofern du keinen Zustand über einen Reboot hinweg speichern möchtest ist ein Weg über eine Datei keine so gut Idee (Beitrag#5). Läuft das Script permanent reicht es völlig die benötigten Bedingungen in einer Variable zu hinterlegen. Wie das aussehen könnte findest du glaub ich ebenfalls in #9 oder so - falls nicht kann ich dir das aber gerne noch mal erklärn ;)

    Bau erst mal dein Script um und wenn du dann noch Fragen hast bitte das komplette Script zeigen.

    • Offizieller Beitrag


    ... Abhandlung der Events im Script selbst behandeln aber von der Callback nur das Event in ein Queue packen.
    Beispiel dazu findest du über FAQ => Nützliche Links / Linksammlung => Interrupt => #8 oder #9

    meigrafd: #7? :-/
    Automatisch zusammengefügt:


    Sorry, korrigiert ... und ist es richtig, das man diese Tags händig eingeben muss, ebenso wie Fett etc. ?

    Falls Du Adblock Plus o.ä. installiert hast, musst Du die Domain "forum-raspberrypi.de" aktivieren bzw. zulassen um die Schaltflächen zu sehen.

  • meigrafd: #7? :-/

    #7 sowie die davor sind nicht so toll - deshalb der Hinweis in der Linksammlung => Wichtig: Die Beiträge haben eine gewisse Entwicklung durchlebt. Mittlerweile solltet ihr den letzten bevorzugen!
    Oder was meinst du mit #7 ?

    Ich werf mal noch https://github.com/meigrafd/Sample-Code in den Raum, da findet sich bestimmt auch irgend was brauchbares :fies:

  • Das mit dem direkten Abfragen anderer GPIO's werde ich testen,
    aber was mir dann negativ aufgefallen ist, das andere Interupts durch die lange Callback-Behandlung nicht erkannt werden. Auch wenn ich das "sleep 1" herausnehme, andere Routinen brauchen auch einige Zeit und dadurch könnten andere "ankommende" Impulse (vom Stromzähler z.B.) nicht verarbeitet werden.

    Zeitmessung Heizung (Python)
    Hier lese ich, das es besser ist, zeitaufwendigere Routinen in eine "Queue" hinzuzufügen statt direkt in Callback.
    Wie würde das in meinem Fall aussehen, so eine "Queue"? Aus dem Callback eine Subroutine innerhalb des Python-Scripts starten?
    (wo ist in dem "Zeitmessung Heizung" dieser erwähnte Queue Aufruf realisiert?)

    Einmal editiert, zuletzt von topsurfer (18. März 2017 um 12:13)

  • Siehe Beitrag#8

    Wenn du den Code liest und die Festlegung der "callback" findest, sollte sich deine Frage eigentlich erübrigen

    Was da im einzelnen Passiert wird auch in #9 beschrieben => FAQ => Nützliche Links / Linksammlung => Interrupt => #9

    Wenn weiterhin etwas unklar ist dann bitte die Frage genauer spezifizieren

  • Habe den Code von hier mal angeschaut (http://codepad.org/b5IkKMY2),
    die Events werden in die Event-Queue geschoben und von dort "nacheinander" abgearbeitet. Und während dieser Abarbeitung können bei anliegenden GPIO-Signalen weitere Jobs in die Queue geschoben werden.

    In der "while" Schleife kann ich den auslösenden GPIO und auch den Signalwechsel (Flanke) erkennen, aber wo sehe ich hier die exakte Auslösezeit des Events?
    Im Codebeispiel steht:
    ...
    triggerTime = time()
    ....

    Aber diese Zeit ist doch die Zeit der Abarbeitung in der While-Schleife, nicht wann der Event aufgetreten ist. Korrekt?
    Müßte/könnte man nicht auch die Auslösezeit dem Queue mitübergeben? Wie? ;)


  • In der "while" Schleife kann ich den auslösenden GPIO und auch den Signalwechsel (Flanke) erkennen, aber wo sehe ich hier die exakte Auslösezeit des Events?

    Die kannst du mit in die tuple aufnehmen wenn du das benötigst. So wie es zum Beispiel hier gemacht wird: https://github.com/meigrafd/Sampl…t_stoppuhr_2.py

    Im Codebeispiel steht:
    ...
    triggerTime = time()
    ....

    Aber diese Zeit ist doch die Zeit der Abarbeitung in der While-Schleife, nicht wann der Event aufgetreten ist. Korrekt?

    Ja.
    Wobei dort davon auszugehen ist das die while sehr schnell abgearbeitet wird da in der while nichts anderes behandelt wird und Zeile 29 die while solange blockiert bis ein Eintrag im Queue eingefügt wurde.

    Müßte/könnte man nicht auch die Auslösezeit dem Queue mitübergeben? Wie? ;)

    Wofür brauchst du das? In deinen bisherigen Beiträgen sehe ich kein Bedarf dafür :s

  • Zeile 16 von deinem Beispiel habe ich so geändert, denke das ist was du meintest:
    q.put( (channel, GPIO.input(channel), datetime.now()) )

    In der while-Schleife kann ich dann die Impulszeit als: job[2] auslesen und verwenden.

    Die genaue Auslösezeit benötige ich für die anderen (zwei) GPIO's, welche Strom und Wasserverbrauch erfassen.
    Dort wird die exakte Zeit benötigt,c um zu ermitteln, welche Zeit zwischen zwei Impulsen liegt um hochzurechne, wie der aktuelle kWh (Verbrauch/Stunde) ist ...

    Bei den (drei) GPIO's von der Alarmanlage ist diese genaue Auslösezeit nicht notwendig.

Jetzt mitmachen!

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