En effet, il y a de nombreuses façons de faire ce genre de programme.
Voici ce que je ferais pour ma part (dans la loop) :
D'abord lecture des boutons :
bool AetatBouton = digitalRead(AB);
bool BetatBouton = digitalRead(BB);
delay(30); // antirebond
Ensuite mise à jour des états des leds: Si le bouton A est appuyé, la led B ne doit pas clignoter, la ledA doit clignoter si elle était éteinte ou s'éteindre si elle clignotait. Enfin, on initialise un chrono pour commander le clignotement de la led A si elle doit clignoter. Les variables doivent être déclarées en global ou au début de la loop.
if (!AetatBouton) { // Bouton A appuyé
AledCligno = !AledCligno;
BledCligno = false;
if (AledCligno) Achrono = millis();
}
Et même chose avec la led B.
Puis on gère les clignotants. Je propose de déclarer des choses en global :
#define AperiodeCligno 1000 // ms
#define ArapportCyclique 50 // %
#define BperiodeCligno 2000
#define BrapportCyclique 75
Le rapport cyclique est le pourcentage de temps allumé lors du clignotement. A priori on met 50 (%) mais j'ai mis une autre valeur pour voir la différence.
Ça donne ensuite dans la loop (led A) :
unsigned long AdureeAllume = AperiodeCligno * ArapportCyclique / 100;
if (AledCligno) {
if ((millis() - Achrono) % AperiodeCligno < AdureeAllume) digitalWrite(A, HIGH);
else digitalWrite(A, LOW);
}
Pour éviter de recalculer AdureeAllume à chaque fois, on peut la déclarer en global et faire le calcul une fois pour toutes dans le setup.
La fonction % (modulo) calcule le reste de la division du premier argument par le second. Le test regarde donc si le temps écoulé depuis le lancement du chrono de la led A (c'est à dire le moment où on a appuyé sur le bouton A pour lancer le clignotement) - module la période de clignotement - est inférieur au rapport cyclique : si oui on allume, sinon on éteint.
Il reste à faire la même chose pour la led B.
Je n'ai pas testé, c'est juste une idée pour l'instant, je te laisse voir si tu veux le mettre en oeuvre.