#170Anfänger

Raspberry Pi Pico Einparkhilfe (HC-SR04 + 3 LEDs + Summer)

Die Einparkhilfe aus dem Auto für deinen Schreibtisch! Der **Raspberry Pi Pico** misst mit einem **HC-SR04-Ultraschallsensor** etwa 16-mal pro Sekunde den Abstand zum Hindernis. Je näher es kommt, desto mehr **LEDs in Grün, Gelb und Rot** leuchten und desto schneller piept der **Summer**; unter 10 cm wird daraus ein Dauerton und die rote LED blinkt. Ultraschallmessung, Töne per PWM und nicht blockierendes Timing in einem Projekt.

0.0(0)
1 abgeschlossen
Raspberry Pi Pico Einparkhilfe (HC-SR04 + 3 LEDs + Summer)
Die Einparkhilfe aus dem Auto, als Version für den Schreibtisch. Der HC-SR04 sendet einen Ton, der für deine Ohren zu hoch ist, und misst über das Echo, wie weit ein Hindernis entfernt ist; kommt etwas näher als einen Meter, leuchtet die grüne LED und der Summer piept langsam. Je näher es kommt, desto mehr leuchten auch Gelb und Rot und desto schneller und höher wird das Piepen; unter 10 Zentimetern hört der Ton nicht mehr auf und das rote Licht blinkt.

Video

Schaltplan

Raspberry Pi Pico Einparkhilfe (HC-SR04 + 3 LEDs + Summer) - Circuit

Quellcode

