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)