#202Başlangıç

Raspberry Pi Pico İkili Saat (6 LED + Buton)

Bu saat rakam kullanmıyor! Raspberry Pi Pico ile saati ikili (binary) sayılarla gösteren bir saat yapıyoruz. 6 LED 32-16-8-4-2-1 basamaklarıdır; yanan LED'leri toplayınca saniye, dakika ya da saat okunur. Tek bir buton alanlar arasında geçer ve saati ayarlar, her saat başında LED'lerde ışık turu döner.

0.0(0)
Raspberry Pi Pico İkili Saat (6 LED + Buton)
Saati rakamla değil, ışıklarla söyleyen bir saat: altı LED ikili sayı sistemiyle saniyeyi, dakikayı ya da saati gösterir. Soldan sağa LED'ler 32, 16, 8, 4, 2 ve 1 değerindedir; yanan LED'lerin toplamı o anki değeri verir. Tek butonla saniye, dakika ve saat arasında geçer, uzun basıp saati kurarsın; her saat başında LED'lerde bir ışık turu döner.

Video

Devre Şeması

Raspberry Pi Pico İkili Saat (6 LED + Buton) - Circuit

Kaynak Kodu

MicroPython
1# ─────────────────────────────────────────
2#   BlueGrays · bluegrays.com
3#   Raspberry Pi Pico İkili Saat (6 LED + Buton)
4# ─────────────────────────────────────────
5# Saati ikili (binary) sayılarla gösteren saat. 6 LED 32-16-8-4-2-1
6# basamaklarıdır; yanan LED'lerin toplamı değeri verir. Butona kısa basış
7# saniye, dakika ve saat arasında geçer; uzun basış seçili alanı ayarlar.
8# Her tam saatte LED'lerde bir ışık turu döner, karttaki LED saniyeyi
9# atar.
10#
11# Pinler:
12#   GP2  -> LED 1 (bit 0), 220 ohm dirençle
13#   GP3  -> LED 2 (bit 1), 220 ohm dirençle
14#   GP4  -> LED 4 (bit 2), 220 ohm dirençle
15#   GP5  -> LED 8 (bit 3), 220 ohm dirençle
16#   GP6  -> LED 16 (bit 4), 220 ohm dirençle
17#   GP7  -> LED 32 (bit 5), 220 ohm dirençle
18#   GP15 -> Buton (diğer ucu GND)
19#   LED  -> Karttaki LED (saniye atımı)
20#   GND  -> LED katotları, buton
21
22from machine import Pin
23import time
24
25# ============ AYARLAR ============
26START_TIME = (12, 59, 50)  # Açılış saati (saat, dakika, saniye)
27SEC, MIN, HOUR = range(3)
28START_MODE = SEC       # Açılışta gösterilen alan
29LONG_MS = 800          # Uzun basış süresi
30DEBOUNCE_MS = 20       # Buton titreşim süresi
31MODE_MS = 500          # Mod işaretinin süresi
32BLINK_MS = 300         # Ayar modunda yanıp sönme
33SET_TIMEOUT_MS = 10000 # Bu kadar basılmazsa ayar kaydedilir
34SWEEP_STEP_MS = 60     # Tam saat ışık turunda adım
35SWEEP_ROUNDS = 2       # Işık turu sayısı
36TICK_MS = 100          # Karttaki LED'in yanma süresi
37LOOP_MS = 5            # Döngü adımı
38
39# Sırayla bit 0 (1) ... bit 5 (32)
40LED_PINS = (2, 3, 4, 5, 6, 7)
41MODE_NAMES = ("SANIYE / SECONDS", "DAKIKA / MINUTES", "SAAT / HOURS")
42# Mod işareti: soldan 1, 2 ya da 3 LED (saniye, dakika, saat)
43MODE_MARKS = (0b100000, 0b110000, 0b111000)
44
45
46# ============ DONANIM ============
47leds = [Pin(gp, Pin.OUT, value=0) for gp in LED_PINS]
48# "LED" adı Pico'da da Pico W'de de karttaki LED'i bulur (Pico W'de GP pini değil)
49tick_led = Pin("LED", Pin.OUT, value=0)   # Pico'nun karttaki LED'i
50
51
52class Button:
53    # Pull-up'lı buton: basınca 0 okunur. update() 1 = basıldı, -1 = bırakıldı
54    def __init__(self, gp):
55        self.pin = Pin(gp, Pin.IN, Pin.PULL_UP)
56        self.down = False
57        self.changed_at = time.ticks_ms()
58
59    def update(self, now):
60        pressed = self.pin.value() == 0
61        if pressed != self.down and time.ticks_diff(now, self.changed_at) >= DEBOUNCE_MS:
62            self.down = pressed
63            self.changed_at = now
64            return 1 if pressed else -1
65        return 0
66
67    def held_ms(self, now):
68        return time.ticks_diff(now, self.changed_at)
69
70
71button = Button(15)
72shown = -1                 # LED'lerdeki son desen
73
74
75def show_bits(pattern):
76    # Desen değiştiyse 6 LED'i yaz: bit i -> LED i
77    global shown
78    if pattern == shown:
79        return
80    shown = pattern
81    for i, led in enumerate(leds):
82        led.value((pattern >> i) & 1)
83
84
85def binary(v):
86    # 6 haneli ikili yazı, örnek 13 -> 001101
87    return "".join("1" if v >> i & 1 else "0" for i in range(5, -1, -1))
88
89
90# ============ SAAT ============
91clock_s = (START_TIME[0] * 3600 + START_TIME[1] * 60 + START_TIME[2]) % 86400
92start = time.ticks_ms()
93next_second = time.ticks_add(start, 1000)
94tick_off_at = start
95
96
97def hms():
98    return clock_s // 3600, clock_s // 60 % 60, clock_s % 60
99
100
101def field_value(m):
102    h, mi, s = hms()
103    return (s, mi, h)[m]
104
105
106def time_text():
107    return "%02d:%02d:%02d" % hms()
108
109
110# ============ DURUM ============
111mode = START_MODE
112setting = False            # Ayar modu
113long_done = False          # Bu basışta uzun basış işlendi
114marker_until = start       # Mod işaretinin bitiş zamanı
115sweep_at = None            # Işık turunun başlangıcı
116blink_ref = start          # Yanıp sönmenin başlangıcı
117last_press = start         # Ayar modunda son basış
118
119
120def report(prefix):
121    v = field_value(mode)
122    print("%s %s: %d = %s  (%s)" % (prefix, MODE_NAMES[mode], v, binary(v), time_text()))
123
124
125def save_setting(now):
126    global setting
127    setting = False
128    print("Saat ayarlandi / Time set: %s" % time_text())
129
130
131def on_short(now):
132    global mode, marker_until, clock_s, blink_ref, last_press
133    if setting:
134        # Ayar modunda her kısa basış seçili alanı 1 artırır
135        h, mi, s = hms()
136        if mode == HOUR:
137            h = (h + 1) % 24
138        else:
139            mi = (mi + 1) % 60
140        clock_s = h * 3600 + mi * 60 + s
141        blink_ref = now
142        last_press = now
143        report("+1")
144    else:
145        mode = (mode + 1) % 3
146        marker_until = time.ticks_add(now, MODE_MS)
147        report("Mod / Mode")
148
149
150def on_long(now):
151    global setting, clock_s, next_second, blink_ref, last_press
152    if setting:
153        if mode == MIN:
154            # Dakika ayarlanınca saniye sıfırdan başlar
155            clock_s -= clock_s % 60
156            next_second = time.ticks_add(now, 1000)
157        save_setting(now)
158    elif mode == SEC:
159        # Saniye modunda uzun basış saniyeyi sıfırlar (radyo sinyaliyle eşitleme)
160        clock_s -= clock_s % 60
161        next_second = time.ticks_add(now, 1000)
162        print("Saniye sifirlandi / Seconds zeroed: %s" % time_text())
163    else:
164        setting = True
165        blink_ref = now
166        last_press = now
167        report("Ayar / Set")
168
169
170def frame(now):
171    # O anki LED deseni: ışık turu > mod işareti > ayar (yanıp söner) > değer
172    if sweep_at is not None:
173        step = time.ticks_diff(now, sweep_at) // SWEEP_STEP_MS
174        pos = step % 10
175        return 1 << (pos if pos < 6 else 10 - pos)     # 0..5..1 ileri geri
176    if time.ticks_diff(marker_until, now) > 0:
177        return MODE_MARKS[mode]
178    if setting and time.ticks_diff(now, blink_ref) // BLINK_MS % 2:
179        return 0
180    return field_value(mode)
181
182
183# ============ ANA DÖNGÜ ============
184print("== BlueGrays · bluegrays.com ==")
185print("Pico Ikili Saat / Binary Clock")
186print("Kisa basis: alan degistir, uzun basis: ayarla / Short press: next field, long: set")
187print("LED'ler / LEDs: 32 16 8 4 2 1")
188report("Mod / Mode")
189
190next_loop = time.ticks_ms()
191while True:
192    now = time.ticks_ms()
193
194    # Saniye sayacı: bir sonraki saniye bir öncekine eklenir, kayma olmaz
195    if time.ticks_diff(now, next_second) >= 0:
196        next_second = time.ticks_add(next_second, 1000)
197        clock_s = (clock_s + 1) % 86400
198        tick_led.value(1)
199        tick_off_at = time.ticks_add(now, TICK_MS)
200        if clock_s % 60 == 0:
201            print("Saat / Time %s" % time_text()[:5])
202        if clock_s % 3600 == 0 and not setting:
203            sweep_at = now                 # Tam saat: ışık turu
204    if not setting and time.ticks_diff(now, tick_off_at) >= 0:
205        tick_led.value(0)
206    if sweep_at is not None and time.ticks_diff(now, sweep_at) >= SWEEP_STEP_MS * 10 * SWEEP_ROUNDS:
207        sweep_at = None
208
209    # Buton: kısa basış bırakınca, uzun basış LONG_MS dolunca (bırakmadan) işlenir
210    b = button.update(now)
211    if b == 1:
212        long_done = False
213        sweep_at = None                    # Basış ışık turunu keser
214    elif button.down and not long_done and button.held_ms(now) >= LONG_MS:
215        long_done = True
216        on_long(now)
217    elif b == -1 and not long_done:
218        on_short(now)
219
220    if setting:
221        tick_led.value(1)          # Ayarda karttaki LED yanık
222        if time.ticks_diff(now, last_press) >= SET_TIMEOUT_MS:
223            save_setting(now)
224
225    show_bits(frame(now))
226
227    # Sabit adım: bir sonraki 5 ms'ye kadar bekle
228    next_loop = time.ticks_add(next_loop, LOOP_MS)
229    wait = time.ticks_diff(next_loop, time.ticks_ms())
230    if wait > 0:
231        time.sleep_ms(wait)
232    else:
233        next_loop = time.ticks_ms()
234

