Privater Webserver von Manfred Höfer mit Apache2 auf Banana Pi M2 Berry
Projekte mit Raspberry Pi 3B und Zero (2)W
Datum und Zeit: Donnerstag, 03. Juli 2025, 16:19:47

Bewegungsmelder

Idee für eine Steuerung der Arbeitsplatzleuchte per Bewegungsmelder über 433 MHz

Auf dem Schreibtisch, mit Laptop und Raspberry Pi, steht eine Arbeitsplatzleuchte, die je nach Tageszeit und Helligkeit zum Einsatz kommt. Häufig ist es der Fall, dass ich den Platz verlasse und nach unbestimmter Zeit wieder zurückkehre. Mache ich solange die Lampe aus oder nicht?
Dabei ist die Idee entstanden, die Arbeitsplatzleuchte per Bewegungsmelder und Funksteckdose zu steuern. Die Steuerung muß natürlich abhängig von der Helligkeit im Raum erfolgen. Außerdem soll sie nicht gleich ausgehen, wenn ich nur wenige Minuten weg bin.
Im Internet gibt es zu diesem Thema eine ganze Reihe von Veröffentlichungen, von denen aber keine meine Vorstellungen 1:1 erfüllt.

https://tutorials-raspberrypi.de/raspberry-pi-funksteckdosen-433-mhz-steuern/
https://www.einplatinencomputer.com/raspberry-pi-433-mhz-funksteckdose-schalten/
https://tutorials-raspberrypi.de/raspberry-pi-openhab-funksteckdosen-433-mhz-schalten/
sind einige Beispiele, deren Prinzip ich mir zum Vorbild genommen habe. In den Beiträgen sind die Steuerung der Steckdosen und deren Einstellungen gut beschrieben.
In keinem Beitrag wird aber auf die Steuerung per Pythonscript eingegangen. Nach längerem Suchen bin ich dann bei https://pastebin.com/aRipYrZ6 und https://github.com/steffenschroeder/tarnow/issues/4 gelandet. Hier wird die Klasse "RemoteSwitch" in Python beschrieben und dokumentiert. Nach einem Probeprogramm funktioniert die Klasse perfekt für meine Steuerung.

Über einen Fotowiderstand soll die Helligkeit im Raum ermittelt werden. Beim Eintreten eines gewählten Wertes und Feststellung einer Bewegung geht ein Signal an die Funktsteckdose, damit die Arbeitsplatzleuchte eingeschaltet wird.
Gleichzeitig wird ein Zähler auf 10 Minuten gestellt. Sobald wieder eine Bewegung erkannt ist, stellt sich der Zähler wieder auf 10 Minuten. Kommt aber 10 Minuten keine Bewegungsmeldung, dann wird die Arbeitsplatzleuchte ausgeschaltet. Außerdem wird ständig die Helligkeit geprüft, so dass beim Über- oder Unterschreiten des Helligkeitswertes (700 OHM) die Arbeitsplatzleuchte entsprechend aus- oder eingeschaltet wird.
Die 10 Minuten habe ich für mich als günstigsten Wert herausgefunden, denn innerhalb der 10 Minuten bewegt man sich am Schreibtisch so, dass der Bewegungsmelder den Zähler wieder hoch setzt.
Die Kontroll-LED ist direkt an dem HC-SR501 angeschlossen und funktioniert, unabhängig von der Helligkeit, sobald die Versorgungsspannung an der Schaltung angeschlossen ist. Die Einstellung des Empfindlichkeitsreglers am HC-SR501 habe ich vorher auf einem Breadboard vorgenommen. Den zweiten Reglers am HC-SR501 habe ich auf ca. 20 sek. eingestellt. Die Steckbrücke ist auf die inneren Pins gesteckt. Damit wird der Zähler im Programm frühestens nach 20 Sekunden wieder auf 10 Minuten hochgesetzt.
Das bedeutet, bei Bewegungserkennung wechselt das Data-Signal am HC-SR501 von 0 auf 1 und nach 20 Sekunden wieder auf 0. Dann ist der Weg für die nächste Bewegungserkennung frei. Im Programm realisiert die Zeile "GPIO.add_event_detect(GPIO_PIR, GPIO.RISING, callback=MOTION)" die Auswertung der Bewegungserkennung.
Damit die Funksteckdose ihr Signal erhält, sendet der Raspberry Pi Zero über das Modul HFY-FST per 433MHz eine Sequenz für das Ein- oder Ausschalten des Stromkreises.
Die Funktsteckdosen und das Netzteil vom Raspberry Pi sollten entsprechende Sicherheitkennzeichen haben, damit eine gefahrlose Verwendung möglich ist.

Die Schaltung


Schaltzeichnung

Das Programm

#!/usr/bin/python3
# -*- coding: utf-8 -*-
"""
Einschalten einer Lampe, wenn es dunkel genug ist und eine Bewegung erkannt wird;
Mit einem Fotowiderstand prüfen, ob es dunkel ist (Ohmwert ermitteln);
Zeitschleife, die durch PIR immer wieder auf max_zeit gesetzt wird;
Wenn innerhalb einer bestimmten Zeit (10 min) keine Bewegung erkannt wurde oder es hell genug ist, wird die Lampe ausgeschaltet;
"""
import RPi.GPIO as GPIO
import time
import datetime
from gpiozero import MCP3008
from elropi import RemoteSwitch

# BCM GPIO-Referenen verwenden (anstelle der Pin-Nummern) und GPIO-Eingang definieren
GPIO.setmode(GPIO.BCM)
GPIO_PIR = 4 # Bewegungsmelder an GPIO4
zeit = 600 # 10 min
ldr = MCP3008 (channel = 0)
Zaehler = 0
GPIO.setwarnings(False)

