Raspberry Pi5 - HMDI Ausgang schalten wenn Bewegung erkannt über den PIR Sensor HC-SR501

Python auf Einplatinencomputer wie Raspberry Pi, Banana Pi / Python für Micro-Controller
Antworten
Benutzeravatar
DorSushi
User
Beiträge: 7
Registriert: Dienstag 8. April 2025, 22:04

Guten Abend zusammen,
Ich nutze einen Raspberry P5 mit Bookworm. Darauf läuft pihole, Magic Mirror und iobroker. Daran über HDMI angeschlossen ist ein Bildschirm welcher sich nur einschalten soll, wenn eine Bewegung erkannt wird und nach einer gewissen zeit wieder abschalten soll. Das ganze soll über die Deaktivierung des HDMI Signals passieren. Lange Zeit hatte ich das über den Magic Mirror und ein Modul gelöst. Da sich der Entwickler zurück gezogen hat und ich nach einer "stand alone" Lösung suche, wollte ich das per script lösen. Nach viel suchen und testen von scripten stoße ich an meine Grenzen. Ich bin Neuling in python und wollte euch daher um Hilfe bitten. Ich versuche mal so viele Informationen wie möglich hier zu schreiben:

die alte config datei mit eventuell Hinweisen (das Modul ist deaktiviert da es eh nicht mehr funktioniert):

Code: Alles auswählen

{
		module: 'MMM-Pir',
		position: 'top_center',
		  config: {
		    Display: {
		      timeout: 3 * 60 * 1000,
		      style: 4,
		      colorFrom: "#FF0000",
		      colorTo: "#00FF00",
		      mode: 3,
		      counter: true,
			waylandDisplayName: "wayland-0",
		      lastPresence: false,
		      lastPresenceTimeFormat: "LL H:mm",
		      availability: true,
		      autoDimmer: false,
		      xrandrForceRotation: "normal",
		      wrandrForceMode: null,
		      relayGPIOPin: 0,
		      ddcutil: {
			powerOnCode: "01",
			powerOffCode: "04",
			skipSetVcpCheck: false
		      }
		    },
		    Pir: {
		      mode: 0,
		      gpio: 23
		    },
		},
	},
das script was ich aktuell versuche zu nutzen worauf auch der Bewegungsmelder reagiert hdmi_1.py:

Code: Alles auswählen

import RPi.GPIO as GPIO
import time
from threading import Timer
import subprocess


GPIO.setmode(GPIO.BCM)
GPIO.setup(23, GPIO.IN)
SHUTOFF_DELAY = 120 # in seconds, how long the monitor will be on until next button press or PIR detection
timer = False
monitor_is_on = True

def monitor_off():
  global monitor_is_on
  #subprocess.call("sh /home/pi/monitor_on.sh", shell=True)
  monitor_is_on = False

def monitor_on():
  global monitor_is_on
  #subprocess.call("sh /home/pi/monitor_off.sh", shell=True)
  #subprocess.call(['fbset -depth 8'], shell=True)
  #subprocess.call(['fbset -depth 16'], shell=True)
  #subprocess.call(['xrefresh'], shell=True)
  monitor_is_on = True


while True:
  time.sleep(1.0)
  movement = GPIO.input(23)
  if movement:
    if timer:
      print ("Monitor an")
      timer.cancel()
      timer = False
    if not monitor_is_on:
      print ("Monitor aus")
      monitor_on()
  else:
    if not timer:
      print ("start timer")
      timer = Timer(1*1, monitor_off)
      timer.start()
das funktioniert allerdings nur wenn ich die beiden scripte monitor_on.sh und monitor_off.sh deaktiviere. Sonst kommt der Fehler "failed to connect to display". Zumindest erkenne ich durch das script das das "signal" funktioniert :D

Inhalt der monitor_off.sh:

Code: Alles auswählen

