Raspberry Pi Pico Park Sensörü (HC-SR04 + 3 LED + Buzzer)
Arabalardaki geri park sensörünü masana getir! **Raspberry Pi Pico**, **HC-SR04 ultrasonik sensörle** önündeki engele olan mesafeyi saniyede yaklaşık 16 kez ölçer. Engel yaklaştıkça **yeşil, sarı ve kırmızı LED** sırayla yanar, **buzzer**'ın bip sesi hızlanır; 10 cm'nin altında ses kesintisiz öter ve kırmızı LED yanıp söner. Ultrasonik ölçüm, PWM ile ses ve bloklamayan zamanlama tek projede.

Video
Devre Şeması

Kaynak Kodu
1# ─────────────────────────────────────────
2# BlueGrays · bluegrays.com
3# Raspberry Pi Pico Park Sensörü (HC-SR04 + 3 LED + Buzzer)
4# ─────────────────────────────────────────
5# Araç park sensörü. HC-SR04 engele olan mesafeyi ölçer; engel yaklaştıkça
6# yeşil, sarı ve kırmızı LED sırayla yanar, buzzer bip sesi hızlanır. Çok
7# yakında ses sürekli olur ve kırmızı LED yanıp söner. Mesafe seri
8# monitörde cm.
9#
10# Pinler:
11# GP27 -> HC-SR04 TRIG
12# GP26 -> HC-SR04 ECHO (gerçek devrede 1k + 2k bölücü)
13# VBUS -> HC-SR04 VCC (5V), GND.6 -> HC-SR04 GND
14# GP4 -> 220 ohm -> Kırmızı LED (katot GND)
15# GP8 -> 220 ohm -> Sarı LED (katot GND)
16# GP12 -> 220 ohm -> Yeşil LED (katot GND)
17# GP17 -> Buzzer (+), diğer ucu GND
18
19from machine import Pin, PWM, time_pulse_us
20import time
21
22# ============ AYARLAR ============
23GREEN_CM = 100 # Bu mesafede yeşil yanar, bip başlar
24YELLOW_CM = 50 # Sarı da yanar
25RED_CM = 25 # Kırmızı da yanar
26STOP_CM = 10 # Sürekli ses + yanıp sönen kırmızı
27
28BEEP_MS = 60 # Tek bip süresi
29SLOW_GAP_MS = 700 # GREEN_CM'de iki bip arası
30FAST_GAP_MS = 50 # STOP_CM'ye yakın bip arası
31VOLUME = 32768 # PWM doluluk (0-65535), 32768 = %50
32FLASH_MS = 120 # DUR bölgesinde kırmızı yanıp sönme
33
34MEASURE_MS = 60 # Ölçüm aralığı; HC-SR04 için en az 60 ms
35PRINT_MS = 250 # Seri monitöre yazma aralığı
36ECHO_TIMEOUT_US = 12000 # ~2 m'den uzak = engel yok
37SOUND_CM_PER_US = 0.0343 # Ses hızı (20 C)
38LOOP_MS = 5 # Ana döngü adımı
39
40# Bölgeler yakından uzağa: (ad, üst sınır cm, (yeşil, sarı, kırmızı), 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) # Engel yok bölgesi
48STOP = 0 # DUR bölgesinin sırası
49
50# ============ DONANIM ============
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# ============ ÖLÇÜM ============
61def measure_cm():
62 # 10 us TRIG darbesi gönder, ECHO'nun HIGH kaldığı süreyi ölç
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 # Yansıma yok ya da çok uzak
71 # Ses gidip dönüyor, bu yüzden yolun yarısı
72 return pulse * SOUND_CM_PER_US / 2
73
74
75def median3(values):
76 # Son 3 ölçümün ortancası: tek hatalı okuma LED'leri titretmez
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 # Mesafe STOP_CM -> GREEN_CM arasında bip aralığı FAST -> SLOW doğrusal büyür
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# ============ SES ============
98tone_on = False
99tone_hz = 0
100
101
102def tone(hz):
103 # Aynı ton zaten çalıyorsa PWM'e dokunma
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 # Açılışta LED'ler ve buzzer kısa test: yeşil -> sarı -> kırmızı
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# ============ ANA DÖNGÜ ============
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 # Engel yok için yer tutucu
147history = [FAR, FAR, FAR] # Son 3 ölçüm
148distance = None # Süzülmüş mesafe (cm)
149zone = CLEAR
150last_zone = -1
151now = time.ticks_ms()
152next_measure = now
153next_print = now
154last_beep = time.ticks_add(now, -10000) # İlk bip hemen çalsın
155beep_end = now
156
157while True:
158 now = time.ticks_ms()
159
160 # 1) Ölçüm: her MEASURE_MS'de bir, ortanca süzgeçle
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) LED'ler: çubuk gösterge, DUR bölgesinde kırmızı yanıp söner
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) Ses: bloklamayan bip zamanlayıcısı
183 if zone == CLEAR:
184 silence()
185 elif zone == STOP:
186 tone(ZONES[STOP][3]) # Çok yakın: sürekli ses
187 else:
188 if tone_on and time.ticks_diff(now, beep_end) >= 0:
189 silence()
190 # Aralık her turda yeniden hesaplanır: engel yaklaşınca sonraki bip hemen hızlanır
191 period = BEEP_MS + beep_gap_ms(distance)
192 if not tone_on and time.ticks_diff(now, last_beep) >= period:
193 tone(ZONES[zone][3])
194 last_beep = now
195 beep_end = time.ticks_add(now, BEEP_MS)
196
197 # 4) Seri monitör: mesafe cm olarak
198 if time.ticks_diff(now, next_print) >= 0:
199 next_print = time.ticks_add(now, PRINT_MS)
200 if distance is None:
201 print("Mesafe / Distance: --- (engel yok / no obstacle)")
202 else:
203 print("Mesafe / Distance: %5.1f cm" % distance)
204
205 time.sleep_ms(LOOP_MS)
206Sıkça Sorulanlar
Gerçek devrede ECHO için neden gerilim bölücü gerekiyor?▾
HC-SR04 5V ile çalışır ve ECHO çıkışı 5V verir, Pico'nun pinleri ise en fazla 3,3V kabul eder. ECHO'yu 1 kΩ üzerinden GP26'ya, GP26'yı 2 kΩ ile GND'ye bağla; pine yaklaşık 3,3V ulaşır. Wokwi'de bölücü gerekmez.
Uyarı mesafelerini nasıl değiştiririm?▾
Kodun başındaki `GREEN_CM`, `YELLOW_CM`, `RED_CM` ve `STOP_CM` sabitlerini değiştir. Eşikleri `STOP_CM < RED_CM < YELLOW_CM < GREEN_CM` sırasını koruyarak ayarla; örneğin `STOP_CM = 30`, `RED_CM = 50`, `YELLOW_CM = 100` ve `GREEN_CM = 150` kullanabilirsin. LED'ler ve bip yeni eşiklere kendiliğinden uyar.
Bip neden bölge bölge değil de sürekli hızlanıyor?▾
`beep_gap_ms()` bip aralığını mesafeye göre doğrusal hesaplar: 100 cm'de 700 ms, 10 cm'de 50 ms. Aralık ana döngünün her turunda yeniden hesaplandığı için engel yaklaştığı anda bir sonraki bip öne çekilir. Bölgeler yalnızca LED'leri ve tonu değiştirir.
Ek kütüphane kurmam gerekiyor mu?▾
Hayır. Ölçüm için gereken `time_pulse_us()` fonksiyonu `machine` modülünde hazır gelir. Pico'ya MicroPython yükle, Thonny'de kodu Pico'ya `main.py` adıyla kaydet; sensör her açılışta LED testi ve üç bip ile kendiliğinden başlar.