Sıkça Sorulanlar

İkili saat nasıl okunur?

LED'ler soldan sağa 32, 16, 8, 4, 2 ve 1 değerindedir. Yanan LED'lerin değerlerini topla: 001101 deseninde 8, 4 ve 1 yanıyor, yani 13. Saat en fazla 23 olduğu için saat alanında en soldaki LED hiç yanmaz. Seri monitör her değeri ikili karşılığıyla yazar.

Neden 6 LED yetiyor?

6 bit ile 0'dan 63'e kadar sayılabilir (2 üzeri 6 = 64 değer). Saniye ve dakika en fazla 59, saat en fazla 23'tür; hepsi 6 bite sığar. Saati, dakikayı ve saniyeyi aynı anda görmek istersen her alan için ayrı bir LED sırası gerekir (toplam 17 LED).

Elektrik kesilince saat sıfırlanıyor mu?

Evet. Pico'da pil destekli bir saat yoktur, kod her açılışta `START_TIME` değerinden başlar. Saati koruması için DS1307 gibi pilli bir RTC modülü eklenebilir. Bu projede açıldıktan sonra butonla saat ve dakikayı birkaç saniyede ayarlayabilirsin.

LED'leri farklı renk yapabilir miyim?

Evet. Kırmızı, yeşil, sarı ve turuncu LED'ler 3.3 V'ta 220 Ω ile rahat yanar. Mavi ve beyaz LED'lerin eşik gerilimi yüksektir (yaklaşık 3 V), 3.3 V'ta sönük kalabilir; onlarda direnci 100 Ω'a indir. Büyük basamakları başka renk yapmak okumayı kolaylaştırır.