wlr-randr --output HDMI-A-1 --off
Inhalt der monitor_on.sh

Code: Alles auswählen

wlr-randr --output HDMI-A-1 --on
- Der Sensor ist angeschlossen an pin 23
- Raspberry PI5 mit Bookworm
- Sensor - HC-SR501
- zum testen nutze ich Thonny und das terminal

Starte ich das script über das terminal kommt dann der Fehler:

Code: Alles auswählen

sudo python3 hdmi_1.py
start timer
error: XDG_RUNTIME_DIR is invalid or not set in the environment.
failed to connect to display
Noch ein Fehler / Hinweis:

Code: Alles auswählen

pi@raspberrypi:~ $ wlr-randr --output HDMI-A-1 --off
pi@raspberrypi:~ $ wlr-randr --output HDMI-A-1 --on
failed to apply configuration
Danach bleibt der Monitor dunkel. Nur ein reboot lässt den Monitor wieder zum leben erwachen
Benutzeravatar
DorSushi
User
Beiträge: 7
Registriert: Dienstag 8. April 2025, 22:04

habe selber eine Lösung gefunden. Da es aber niemand liest und daher kein interesse dran ist lad ich da nix hoch.. mfg
einfachTobi
User
Beiträge: 510
Registriert: Mittwoch 13. November 2019, 08:38

Das ist eine komische Einstellung. Woher nimmst du die Info, dass hier niemand liest? Und selbst wenn hier bisher niemand mitgelesen hat, wäre es sinnvoll die Lösung für Leute zu posten, die in Zukunft dieses Problem haben.
Benutzeravatar
__blackjack__
User
Beiträge: 13905
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@DorSushi: Wenn in Zukunft jemand den Beitrag findet und ein ähnliches Problem hat, wird der sich sicher denken, „der hat eine Lösung, sagt das auch, und zeigt die absichtlich nicht — was für ein netter Mensch“. 🫤

Anmerkungen zum Quelltext: Eingerückt wird in Python per Konvention mit vier Leerzeichen pro Ebene.

``as`` beim ``import`` ist zum umbenennen da, `GPIO` wird aber gar nicht umbenannt.

Auf Modulebene sollte nur Code stehen der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst.

Warum ist bei `print()` zwischen Funktionsname um öffnender Klammer immer ein Leerzeichen? Das gehört da nicht hin.

Magische Zahlwerte, und dann auch noch wiederholt, sollten als Konstanten mit sprechenden Namen definiert werden. Das macht den Quelltext verständlicher und weniger fehleranfällig wenn man den Wert mal ändern will oder muss.

Es fehlt der Aufruf von `GPIO.cleanup()` am Programmende.

Globale Variablen haben in einem sauberen Programm nichts zu suchen. Das ist in normalen, sequentiell ablaufenden Programmen schon keine gute Idee, bei Programmen mit Nebenläufigkeit ist das noch unübersichtlicher.

Da an- und abschalten des Monitors offenbar mehrere Schritte umfasst, mit Aufrufen von externen Programmen, ist das alles andere als atomar und muss bei Threads entsprechend abgesichert werden, damit der Zustand konsistent ist/bleibt. Zustand, Operationen, und deren Threadsicherheit kann man beispielsweise in einem `Monitor`-Objekt verpacken.

Der gleiche Name sollte möglichst immer an den gleichen (Duck-)Typ gebunden werden. Also nicht mal ein Wahrheitswert und mal ein `Timer`-Objekt. Der vorgesehe Wert für „kein Wert“ ist in Python `None`.

`subprocess.call()` ist von `subprocess.run()` abgelöst worden. Siehe Dokumentation für die Gründe.

``shell=True`` sollte man da nicht verwenden denn das startet eine unnötige Shell zwischen dem eigenen Programm und dem was man da startet und bringt die ganzen Probleme mit sich wegen denen man `subprocess.run()` überhaupt verwenden sollte. Es ist auch eigenartig bis falsch bei diesem Argument dann das Kommando trotzdem als Liste mit nur einem Element zu übergeben.

