from machine import Pin, I2C, ADC
from ssd1306 import SSD1306_I2C
import utime
# ----------------------------------------------------------
# 1. INITIALISATION DU MATÉRIEL
# ----------------------------------------------------------
# OLED via I2C (SDA=GP0, SCL=GP1)
i2c = I2C(0, sda=Pin(0), scl=Pin(1), freq=400_000)
oled = SSD1306_I2C(128, 64, i2c)
# Bouton sur GP15 (pull-up interne → actif à l'état BAS)
btn = Pin(15, Pin.IN, Pin.PULL_UP)
# LED sur GP14
led = Pin(14, Pin.OUT)
# Potentiomètre sur ADC0 (GP26)
pot = ADC(26)
# ----------------------------------------------------------
# 2. VARIABLES D'ÉTAT
# ----------------------------------------------------------
running = False # chronomètre actif ?
elapsed_ms = 0 # temps cumulé en ms
start_tick = 0 # tick de référence (utime.ticks_ms)
last_btn_state = 1 # dernier état lu du bouton (1 = relâché)
pot_reset_done = False # évite les réinitialisations répétées
RESET_THRESHOLD = 63000 # ~96 % du max ADC (65535) – ajustez si besoin
# ----------------------------------------------------------
# 3. FONCTIONS UTILITAIRES
# ----------------------------------------------------------
def ms_to_display(ms):
"""Convertit des millisecondes en (mm, ss, cs centièmes)."""
centis = ms // 10
s_tot = centis // 100
cs = centis % 100
mm = s_tot // 60
ss = s_tot % 60
return mm, ss, cs
def draw_screen(mm, ss, cs, state_txt, msg=""):
"""Rafraîchit l'écran OLED."""
oled.fill(0)
# Titre
oled.text(" CHRONOMETRE", 0, 0)
oled.hline(0, 10, 128, 1)
# Temps format MM:SS:CC
time_str = "{:02d}:{:02d}:{:02d}".format(mm, ss, cs)
oled.text(time_str, 24, 22) # centré ~
# État
oled.text("Etat: " + state_txt, 0, 40)
# Message temporaire (reset…)
if msg:
oled.text(msg, 0, 52)
oled.show()
# ----------------------------------------------------------
# 4. BOUCLE PRINCIPALE
# ----------------------------------------------------------
msg_timer = 0 # durée d'affichage du message temporaire
temp_msg = ""
draw_screen(0, 0, 0, "ARRETE") # écran initial
while True:
now = utime.ticks_ms()
# ── 4a. Lecture bouton (détection front descendant) ──
btn_state = btn.value()
if btn_state == 0 and last_btn_state == 1:
# Appui détecté → bascule l'état
if running:
# PAUSE : on mémorise le temps écoulé
elapsed_ms += utime.ticks_diff(now, start_tick)
running = False
led.value(0)
else:
# DÉMARRAGE
start_tick = now
running = True
led.value(1)
utime.sleep_ms(50) # anti-rebond simple
last_btn_state = btn_state
# ── 4b. Calcul du temps courant ──
if running:
current_ms = elapsed_ms + utime.ticks_diff(utime.ticks_ms(), start_tick)
else:
current_ms = elapsed_ms
# ── 4c. Lecture potentiomètre → reset ──
pot_val = pot.read_u16()
if pot_val >= RESET_THRESHOLD:
if not pot_reset_done:
# Réinitialisation
elapsed_ms = 0
start_tick = utime.ticks_ms()
current_ms = 0
pot_reset_done = True
temp_msg = "** RESET **"
msg_timer = utime.ticks_ms()
else:
pot_reset_done = False # autorise un prochain reset
# ── 4d. Effacement du message temporaire après 1,5 s ──
if temp_msg and utime.ticks_diff(utime.ticks_ms(), msg_timer) > 1500:
temp_msg = ""
# ── 4e. Affichage OLED ──
mm, ss, cs = ms_to_display(current_ms)
state_label = "EN COURS" if running else "ARRETE"
draw_screen(mm, ss, cs, state_label, temp_msg)
utime.sleep_ms(30) # ~33 fps, évite de saturer l'I2C