from machine import Pin, PWM
from neopixel import NeoPixel
import time

# ---------- Réglages ----------
NB_LED = 24
PIN_LED = 5
PIN_SERVO = 18
PINS_PAS = (19, 21, 22, 23)      # IN1, IN2, IN3, IN4 ( branchement su servo moteur 360°)

# Moteur pas à pas (360°)
DELAI_US = 2000                  # plus petit = plus rapide (minimum conseillé : 1500)
SENS = 1                         # 1 ou -1 pour inverser le sens

# LED : blanc un peu jaune qui change d'intensité en fonction du rayonnement 
BLANC_CHAUD = (255, 190, 90)
LUM_MIN = 0.03                   # intensité minimale (0 à 1)
LUM_MAX = 0.25                   # intensité maximale (monte doucement)
PAS_LUM = 0.01                   # vitesse du changement

# Servo 180°
ANGLE_MAX = 180
PALIER = 45                      
PAUSE_MS = 1500                  
DELAI_SERVO_MS = 30              

# ---------- Matériel ----------
np = NeoPixel(Pin(PIN_LED), NB_LED)
servo = PWM(Pin(PIN_SERVO), freq=50)
IN = [Pin(p, Pin.OUT) for p in PINS_PAS]
SEQ = [(1,1,0,0), (0,1,1,0), (0,0,1,1), (1,0,0,1)]

def angle(deg):
    deg = max(0, min(180, deg))
    us = 500 + deg / 180 * 2000
    servo.duty_u16(int(us / 20000 * 65535))

# ---------- États ----------
etape = 0
t_pas = time.ticks_us()

lum = LUM_MIN
sens_lum = 1
t_led = time.ticks_ms()

ang = 0
etat = "monte"                   # "monte ", "pause", "descend les état change en fonction du niveau de d'eau"
etat_apres = "monte"
t_fin_pause = 0
t_servo = time.ticks_ms()
angle(0)

try:
    print("Test en cours (bouton stop pour arrêter)")
    while True:
        # --- Moteur pas à pas : rapide et continu ---
        now_us = time.ticks_us()
        if time.ticks_diff(now_us, t_pas) >= DELAI_US:
            t_pas = now_us
            etape = (etape + SENS) % 4
            for p, v in zip(IN, SEQ[etape]):
                p.value(v)

        now = time.ticks_ms()

        # --- LED : respiration en blanc chaud ---
        if time.ticks_diff(now, t_led) >= 30:
            t_led = now
            lum += sens_lum * PAS_LUM
            if lum >= LUM_MAX:
                lum = LUM_MAX
                sens_lum = -1
            elif lum <= LUM_MIN:
                lum = LUM_MIN
                sens_lum = 1
            np.fill(tuple(int(c * lum) for c in BLANC_CHAUD))
            np.write()

        # --- Servo ---
        if etat == "pause":
            if time.ticks_diff(now, t_fin_pause) >= 0:
                etat = etat_apres
                t_servo = now
        elif time.ticks_diff(now, t_servo) >= DELAI_SERVO_MS:
            t_servo = now
            if etat == "monte":
                ang += 1
                angle(ang)
                if ang >= ANGLE_MAX:
                    etat, etat_apres = "pause", "descend"
                    t_fin_pause = time.ticks_add(now, PAUSE_MS)
                elif ang % PALIER == 0:
                    etat, etat_apres = "pause", "monte"
                    t_fin_pause = time.ticks_add(now, PAUSE_MS)
            else:                # descend
                ang -= 2
                angle(ang)
                if ang <= 0:
                    ang = 0
                    etat, etat_apres = "pause", "monte"
                    t_fin_pause = time.ticks_add(now, PAUSE_MS)
finally:
    servo.deinit()
    np.fill((0, 0, 0))
    np.write()
    for p in IN:
        p.value(0)
    print("Arrêt")