Ein Shell-Skript explizit mit ``sh`` zu starten riecht komisch, denn das sollte ja eigentlich in dem Skript selbst in der She-Bang-Zeile stehen, womit das ausgeführt werden muss.

Und dann machen einzeilige Shell-Skripte wenig Sinn, wenn man das was da in der Zeile steht, auch direkt in das Python-Programm schreiben kann.

Zwischenstand (ungetestet):

Code: Alles auswählen

#!/usr/bin/env python3
import subprocess
import time
from threading import Lock, Timer

from RPi import GPIO

PIR_PIN = 23
#
# In seconds, how long the monitor will be on until next button press or motion
# detection.
#
SHUTOFF_DELAY = 120


class Monitor:
    COMMAND = ["wlr-randr", "--output", "HDMI-A-1"]

    def __init__(self):
        self._lock = Lock()
        self._is_on = True

    @property
    def is_on(self):
        with self._lock:
            return self._is_on

    def switch_on(self):
        with self._lock:
            subprocess.run([*self.COMMAND, "--on"], check=True)
            self._is_on = True
            # subprocess.run(["fbset", "-depth", "8"], check=True)
            subprocess.run(["fbset", "-depth", "16"], check=True)
            subprocess.run(["xrefresh"], check=True)

    def switch_off(self):
        with self._lock:
            subprocess.run([*self.COMMAND, "--off"], check=True)
            self._is_on = False


def main():
    try:
        GPIO.setmode(GPIO.BCM)
        GPIO.setup(PIR_PIN, GPIO.IN)
        monitor = Monitor()
        shutoff_timer = None
        while True:
            time.sleep(1)
            if GPIO.input(PIR_PIN):
                if shutoff_timer:
                    print("Monitor an")
                    shutoff_timer.cancel()
                    shutoff_timer = None

                if not monitor.is_on:
                    print("Monitor aus")
                    monitor.switch_on()
            else:
                if not shutoff_timer:
                    print("start timer")
                    shutoff_timer = Timer(SHUTOFF_DELAY, monitor.switch_off)
                    shutoff_timer.start()

    finally:
        GPIO.cleanup()


if __name__ == "__main__":
    main()
“I am Dyslexic of Borg, Your Ass will be Laminated” — unknown
Benutzeravatar
DorSushi
User
Beiträge: 7
Registriert: Dienstag 8. April 2025, 22:04

Hallo, es tut mir leid das ich so emotional reagiert habe. Ich war genervt weil ich seit Tagen eine Lösung gesucht hatte und nichts funktionieren wollte. War schon bissl doof von mir.
Ich werde die Lösung noch hier Posten. Da ich Python sehr selten bis gar nicht nutzte weiß ich leider nix von solchen Änderungen wie Beispielsweise das subprocess.call() von subprocess.run() abgelöst wurde. Desweiteren gibt es ja diese "import" Sachen was sowas wie eine "Bibliothek" ist.
Da weiß ich auch nicht was für Funktionen / Wörter es gibt und deren Anwendungen. Ich will mal versuchen das raus zu suchen und mich mal belesen. (Gibt es da direkt links wo man sich da als Leihe belesen kann?)

Ich hab mir das nun selber zusammen geschrieben bis es irgendwie ging...

Anschluss des HC-SR501:
VCC an eine 5 Volt PIN des Rpi 5
GND an einen GND PIN des Rpi 5
OUT an einen digitalen Eingas PIN des Rpi 5 (in meinem Fall der GPIO 23 Hardware pin 16)
Einstellungen in der config des raspberry:

Code: Alles auswählen

sudo raspi-config
-> advanced options -> wayland -> labwbc (X11 ging nicht bei mir da der Monitor grau bleibt)