MicroPython
1# ─────────────────────────────────────────
2#   BlueGrays · bluegrays.com
3#   Raspberry Pi Pico Einparkhilfe (HC-SR04 + 3 LEDs + Summer)
4# ─────────────────────────────────────────
5# Parksensor fürs Auto. Der HC-SR04 misst den Abstand zu einem Hindernis;
6# kommt es näher, leuchten nacheinander die grüne, gelbe und rote LED auf
7# und die Pieptöne werden schneller. Ganz nah wird der Ton dauerhaft und
8# die rote LED blinkt.
9#
10# Pins:
11#   GP27 -> HC-SR04 TRIG
12#   GP26 -> HC-SR04 ECHO (1k + 2k Teiler bei echter Hardware)
13#   VBUS -> HC-SR04 VCC (5V), GND.6 -> HC-SR04 GND
14#   GP4  -> 220 Ohm -> rote LED (Kathode an GND)
15#   GP8  -> 220 Ohm -> gelbe LED (Kathode an GND)
16#   GP12 -> 220 Ohm -> grüne LED (Kathode an GND)
17#   GP17 -> Buzzer (+), anderes Beinchen an GND
18
19from machine import Pin, PWM, time_pulse_us
20import time
21
22# ============ EINSTELLUNGEN ============
23GREEN_CM = 100         # Grün an, Piepen beginnt
24YELLOW_CM = 50         # Gelb kommt dazu
25RED_CM = 25            # Rot kommt dazu
26STOP_CM = 10           # Dauerton + blinkendes Rot
27
28BEEP_MS = 60           # Länge eines Pieps
29SLOW_GAP_MS = 700      # Pause zwischen Pieptönen bei GREEN_CM
30FAST_GAP_MS = 50       # Pause zwischen Pieptönen nahe STOP_CM
31VOLUME = 32768         # PWM-Tastverhältnis, 32768 = 50%
32FLASH_MS = 120         # Blinkperiode des roten Lichts in der STOP-Zone
33
34MEASURE_MS = 60        # Messintervall, mindestens 60 ms
35PRINT_MS = 250         # Serial-Ausgabeintervall
36ECHO_TIMEOUT_US = 12000  # jenseits von ~2 m = kein Hindernis
37SOUND_CM_PER_US = 0.0343  # Schallgeschwindigkeit (20 C)
38LOOP_MS = 5            # Schritt der Hauptschleife
39
40# Zonen von nah nach fern: (Name, Obergrenze cm, (grün, gelb, rot), Ton Hz)
41ZONES = (
42    ("DUR / STOP", STOP_CM, (1, 1, 1), 1900),
43    ("KIRMIZI / RED", RED_CM, (1, 1, 1), 1900),
44    ("SARI / YELLOW", YELLOW_CM, (1, 1, 0), 1500),
45    ("YESIL / GREEN", GREEN_CM, (1, 0, 0), 1200),
46)
47CLEAR = len(ZONES)     # Zone ohne Hindernis
48STOP = 0               # Index der STOP-Zone
49
50# ============ HARDWARE ============
51trig = Pin(27, Pin.OUT, value=0)
52echo = Pin(26, Pin.IN)
53led_green = Pin(12, Pin.OUT, value=0)
54led_yellow = Pin(8, Pin.OUT, value=0)
55led_red = Pin(4, Pin.OUT, value=0)
56buzzer = PWM(Pin(17))
57buzzer.duty_u16(0)
58
59
60# ============ MESSUNG ============
61def measure_cm():
62    # Einen 10-us-TRIG-Impuls senden, messen, wie lange ECHO auf HIGH bleibt
63    trig.value(0)
64    time.sleep_us(2)
65    trig.value(1)
66    time.sleep_us(10)
67    trig.value(0)
68    pulse = time_pulse_us(echo, 1, ECHO_TIMEOUT_US)
69    if pulse < 0:
70        return None    # Kein Echo oder zu weit
71    # Der Schall läuft hin und zurück: halbieren
72    return pulse * SOUND_CM_PER_US / 2
73
74
75def median3(values):
76    # Median der letzten 3 Messwerte: Ein schlechter Messwert lässt die LEDs nicht flackern
77    a, b, c = values
78    return max(min(a, b), min(max(a, b), c))
79
80
81def zone_of(dist):
82    if dist is None:
83        return CLEAR
84    for i, zone in enumerate(ZONES):
85        if dist <= zone[1]:
86            return i
87    return CLEAR
88
89
90def beep_gap_ms(dist):
91    # Zwischen STOP_CM und GREEN_CM wächst die Piep-Pause linear von FAST bis SLOW
92    ratio = (dist - STOP_CM) / (GREEN_CM - STOP_CM)
93    ratio = min(1.0, max(0.0, ratio))
94    return int(FAST_GAP_MS + ratio * (SLOW_GAP_MS - FAST_GAP_MS))
95
96
97# ============ SOUND ============
98tone_on = False
99tone_hz = 0
100
101
102def tone(hz):
103    # PWM in Ruhe lassen, wenn der Ton schon an ist
104    global tone_on, tone_hz
105    if tone_on and tone_hz == hz:
106        return
107    buzzer.freq(hz)
108    buzzer.duty_u16(VOLUME)
109    tone_on = True
110    tone_hz = hz
111
112
113def silence():
114    global tone_on
115    if tone_on:
116        buzzer.duty_u16(0)
117        tone_on = False
118
119
120def set_leds(green, yellow, red):
121    led_green.value(green)
122    led_yellow.value(yellow)
123    led_red.value(red)
124
125
126def self_test():
127    # Kurzer Einschalttest von LEDs und Buzzer: Grün -> Gelb -> Rot
128    for leds, hz in (((1, 0, 0), 1200), ((1, 1, 0), 1500), ((1, 1, 1), 1900)):
129        set_leds(*leds)
130        tone(hz)
131        time.sleep_ms(90)
132        silence()
133        time.sleep_ms(160)
134    set_leds(0, 0, 0)
135
136
137# ============ HAUPTSCHLEIFE ============
138print("== BlueGrays · bluegrays.com ==")
139print("Pico Park Sensoru / Parking Sensor")
140print("Yesil <= %d cm, sari <= %d cm, kirmizi <= %d cm, surekli ses <= %d cm"
141      % (GREEN_CM, YELLOW_CM, RED_CM, STOP_CM))
142print("Green <= %d cm, yellow <= %d cm, red <= %d cm, continuous tone <= %d cm"
143      % (GREEN_CM, YELLOW_CM, RED_CM, STOP_CM))
144self_test()
145
146FAR = 999.0                       # Platzhalter für kein Hindernis
147history = [FAR, FAR, FAR]         # Letzte 3 Messwerte
148distance = None                   # Gefilterter Abstand (cm)
149zone = CLEAR
150last_zone = -1
151now = time.ticks_ms()
152next_measure = now
153next_print = now
154last_beep = time.ticks_add(now, -10000)   # Der erste Piep ertönt sofort
155beep_end = now
156
157while True:
158    now = time.ticks_ms()
159
160    # 1) Messung: alle MEASURE_MS, mit Medianfilter
161    if time.ticks_diff(now, next_measure) >= 0:
162        next_measure = time.ticks_add(now, MEASURE_MS)
163        reading = measure_cm()
164        history = history[1:] + [reading if reading is not None else FAR]
165        filtered = median3(history)
166        distance = None if filtered >= FAR else filtered
167        zone = zone_of(distance)
168        if zone != last_zone:
169            name = "ENGEL YOK / CLEAR" if zone == CLEAR else ZONES[zone][0]
170            print("Bolge / Zone ->", name)
171            last_zone = zone
172
173    # 2) LEDs: Balkenanzeige, Rot blinkt in der STOP-Zone
174    if zone == CLEAR:
175        set_leds(0, 0, 0)
176    elif zone == STOP:
177        flash_on = (now // FLASH_MS) % 2 == 0
178        set_leds(1, 1, 1 if flash_on else 0)
179    else:
180        set_leds(*ZONES[zone][2])
181
182    # 3) Sound: nicht blockierender Beep-Timer
183    if zone == CLEAR:
184        silence()
185    elif zone == STOP:
186        tone(ZONES[STOP][3])          # Sehr nah: Dauerton
187    else:
188        if tone_on and time.ticks_diff(now, beep_end) >= 0:
189            silence()
190        # Die Pause wird in jedem Durchlauf neu berechnet: Der nächste Piep wird schneller, sobald
191        # du näher kommst
192        period = BEEP_MS + beep_gap_ms(distance)
193        if not tone_on and time.ticks_diff(now, last_beep) >= period:
194            tone(ZONES[zone][3])
195            last_beep = now
196            beep_end = time.ticks_add(now, BEEP_MS)
197
198    # 4) Serial Monitor: Abstand in cm
199    if time.ticks_diff(now, next_print) >= 0:
200        next_print = time.ticks_add(now, PRINT_MS)
201        if distance is None:
202            print("Mesafe / Distance: --- (engel yok / no obstacle)")
203        else:
204            print("Mesafe / Distance: %5.1f cm" % distance)
205
206    time.sleep_ms(LOOP_MS)
207

FAQ

Warum braucht ECHO in der echten Schaltung einen Spannungsteiler?▾

Der HC-SR04 läuft mit 5V und gibt an ECHO 5V aus, die Pins des Pico vertragen aber höchstens 3,3V. Verbinde ECHO über 1 kΩ mit GP26 und GP26 über 2 kΩ mit GND, dann liegen am Pin etwa 3,3V an. In Wokwi ist kein Teiler nötig.

Wie ändere ich die Warnabstände?▾

Ändere die Konstanten `GREEN_CM`, `YELLOW_CM`, `RED_CM` und `STOP_CM` am Anfang des Codes. Behalte dabei die Reihenfolge `STOP_CM < RED_CM < YELLOW_CM < GREEN_CM` bei; zum Beispiel mit `STOP_CM = 30`, `RED_CM = 50`, `YELLOW_CM = 100` und `GREEN_CM = 150`. LEDs und Pieptöne richten sich automatisch nach den neuen Schwellen.

Warum wird das Piepen stufenlos schneller und nicht zonenweise?▾

`beep_gap_ms()` berechnet die Pause linear aus der Entfernung: 700 ms bei 100 cm, 50 ms bei 10 cm. Sie wird bei jedem Durchlauf der Hauptschleife neu berechnet, daher kommt der nächste Piepton sofort früher, sobald sich das Hindernis nähert. Die Zonen ändern nur LEDs und Tonhöhe.

Muss ich eine Bibliothek installieren?▾

Nein. Die Funktion `time_pulse_us()` für die Messung gehört zum eingebauten Modul `machine`. Spiele MicroPython auf den Pico und speichere den Code mit Thonny als `main.py` darauf; der Sensor startet dann bei jedem Einschalten mit LED-Test und drei Pieptönen.