nun allen Experten nochmals Dank für die Geduld mit einem der weiss,
dass er nichts weiss. Hier der (hoffentlich) definite Code:
nun allen Experten nochmals Dank für die Geduld mit einem der weiss,
dass er nichts weiss. Hier der (hoffentlich) definite Code:
keepfear: Also ich ärgere mich nicht wenn ich Kommentare auch
mehmals gesagt bekomme, im Gegenteil ich versuche Sie zu begreiffen.
Ich verstehe schon, dass eine while Schlaufe die CPU dauernd auf
Trab hält. Nur, es funktionierte einfach nicht anderst und ich sah nicht
wo der Fehler war.
Aber, Dein Code nach entfernen der Decoratoren (Nr. 4 in #80)
funktioniert und ich denke ich bin am Ziel !!
Die Unterschiede zwischen button.when_pressed/button.when_released
und button.when_held habe ich getestet. Meine Absicht Störsignale zu
unterdrücken - mittels s/w - basiert nach wie vor auf der Idee dazu die
hold_time als Parameter von when_held zu benutzen: Nur ein Signal das
genügend lange ist (> hold_time) d.h. vom PIR kommt, kann die Funktionen
aufrufen. Deshalb kann ich die hold_time nicht kürzer als die PIR-
Anstiegsflanke wählen, die ich sowieso nicht kenne, sonst könnte auch ein
Störsignal eine "reguläre" PIR Reaktion auslösen. Oder ist diese Idee falsch ??
Habe noch festgestellt, dass sich hold_time und PIR-Haltezeit addieren bis
die Funktionen ausgeführt werden.
@DeaD_EyE:
Dein thread hat funktioniert, aber die eigentliche Funktion pir.when_held =
partial(.....) dann nicht mehr.
beide Versionen, die mit der Zusammenfassung beider Funktionen (Foto m
achen, per email schicken) in einem task(Funktion) und die mit einem
zeitlich getrennen scheduler haben funktioniert.
ich sags jetzt zum x-ten Mal: Wenn ich die while Schleife weglasse passiert
nach einer Bewegung am PIR nichts...
Dann noch mein letzter Punkt, ein 2. thread zur Aufnahme und e-mail Versenden
eines Fotos täglich/nächtlich zu vorgegebener Zeit:
Habe den def main() Block in Anlehnung an eine andere Installation ergänzt
nach import von schedule und threading:
def main():
pir = Button(BUTTON_PIN, hold_time=65)
ir_light = DigitalOutputDevice(RELAIS_PIN)
push_bullet = Pushbullet(PUSHBULLET_API_KEY)
with picamera.PiCamera() as camera:
schedule.every().day.at("21:49").do(get_picture(ir_light,camera),
send_mail())
threading.Thread(target=schedule_thread).start()
try:
while True:
pir.when_held = partial(on_motion, push_bullet, ir_light,
camera)
pause()
except KeyboardInterrupt:
pass
if __name__ == "__main__":
main()
Alles anzeigen
erstaunlicherweise werden beide Funktionen get_picture(ir_light, camera und
send_mail() unmittelbar nach Aktivierung des Scripts ausgeführt, unabhängig
von der eingegebenen Zeit und das Script bricht ab mit:
root@raspberrypiZeroHome1:/home/pi# python3 onMotion_v0.py
2023-05-19 21:52:14,563 - root - INFO - Foto aufgenommen
2023-05-19 21:52:14,674 - root - INFO - Foto angehaengt
2023-05-19 21:52:15,357 - root - INFO - e-mail gesendet
Traceback (most recent call last):
File "/home/pi/onMotion_v0.py", line 111, in <module>
main()
File "/home/pi/onMotion_v0.py", line 100, in main
schedule.every().day.at("21:54").do(get_picture(ir_light,camera), send_mail())
File "/usr/local/lib/python3.9/dist-packages/schedule/__init__.py", line 657, in do
self.job_func = functools.partial(job_func, *args, **kwargs)
TypeError: the first argument must be callable
Möglicherweise ist in der schedule Methode in Argument zuviel ?
Nun das Sript entsprechend angepasst, mit dem selben Test
Resultat wie in #70 und #72 :
eine Signaliversion oder Erfassung der abfallenden Flanke löst
das Problem der Unterscheidung zwischen reeler Bewegung und
elektromagnetischem Störimpuls nicht.
Verwende mittlerweile das Modul Button mit when_held und
hold_time und das geht.
ja, das funktioniert im Prinzip: Die Funktion test_on(button)
wird aufgerufen, aber erst nach Ablauf der Haltezeit des PIR, ich hatte
erwartet nach Ablauf der hold_time bzw. nach 2 Sekunden.
Aber die Idee zur Unterdrückung von Störimpulsen scheint trotzdem
zu funktionieren: Habe die hold_time auf 65 sec gesetzt, 5 sec länger
als die PIR-Haltezeit (z. Z. 60 sec) um so einen Störimpuls zu simulieren
und die Funktion wird nicht aufgerufen.
Das heisst aber, dass in meiner definitiven Installation eine (unbefugte)
Bewegung erst nach Ablauf der PIR-Haltezeit die verschiedenen
Funktionen, Foto, SMS etc. erfolgen. Die PIR Haltezeit ist verkürzbar.
Habe mittlerweile von MotionSensor auf Button gewechselt. S.O.
Invertieren, wie soll das gehen ? Du lieferst ja die Antwort gleich mit:
"Ich habe das nun mangels nicht vorhandener Hardware nicht nachprüfen können"
hatte initial keine while Schleife, dann passierte gar nichts. Erst nach Einfügen der
Schleife funktionierts.
In dieser vergangenen Themenfolge habe ich auf diesem ausgezeichneten Forum
viel gelernt und begriffen, anfänglich hatte ich nur Code abgeschrieben/kopiert.
Habe erkennen müssen, dass mein aktuelles Script mit pir.when_pressed() und
pir.when_released() mein Ziel doch nicht erfüllt. Ich brauche pir.when_held
um mit einer hold_time von einigen Sekunden, die von der PIR-Haltezeit immer
übertroffen wird, die viel kürzeren Störimpulse zu unterdrücken.
Nur schaffe ich das noch nicht, folgendes Testscript, aus einem anderen Projekt übernommen
zeigt keine Reaktion:
#!/usr/bin/python3
from gpiozero import Button
from signal import pause
button = Button(11, hold_time = 2)
Button.was_held = False
def test_on(button):
print('test aufgerufen')
Button.was_held = True
print('Funktionen')
def test_off(button):
if not button.was_held:
Button.was_held = False
def main():
button.when_held = test_on
button.when_released = test_off
pause()
print('Init abgeschlossen')
if __name__ == "__main__":
main()
Alles anzeigen
mit der Funktionalität des Scripts wie folgt kann ich gut leben,
Störmeldungen sind nicht mehr aufgetreten und das Problem des
Script Abbruches ist mit einer service unit gelöst:
https://gist.github.com/luemar/17d7659…fb4f4259aadefd3
Allen Experten nochmals herzlichen Dank .
Also wie gesagt, das Problem der Störsignale wie ich sie am Anfang
meines Projektes hatte sind bist jetzt eliminiert.
Meine Überwachungsanlage funktioniert mit folgendem Script:
https://gist.github.com/luemar/17d7659…fb4f4259aadefd3
Vielen Dank für die vielseitige und immer prompte Hilfe .
ist mir noch aufgefallen, dass die partial Funktion nicht mehr
gebraucht wird ?
ja, funktioniert bis auf die Tatsache, dass nach der ersten Bewegung
am PIR das Script in der while Schlaufe endlos abläuft.
ja, das deckt sich mit meiner Auffassung, die Haltezeit (besserer Ausdruck)
habe ich als Verzögerungszeit bezeichnet.
Habe Deinen Hinweis #33 umgesetzt:
1. wait_for_press ist m.E. ungeeignet da in meinem Script (unten) das
print statement im Abstand von 5 Sekunden sooft erscheint bis die Haltezeit
abgelaufen ist, in meinem definitiven Script würden dann solange Fotos
gemacht, emails und sms gesendet:
#!/usr/bin/python3
from gpiozero import Button
from time import sleep
def main():
pir = Button(11, None, True)
while True:
pir.wait_for_press()
print("PIR akiviert")
sleep(5)
if __name__ == "__main__":
main()
Alles anzeigen
2. when_pressed und when_released könnte funktionieren:
#!/usr/bin/python3
from gpiozero import Button
from signal import pause
def print_msg_1():
print('PIR aktiviert')
def print_msg_2():
print('PIR Haltezeit abgelaufen')
def main():
pir = Button(11, None, True)
while True:
pir.when_pressed = print_msg_1
pir.when_released = print_msg_2
pause()
if __name__ == "__main__":
main()
Alles anzeigen
Werde es in meinem definitiven Script (im Forum Beitrag nohup #49) einbauen.
hier das Script:
#!/usr/bin/python3
import logging
import smtplib
from email.header import Header
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from functools import partial
from pathlib import Path
from signal import pause
from socket import gaierror
from time import sleep
import picamera
from gpiozero import DigitalOutputDevice, MotionSensor
from pushbullet import Pushbullet
logging.basicConfig(
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
level=logging.INFO,
)
PATH_TO_PICTURE = Path("/home/pi/bild1.jpg")
MOTION_PIN = 11
RELAIS_PIN = 17
MAIL_FROM = "my email address"
MAIL_TO = "my email address"
SMTP_HOST = "mein Postausgangsserver"
SMTP_PORT = 465
SMTP_USER = "my user name"
SMTP_PASSWORD = "my password"
MAIL_SUBJECT = "von RPI 3 Home1"
MESSAGE_TEXT = "Foto von RPI 3 Home1"
PUSHBULLET_API_KEY = "mein neuer API key"
PHONE_NUMBER = "my mobile number"
def get_picture(ir_light, camera):
camera.rotation = 90
try:
ir_light.on()
try:
sleep(0.5)
camera.capture(str(PATH_TO_PICTURE), resize=(740, 480))
finally:
ir_light.off()
logging.info("Foto aufgenommen")
except picamera.exc.PiCameraError:
logging.exception("Camera Fehler")
def push_to_bullet(push_bullet):
try:
push_bullet.push_sms(
push_bullet.devices[0], PHONE_NUMBER, "RPI 3 Home1 ausgeloest"
)
logging.info("sms gesendet")
except Exception:
logging.exception("sms Fehler")
def send_mail():
message = MIMEMultipart()
message["From"] = MAIL_FROM
message["To"] = MAIL_TO
message["Subject"] = Header(MAIL_SUBJECT)
message.attach(MIMEText(MESSAGE_TEXT))
message.attach(MIMEImage(PATH_TO_PICTURE.read_bytes()))
logging.info("Foto angehaengt")
try:
with smtplib.SMTP_SSL(SMTP_HOST, SMTP_PORT) as smtp:
smtp.login(SMTP_USER, SMTP_PASSWORD)
smtp.sendmail(MAIL_FROM, MAIL_TO, message.as_string())
logging.info("e-mail gesendet")
except gaierror:
logging.exception("e-mail Fehler")
def on_motion(push_bullet, ir_light, camera):
try:
logging.info("PIR 3 Home1 wurde ausgeloest")
get_picture(ir_light, camera)
push_to_bullet(push_bullet)
send_mail()
except Exception:
logging.exception("Unerwartete Ausnahme!")
#def on_no_motion():
#logging.info("im Schlafmodus")
def main():
motion_sensor = MotionSensor(MOTION_PIN)
ir_light = DigitalOutputDevice(RELAIS_PIN)
push_bullet = Pushbullet(PUSHBULLET_API_KEY)
with picamera.PiCamera() as camera:
try:
motion_sensor.wait_for_motion = partial(
on_motion, push_bullet, ir_light, camera
)
#motion_sensor.when_no_motion = on_no_motion
pause()
except KeyboardInterrupt:
pass
if __name__ == "__main__":
main()
Alles anzeigen
vielen Dank.
Zuerst möchte ich etwas Grundsätzliches klären um nicht mit einer falschen Vorstellung
zu arbeiten:
'wie lange die Flanke steht' wird doch von der eingestellten Verzögerungszeit des PIR bestimmt ?
erlaube mir mich - nach längerer Arbeit mein Script zu verbessern - nochmals zu Wort zu melden:
Nach meinem Verständniss erzeugen elektromagnetische Wellen im Umkreis einer Schaltung
elektrische Impulse/Störsignale in den Drähten dieser Schaltung.
In meinem Fall waren es mit grösster Wahrscheinlichkeit die in meiner "Konstruktion" integrierten
Netzteile für 5V (SANMIM SM-PLF12B, Chinesische Billigware, funktionieren aber anderweitig seit
Jahr und Tag) und für 12V (Mean Well IRM-20-12).
Ich kann mir aber nicht vorstellen wie der ca. 20cm lange "Draht" - es ist ein abgeschirmtes
TV-Coaxialkabel, Abschirmung am GND - vom PIR zum RPi Pin als Antenne wirken kann.
Ob die kritische Spannung (ca. 2.7V) in einem Draht/Antenne durch ein elektromagnetisches Stör-
signal erreicht wird, hängt das nicht vom Verhältnis Länge des Störsignals/Steilheit der Anstiegskurve
es PIR ab ?
Auf jedenfall treten seit Auslagerung der Netztteile - für 5V wird ein Mean Well RS-15-5 benutzt -
keine Störungen mehr auf.
Sollten nach definitiver Installation meiner "Konstruktion" doch noch Störungen kommen würde
ich entweder einen Kondensator einbauen oder die s/w Lösung mit gpiozero Button nehmen.
Habe 2 Tests gemacht:
1. Test funktioniert:
#!/usr/bin/python3
from gpiozero import Button
from time import sleep
PIR = Button(11, None, True)
while True:
if PIR.is_pressed:
print("PIR akiviert")
else:
print("PIR inaktiv")
sleep(2)
Alles anzeigen
2. Test mit when_held funktioniert (noch) nicht ???
Hier könnte man mit der hold_time Störsignale ausfiltern:
nach Korrektur meines Tippfehlers geht nichts, PIR wird nicht ausgelöst.
Ich gehe wieder zurück zu on_motion und no_on_motion.
Mein Ziel ist es - wenn das Script zuverlässig und ohne Fehlmeldungen läuft -
den PIR und das Script mit Wartezeiten so einzustellen, dass im Falle eines
unbefugten Eindringens nicht laufend Fotos und SMS gemacht und geschickt
werden.
mit wait_for_motion gibts schon wieder einen Traceback:
......
AttributeError: 'MotionSensor' object has no attribute 'wait_for__motion'
Dabei ist das Objekt ausführlich in 'read the docs' von gpiozero aufgeführt.
Aber wenn ich in Deinem Script #49
motion_sensor.when_no_motion = on_no_motion einfach
weglasse geht's.
Der Jumper ist z.Z. auf 'Single' gestellt, jede Bewegung führt zu einer Auslösungdes PIR nachdem
die Reaktionszeit d.h. die im rechten Potentiometer eingestellte Zeit abgelaufen ist.
Obwohl ich denselben PIR wie in Deinem Beitrag #57 eingebaut habe, stimmen meine Handhabung
und Erfahrung nicht mit den Angaben von Reichelt überein:
1. Erwähnt Reichelt 3 Einstellungsmöglichkeiten, es gibt aber nur 2 Potentiometer.
2. Regelt das Potentiometer rechts die sog. Reaktionszeit, die Zeit, die der PIR high ausgibt und die geht
nach meinen Angaben nicht bis 18 Sekunden sondern bis 5 Minuten (exponentiell nac Potieinstellung).
Ich denke das Thema sollte zu einem Ende kommen. Ich will noch einen 2. thread einbauen mit dem ich
jede Nacht ein Foto bekomme und ich muss noch das Thema '2 Bewegungssensoren imultan auslösen'
bearbeiten.
Ich bedanke mich bei allen Experten für ihre Geduld und Hilfe.
bis jetzt wurde es für mich immer verworrener, nach jeder Anpassung
des Codes neue Fehlermeldung.
Nun mit der letzten Version in #49 von Keepfear funktionierts
mit einer Anmerkung bezüglich when_no_motion:
Wenn ich das Script starte kommt nach einigen Sekunden, wie vorgesehen
Dann löst nach einer Bewegung am PIR motion_sensor.when_motion die
def on_motion() Funktion wie vorgesehen aus.
Wenn keine Bewegung mehr stattfindet löst nach jetzt ca. 60 Sekunden
motion_sensor.when_no_motion die def on_no_motion() Funktion aus,
wobei diese ca. 60 Sekunden oder Wartezeit durch die Verzögerungseinstellung
am PIR bestimmt wird.
Wenn aber Bewegung vor Ablauf dieser ca. 60 Sekunden statfindet erfolgt
def on_no_motion() und nach erneuter Bewegung dann wieder
def on_motion().
Wäre es nicht einfacher nur wait_for_motion zu benutzen ?