Es gibt 3 Dateien die in meinem Fall im ~/home/pi/ Verzeichnis liegen:
motion_hdmi_rpi5.py - das script
mon.sh - hdmi ein
mof.sh - hdmi aus
und einen Eintrag in der crontab Datei des Raspberry:

Code: Alles auswählen

crontab -e
zum bearbeiten

motion_hdmi_rpi5.py:

Code: Alles auswählen

from gpiozero import MotionSensor
from signal import pause
import subprocess
import time

pir = MotionSensor(23)

def motion_function():
    #print("Motion Detected")
    subprocess.call("sh /home/pi/mon.sh", shell=True)
    time.sleep(120)
    
def no_motion_function():
    #print("Motion stopped")
    subprocess.call("sh /home/pi/mof.sh", shell=True)

pir.when_motion = motion_function
pir.when_no_motion = no_motion_function

pause()
mon.sh:

Code: Alles auswählen

#!/bin/bash
export WAYLAND_DISPLAY=wayland-0
export XDG_RUNTIME_DIR=/run/user/1000
/usr/bin/wlr-randr --output HDMI-A-1 --on --mode 1440x900
mof.sh:

Code: Alles auswählen

#!/bin/bash
export WAYLAND_DISPLAY=wayland-0
export XDG_RUNTIME_DIR=/run/user/1000
/usr/bin/wlr-randr --output HDMI-A-1 --off
print habe ich deaktiviert weil es nur zum testen für das Terminal war

Eintrag im crontab:

Code: Alles auswählen

#pir sensor
@reboot  python /home/pi/motion_hdmi_rpi5.py &
So wird das Script bei jedem reboot aktiviert


Eventuell gibts ja an dem Code noch was zu verbessern, anzupassen oder zu optimieren. Vielleicht könnt ihr mir da noch Tipps geben :roll:
Ich hab bei mir einfach sleep (120) genutzt um das hdmi Signal aktiviert zu lassen. Gibt es zusätzlich die Möglichkeit wenn man sich vor dem Sensor bewegt, das die slepp funktion wieder reaktiviert? Soll bedeuten solange Bewegung ist soll der hdmi on befehl aktiv sein bevor die 120 Sekunden sleep aktiviert werden.




Sorry noch mal für mein Verhalten... :|
Sirius3
User
Beiträge: 18203
Registriert: Sonntag 21. Oktober 2012, 17:20

Es ist schon sehr komisch, ein bash-Skript explizit mit sh aufzurufen, und das auch noch mit einem subprocess-Aufruf mit shell=True.
Wenn Du schon subprocess benutzt, sind die zusätzlichen Skripte unnötig.
Alle konstanten Werte sollten explizit als Konstanten definiert werden, damit man sie einfach ändern kann.
In einem Callback sollten keine langlaufenden Funktionen stehen. In Deinem Fall sind die Callbacks gar nicht nötig, weil der MotionSensor schon passende Funktionen bereitstellt.

Code: Alles auswählen

import subprocess
from gpiozero import MotionSensor

SENSOR_PIN = 23
TIMEOUT = 120
RANDR_PROC = "/usr/bin/wlr-randr"
MONITOR_DEVICE = "HDMI-A-1"
MONITOR_MODE = "1440x900"
WAYLAND_DISPLAY = "wayland-0"
XDG_RUNTIME_DIR = "/run/user/1000"

def switch_monitor(*args):
    subprocess.run([
        RANDR_PROC,
        "--output", MONITOR_DEVICE,
    ], env={
        "WAYLAND_DISPLAY": WAYLAND_DISPLAY,
        "XDG_RUNTIME_DIR": XDG_RUNTIME_DIR,
    })

def main():
    pir = MotionSensor(SENSOR_PIN)
    state = None
    while True:
        pir.wait_for_motion(timeout=TIMEOUT)
        if pir.motion_detected:
            if not state:
                switch_monitor("--on", "--mode", MONITOR_MODE)
            state = True
        else:
            # no signal
            if state:
                switch_monitor("--off")
            state = False
        pir.wait_for_no_motion()