default_key = [1,0,1,0,0] # Einstellung von der Fernbedienung der Steckdosen
default_pin = 18 # GPIO 18
# Device 8 bedeutet Steckdose D auf der Fernbedienung
steckdose = RemoteSwitch(device= 8, key=default_key,	pin=default_pin)


def dunkel():
    global wert
    wert = int((ldr.raw_value / 1023) * 1000) # Helligkeitswert in OHM
    if wert > 700:  # dunkel
        return (True)
    return (False)    # hell

# Callback-Funktion wenn Bewegung erkannt wird
def MOTION(PIR_GPIO):
   global wert
   global Zaehler
   Zaehler = 0 # Zähler 10 min wieder auf 0 setzen
   if dunkel():
      steckdose.switchOn() # EIN
   else:
      steckdose.switchOff() # AUS
      
# Set pin as input beim Bewegungsmelder
GPIO.setup(GPIO_PIR,GPIO.IN)
# Schleife, bis PIR == 0 ist
while GPIO.input(GPIO_PIR) != 0:
    time.sleep(0.1)

try:
    # Ereignis definieren: steigende Flanke
    GPIO.add_event_detect(GPIO_PIR, GPIO.RISING, callback=MOTION)
    # Callback wird durch die Flanke aktiviert
    while True:
        # AUS, wenn 10 Minuten keine Bewegung war
        time.sleep(1) # 1 Sekunde 
        Zaehler +=1  # maximum 600
        if Zaehler == zeit:
            steckdose.switchOff() 
                
except RuntimeError:
  # Programm beenden
  steckdose.switchOff()
  GPIO.cleanup()

finally:
    steckdose.switchOff()
    GPIO.cleanup()

elropi.py mit der Klasse RemoteSwitch

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
"elropi.py" for switching Elro devices using Python on Raspberry Pi
by Heiko H. 2012

https://github.com/steffenschroeder/tarnow/issues/4
https://pastebin.com/aRipYrZ6

This file uses RPi.GPIO to output a bit train to a 433.92 MHz transmitter, allowing you
to control light switches from the Elro brand.

Credits:
This file is mostly a port from C++ and Wiring to Python and the RPi.GPIO library, based on 
C++ source code written by J. Lukas:
	http://www.jer00n.nl/433send.cpp
and Arduino source code written by Piepersnijder:
	http://gathering.tweakers.net/forum/view_message/34919677
Some parts have been rewritten and/or translated.

This code uses the Broadcom GPIO pin naming by default, which can be changed in the 
"GPIOMode" class variable below. 
For more on pin naming see: http://elinux.org/RPi_Low-level_peripherals

Version 1.0

TEST mit GPIO 18, Pin 12
Aufruf 
python ./elropi.py 8 1 # Steckdose D EIN
python ./elropi.py 8 0 # Steckdose D AUS

"""

import time
import RPi.GPIO as GPIO

class RemoteSwitch(object):
	repeat = 10 # Number of transmissions
	pulselength = 300 # microseconds
	GPIOMode = GPIO.BCM
	
	def __init__(self, device, key=[1,1,1,1,1], pin=18):
		''' 
		devices: A = 1, B = 2, C = 4, D = 8, E = 16  
		key: according to dipswitches on your Elro receivers
		pin: according to Broadcom pin naming
		'''		
		self.pin = pin 
		self.key = key
		self.device = device
		GPIO.setmode(self.GPIOMode)
		GPIO.setup(self.pin, GPIO.OUT)
		
	def switchOn(self):
		self._switch(GPIO.HIGH)

	def switchOff(self):
		self._switch(GPIO.LOW)

	def _switch(self, switch):
		self.bit = [142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 136, 128, 0, 0, 0]		

		for t in range(5):
			if self.key[t]:
				self.bit[t]=136	
		x=1
		for i in range(1,6):
			if self.device & x > 0:
				self.bit[4+i] = 136
			x = x<<1

		if switch == GPIO.HIGH:
			self.bit[10] = 136
			self.bit[11] = 142
				
		bangs = []
		for y in range(16):
			x = 128
			for i in range(1,9):
				b = (self.bit[y] & x > 0) and GPIO.HIGH or GPIO.LOW
				bangs.append(b)
				x = x>>1
				
		GPIO.output(self.pin, GPIO.LOW)
		for z in range(self.repeat):
			for b in bangs:
				GPIO.output(self.pin, b)
				time.sleep(self.pulselength/1000000.)
		
		
if __name__ == '__main__':
	import sys
	GPIO.setwarnings(False)
	
	if len(sys.argv) < 3:
		print ("usage:sudo python %s int_device int_state (e.g. '%s 2 1' switches device 2 on)" % (sys.argv[0], sys.argv[0]))  
		sys.exit(1)
	
	
	# Change the key[] variable below according to the dipswitches on your Elro receivers.
	# default_key = [1,0,0,0,1] 
	default_key = [1,0,1,0,0]
	# change the pin accpording to your wiring
	default_pin =18
	device = RemoteSwitch(  device= int(sys.argv[1]), 
							key=default_key, 
							pin=default_pin)

	if int(sys.argv[2]):
		device.switchOn()
	else: 
		device.switchOff()

Fernbedienung und Steckdose Im Bild ist der DIP-Schalter der Steckdose und der Fernbedienung sichtbar. Der linke Teil von 1-5 ist die Codierung des Funkkanals und die Codierung A-E gehört zum Namen der Steckdose auf der Fernbedienung.
Steckdose = Wert: A = 1, B = 2, C = 4, D = 8, E = 16