#202Pemula

Jam Biner Raspberry Pi Pico (6 LED + Tombol)

Jam ini tidak punya angka! Kita membuat jam dengan Raspberry Pi Pico yang menampilkan waktu dalam biner. 6 LED adalah posisi 32-16-8-4-2-1; jumlahkan yang menyala dan kamu membaca detik, menit, atau jam. Satu tombol mengganti bagian yang ditampilkan dan mengatur waktu, dan sapuan cahaya berjalan melintasi LED setiap jam tepat.

0.0(0)
Jam Biner Raspberry Pi Pico (6 LED + Tombol)
Jam yang menunjukkan waktu dengan lampu, bukan angka: enam LED menampilkan detik, menit, atau jam dalam biner. Dari kiri ke kanan, nilai LED-nya 32, 16, 8, 4, 2, dan 1, dan menjumlahkan yang menyala memberimu nilai terkini. Satu tombol berganti antara detik, menit, dan jam, tekanan panjang memungkinkanmu mengatur waktu, dan setiap jam tepat, sapuan cahaya berjalan melintasi LED.

Video

Skema rangkaian

Jam Biner Raspberry Pi Pico (6 LED + Tombol) - Circuit

Kode sumber

MicroPython
1# ─────────────────────────────────────────
2#   BlueGrays · bluegrays.com
3#   Jam Biner Raspberry Pi Pico (6 LED + Tombol)
4# ─────────────────────────────────────────
5# Jam yang menampilkan waktu sebagai bilangan biner. 6 LED adalah posisi
6# nilai 32-16-8-4-2-1; jumlah LED yang menyala adalah nilainya. Tekan
7# singkat mengganti antara detik, menit, dan jam; tekan lama mengatur
8# bagian tersebut. Setiap jam tepat, sapuan cahaya berjalan, dan LED
9# onboard berdetak setiap detik.
10#
11# Pin:
12#   GP2  -> LED 1 (bit 0), lewat 220 ohm
13#   GP3  -> LED 2 (bit 1), lewat 220 ohm
14#   GP4  -> LED 4 (bit 2), lewat 220 ohm
15#   GP5  -> LED 8 (bit 3), lewat 220 ohm
16#   GP6  -> LED 16 (bit 4), lewat 220 ohm
17#   GP7  -> LED 32 (bit 5), lewat 220 ohm
18#   GP15 -> Tombol (kaki lainnya ke GND)
19#   LED  -> LED onboard (detak detik)
20#   GND  -> Katoda LED, tombol
21
22from machine import Pin
23import time
24
25# ============ PENGATURAN ============
26START_TIME = (12, 59, 50)  # Waktu awal (jam, menit, detik)
27SEC, MIN, HOUR = range(3)
28START_MODE = SEC       # Bagian yang ditampilkan di awal
29LONG_MS = 800          # Waktu tekan lama
30DEBOUNCE_MS = 20       # Waktu debounce tombol
31MODE_MS = 500          # Berapa lama penanda mode tampil
32BLINK_MS = 300         # Periode kedip di mode atur
33SET_TIMEOUT_MS = 10000 # Mode atur menyimpan setelah idle selama ini
34SWEEP_STEP_MS = 60     # Langkah sapuan jam tepat
35SWEEP_ROUNDS = 2       # Jumlah sapuan
36TICK_MS = 100          # Panjang kedipan LED onboard
37LOOP_MS = 5            # Langkah loop
38
39# Berurutan bit 0 (1) ... bit 5 (32)
40LED_PINS = (2, 3, 4, 5, 6, 7)
41MODE_NAMES = ("SANIYE / SECONDS", "DAKIKA / MINUTES", "SAAT / HOURS")
42# Penanda mode: 1, 2, atau 3 LED dari kiri (detik, menit, jam)
43MODE_MARKS = (0b100000, 0b110000, 0b111000)
44
45
46# ============ HARDWARE ============
47leds = [Pin(gp, Pin.OUT, value=0) for gp in LED_PINS]
48# Nama "LED" menemukan LED onboard di Pico maupun Pico W (di W bukan pin GP)
49tick_led = Pin("LED", Pin.OUT, value=0)   # LED onboard Pico
50
51
52class Button:
53    # Tombol pull-up: membaca 0 ketika ditekan. update() 1 = ditekan, -1 = dilepas
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                 # Pola terakhir di LED
73
74
75def show_bits(pattern):
76    # Jika pola berubah, tulis 6 LED: 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    # Teks biner 6 digit, misalnya 13 -> 001101
87    return "".join("1" if v >> i & 1 else "0" for i in range(5, -1, -1))
88
89
90# ============ JAM ============
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# ============ STATUS ============
111mode = START_MODE
112setting = False            # Mode atur
113long_done = False          # Tekan lama sudah ditangani untuk penekanan ini
114marker_until = start       # Kapan penanda mode berakhir
115sweep_at = None            # Awal sapuan cahaya
116blink_ref = start          # Awal siklus kedip
117last_press = start         # Penekanan terakhir di mode atur
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        # Di mode atur, setiap tekan singkat menambah 1 ke bagian yang dipilih
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            # Setelah menit diatur, detik mulai lagi dari nol
155            clock_s -= clock_s % 60
156            next_second = time.ticks_add(now, 1000)
157        save_setting(now)
158    elif mode == SEC:
159        # Di mode detik, tekan lama membuat detik jadi nol (sinkron dengan sinyal waktu)
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    # Pola LED sekarang: sapuan > penanda mode > atur (berkedip) > nilai
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)     # bolak-balik
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# ============ LOOP UTAMA ============
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    # Penghitung detik: setiap detik berikutnya ditambahkan ke detik terakhir, jadi tidak pernah
195    # bergeser
196    if time.ticks_diff(now, next_second) >= 0:
197        next_second = time.ticks_add(next_second, 1000)
198        clock_s = (clock_s + 1) % 86400
199        tick_led.value(1)
200        tick_off_at = time.ticks_add(now, TICK_MS)
201        if clock_s % 60 == 0:
202            print("Saat / Time %s" % time_text()[:5])
203        if clock_s % 3600 == 0 and not setting:
204            sweep_at = now                 # Jam tepat: sapuan cahaya
205    if not setting and time.ticks_diff(now, tick_off_at) >= 0:
206        tick_led.value(0)
207    if sweep_at is not None and time.ticks_diff(now, sweep_at) >= SWEEP_STEP_MS * 10 * SWEEP_ROUNDS:
208        sweep_at = None
209
210    # Tombol: tekan singkat bekerja ketika dilepas, tekan lama begitu LONG_MS terlewati
211    b = button.update(now)
212    if b == 1:
213        long_done = False
214        sweep_at = None                    # Penekanan menghentikan sapuan
215    elif button.down and not long_done and button.held_ms(now) >= LONG_MS:
216        long_done = True
217        on_long(now)
218    elif b == -1 and not long_done:
219        on_short(now)
220
221    if setting:
222        tick_led.value(1)          # LED onboard nyala selama mengatur
223        if time.ticks_diff(now, last_press) >= SET_TIMEOUT_MS:
224            save_setting(now)
225
226    show_bits(frame(now))
227
228    # Langkah tetap: tunggu sampai 5 ms berikutnya
229    next_loop = time.ticks_add(next_loop, LOOP_MS)
230    wait = time.ticks_diff(next_loop, time.ticks_ms())
231    if wait > 0:
232        time.sleep_ms(wait)
233    else:
234        next_loop = time.ticks_ms()
235

