#202Débutant

Horloge binaire avec Raspberry Pi Pico (6 LED + bouton)

Cette horloge n'a pas de chiffres ! On fabrique avec le Raspberry Pi Pico une horloge qui affiche l'heure en binaire. Les 6 LED sont les rangs 32-16-8-4-2-1 ; additionne celles qui sont allumées et tu lis les secondes, les minutes ou les heures. Un seul bouton change de champ et règle l'heure, et à chaque heure pile un balayage lumineux parcourt les LED.

0.0(0)
Horloge binaire avec Raspberry Pi Pico (6 LED + bouton)
Une horloge qui donne l'heure avec des lumières au lieu de chiffres : six LED affichent les secondes, les minutes ou les heures en binaire. De gauche à droite, les LED valent 32, 16, 8, 4, 2 et 1, et la somme de celles qui sont allumées donne la valeur du moment. Un seul bouton passe des secondes aux minutes puis aux heures, un appui long permet de régler l'heure, et à chaque heure pile une vague de lumière parcourt les LED.

Vidéo

Schéma du circuit

Horloge binaire avec Raspberry Pi Pico (6 LED + bouton) - Circuit

Code source

MicroPython
1# ─────────────────────────────────────────
2#   BlueGrays · bluegrays.com
3#   Horloge binaire avec Raspberry Pi Pico (6 LED + bouton)
4# ─────────────────────────────────────────
5# Une horloge qui affiche l'heure en nombres binaires. Les 6 LED sont les
6# rangs 32-16-8-4-2-1 ; les LED allumées s'additionnent pour donner la
7# valeur. Un appui court passe des secondes aux minutes et aux heures, un
8# appui long règle le champ. À chaque heure pile un balayage lumineux
9# passe, et la LED de la carte bat les secondes.
10#
11# Broches :
12#   GP2  -> LED 1 (bit 0), via 220 ohms
13#   GP3  -> LED 2 (bit 1), via 220 ohms
14#   GP4  -> LED 4 (bit 2), via 220 ohms
15#   GP5  -> LED 8 (bit 3), via 220 ohms
16#   GP6  -> LED 16 (bit 4), via 220 ohms
17#   GP7  -> LED 32 (bit 5), via 220 ohms
18#   GP15 -> Bouton (autre patte sur GND)
19#   LED  -> LED de la carte (battement des secondes)
20#   GND  -> Cathodes des LED, bouton
21
22from machine import Pin
23import time
24
25# ============ RÉGLAGES ============
26START_TIME = (12, 59, 50)  # Heure de départ (h, m, s)
27SEC, MIN, HOUR = range(3)
28START_MODE = SEC       # Champ affiché au démarrage
29LONG_MS = 800          # Durée d'un appui long
30DEBOUNCE_MS = 20       # Temps anti-rebond du bouton
31MODE_MS = 500          # Durée d'affichage du repère de mode
32BLINK_MS = 300         # Période de clignotement en mode réglage
33SET_TIMEOUT_MS = 10000 # Le mode réglage enregistre après ce temps sans appui
34SWEEP_STEP_MS = 60     # Pas du balayage de l'heure pile
35SWEEP_ROUNDS = 2       # Nombre de balayages
36TICK_MS = 100          # Durée d'éclair de la LED de la carte
37LOOP_MS = 5            # Pas de la boucle
38
39# Dans l'ordre bit 0 (1) ... bit 5 (32)
40LED_PINS = (2, 3, 4, 5, 6, 7)
41MODE_NAMES = ("SANIYE / SECONDS", "DAKIKA / MINUTES", "SAAT / HOURS")
42# Repère de mode : 1, 2 ou 3 LED depuis la gauche (secondes, minutes, heures)
43MODE_MARKS = (0b100000, 0b110000, 0b111000)
44
45
46# ============ MATÉRIEL ============
47leds = [Pin(gp, Pin.OUT, value=0) for gp in LED_PINS]
48# Le nom "LED" trouve la LED de la carte sur le Pico comme sur le Pico W (pas une broche GP sur le
49# W)
50tick_led = Pin("LED", Pin.OUT, value=0)   # La LED sur la carte du Pico
51
52
53class Button:
54    # Bouton avec pull-up : lit 0 à l'appui. update() 1 = appuyé, -1 = relâché
55    def __init__(self, gp):
56        self.pin = Pin(gp, Pin.IN, Pin.PULL_UP)
57        self.down = False
58        self.changed_at = time.ticks_ms()
59
60    def update(self, now):
61        pressed = self.pin.value() == 0
62        if pressed != self.down and time.ticks_diff(now, self.changed_at) >= DEBOUNCE_MS:
63            self.down = pressed
64            self.changed_at = now
65            return 1 if pressed else -1
66        return 0
67
68    def held_ms(self, now):
69        return time.ticks_diff(now, self.changed_at)
70
71
72button = Button(15)
73shown = -1                 # Dernier motif sur les LED
74
75
76def show_bits(pattern):
77    # Si le motif a changé, écrire les 6 LED : bit i -> LED i
78    global shown
79    if pattern == shown:
80        return
81    shown = pattern
82    for i, led in enumerate(leds):
83        led.value((pattern >> i) & 1)
84
85
86def binary(v):
87    # Texte binaire sur 6 chiffres, par ex. 13 -> 001101
88    return "".join("1" if v >> i & 1 else "0" for i in range(5, -1, -1))
89
90
91# ============ HORLOGE ============
92clock_s = (START_TIME[0] * 3600 + START_TIME[1] * 60 + START_TIME[2]) % 86400
93start = time.ticks_ms()
94next_second = time.ticks_add(start, 1000)
95tick_off_at = start
96
97
98def hms():
99    return clock_s // 3600, clock_s // 60 % 60, clock_s % 60
100
101
102def field_value(m):
103    h, mi, s = hms()
104    return (s, mi, h)[m]
105
106
107def time_text():
108    return "%02d:%02d:%02d" % hms()
109
110
111# ============ ÉTAT ============
112mode = START_MODE
113setting = False            # Mode réglage
114long_done = False          # Appui long déjà traité pour cet appui
115marker_until = start       # Fin du repère de mode
116sweep_at = None            # Début du balayage lumineux
117blink_ref = start          # Début du cycle de clignotement
118last_press = start         # Dernier appui en mode réglage
119
120
121def report(prefix):
122    v = field_value(mode)
123    print("%s %s: %d = %s  (%s)" % (prefix, MODE_NAMES[mode], v, binary(v), time_text()))
124
125
126def save_setting(now):
127    global setting
128    setting = False
129    print("Saat ayarlandi / Time set: %s" % time_text())
130
131
132def on_short(now):
133    global mode, marker_until, clock_s, blink_ref, last_press
134    if setting:
135        # En mode réglage, chaque appui court ajoute 1 au champ choisi
136        h, mi, s = hms()
137        if mode == HOUR:
138            h = (h + 1) % 24
139        else:
140            mi = (mi + 1) % 60
141        clock_s = h * 3600 + mi * 60 + s
142        blink_ref = now
143        last_press = now
144        report("+1")
145    else:
146        mode = (mode + 1) % 3
147        marker_until = time.ticks_add(now, MODE_MS)
148        report("Mod / Mode")
149
150
151def on_long(now):
152    global setting, clock_s, next_second, blink_ref, last_press
153    if setting:
154        if mode == MIN:
155            # Après le réglage des minutes, les secondes repartent de zéro
156            clock_s -= clock_s % 60
157            next_second = time.ticks_add(now, 1000)
158        save_setting(now)
159    elif mode == SEC:
160        # En mode secondes, un appui long remet les secondes à zéro (synchro sur un signal horaire)
161        clock_s -= clock_s % 60
162        next_second = time.ticks_add(now, 1000)
163        print("Saniye sifirlandi / Seconds zeroed: %s" % time_text())
164    else:
165        setting = True
166        blink_ref = now
167        last_press = now
168        report("Ayar / Set")
169
170
171def frame(now):
172    # Motif des LED à cet instant : balayage > repère de mode > réglage (clignote) > valeur
173    if sweep_at is not None:
174        step = time.ticks_diff(now, sweep_at) // SWEEP_STEP_MS
175        pos = step % 10
176        return 1 << (pos if pos < 6 else 10 - pos)     # aller-retour
177    if time.ticks_diff(marker_until, now) > 0:
178        return MODE_MARKS[mode]
179    if setting and time.ticks_diff(now, blink_ref) // BLINK_MS % 2:
180        return 0
181    return field_value(mode)
182
183
184# ============ BOUCLE PRINCIPALE ============
185print("== BlueGrays · bluegrays.com ==")
186print("Pico Ikili Saat / Binary Clock")
187print("Kisa basis: alan degistir, uzun basis: ayarla / Short press: next field, long: set")
188print("LED'ler / LEDs: 32 16 8 4 2 1")
189report("Mod / Mode")
190
191next_loop = time.ticks_ms()
192while True:
193    now = time.ticks_ms()
194
195    # Compteur de secondes : chaque seconde s'ajoute à la précédente, donc aucune dérive
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                 # Heure pile : balayage lumineux
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    # Bouton : un appui court agit au relâchement, un appui long dès que LONG_MS est écoulé
211    b = button.update(now)
212    if b == 1:
213        long_done = False
214        sweep_at = None                    # Un appui arrête le balayage
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 de la carte allumée pendant le réglage
223        if time.ticks_diff(now, last_press) >= SET_TIMEOUT_MS:
224            save_setting(now)
225
226    show_bits(frame(now))
227
228    # Pas fixe : attendre les 5 ms suivantes
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