if __name__ == "__main__":
    main()
Benutzeravatar
DorSushi
User
Beiträge: 7
Registriert: Dienstag 8. April 2025, 22:04

das heist es würde nur das script reichen so wie du es rein gestellt hast ohne die beiden *.sh dateien?
Ich kann acuh nix mit den Fehlern die du beschrieben hast bzw welche zu viele sind nicht viel anfangen. :roll:
Sorry ich bin da nicht so fit. Es hatte halt so funktioniert...
Benutzeravatar
__blackjack__
User
Beiträge: 13905
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@DorSushi: Dass das vorher so funktioniert hat stelle ich mal in Zweifel. Wir wissen nicht so genau was das konkrete Backend von GPIOZero macht, aber wenn das Ereignisse queued, dann führen erneute Bewegungserkennungen zu immer neuen zwei Minuten die sich nicht überlappen, sondern alle seriell nacheinander abgewartet werden. Sollte es Ereignisse ignorieren, dann wird der Monitor dagegen nach zwei Minuten dunkel, auch wenn zwischendurch Bewegung stattfand. Also in beiden Fällen nicht das was man will. Und man weiss nicht was von beidem passiert, oder vielleicht sogar noch etwas ganz anderes wie Programmabbruch wenn die Queue eine Grössenbegrenzung hat, oder es aus anderen Gründen wichtig ist, dass der Code in dem Benachrichtigungsthread tatsächlich etwas tun kann.
“I am Dyslexic of Borg, Your Ass will be Laminated” — unknown
Benutzeravatar
DorSushi
User
Beiträge: 7
Registriert: Dienstag 8. April 2025, 22:04

@__blackjack__:
Also bis jetzt funktioniert es so.
Ich werde morgen mal das andere script ausprobieren und ein feedback geben wie es sich verhalten hat. Als ich das in einem Modul des MagicMirror noch intergriert hatte, gab es da sogar einen visuellen Timer der das mit der "reaktivierung" angezeigt hat. Da lief einfach ein counter runter und sobald wieder "motion" dedektiert wurde, hat er wieder bei 2 Minuten angefangen.
Wie schon gesagt, mir fehlen dazu die Programmier-Erfarungen. Ich bin dankbar für eure Tips aber leider sind es noch zu viele "Fachbegriffe". AUf alle fäll ist es ein sehr spannendes Thema.

Ich könnte ja mal in den Ordnern des MagicMirror unter dem Modul schauen ob man da was entdeckt wie das geschrieben wurde oder ich lade mal eine zip Datei hoch wo sich die Dateien darin befinden wenn ihr eventuell interesse daran habt?
Ist ja alles open source
Benutzeravatar
DorSushi
User
Beiträge: 7
Registriert: Dienstag 8. April 2025, 22:04

Hallo, ich habe das Script mal in Thonny geöffnet und gestartet. Thonny prüft das ja und gibt direkt Fehlermeldungen aus.

Code: Alles auswählen

>>> %Run motion.py
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/gpiozero/pins/pi.py", line 411, in pin
    pin = self.pins[info]