FAQ

Bagaimana cara membaca jam biner?

Dari kiri ke kanan, nilai LED-nya 32, 16, 8, 4, 2, dan 1. Jumlahkan nilai LED yang menyala: di pola 001101, 8, 4, dan 1 menyala, jadi nilainya 13. Jam tidak pernah melebihi 23, jadi LED paling kiri tetap padam di bagian jam. Serial monitor mencetak setiap nilai beserta bentuk binernya.

Kenapa 6 LED sudah cukup?

6 bit menghitung dari 0 sampai 63 (2 pangkat 6 = 64 nilai). Detik dan menit naik sampai 59 dan jam sampai 23, jadi semuanya muat dalam 6 bit. Untuk melihat jam, menit, dan detik sekaligus, kamu butuh baris LED terpisah untuk setiap bagian (total 17 LED).

Apakah jamnya ter-reset setelah listrik padam?

Ya. Pico tidak punya jam berbaterai, jadi kode mulai dari `START_TIME` setiap kali boot. Modul RTC berbaterai seperti DS1307 akan menjaga waktunya. Di proyek ini kamu bisa mengatur jam dan menit dengan tombol dalam beberapa detik setelah dinyalakan.

Bisakah aku memakai LED dengan warna berbeda?

Ya. LED merah, hijau, kuning, dan oranye menyala bagus di 3,3 V dengan 220 Ω. LED biru dan putih butuh sekitar 3 V dan bisa terlihat redup di 3,3 V; turunkan resistornya ke 100 Ω. Memberi warna berbeda untuk posisi bernilai tinggi membuat jam lebih mudah dibaca.