Comment lit-on une horloge binaire ?

De gauche à droite, les LED valent 32, 16, 8, 4, 2 et 1. Additionne les valeurs des LED allumées : dans le motif 001101, ce sont 8, 4 et 1, donc 13. Les heures ne dépassent jamais 23, la LED de gauche reste donc éteinte pour les heures. Le moniteur série affiche chaque valeur avec sa forme binaire.

Pourquoi 6 LED suffisent-elles ?

Avec 6 bits on compte de 0 à 63 (2 puissance 6 = 64 valeurs). Les secondes et les minutes montent jusqu'à 59 et les heures jusqu'à 23 : tout tient sur 6 bits. Pour voir heures, minutes et secondes en même temps, il faudrait une rangée de LED par champ (17 LED au total).

L'horloge se remet-elle à zéro après une coupure ?

Oui. Le Pico n'a pas d'horloge sauvegardée par pile, le code repart de `START_TIME` à chaque démarrage. Un module RTC avec pile comme le DS1307 garderait l'heure. Dans ce projet, tu règles les heures et les minutes au bouton en quelques secondes après la mise sous tension.

Puis-je utiliser d'autres couleurs de LED ?

Oui. Les LED rouges, vertes, jaunes et orange s'allument bien en 3,3 V avec 220 Ω. Les LED bleues et blanches demandent environ 3 V et peuvent rester faibles en 3,3 V ; passe leur résistance à 100 Ω. Une autre couleur pour les rangs élevés rend l'horloge plus facile à lire.