4.11 Dies und Das
Sourcecode zu Abstands- und Bewegungssensoren sowie die Verwendung einen PWM-Buzzers.
PIR-Sensor - Bewegungsmelder
1. PIR-Sensor schaltet LED, geht aber zwischendurch aus
Die Anregungen und der erste Sourcecode stammen von Rui Santos & Sara Santos - Random Nerd Tutorials: https://randomnerdtutorials.com/raspberry-pi-pico-motion-pir-micropython/
| # Sourcecode Rui Santos & Sara Santos - Random Nerd Tutorials
# Complete project details at https://RandomNerdTutorials.com/raspberry-pi-pico-motion-pir-micropython/
# CamelCase, Vereinfachungen und ziemlich komplette Überarbeitung Jörg Thomaschewski, 21.11.2025
from machine import Pin
from time import sleep
# PIR-Sensor-Pin GPIO 16 = Hardware-Pin 21 (dort wo wir früher die externe LED immer angeschlossen haben)
pirPin = Pin(16, Pin.IN)
ledPin = Pin("LED", Pin.OUT)
motionDetected = False
motionStoppedPrinted = False
# Interrupt-Handler für PIR-Sensor
def pirInterrupt(pin):
global motionDetected
if pin.value() == 1: # Bewegung erkannt (rising edge)
motionDetected = True
ledPin.value(1)
else: # Bewegung gestoppt (falling edge)
motionDetected = False
ledPin.value(0)
# Interrupts aktivieren für steigende & fallende Flanken
pirPin.irq(trigger=(Pin.IRQ_RISING | Pin.IRQ_FALLING), handler=pirInterrupt)
# Hauptprogramm
while True:
if motionDetected and not motionStoppedPrinted:
print("Motion detected!")
motionStoppedPrinted = True
elif not motionDetected and motionStoppedPrinted:
print("Motion stopped")
motionStoppedPrinted = False
sleep(0.1)
|
Es zeigt sich aber, dass der PIR-Sensor auch bei gleichbleibender Bewegung einige "LOW"-Lücken hat. Auch ansonsten ist der Sourcecode nicht optimal und wir verbessern ihn hier.
2. PIR-Rohsignal auslesen
| # PIR-Rohsignal auslesen
# Jörg Thomaschewski, 21.11.2025
from machine import Pin
from time import sleep
# PIR-Sensor-Pin GPIO 16 = Hardware-Pin 21 (dort wo wir früher die externe LED immer angeschlossen haben)
pirPin = Pin(16, Pin.IN)
while True:
value = pirPin.value()
print(value)
sleep(0.1) # 0.1s Auflösung
|
Aufgrund der Anzahl der "0"-Werte während der Bewegung kann eine "Nachlauf"-Zeit abgeschätzt werden, sodass die bei einer kontinuierlichen Bewegung die LED immer an bleibt.
Dies kann man aber nicht einfach mit sleep() lösten, da man dann das nächste Signal verpassen würde.
3. PIR-Sensor schaltet LED, einfache Version und mit "Nachlaufzeit"
| # PIR-Rohsignal auslesen und LED schalten (einfache Version)
# Jörg Thomaschewski, 21.11.2025
from machine import Pin
from time import ticks_ms, sleep
# PIR-Sensor-Pin GPIO 16 = Hardware-Pin 21 (dort wo wir früher die externe LED immer angeschlossen haben)
pirPin = Pin(16, Pin.IN)
# LED (z. B. Onboard-LED)
ledPin = Pin("LED", Pin.OUT)
# Dauer, wie lange die LED nach dem letzten "Bewegung erkannt" eingeschaltet bleibt
# 2500 ms (= 2.5 Sekunden) kompensieren die LOW-Pausen des Sensors
holdTime = 2500
# Zeitpunkt, zu dem zuletzt Bewegung erkannt wurde
lastMotion = 0
while True:
# Aktuellen Wert des Sensors lesen:
# 1 = Bewegung erkannt
# 0 = keine Bewegung
value = pirPin.value()
# Wenn der Sensor "1" meldet, speichern wir die aktuelle Zeit.
# ticks_ms() gibt die Zeit seit Systemstart in Millisekunden zurück.
if value == 1:
lastMotion = ticks_ms()
# Jetzt prüfen wir, wie viel Zeit seit der letzten Bewegung vergangen ist.
#
# Wenn die Zeit kleiner als 'holdTime' ist, gilt Bewegung als "aktiv",
# auch wenn der Sensor zwischendurch kurze 0-Signale liefert.
#
# Dadurch verhindern wir das Flackern der LED.
if ticks_ms() - lastMotion < holdTime:
ledPin.value(1) # LED AN
else:
ledPin.value(0) # LED AUS
# Kurze Pause, um die CPU zu entlasten
sleep(0.05)
|
Diese Version ist viel einfacher als die zuerst gezeigte Version. Und der irq(trigger...) in der ersten Version hilft uns auch nur wenig weiter, da wir dort ebenfalls eine while True als Endlos-Schleife hatten.
4. PIR-Sensor schaltet LED, ohne while True
Hier eine Version ohne while True.
| # PIR auslesen und LED schalten (IRQ und periodischer Timer)
# Jörg Thomaschewski mit Hilfe von ChataGPT, 21.11.2025
from machine import Pin, Timer
from time import ticks_ms, ticks_diff
ledPin = Pin("LED", Pin.OUT)
# PIR-Sensor-Pin GPIO 16 = Hardware-Pin 21 (dort wo wir früher die externe LED immer angeschlossen haben)
pirPin = Pin(16, Pin.IN)
# Wie lange soll die LED nach der letzten Bewegung an bleiben? (in ms)
holdTimeMs = 3000
# Zeitpunkt der letzten erkannten Bewegung
lastMotionTime = 0
# Merken, ob wir gerade im "Bewegung aktiv"-Zustand sind
motionActive = False
def pirInterrupt(pin):
global lastMotionTime, motionActive
if pin.value() == 1:
now = ticks_ms()
lastMotionTime = now
# Wenn vorher keine Bewegung aktiv war -> LED einschalten
if not motionActive:
motionActive = True
ledPin.value(1)
def checkTimeout(timer):
global motionActive, lastMotionTime
if motionActive:
now = ticks_ms()
# ticks_diff ist sicherer als einfache Subtraktion (Überlauf)
if ticks_diff(now, lastMotionTime) > holdTimeMs:
motionActive = False
ledPin.value(0)
# PIR-Interrupt: nur auf steigende Flanke reagieren
pirPin.irq(trigger=Pin.IRQ_RISING, handler=pirInterrupt)
# Timer, der alle 100 ms prüft, ob die Bewegung schon "zu lange" her ist
timeoutTimer = Timer()
timeoutTimer.init(mode=Timer.PERIODIC, period=100, callback=checkTimeout)
# Kein while True nötig.
# LED wird ausschließlich durch:
# - pirInterrupt (Bewegung erkannt)
# - checkTimeout (Bewegung lange vorbei)
# gesteuert.
|
Um den Unterschied zu verstehen hier nochmals LED-Beispiele aus Kap. "3.1 LED blinken"
while True versus Timer-Steuerung
| # Eine LED blinken lassen
# Einfache Version für Anfänger
# J. Thomaschewski, 12.08.2024
from machine import Pin
import time
led = Pin('LED', Pin.OUT)
while True:
led.value(1) # LED einschalten
time.sleep(0.5) # 0,5 Sekunden warten
led.value(0) # LED ausschalten
time.sleep(0.5) # 0,5 Sekunden warten
print('Hier komme ich nie aus der Schleife raus')
|
Besser: Der Timer ruft die Funktion in einem festen Zeitabstand auf.
| # Eine LED blinken lassen
# J. Thomaschewski, 12.08.2024
from machine import Pin, Timer
ledGreen = Pin('LED', Pin.OUT)
def blinkGreen(timer):
ledGreen.toggle()
Timer().init(freq=2, callback=blinkGreen)
print('Hier gibt es keine Endlosschleife')
|
Trigger und Timer
Wir haben also die Möglichkeit etwas per Timer zu steuern Timer().init(freq=2, callback=blinkGreen).
Oder per Trigger (= Auslöser) zu steuern pirPin.irq(trigger=Pin.IRQ_RISING, handler=pirInterrupt).
Abstandssensor HC-SR04 Ultrasonic Sensor und Buzzer
1. Abstandssensor HC-SR04 mit Ausgabe auf der Konsole
Download hcsr.py von https://github.com/rsc1975/micropython-hcsr04
| # Rui Santos & Sara Santos - Random Nerd Tutorials
# Complete project details at https://RandomNerdTutorials.com/raspberry-pi-pico-hc-sr04-micropython/
# CamelCase, print-Anweisung, try/except, cm-Distance geändert Jörg Thomaschewski; 22.11.2026
from machine import Pin
import time
from hcsr04 import HCSR04
# GPIO 16 = Hardware-Pin 21 an echo
# GPIO 17 = Hardware-Pin 22 an trigger
# Wenn immer Distance -1mm augegeben wird, sind vermutlich die Pins vertauscht
sensor = HCSR04(trigger_pin=17, echo_pin=16, echo_timeout_us=30000)
while True:
distanceCm = sensor.distance_cm()
print(f"Distance: {distanceCm:.2f} cm")
time.sleep(1)
|
2. Abstandssensor HC-SR04 mit LED
Interne LED soll langsamer und schneller blinken, je nach Abstand.
| # Abstandssensor HCSR04
# Interne LED soll langsamer und schneller blinken
# Jörg Thomaschewski; 22.11.2026
from machine import Pin
import time
from hcsr04 import HCSR04
sensor = HCSR04(trigger_pin=17, echo_pin=16, echo_timeout_us=30000)
# GPIO 16 = Hardware-Pin 21 an echo
# GPIO 17 = Hardware-Pin 22 an trigger
# Wenn immer Distance -1mm augegeben wird, sind vermutlich die Pins vertauscht
led = Pin('LED', Pin.OUT)
while True:
distanceCm = sensor.distance_cm()
print(f"Distance: {distanceCm:.2f} cm")
if distanceCm < 20:
blinkDelay = 0.05 # sehr schnell
elif distanceCm < 100:
blinkDelay = 0.5 # langsam
else:
led.value(0)
time.sleep(1)
continue
led.value(1)
time.sleep(blinkDelay)
led.value(0)
time.sleep(blinkDelay)
|
3. Buzzer ausprobieren (arbeitet mit PWM)
| # PWM-Buzzer ausprobieren
# Jörg Thomaschewski; 22.11.2026
from machine import Pin, PWM
import time
buzzer = PWM(Pin(15))
# GPIO 15 = Hardware-Pin 20 an buzzer
# Anderen Buzzer-Pin an Masse/Minus
buzzer.freq(2000) # 2 kHz Tonfrequenz
while True:
buzzer.duty_u16(30000) # Ton an
time.sleep(0.2)
buzzer.duty_u16(0) # Ton aus
time.sleep(0.2)
|
4. Abstandssensor HC-SR04 mit LED und Buzzer
| # Abstandssensor HCSR04
# Interne LED soll langsamer und schneller blinken
# Jörg Thomaschewski; 22.11.2026
from machine import Pin, PWM
import time
from hcsr04 import HCSR04
sensor = HCSR04(trigger_pin=17, echo_pin=16, echo_timeout_us=30000)
led = Pin('LED', Pin.OUT)
buzzer = PWM(Pin(15))
# GPIO 15 = Hardware-Pin 20 an buzzer
# Anderen Buzzer-Pin an Masse/Minus
# GPIO 16 = Hardware-Pin 21 an echo
# GPIO 17 = Hardware-Pin 22 an trigger
while True:
distanceCm = sensor.distance_cm()
print(f"Distance: {distanceCm:.2f} cm")
if distanceCm < 20:
# LED sehr schnell blinken, Buzzer dauerhaft
led.value(1)
buzzer.freq(2000)
buzzer.duty_u16(30000)
time.sleep(0.05)
led.value(0)
time.sleep(0.05)
elif distanceCm < 100:
# LED langsam blinken, Buzzer im gleichen Rhythmus
blinkDelay = 0.5
led.value(1)
buzzer.freq(2000)
buzzer.duty_u16(30000)
time.sleep(blinkDelay)
led.value(0)
buzzer.duty_u16(0)
time.sleep(blinkDelay)
else:
# Alles aus
led.value(0)
buzzer.duty_u16(0)
time.sleep(1)
|
Sensor RCWL-0516 Microwellen Radar Näherungssensor
| # Sensor RCWL-0516 Microwellen Radar Näherungssensor
# Complete project details at https://RandomNerdTutorials.com/raspberry-pi-pico-rcwl-0516-micropython/
# CamelCase und diverse Änderungen Jörg Thomaschewski, 22.11.2025
from machine import Pin
import time
led = Pin('LED', Pin.OUT)
sensor = Pin(16, Pin.IN) # Hardware-Pin 21 = GPIO16 an "Out"
state = 0
while True:
if sensor.value() == 1:
led.on()
if state == 0:
print("Motion detected!")
state = 1
else:
led.off()
if state == 1:
print("Motion stopped!")
state = 0
time.sleep(0.1)
|