KeyError: PinInfo(number=16, name='GPIO23', names=frozenset({'23', 'BCM23', 'J8:16', 'WPI4', 23, 'GPIO23', 'BOARD16'}), pull='', row=8, col=2, interfaces=frozenset({'', 'dpi', 'sdio', 'jtag', 'i2c', 'gpio'}))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/pi/motion.py", line 38, in <module>
    main()
  File "/home/pi/motion.py", line 22, in main
    pir = MotionSensor(SENSOR_PIN)
  File "/usr/lib/python3/dist-packages/gpiozero/devices.py", line 108, in __call__
    self = super().__call__(*args, **kwargs)
  File "/usr/lib/python3/dist-packages/gpiozero/input_devices.py", line 588, in __init__
    super().__init__(
  File "/usr/lib/python3/dist-packages/gpiozero/input_devices.py", line 257, in __init__
    super().__init__(
  File "/usr/lib/python3/dist-packages/gpiozero/mixins.py", line 243, in __init__
    super().__init__(*args, **kwargs)
  File "/usr/lib/python3/dist-packages/gpiozero/input_devices.py", line 79, in __init__
    super().__init__(pin, pin_factory=pin_factory)
  File "/usr/lib/python3/dist-packages/gpiozero/devices.py", line 553, in __init__
    pin = self.pin_factory.pin(pin)
  File "/usr/lib/python3/dist-packages/gpiozero/pins/pi.py", line 413, in pin
    pin = self.pin_class(self, info)
  File "/usr/lib/python3/dist-packages/gpiozero/pins/lgpio.py", line 126, in __init__
    lgpio.gpio_claim_input(
  File "/usr/lib/python3/dist-packages/lgpio.py", line 755, in gpio_claim_input
    return _u2i(_lgpio._gpio_claim_input(handle&0xffff, lFlags, gpio))
  File "/usr/lib/python3/dist-packages/lgpio.py", line 458, in _u2i
    raise error(error_text(v))
lgpio.error: 'GPIO busy'
>>> ]
Ich stelle mal die Fehler mit dem Verweis hier mit rein. Wie gesagt ich bin blutiger Anfänger :):
line 108

Code: Alles auswählen

self = super().__call__(*args, **kwargs)
        # At this point __new__ and __init__ have all been run. We now fix the
        # set of attributes on the class by dir'ing the instance and creating a
        # frozenset of the result called __attrs__ (which is queried by
        # GPIOBase.__setattr__). An exception is made for SharedMixin devices
        # which can be constructed multiple times, returning the same instance
line 588

Code: Alles auswählen

super().__init__(
            pin, pull_up=pull_up, active_state=active_state,
            threshold=threshold, queue_len=queue_len, sample_wait=1 /
            sample_rate, partial=partial, pin_factory=pin_factory, average=mean)
        self._queue.start()
line 257

Code: Alles auswählen

super().__init__(
            pin, pull_up=pull_up, active_state=active_state,
            pin_factory=pin_factory)
line 243

Code: Alles auswählen

super().__init__(*args, **kwargs)
        self._active_event = Event()
        self._inactive_event = Event()
        self._last_active = None
        self._last_changed = self.pin_factory.ticks()
line 79

Code: Alles auswählen

super().__init__(pin, pin_factory=pin_factory)
        try:
            self.pin.function = 'input'
            pull = {None: 'floating', True: 'up', False: 'down'}[pull_up]
            if self.pin.pull != pull:
                self.pin.pull = pull
line 533

Code: Alles auswählen

 pin = self.pin_factory.pin(pin)
        self._pin = pin
        self._active_state = True
        self._inactive_state = False
line 413

Code: Alles auswählen

pin = self.pin_class(self, info)
                self.pins[info] = pin
            return pin
        raise PinInvalidPin(f'{name} is not a valid pin name')
line 126
lgpio.gpio_claim_input(
self.factory._handle, self._number, lgpio.SET_PULL_NONE)
line 755

Code: Alles auswählen

return _u2i(_lgpio._gpio_claim_input(handle&0xffff, lFlags, gpio))
line 458

Code: Alles auswählen

 raise error(error_text(v))
   return v
Hier mal die Datei als ganzes falls benötigt. Daher kommen die Meldungenhttps://www.transfernow.net/dl/20250412SVbWoEFc
Benutzeravatar
Dennis89
User
Beiträge: 1503
Registriert: Freitag 11. Dezember 2020, 15:13

Hallo,

sind während deinem Versuch das Skript zu starten, alle anderen Skripte die auf GPIO's zugreifen gestoppt und sind die Pin's "aufgeräumt"? Am besten mal sicher gehen das keins deiner Skripte automatisch beim Start ausgeführt wird, den Pi neu starten und dann nur das neue Skript testen.

Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
Benutzeravatar
__blackjack__
User
Beiträge: 13905
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@DorSushi: Nein ich denke nicht das es bis jetzt so funktioniert. Du bist einfach beim testen nur noch nicht in einen ungewünschten Fall gelaufen. Und es kann sogar sein, dass Du das niemals tust, aber dann verlässt sich der Code auf nicht garantiertes Verhalten von GPIOZero, beziehungsweise dem verwendeten Backend. Sich auf undefiniertes Verhalten oder nicht garantierte Implementierungsdetails zu verlassen ist auch dann ein echter Programmfehler wenn das Programm scheinbar das tut was es soll.

Die Fehlermeldung ist nicht von Thonny sondern ganz normal von dem Programm. Die hätte man so auch ohne Thonny bekommen. Der Pin ist von einem anderen Programm belegt. Das muss erst beendet werden.
“I am Dyslexic of Borg, Your Ass will be Laminated” — unknown
Benutzeravatar
DorSushi
User
Beiträge: 7
Registriert: Dienstag 8. April 2025, 22:04

Hallihallo, zuerst war es mein Fehler das es nicht funktioniert hat. Ich hatte es vergessen zu deaktivieren im Crontab. Nach Deaktivierung im Crontab bleibt der Monitor leider an und somit auch das HDMI Signal aktiviert. Ich werde mal das Skript über das Terminal starten und ein Feedback geben ob es Fehlermeldungen gibt.

Ergebnis:
Funktioniert leider nicht. Das Skript läuft und das Terminal liefert auch was aber das HDMI bleibt aktiv.

Code: Alles auswählen

python motion.py
HDMI-A-1 "DO NOT USE - RTK 32V3H-H6A 0x00000001 (HDMI-A-1)"
  Physical size: 700x390 mm
  Enabled: yes
  Modes:
    720x400 px, 70.082001 Hz
    640x480 px, 59.939999 Hz
    640x480 px, 60.000000 Hz
    640x480 px, 72.808998 Hz
    640x480 px, 75.000000 Hz
    720x480 px, 59.939999 Hz
    720x480 px, 59.939999 Hz
    720x480 px, 59.939999 Hz
    720x480 px, 60.000000 Hz
    720x480 px, 60.000000 Hz
    720x576 px, 50.000000 Hz
    720x576 px, 50.000000 Hz
    720x576 px, 50.000000 Hz
    800x600 px, 56.250000 Hz
    800x600 px, 60.317001 Hz
    800x600 px, 72.188004 Hz
    800x600 px, 75.000000 Hz
    1024x768 px, 60.004002 Hz
    1024x768 px, 70.069000 Hz
    1024x768 px, 75.028999 Hz
    1280x720 px, 50.000000 Hz
    1280x720 px, 50.000000 Hz
    1280x720 px, 59.939999 Hz
    1280x720 px, 60.000000 Hz
    1440x900 px, 59.901001 Hz (current)
    1440x900 px, 74.984001 Hz
    1440x900 px, 84.842003 Hz
    1280x1024 px, 75.025002 Hz
    1920x1080 px, 50.000000 Hz
    1920x1080 px, 50.000000 Hz
    1920x1080 px, 59.939999 Hz
    1920x1080 px, 60.000000 Hz
    1280x720 px, 60.000000 Hz (preferred)
  Position: 0,0
  Transform: normal
  Scale: 1.000000
HDMI-A-1 "DO NOT USE - RTK 32V3H-H6A 0x00000001 (HDMI-A-1)"
  Physical size: 700x390 mm
  Enabled: yes
  Modes:
    720x400 px, 70.082001 Hz
    640x480 px, 59.939999 Hz
    640x480 px, 60.000000 Hz
    640x480 px, 72.808998 Hz
    640x480 px, 75.000000 Hz
    720x480 px, 59.939999 Hz
    720x480 px, 59.939999 Hz
    720x480 px, 59.939999 Hz
    720x480 px, 60.000000 Hz
    720x480 px, 60.000000 Hz
    720x576 px, 50.000000 Hz
    720x576 px, 50.000000 Hz
    720x576 px, 50.000000 Hz
    800x600 px, 56.250000 Hz
    800x600 px, 60.317001 Hz
    800x600 px, 72.188004 Hz
    800x600 px, 75.000000 Hz
    1024x768 px, 60.004002 Hz
    1024x768 px, 70.069000 Hz
    1024x768 px, 75.028999 Hz
    1280x720 px, 50.000000 Hz
    1280x720 px, 50.000000 Hz
    1280x720 px, 59.939999 Hz
    1280x720 px, 60.000000 Hz
    1440x900 px, 59.901001 Hz (current)
    1440x900 px, 74.984001 Hz
    1440x900 px, 84.842003 Hz
    1280x1024 px, 75.025002 Hz
    1920x1080 px, 50.000000 Hz
    1920x1080 px, 50.000000 Hz
    1920x1080 px, 59.939999 Hz
    1920x1080 px, 60.000000 Hz
    1280x720 px, 60.000000 Hz (preferred)
  Position: 0,0
  Transform: normal
  Scale: 1.000000
HDMI-A-1 "DO NOT USE - RTK 32V3H-H6A 0x00000001 (HDMI-A-1)"
  Physical size: 700x390 mm
  Enabled: yes
  Modes:
    720x400 px, 70.082001 Hz
    640x480 px, 59.939999 Hz
    640x480 px, 60.000000 Hz
    640x480 px, 72.808998 Hz
    640x480 px, 75.000000 Hz
    720x480 px, 59.939999 Hz
    720x480 px, 59.939999 Hz
    720x480 px, 59.939999 Hz
    720x480 px, 60.000000 Hz
    720x480 px, 60.000000 Hz
    720x576 px, 50.000000 Hz
    720x576 px, 50.000000 Hz
    720x576 px, 50.000000 Hz
    800x600 px, 56.250000 Hz
    800x600 px, 60.317001 Hz
    800x600 px, 72.188004 Hz
    800x600 px, 75.000000 Hz
    1024x768 px, 60.004002 Hz
    1024x768 px, 70.069000 Hz
    1024x768 px, 75.028999 Hz
    1280x720 px, 50.000000 Hz
    1280x720 px, 50.000000 Hz
    1280x720 px, 59.939999 Hz
    1280x720 px, 60.000000 Hz
    1440x900 px, 59.901001 Hz (current)
    1440x900 px, 74.984001 Hz
    1440x900 px, 84.842003 Hz
    1280x1024 px, 75.025002 Hz
    1920x1080 px, 50.000000 Hz
    1920x1080 px, 50.000000 Hz
    1920x1080 px, 59.939999 Hz
    1920x1080 px, 60.000000 Hz
    1280x720 px, 60.000000 Hz (preferred)
  Position: 0,0
  Transform: normal
  Scale: 1.000000
^CTraceback (most recent call last):
  File "/home/pi/motion.py", line 38, in <module>
    main()
  File "/home/pi/motion.py", line 25, in main
    pir.wait_for_motion(timeout=TIMEOUT)
  File "/usr/lib/python3/dist-packages/gpiozero/mixins.py", line 278, in wait_for_active
    return self._active_event.wait(timeout)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/threading.py", line 622, in wait
    signaled = self._cond.wait(timeout)
               ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/threading.py", line 324, in wait
    gotit = waiter.acquire(True, timeout)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
KeyboardInterrupt
Es wurde 3 mal Bewegung erkannt
Antworten